mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Merge remote-tracking branch 'origin/main' into alexd/yummy-bug
This commit is contained in:
Vendored
+1
-1
@@ -7,7 +7,7 @@
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"August 2023\""
|
||||
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"September 2023\""
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release\n\n// current milestone name\n$milestone=milestone:\"August 2023\""
|
||||
"value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-python repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-l10n repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release\n\n// current milestone name\n$milestone=milestone:\"September 2023\""
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
||||
@@ -34,7 +34,7 @@ steps:
|
||||
displayName: Download openssl prebuilt
|
||||
inputs:
|
||||
command: custom
|
||||
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.8
|
||||
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.10
|
||||
customRegistry: useFeed
|
||||
customFeed: "Monaco/openssl-prebuilt"
|
||||
workingDir: $(Build.ArtifactStagingDirectory)
|
||||
@@ -42,7 +42,7 @@ steps:
|
||||
- script: |
|
||||
set -e
|
||||
mkdir $(Build.ArtifactStagingDirectory)/openssl
|
||||
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.8.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
|
||||
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.10.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
|
||||
displayName: Extract openssl prebuilt
|
||||
|
||||
# inspired by: https://github.com/emk/rust-musl-builder/blob/main/Dockerfile
|
||||
|
||||
@@ -23,7 +23,7 @@ steps:
|
||||
displayName: Download openssl prebuilt
|
||||
inputs:
|
||||
command: custom
|
||||
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.8
|
||||
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.10
|
||||
customRegistry: useFeed
|
||||
customFeed: "Monaco/openssl-prebuilt"
|
||||
workingDir: $(Build.ArtifactStagingDirectory)
|
||||
@@ -31,7 +31,7 @@ steps:
|
||||
- script: |
|
||||
set -e
|
||||
mkdir $(Build.ArtifactStagingDirectory)/openssl
|
||||
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.8.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
|
||||
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.10.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
|
||||
displayName: Extract openssl prebuilt
|
||||
|
||||
- template: ../cli/install-rust-posix.yml
|
||||
|
||||
@@ -26,7 +26,7 @@ steps:
|
||||
displayName: Download openssl prebuilt
|
||||
inputs:
|
||||
command: custom
|
||||
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.8
|
||||
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.10
|
||||
customRegistry: useFeed
|
||||
customFeed: "Monaco/openssl-prebuilt"
|
||||
workingDir: $(Build.ArtifactStagingDirectory)
|
||||
@@ -34,7 +34,7 @@ steps:
|
||||
- script: |
|
||||
set -e
|
||||
mkdir $(Build.ArtifactStagingDirectory)/openssl
|
||||
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.8.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
|
||||
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.10.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
|
||||
displayName: Extract openssl prebuilt
|
||||
|
||||
- ${{ if eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true) }}:
|
||||
|
||||
@@ -26,14 +26,14 @@ steps:
|
||||
displayName: Download openssl prebuilt
|
||||
inputs:
|
||||
command: custom
|
||||
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.8
|
||||
customCommand: pack @vscode-internal/openssl-prebuilt@0.0.10
|
||||
customRegistry: useFeed
|
||||
customFeed: "Monaco/openssl-prebuilt"
|
||||
workingDir: $(Build.ArtifactStagingDirectory)
|
||||
|
||||
- powershell: |
|
||||
mkdir $(Build.ArtifactStagingDirectory)/openssl
|
||||
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.8.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
|
||||
tar -xvzf $(Build.ArtifactStagingDirectory)/vscode-internal-openssl-prebuilt-0.0.10.tgz --strip-components=1 --directory=$(Build.ArtifactStagingDirectory)/openssl
|
||||
displayName: Extract openssl prebuilt
|
||||
|
||||
- template: ../cli/install-rust-win32.yml
|
||||
@@ -54,8 +54,8 @@ steps:
|
||||
VSCODE_CLI_ARTIFACT: unsigned_vscode_cli_win32_x64_cli
|
||||
VSCODE_CHECK_ONLY: ${{ parameters.VSCODE_CHECK_ONLY }}
|
||||
VSCODE_CLI_ENV:
|
||||
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-windows-static-md/lib
|
||||
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-windows-static-md/include
|
||||
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-windows-static/lib
|
||||
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/x64-windows-static/include
|
||||
RUSTFLAGS: "-C target-feature=+crt-static"
|
||||
|
||||
- ${{ if eq(parameters.VSCODE_BUILD_WIN32_ARM64, true) }}:
|
||||
@@ -66,8 +66,8 @@ steps:
|
||||
VSCODE_CLI_ARTIFACT: unsigned_vscode_cli_win32_arm64_cli
|
||||
VSCODE_CHECK_ONLY: ${{ parameters.VSCODE_CHECK_ONLY }}
|
||||
VSCODE_CLI_ENV:
|
||||
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-windows-static-md/lib
|
||||
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-windows-static-md/include
|
||||
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-windows-static/lib
|
||||
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/arm64-windows-static/include
|
||||
RUSTFLAGS: "-C target-feature=+crt-static"
|
||||
|
||||
- ${{ if eq(parameters.VSCODE_BUILD_WIN32_32BIT, true) }}:
|
||||
@@ -78,6 +78,6 @@ steps:
|
||||
VSCODE_CLI_ARTIFACT: unsigned_vscode_cli_win32_ia32_cli
|
||||
VSCODE_CHECK_ONLY: ${{ parameters.VSCODE_CHECK_ONLY }}
|
||||
VSCODE_CLI_ENV:
|
||||
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/x86-windows-static-md/lib
|
||||
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/x86-windows-static-md/include
|
||||
OPENSSL_LIB_DIR: $(Build.ArtifactStagingDirectory)/openssl/x86-windows-static/lib
|
||||
OPENSSL_INCLUDE_DIR: $(Build.ArtifactStagingDirectory)/openssl/x86-windows-static/include
|
||||
RUSTFLAGS: "-C target-feature=+crt-static"
|
||||
|
||||
@@ -734,7 +734,7 @@
|
||||
"--tab-sizing-current-width",
|
||||
"--tab-sizing-fixed-min-width",
|
||||
"--tab-sizing-fixed-max-width",
|
||||
"--editor-group-title-height",
|
||||
"--editor-group-tab-height",
|
||||
"--testMessageDecorationFontFamily",
|
||||
"--testMessageDecorationFontSize",
|
||||
"--title-border-bottom-color",
|
||||
|
||||
@@ -278,8 +278,8 @@ fn make_socket_rpc(
|
||||
port_forwarding: Option<PortForwarding>,
|
||||
requires_auth: AuthRequired,
|
||||
platform: Platform,
|
||||
http_requests: HttpRequestsMap,
|
||||
) -> RpcDispatcher<MsgPackSerializer, HandlerContext> {
|
||||
let http_requests = Arc::new(std::sync::Mutex::new(HashMap::new()));
|
||||
let server_bridges = ServerMultiplexer::new();
|
||||
let mut rpc = RpcBuilder::new(MsgPackSerializer {}).methods(HandlerContext {
|
||||
did_update: Arc::new(AtomicBool::new(false)),
|
||||
@@ -377,7 +377,10 @@ fn make_socket_rpc(
|
||||
);
|
||||
rpc.register_sync("httpheaders", |p: HttpHeadersParams, c| {
|
||||
if let Some(req) = c.http_requests.lock().unwrap().get(&p.req_id) {
|
||||
trace!(c.log, "got {} response for req {}", p.status_code, p.req_id);
|
||||
req.initial_response(p.status_code, p.headers);
|
||||
} else {
|
||||
warning!(c.log, "got response for unknown req {}", p.req_id);
|
||||
}
|
||||
Ok(EmptyObject {})
|
||||
});
|
||||
@@ -388,6 +391,7 @@ fn make_socket_rpc(
|
||||
req.body(p.segment);
|
||||
}
|
||||
if p.complete {
|
||||
trace!(c.log, "delegated request {} completed", p.req_id);
|
||||
reqs.remove(&p.req_id);
|
||||
}
|
||||
}
|
||||
@@ -441,6 +445,7 @@ async fn process_socket(
|
||||
port_forwarding,
|
||||
requires_auth,
|
||||
platform,
|
||||
http_requests.clone(),
|
||||
);
|
||||
|
||||
{
|
||||
@@ -497,6 +502,7 @@ async fn process_socket(
|
||||
}),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
http_requests.lock().unwrap().insert(id, r);
|
||||
|
||||
tx_counter += serialized.len();
|
||||
|
||||
@@ -16,6 +16,7 @@ use serde::{Deserialize, Serialize};
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum ClientRequestMethod<'a> {
|
||||
servermsg(RefServerMessageParams<'a>),
|
||||
serverclose(ServerClosedParams),
|
||||
serverlog(ServerLog<'a>),
|
||||
makehttpreq(HttpRequestParams<'a>),
|
||||
version(VersionResponse),
|
||||
@@ -89,6 +90,11 @@ pub struct ServerMessageParams {
|
||||
pub body: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct ServerClosedParams {
|
||||
pub i: u16,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct RefServerMessageParams<'a> {
|
||||
pub i: u16,
|
||||
|
||||
@@ -32,6 +32,7 @@ impl ServerBridge {
|
||||
match read.read(&mut read_buf).await {
|
||||
Err(_) => return,
|
||||
Ok(0) => {
|
||||
let _ = target.server_closed().await;
|
||||
return; // EOF
|
||||
}
|
||||
Ok(s) => {
|
||||
|
||||
@@ -9,7 +9,7 @@ use tokio::sync::mpsc;
|
||||
use crate::msgpack_rpc::MsgPackCaller;
|
||||
|
||||
use super::{
|
||||
protocol::{ClientRequestMethod, RefServerMessageParams, ToClientRequest},
|
||||
protocol::{ClientRequestMethod, RefServerMessageParams, ServerClosedParams, ToClientRequest},
|
||||
server_multiplexer::ServerMultiplexer,
|
||||
};
|
||||
|
||||
@@ -81,25 +81,43 @@ impl ServerMessageSink {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn server_closed(&mut self) -> Result<(), mpsc::error::SendError<SocketSignal>> {
|
||||
self.server_message_or_closed(None).await
|
||||
}
|
||||
|
||||
pub async fn server_message(
|
||||
&mut self,
|
||||
body: &[u8],
|
||||
) -> Result<(), mpsc::error::SendError<SocketSignal>> {
|
||||
let id = self.id;
|
||||
self.server_message_or_closed(Some(body)).await
|
||||
}
|
||||
|
||||
async fn server_message_or_closed(
|
||||
&mut self,
|
||||
body: Option<&[u8]>,
|
||||
) -> Result<(), mpsc::error::SendError<SocketSignal>> {
|
||||
let i = self.id;
|
||||
let mut tx = self.tx.take().unwrap();
|
||||
let body = self.get_server_msg_content(body);
|
||||
let msg = RefServerMessageParams { i: id, body };
|
||||
let msg = body
|
||||
.map(|b| self.get_server_msg_content(b))
|
||||
.map(|body| RefServerMessageParams { i, body });
|
||||
|
||||
let r = match &mut tx {
|
||||
ServerMessageDestination::Channel(tx) => {
|
||||
tx.send(SocketSignal::from_message(&ToClientRequest {
|
||||
id: None,
|
||||
params: ClientRequestMethod::servermsg(msg),
|
||||
params: match msg {
|
||||
Some(msg) => ClientRequestMethod::servermsg(msg),
|
||||
None => ClientRequestMethod::serverclose(ServerClosedParams { i }),
|
||||
},
|
||||
}))
|
||||
.await
|
||||
}
|
||||
ServerMessageDestination::Rpc(caller) => {
|
||||
caller.notify("servermsg", msg);
|
||||
match msg {
|
||||
Some(msg) => caller.notify("servermsg", msg),
|
||||
None => caller.notify("serverclose", ServerClosedParams { i }),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"watch": "gulp watch-extension:configuration-editing"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonc-parser": "^2.2.1",
|
||||
"jsonc-parser": "^3.2.0",
|
||||
"@octokit/rest": "19.0.4",
|
||||
"tunnel": "^0.0.6"
|
||||
},
|
||||
|
||||
@@ -3,41 +3,39 @@
|
||||
|
||||
|
||||
"@octokit/auth-token@^3.0.0":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.2.tgz#a0fc8de149fd15876e1ac78f6525c1c5ab48435f"
|
||||
integrity sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==
|
||||
dependencies:
|
||||
"@octokit/types" "^8.0.0"
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-3.0.4.tgz#70e941ba742bdd2b49bdb7393e821dea8520a3db"
|
||||
integrity sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==
|
||||
|
||||
"@octokit/core@^4.0.0":
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.1.0.tgz#b6b03a478f1716de92b3f4ec4fd64d05ba5a9251"
|
||||
integrity sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/core/-/core-4.2.4.tgz#d8769ec2b43ff37cc3ea89ec4681a20ba58ef907"
|
||||
integrity sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==
|
||||
dependencies:
|
||||
"@octokit/auth-token" "^3.0.0"
|
||||
"@octokit/graphql" "^5.0.0"
|
||||
"@octokit/request" "^6.0.0"
|
||||
"@octokit/request-error" "^3.0.0"
|
||||
"@octokit/types" "^8.0.0"
|
||||
"@octokit/types" "^9.0.0"
|
||||
before-after-hook "^2.2.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/endpoint@^7.0.0":
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-7.0.3.tgz#0b96035673a9e3bedf8bab8f7335de424a2147ed"
|
||||
integrity sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-7.0.6.tgz#791f65d3937555141fb6c08f91d618a7d645f1e2"
|
||||
integrity sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==
|
||||
dependencies:
|
||||
"@octokit/types" "^8.0.0"
|
||||
"@octokit/types" "^9.0.0"
|
||||
is-plain-object "^5.0.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/graphql@^5.0.0":
|
||||
version "5.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-5.0.4.tgz#519dd5c05123868276f3ae4e50ad565ed7dff8c8"
|
||||
integrity sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==
|
||||
version "5.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-5.0.6.tgz#9eac411ac4353ccc5d3fca7d76736e6888c5d248"
|
||||
integrity sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==
|
||||
dependencies:
|
||||
"@octokit/request" "^6.0.0"
|
||||
"@octokit/types" "^8.0.0"
|
||||
"@octokit/types" "^9.0.0"
|
||||
universal-user-agent "^6.0.0"
|
||||
|
||||
"@octokit/openapi-types@^13.11.0":
|
||||
@@ -50,6 +48,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-14.0.0.tgz#949c5019028c93f189abbc2fb42f333290f7134a"
|
||||
integrity sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==
|
||||
|
||||
"@octokit/openapi-types@^18.0.0":
|
||||
version "18.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-18.0.0.tgz#f43d765b3c7533fd6fb88f3f25df079c24fccf69"
|
||||
integrity sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==
|
||||
|
||||
"@octokit/plugin-paginate-rest@^4.0.0":
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-4.3.1.tgz#553e653ee0318605acd23bf3a799c8bfafdedae3"
|
||||
@@ -63,30 +66,30 @@
|
||||
integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==
|
||||
|
||||
"@octokit/plugin-rest-endpoint-methods@^6.0.0":
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.7.0.tgz#2f6f17f25b6babbc8b41d2bb0a95a8839672ce7c"
|
||||
integrity sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==
|
||||
version "6.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.8.1.tgz#97391fda88949eb15f68dc291957ccbe1d3e8ad1"
|
||||
integrity sha512-QrlaTm8Lyc/TbU7BL/8bO49vp+RZ6W3McxxmmQTgYxf2sWkO8ZKuj4dLhPNJD6VCUW1hetCmeIM0m6FTVpDiEg==
|
||||
dependencies:
|
||||
"@octokit/types" "^8.0.0"
|
||||
"@octokit/types" "^8.1.1"
|
||||
deprecation "^2.3.1"
|
||||
|
||||
"@octokit/request-error@^3.0.0":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-3.0.2.tgz#f74c0f163d19463b87528efe877216c41d6deb0a"
|
||||
integrity sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-3.0.3.tgz#ef3dd08b8e964e53e55d471acfe00baa892b9c69"
|
||||
integrity sha512-crqw3V5Iy2uOU5Np+8M/YexTlT8zxCfI+qu+LxUB7SZpje4Qmx3mub5DfEKSO8Ylyk0aogi6TYdf6kxzh2BguQ==
|
||||
dependencies:
|
||||
"@octokit/types" "^8.0.0"
|
||||
"@octokit/types" "^9.0.0"
|
||||
deprecation "^2.0.0"
|
||||
once "^1.4.0"
|
||||
|
||||
"@octokit/request@^6.0.0":
|
||||
version "6.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-6.2.2.tgz#a2ba5ac22bddd5dcb3f539b618faa05115c5a255"
|
||||
integrity sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==
|
||||
version "6.2.8"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/request/-/request-6.2.8.tgz#aaf480b32ab2b210e9dadd8271d187c93171d8eb"
|
||||
integrity sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==
|
||||
dependencies:
|
||||
"@octokit/endpoint" "^7.0.0"
|
||||
"@octokit/request-error" "^3.0.0"
|
||||
"@octokit/types" "^8.0.0"
|
||||
"@octokit/types" "^9.0.0"
|
||||
is-plain-object "^5.0.0"
|
||||
node-fetch "^2.6.7"
|
||||
universal-user-agent "^6.0.0"
|
||||
@@ -108,13 +111,20 @@
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^13.11.0"
|
||||
|
||||
"@octokit/types@^8.0.0":
|
||||
version "8.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-8.1.1.tgz#92e304e0f00d563667dfdbe0ae6b52e70d5149bb"
|
||||
integrity sha512-7tjk+6DyhYAmei8FOEwPfGKc0VE1x56CKPJ+eE44zhDbOyMT+9yan8apfQFxo8oEFsy+0O7PiBtH8w0Yo0Y9Kw==
|
||||
"@octokit/types@^8.1.1":
|
||||
version "8.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-8.2.1.tgz#a6de091ae68b5541f8d4fcf9a12e32836d4648aa"
|
||||
integrity sha512-8oWMUji8be66q2B9PmEIUyQm00VPDPun07umUWSaCwxmeaquFBro4Hcc3ruVoDo3zkQyZBlRvhIMEYS3pBhanw==
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^14.0.0"
|
||||
|
||||
"@octokit/types@^9.0.0":
|
||||
version "9.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@octokit/types/-/types-9.3.2.tgz#3f5f89903b69f6a2d196d78ec35f888c0013cac5"
|
||||
integrity sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==
|
||||
dependencies:
|
||||
"@octokit/openapi-types" "^18.0.0"
|
||||
|
||||
"@types/node@18.x":
|
||||
version "18.15.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469"
|
||||
@@ -135,15 +145,15 @@ is-plain-object@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
|
||||
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
|
||||
|
||||
jsonc-parser@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc"
|
||||
integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==
|
||||
jsonc-parser@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76"
|
||||
integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==
|
||||
|
||||
node-fetch@^2.6.7:
|
||||
version "2.6.8"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.8.tgz#a68d30b162bc1d8fd71a367e81b997e1f4d4937e"
|
||||
integrity sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "dotnet/csharp-tmLanguage",
|
||||
"repositoryUrl": "https://github.com/dotnet/csharp-tmLanguage",
|
||||
"commitHash": "772323937fedd65c6dc1c8ce6ea41d97415ed7d1"
|
||||
"commitHash": "525e628edad54c0f7aa15b015310df240803ea66"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,8 +25,8 @@ export async function updateTag(tagName: string | undefined): Promise<boolean |
|
||||
return;
|
||||
}
|
||||
|
||||
const rangesToUpdate = Array.from(editor.selections).reverse()
|
||||
.reduce<TagRange[]>((prev, selection) =>
|
||||
const rangesToUpdate = editor.selections
|
||||
.reduceRight<TagRange[]>((prev, selection) =>
|
||||
prev.concat(getRangesToUpdate(document, selection, rootNode)), []);
|
||||
if (!rangesToUpdate.length) {
|
||||
return;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"watch": "gulp watch-extension:extension-editing"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonc-parser": "^2.2.1",
|
||||
"jsonc-parser": "^3.2.0",
|
||||
"markdown-it": "^12.3.2",
|
||||
"parse5": "^3.0.2"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { l10n } from 'vscode';
|
||||
|
||||
export const implicitActivationEvent = l10n.t("This activation event cannot be explicitly listed by your extension.");
|
||||
export const redundantImplicitActivationEvent = l10n.t("This activation event can be removed as VS Code generates these automatically from your package.json contribution declarations.");
|
||||
@@ -12,10 +12,12 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
//package.json suggestions
|
||||
context.subscriptions.push(registerPackageDocumentCompletions());
|
||||
|
||||
//package.json code actions for lint warnings
|
||||
context.subscriptions.push(registerCodeActionsProvider());
|
||||
|
||||
context.subscriptions.push(new ExtensionLinter());
|
||||
}
|
||||
|
||||
|
||||
function registerPackageDocumentCompletions(): vscode.Disposable {
|
||||
return vscode.languages.registerCompletionItemProvider({ language: 'json', pattern: '**/package.json' }, {
|
||||
provideCompletionItems(document, position, token) {
|
||||
@@ -23,3 +25,11 @@ function registerPackageDocumentCompletions(): vscode.Disposable {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function registerCodeActionsProvider(): vscode.Disposable {
|
||||
return vscode.languages.registerCodeActionsProvider({ language: 'json', pattern: '**/package.json' }, {
|
||||
provideCodeActions(document, range, context, token) {
|
||||
return new PackageDocument(document).provideCodeActions(range, context, token);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import * as MarkdownItType from 'markdown-it';
|
||||
import { commands, languages, workspace, Disposable, TextDocument, Uri, Diagnostic, Range, DiagnosticSeverity, Position, env, l10n } from 'vscode';
|
||||
import { INormalizedVersion, normalizeVersion, parseVersion } from './extensionEngineValidation';
|
||||
import { JsonStringScanner } from './jsonReconstruct';
|
||||
import { implicitActivationEvent, redundantImplicitActivationEvent } from './constants';
|
||||
|
||||
const product = JSON.parse(fs.readFileSync(path.join(env.appRoot, 'product.json'), { encoding: 'utf-8' }));
|
||||
const allowedBadgeProviders: string[] = (product.extensionAllowedBadgeProviders || []).map((s: string) => s.toLowerCase());
|
||||
@@ -32,8 +33,6 @@ const dataUrlsNotValid = l10n.t("Data URLs are not a valid image source.");
|
||||
const relativeUrlRequiresHttpsRepository = l10n.t("Relative image URLs require a repository with HTTPS protocol to be specified in the package.json.");
|
||||
const relativeBadgeUrlRequiresHttpsRepository = l10n.t("Relative badge URLs require a repository with HTTPS protocol to be specified in this package.json.");
|
||||
const apiProposalNotListed = l10n.t("This proposal cannot be used because for this extension the product defines a fixed set of API proposals. You can test your extension but before publishing you MUST reach out to the VS Code team.");
|
||||
const implicitActivationEvent = l10n.t("This activation event cannot be explicitly listed by your extension.");
|
||||
const redundantImplicitActivationEvent = l10n.t("This activation event can be removed as VS Code generates these automatically from your package.json contribution declarations.");
|
||||
const bumpEngineForImplicitActivationEvents = l10n.t("This activation event can be removed for extensions targeting engine version ^1.75 as VS Code will generate these automatically from your package.json contribution declarations.");
|
||||
const starActivation = l10n.t("Using '*' activation is usually a bad idea as it impacts performance.");
|
||||
const parsingErrorHeader = l10n.t("Error parsing the when-clause:");
|
||||
@@ -128,7 +127,7 @@ export class ExtensionLinter {
|
||||
|
||||
const tree = parseTree(document.getText());
|
||||
const info = this.readPackageJsonInfo(this.getUriFolder(document.uri), tree);
|
||||
if (info.isExtension) {
|
||||
if (tree && info.isExtension) {
|
||||
|
||||
const icon = findNodeAtLocation(tree, ['icon']);
|
||||
if (icon && icon.type === 'string') {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { getLocation, Location } from 'jsonc-parser';
|
||||
import { implicitActivationEvent, redundantImplicitActivationEvent } from './constants';
|
||||
|
||||
|
||||
export class PackageDocument {
|
||||
@@ -21,6 +22,24 @@ export class PackageDocument {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public provideCodeActions(_range: vscode.Range, context: vscode.CodeActionContext, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.CodeAction[]> {
|
||||
const codeActions: vscode.CodeAction[] = [];
|
||||
for (const diagnostic of context.diagnostics) {
|
||||
if (diagnostic.message === implicitActivationEvent || diagnostic.message === redundantImplicitActivationEvent) {
|
||||
const codeAction = new vscode.CodeAction(vscode.l10n.t("Remove activation event"), vscode.CodeActionKind.QuickFix);
|
||||
codeAction.edit = new vscode.WorkspaceEdit();
|
||||
const rangeForCharAfter = diagnostic.range.with(diagnostic.range.end, diagnostic.range.end.translate(0, 1));
|
||||
if (this.document.getText(rangeForCharAfter) === ',') {
|
||||
codeAction.edit.delete(this.document.uri, diagnostic.range.with(undefined, diagnostic.range.end.translate(0, 1)));
|
||||
} else {
|
||||
codeAction.edit.delete(this.document.uri, diagnostic.range);
|
||||
}
|
||||
codeActions.push(codeAction);
|
||||
}
|
||||
}
|
||||
return codeActions;
|
||||
}
|
||||
|
||||
private provideLanguageOverridesCompletionItems(location: Location, position: vscode.Position): vscode.ProviderResult<vscode.CompletionItem[]> {
|
||||
let range = this.getReplaceRange(location, position);
|
||||
const text = this.document.getText(range);
|
||||
|
||||
@@ -27,15 +27,15 @@ entities@~2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
|
||||
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
|
||||
|
||||
jsonc-parser@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc"
|
||||
integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==
|
||||
jsonc-parser@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76"
|
||||
integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==
|
||||
|
||||
linkify-it@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8"
|
||||
integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e"
|
||||
integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
|
||||
|
||||
@@ -2465,7 +2465,7 @@
|
||||
"null"
|
||||
],
|
||||
"default": 50,
|
||||
"description": "%config.inputValidationSubjectLength%"
|
||||
"markdownDescription": "%config.inputValidationSubjectLength%"
|
||||
},
|
||||
"git.detectSubmodules": {
|
||||
"type": "boolean",
|
||||
@@ -2659,7 +2659,7 @@
|
||||
"description": "%config.useIntegratedAskPass%"
|
||||
},
|
||||
"git.githubAuthentication": {
|
||||
"deprecationMessage": "This setting is now deprecated, please use `github.gitAuthentication` instead."
|
||||
"markdownDeprecationMessage": "This setting is now deprecated, please use `#github.gitAuthentication#` instead."
|
||||
},
|
||||
"git.timeline.date": {
|
||||
"type": "string",
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
"config.showPushSuccessNotification": "Controls whether to show a notification when a push is successful.",
|
||||
"config.inputValidation": "Controls when to show commit message input validation.",
|
||||
"config.inputValidationLength": "Controls the commit message length threshold for showing a warning.",
|
||||
"config.inputValidationSubjectLength": "Controls the commit message subject length threshold for showing a warning. Unset it to inherit the value of `config.inputValidationLength`.",
|
||||
"config.inputValidationSubjectLength": "Controls the commit message subject length threshold for showing a warning. Unset it to inherit the value of `#git.inputValidationLength#`.",
|
||||
"config.detectSubmodules": "Controls whether to automatically detect git submodules.",
|
||||
"config.detectSubmodulesLimit": "Controls the limit of git submodules detected.",
|
||||
"config.alwaysShowStagedChangesResourceGroup": "Always show the Staged Changes resource group.",
|
||||
|
||||
@@ -495,7 +495,7 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi
|
||||
this.logger.trace(`Opening repository: ${repoPath}`);
|
||||
const existingRepository = await this.getRepositoryExact(repoPath);
|
||||
if (existingRepository) {
|
||||
this.logger.trace(`Repository for path ${repoPath} already exists: ${existingRepository.root})`);
|
||||
this.logger.trace(`Repository for path ${repoPath} already exists: ${existingRepository.root}`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
"%html.completion.attributeDefaultValue.empty%"
|
||||
],
|
||||
"default": "doublequotes",
|
||||
"description": "%html.completion.attributeDefaultValue%"
|
||||
"markdownDescription": "%html.completion.attributeDefaultValue%"
|
||||
},
|
||||
"html.customData": {
|
||||
"type": "array",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"html.format.wrapAttributes.preservealigned": "Preserve wrapping of attributes but align.",
|
||||
"html.format.templating.desc": "Honor django, erb, handlebars and php templating language tags.",
|
||||
"html.format.unformattedContentDelimiter.desc": "Keep text content together between this string.",
|
||||
"html.format.wrapAttributesIndentSize.desc": "Indent wrapped attributes to after N characters. Use `null` to use the default indent size. Ignored if `#html.format.wrapAttributes#` is set to 'aligned'.",
|
||||
"html.format.wrapAttributesIndentSize.desc": "Indent wrapped attributes to after N characters. Use `null` to use the default indent size. Ignored if `#html.format.wrapAttributes#` is set to `aligned`.",
|
||||
"html.suggest.html5.desc": "Controls whether the built-in HTML language support suggests HTML5 tags, properties and values.",
|
||||
"html.trace.server.desc": "Traces the communication between VS Code and the HTML language server.",
|
||||
"html.validate.scripts": "Controls whether the built-in HTML language support validates embedded scripts.",
|
||||
|
||||
@@ -24,7 +24,7 @@ type NotebookMetadata = {
|
||||
pygments_lexer?: string;
|
||||
[propName: string]: unknown;
|
||||
};
|
||||
orig_nbformat: number;
|
||||
orig_nbformat?: number;
|
||||
[propName: string]: unknown;
|
||||
};
|
||||
|
||||
@@ -76,9 +76,7 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
data.metadata = {
|
||||
custom: {
|
||||
cells: [],
|
||||
metadata: {
|
||||
orig_nbformat: 4
|
||||
},
|
||||
metadata: {},
|
||||
nbformat: 4,
|
||||
nbformat_minor: 2
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ export class NotebookSerializer implements vscode.NotebookSerializer {
|
||||
|
||||
// For notebooks without metadata default the language in metadata to the preferred language.
|
||||
if (!json.metadata || (!json.metadata.kernelspec && !json.metadata.language_info)) {
|
||||
json.metadata = json.metadata || { orig_nbformat: defaultNotebookFormat.major };
|
||||
json.metadata = json.metadata || {};
|
||||
json.metadata.language_info = json.metadata.language_info || { name: preferredCellLanguage };
|
||||
}
|
||||
|
||||
@@ -101,8 +101,8 @@ export class NotebookSerializer implements vscode.NotebookSerializer {
|
||||
export function getNotebookMetadata(document: vscode.NotebookDocument | vscode.NotebookData) {
|
||||
const notebookContent: Partial<nbformat.INotebookContent> = document.metadata?.custom || {};
|
||||
notebookContent.cells = notebookContent.cells || [];
|
||||
notebookContent.nbformat = notebookContent.nbformat || 4;
|
||||
notebookContent.nbformat_minor = notebookContent.nbformat_minor ?? 2;
|
||||
notebookContent.metadata = notebookContent.metadata || { orig_nbformat: 4 };
|
||||
notebookContent.nbformat = notebookContent.nbformat || defaultNotebookFormat.major;
|
||||
notebookContent.nbformat_minor = notebookContent.nbformat_minor ?? defaultNotebookFormat.minor;
|
||||
notebookContent.metadata = notebookContent.metadata || {};
|
||||
return notebookContent;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "redhat-developer/vscode-java",
|
||||
"repositoryUrl": "https://github.com/redhat-developer/vscode-java",
|
||||
"commitHash": "5fb57e8e1c5d776b21be13cd7227b25b87edf4a6"
|
||||
"commitHash": "5d224a552cf5f0f8ebccf69e43e2575ed2c13839"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
@@ -44,7 +44,7 @@
|
||||
"suitability for any purpose."
|
||||
],
|
||||
"description": "This grammar was derived from https://github.com/atom/language-java/blob/master/grammars/java.cson.",
|
||||
"version": "1.21.0"
|
||||
"version": "1.22.0"
|
||||
}
|
||||
],
|
||||
"version": 1
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/redhat-developer/vscode-java/commit/5fb57e8e1c5d776b21be13cd7227b25b87edf4a6",
|
||||
"version": "https://github.com/redhat-developer/vscode-java/commit/5d224a552cf5f0f8ebccf69e43e2575ed2c13839",
|
||||
"name": "Java",
|
||||
"scopeName": "source.java",
|
||||
"patterns": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "JuliaEditorSupport/atom-language-julia",
|
||||
"repositoryUrl": "https://github.com/JuliaEditorSupport/atom-language-julia",
|
||||
"commitHash": "ccc0277c9ee9af34a0b50e5fa27a6f5191601b8c"
|
||||
"commitHash": "7cbe6a7c4f2c8275e15f5b6e0722d285730ffb99"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/JuliaEditorSupport/atom-language-julia/commit/ccc0277c9ee9af34a0b50e5fa27a6f5191601b8c",
|
||||
"version": "https://github.com/JuliaEditorSupport/atom-language-julia/commit/7cbe6a7c4f2c8275e15f5b6e0722d285730ffb99",
|
||||
"name": "Julia",
|
||||
"scopeName": "source.julia",
|
||||
"comment": "This grammar is used by Atom (Oniguruma), GitHub (PCRE), and VSCode (Oniguruma),\nso all regexps must be compatible with both engines.\n\nSpecs:\n- https://github.com/kkos/oniguruma/blob/master/doc/RE\n- https://www.pcre.org/current/doc/html/",
|
||||
@@ -356,13 +356,16 @@
|
||||
"name": "keyword.operator.shift.julia"
|
||||
},
|
||||
{
|
||||
"match": "(?:\\s*(::|>:|<:)\\s*((?:(?:Union)?\\([^)]*\\)|[[:alpha:]_$∇][[:word:]⁺-ₜ!′\\.]*(?:(?:{(?:[^{}]|{(?:[^{}]|{[^{}]*})*})*})|(?:\".+?(?<!\\\\)\"))?)))(?:\\.\\.\\.)?",
|
||||
"match": "(?:\\s*(::|>:|<:)\\s*((?:(?:Union)?\\([^)]*\\)|[[:alpha:]_$∇][[:word:]⁺-ₜ!′\\.]*(?:(?:{(?:[^{}]|{(?:[^{}]|{[^{}]*})*})*})|(?:\".+?(?<!\\\\)\"))?)))(?:\\.\\.\\.)?((?:\\.)?'*)",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "keyword.operator.relation.types.julia"
|
||||
},
|
||||
"2": {
|
||||
"name": "support.type.julia"
|
||||
},
|
||||
"3": {
|
||||
"name": "keyword.operator.transpose.julia"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
"git": {
|
||||
"name": "jlelong/vscode-latex-basics",
|
||||
"repositoryUrl": "https://github.com/jlelong/vscode-latex-basics",
|
||||
"commitHash": "30d04562e592305b6f6d41a539b3ccf326888aaf"
|
||||
"commitHash": "3ae82b457c28f0368cbbb47024b0245ef1ff3d33"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
"version": "1.5.3",
|
||||
"version": "1.5.2",
|
||||
"description": "The files in syntaxes/ were originally part of https://github.com/James-Yu/LaTeX-Workshop. They have been extracted in the hope that they can useful outside of the LaTeX-Workshop extension.",
|
||||
"licenseDetail": [
|
||||
"Copyright (c) vscode-latex-basics authors",
|
||||
|
||||
@@ -4,30 +4,74 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/jlelong/vscode-latex-basics/commit/7adad0868ecafbb1df978f1e052d6c3c85c38732",
|
||||
"version": "https://github.com/jlelong/vscode-latex-basics/commit/36411b38cf4ed18e02050249e2162b1316488686",
|
||||
"name": "BibTeX",
|
||||
"scopeName": "text.bibtex",
|
||||
"comment": "Grammar based on description from http://artis.imag.fr/~Xavier.Decoret/resources/xdkbibtex/bibtex_summary.html#comment\n\t\n\tTODO: Does not support @preamble\n\t",
|
||||
"comment": "Grammar based on description from https://github.com/aclements/biblib\n",
|
||||
"patterns": [
|
||||
{
|
||||
"begin": "@Comment",
|
||||
"beginCaptures": {
|
||||
"match": "@(?i:comment)(?=[\\s{(])",
|
||||
"captures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.comment.bibtex"
|
||||
}
|
||||
},
|
||||
"end": "$\\n?",
|
||||
"name": "comment.line.at-sign.bibtex"
|
||||
"name": "comment.block.at-sign.bibtex"
|
||||
},
|
||||
{
|
||||
"begin": "((@)(?i:preamble))\\s*(\\{)\\s*",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.other.preamble.bibtex"
|
||||
},
|
||||
"2": {
|
||||
"name": "punctuation.definition.keyword.bibtex"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.section.preamble.begin.bibtex"
|
||||
}
|
||||
},
|
||||
"end": "\\}",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.preamble.end.bibtex"
|
||||
}
|
||||
},
|
||||
"name": "meta.preamble.braces.bibtex",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#percentage_comment"
|
||||
"include": "#field_value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "((@)(?i:string))\\s*(\\{)\\s*([a-zA-Z0-9\\!\\$\\&\\*\\+\\-\\.\\/\\:\\;\\<\\>\\?\\[\\]\\^\\_\\`\\|]+)",
|
||||
"begin": "((@)(?i:preamble))\\s*(\\()\\s*",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.other.preamble.bibtex"
|
||||
},
|
||||
"2": {
|
||||
"name": "punctuation.definition.keyword.bibtex"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.section.preamble.begin.bibtex"
|
||||
}
|
||||
},
|
||||
"end": "\\)",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.section.preamble.end.bibtex"
|
||||
}
|
||||
},
|
||||
"name": "meta.preamble.parenthesis.bibtex",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#field_value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "((@)(?i:string))\\s*(\\{)\\s*([a-zA-Z!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~][a-zA-Z0-9!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~]*)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.other.string-constant.bibtex"
|
||||
@@ -51,12 +95,12 @@
|
||||
"name": "meta.string-constant.braces.bibtex",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#string_content"
|
||||
"include": "#field_value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "((@)(?i:string))\\s*(\\()\\s*([a-zA-Z0-9\\!\\$\\&\\*\\+\\-\\.\\/\\:\\;\\<\\>\\?\\[\\]\\^\\_\\`\\|]+)",
|
||||
"begin": "((@)(?i:string))\\s*(\\()\\s*([a-zA-Z!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~][a-zA-Z0-9!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~]*)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.other.string-constant.bibtex"
|
||||
@@ -80,12 +124,12 @@
|
||||
"name": "meta.string-constant.parenthesis.bibtex",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#string_content"
|
||||
"include": "#field_value"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "((@)[a-zA-Z]+)\\s*(\\{)\\s*([^\\s,]*)",
|
||||
"begin": "((@)[a-zA-Z!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~][a-zA-Z0-9!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~]*)\\s*(\\{)\\s*([^\\s,}]*)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.other.entry-type.bibtex"
|
||||
@@ -109,13 +153,7 @@
|
||||
"name": "meta.entry.braces.bibtex",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#percentage_comment"
|
||||
},
|
||||
{
|
||||
"include": "#url_field"
|
||||
},
|
||||
{
|
||||
"begin": "([a-zA-Z0-9\\!\\$\\&\\*\\+\\-\\.\\/\\:\\;\\<\\>\\?\\[\\]\\^\\_\\`\\|]+)\\s*(\\=)",
|
||||
"begin": "([a-zA-Z!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~][a-zA-Z0-9!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~]*)\\s*(\\=)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "support.function.key.bibtex"
|
||||
@@ -128,23 +166,14 @@
|
||||
"name": "meta.key-assignment.bibtex",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#percentage_comment"
|
||||
},
|
||||
{
|
||||
"include": "#integer"
|
||||
},
|
||||
{
|
||||
"include": "#string_content"
|
||||
},
|
||||
{
|
||||
"include": "#string_var"
|
||||
"include": "#field_value"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "((@)[a-zA-Z]+)\\s*(\\()\\s*([^\\s,]*)",
|
||||
"begin": "((@)[a-zA-Z!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~][a-zA-Z0-9!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~]*)\\s*(\\()\\s*([^\\s,]*)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.other.entry-type.bibtex"
|
||||
@@ -168,13 +197,7 @@
|
||||
"name": "meta.entry.parenthesis.bibtex",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#percentage_comment"
|
||||
},
|
||||
{
|
||||
"include": "#url_field"
|
||||
},
|
||||
{
|
||||
"begin": "([a-zA-Z0-9\\!\\$\\&\\*\\+\\-\\.\\/\\:\\;\\<\\>\\?\\[\\]\\^\\_\\`\\|]+)\\s*(\\=)",
|
||||
"begin": "([a-zA-Z!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~][a-zA-Z0-9!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~]*)\\s*(\\=)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "support.function.key.bibtex"
|
||||
@@ -187,16 +210,7 @@
|
||||
"name": "meta.key-assignment.bibtex",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#percentage_comment"
|
||||
},
|
||||
{
|
||||
"include": "#integer"
|
||||
},
|
||||
{
|
||||
"include": "#string_content"
|
||||
},
|
||||
{
|
||||
"include": "#string_var"
|
||||
"include": "#field_value"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -209,6 +223,23 @@
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"field_value": {
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#string_content"
|
||||
},
|
||||
{
|
||||
"include": "#integer"
|
||||
},
|
||||
{
|
||||
"include": "#string_var"
|
||||
},
|
||||
{
|
||||
"name": "keyword.operator.bibtex",
|
||||
"match": "#"
|
||||
}
|
||||
]
|
||||
},
|
||||
"integer": {
|
||||
"match": "\\s*(\\d+)\\s*",
|
||||
"captures": {
|
||||
@@ -218,13 +249,13 @@
|
||||
}
|
||||
},
|
||||
"nested_braces": {
|
||||
"begin": "(?<!\\\\)\\{",
|
||||
"begin": "\\{",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.group.begin.bibtex"
|
||||
}
|
||||
},
|
||||
"end": "(?<!\\\\)\\}",
|
||||
"end": "\\}",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.group.end.bibtex"
|
||||
@@ -237,16 +268,10 @@
|
||||
]
|
||||
},
|
||||
"string_var": {
|
||||
"match": "(#)?\\s*([a-zA-Z0-9\\!\\$\\&\\*\\+\\-\\.\\/\\:\\;\\<\\>\\?\\[\\]\\^\\_\\`\\|]+)\\s*(#)?",
|
||||
"match": "[a-zA-Z!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~][a-zA-Z0-9!$&*+\\-./:;<>?@\\[\\\\\\]^_`|~]*",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "keyword.operator.bibtex"
|
||||
},
|
||||
"2": {
|
||||
"0": {
|
||||
"name": "support.variable.bibtex"
|
||||
},
|
||||
"3": {
|
||||
"name": "keyword.operator.bibtex"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -259,23 +284,13 @@
|
||||
"name": "punctuation.definition.string.begin.bibtex"
|
||||
}
|
||||
},
|
||||
"end": "(\\})(?=(?:,?\\s*\\}?\\s*\\n)|(?:\\s*#))",
|
||||
"end": "\\}",
|
||||
"endCaptures": {
|
||||
"1": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.end.bibtex"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#url_cmd"
|
||||
},
|
||||
{
|
||||
"include": "#percentage_comment"
|
||||
},
|
||||
{
|
||||
"match": "@",
|
||||
"name": "invalid.illegal.at-sign.bibtex"
|
||||
},
|
||||
{
|
||||
"include": "#nested_braces"
|
||||
}
|
||||
@@ -288,7 +303,7 @@
|
||||
"name": "punctuation.definition.string.begin.bibtex"
|
||||
}
|
||||
},
|
||||
"end": "\"(?=(?:,?\\s*\\}?\\s*\\n)|(?:\\s*#))",
|
||||
"end": "\"",
|
||||
"endCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.end.bibtex"
|
||||
@@ -296,106 +311,11 @@
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#url_cmd"
|
||||
},
|
||||
{
|
||||
"include": "#percentage_comment"
|
||||
},
|
||||
{
|
||||
"match": "@",
|
||||
"name": "invalid.illegal.at-sign.bibtex"
|
||||
"include": "#nested_braces"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"string_url": {
|
||||
"patterns": [
|
||||
{
|
||||
"begin": "\\{|\"",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.bibtex"
|
||||
}
|
||||
},
|
||||
"end": "(\\}|\")(?=(?:,?\\s*\\}?\\s*\\n)|(?:\\s*#))",
|
||||
"endCaptures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.string.end.bibtex"
|
||||
}
|
||||
},
|
||||
"contentName": "meta.url.bibtex",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#url_cmd"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"percentage_comment": {
|
||||
"patterns": [
|
||||
{
|
||||
"begin": "(^[ \\t]+)?(?=%)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "punctuation.whitespace.comment.leading.bibtex"
|
||||
}
|
||||
},
|
||||
"end": "(?!\\G)",
|
||||
"patterns": [
|
||||
{
|
||||
"begin": "(?<!\\\\)%",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.comment.bibtex"
|
||||
}
|
||||
},
|
||||
"end": "$\\n?",
|
||||
"name": "comment.line.percentage.bibtex"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"url_cmd": {
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "support.function.url.bibtex"
|
||||
},
|
||||
"2": {
|
||||
"name": "punctuation.definition.function.bibtex"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.definition.arguments.begin.bibtex"
|
||||
},
|
||||
"4": {
|
||||
"name": "markup.underline.link.bibtex"
|
||||
},
|
||||
"5": {
|
||||
"name": "punctuation.definition.arguments.end.bibtex"
|
||||
}
|
||||
},
|
||||
"match": "(?:\\s*)((\\\\)(?:url|href))(\\{)([^}]*)(\\})",
|
||||
"name": "meta.function.link.url.bibtex"
|
||||
},
|
||||
"url_field": {
|
||||
"begin": "(url)\\s*(\\=)",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "support.function.key.bibtex"
|
||||
},
|
||||
"2": {
|
||||
"name": "punctuation.separator.key-value.bibtex"
|
||||
}
|
||||
},
|
||||
"end": "(?=[,}])",
|
||||
"name": "meta.key-assignment.url.bibtex",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#string_url"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/jlelong/vscode-latex-basics/commit/30d04562e592305b6f6d41a539b3ccf326888aaf",
|
||||
"version": "https://github.com/jlelong/vscode-latex-basics/commit/66ea1422ac817ff7704359b8ec4934a987024aaa",
|
||||
"name": "LaTeX",
|
||||
"scopeName": "text.tex.latex",
|
||||
"patterns": [
|
||||
@@ -2356,7 +2356,7 @@
|
||||
"name": "meta.definition.label.latex",
|
||||
"patterns": [
|
||||
{
|
||||
"match": "[a-zA-Z0-9\\.,:/*!^_-]",
|
||||
"match": "[\\p{Alphabetic}\\p{Number}\\.,:/*!^_-]",
|
||||
"name": "variable.parameter.definition.label.latex"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { isSupportedEnvironment } from './utils';
|
||||
import { isSupportedEnvironment } from './common/uri';
|
||||
import { IntervalTimer, SequencerByKey } from './common/async';
|
||||
import { generateCodeChallenge, generateCodeVerifier, randomUUID } from './cryptoUtils';
|
||||
import { BetterTokenStorage, IDidChangeInOtherWindowEvent } from './betterSecretStorage';
|
||||
import { LoopbackAuthServer } from './node/authServer';
|
||||
@@ -86,9 +87,9 @@ export class AzureActiveDirectoryService {
|
||||
// For details on why this is set to 2/3... see https://github.com/microsoft/vscode/issues/133201#issuecomment-966668197
|
||||
private static REFRESH_TIMEOUT_MODIFIER = 1000 * 2 / 3;
|
||||
private static POLLING_CONSTANT = 1000 * 60 * 30;
|
||||
|
||||
private _tokens: IToken[] = [];
|
||||
private _refreshTimeouts: Map<string, NodeJS.Timeout> = new Map<string, NodeJS.Timeout>();
|
||||
private _refreshingPromise: Promise<any> | undefined;
|
||||
private _sessionChangeEmitter: vscode.EventEmitter<vscode.AuthenticationProviderAuthenticationSessionsChangeEvent> = new vscode.EventEmitter<vscode.AuthenticationProviderAuthenticationSessionsChangeEvent>();
|
||||
|
||||
// Used to keep track of current requests when not using the local server approach.
|
||||
@@ -96,6 +97,12 @@ export class AzureActiveDirectoryService {
|
||||
private _codeExchangePromises = new Map<string, Promise<vscode.AuthenticationSession>>();
|
||||
private _codeVerfifiers = new Map<string, string>();
|
||||
|
||||
// Used to keep track of tokens that we need to store but can't because we aren't the focused window.
|
||||
private _pendingTokensToStore: Map<string, IToken> = new Map<string, IToken>();
|
||||
|
||||
// Used to sequence requests to the same scope.
|
||||
private _sequencer = new SequencerByKey<string>();
|
||||
|
||||
constructor(
|
||||
private readonly _logger: vscode.LogOutputChannel,
|
||||
_context: vscode.ExtensionContext,
|
||||
@@ -105,15 +112,24 @@ export class AzureActiveDirectoryService {
|
||||
private readonly _env: Environment
|
||||
) {
|
||||
_context.subscriptions.push(this._tokenStorage.onDidChangeInOtherWindow((e) => this.checkForUpdates(e)));
|
||||
_context.subscriptions.push(vscode.window.onDidChangeWindowState(async (e) => e.focused && await this.storePendingTokens()));
|
||||
|
||||
// In the event that a window isn't focused for a long time, we should still try to store the tokens at some point.
|
||||
const timer = new IntervalTimer();
|
||||
timer.cancelAndSet(
|
||||
() => !vscode.window.state.focused && this.storePendingTokens(),
|
||||
// 5 hours + random extra 0-30 seconds so that each window doesn't try to store at the same time
|
||||
(18000000) + Math.floor(Math.random() * 30000));
|
||||
_context.subscriptions.push(timer);
|
||||
}
|
||||
|
||||
public async initialize(): Promise<void> {
|
||||
this._logger.info('Reading sessions from secret storage...');
|
||||
this._logger.trace('Reading sessions from secret storage...');
|
||||
const sessions = await this._tokenStorage.getAll(item => this.sessionMatchesEndpoint(item));
|
||||
this._logger.info(`Got ${sessions.length} stored sessions`);
|
||||
this._logger.trace(`Got ${sessions.length} stored sessions`);
|
||||
|
||||
const refreshes = sessions.map(async session => {
|
||||
this._logger.trace(`Read the following stored session with scopes: ${session.scope}`);
|
||||
this._logger.trace(`[${session.scope}] '${session.id}' Read stored session`);
|
||||
const scopes = session.scope.split(' ');
|
||||
const scopeData: IScopeData = {
|
||||
scopes,
|
||||
@@ -187,12 +203,12 @@ export class AzureActiveDirectoryService {
|
||||
return this._sessionChangeEmitter.event;
|
||||
}
|
||||
|
||||
async getSessions(scopes?: string[]): Promise<vscode.AuthenticationSession[]> {
|
||||
public getSessions(scopes?: string[]): Promise<vscode.AuthenticationSession[]> {
|
||||
if (!scopes) {
|
||||
this._logger.info('Getting sessions for all scopes...');
|
||||
const sessions = this._tokens.map(token => this.convertToSessionSync(token));
|
||||
this._logger.info(`Got ${sessions.length} sessions for all scopes...`);
|
||||
return sessions;
|
||||
return Promise.resolve(sessions);
|
||||
}
|
||||
|
||||
let modifiedScopes = [...scopes];
|
||||
@@ -210,32 +226,7 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
modifiedScopes = modifiedScopes.sort();
|
||||
|
||||
let modifiedScopesStr = modifiedScopes.join(' ');
|
||||
this._logger.info(`Getting sessions for the following scopes: ${modifiedScopesStr}`);
|
||||
|
||||
if (this._refreshingPromise) {
|
||||
this._logger.info('Refreshing in progress. Waiting for completion before continuing.');
|
||||
try {
|
||||
await this._refreshingPromise;
|
||||
} catch (e) {
|
||||
// this will get logged in the refresh function.
|
||||
}
|
||||
}
|
||||
|
||||
let matchingTokens = this._tokens.filter(token => token.scope === modifiedScopesStr);
|
||||
|
||||
// The user may still have a token that doesn't have the openid & email scopes so check for that as well.
|
||||
// Eventually, we should remove this and force the user to re-log in so that we don't have any sessions
|
||||
// without an idtoken.
|
||||
if (!matchingTokens.length) {
|
||||
const fallbackOrderedScopes = scopes.sort().join(' ');
|
||||
this._logger.trace(`No session found with idtoken scopes... Using fallback scope list of: ${fallbackOrderedScopes}`);
|
||||
matchingTokens = this._tokens.filter(token => token.scope === fallbackOrderedScopes);
|
||||
if (matchingTokens.length) {
|
||||
modifiedScopesStr = fallbackOrderedScopes;
|
||||
}
|
||||
}
|
||||
|
||||
const modifiedScopesStr = modifiedScopes.join(' ');
|
||||
const clientId = this.getClientId(scopes);
|
||||
const scopeData: IScopeData = {
|
||||
clientId,
|
||||
@@ -247,31 +238,43 @@ export class AzureActiveDirectoryService {
|
||||
tenant: this.getTenantId(scopes),
|
||||
};
|
||||
|
||||
this._logger.trace(`[${scopeData.scopeStr}] Queued getting sessions`);
|
||||
return this._sequencer.queue(modifiedScopesStr, () => this.doGetSessions(scopeData));
|
||||
}
|
||||
|
||||
private async doGetSessions(scopeData: IScopeData): Promise<vscode.AuthenticationSession[]> {
|
||||
this._logger.info(`[${scopeData.scopeStr}] Getting sessions`);
|
||||
|
||||
const matchingTokens = this._tokens.filter(token => token.scope === scopeData.scopeStr);
|
||||
// If we still don't have a matching token try to get a new token from an existing token by using
|
||||
// the refreshToken. This is documented here:
|
||||
// https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#refresh-the-access-token
|
||||
// "Refresh tokens are valid for all permissions that your client has already received consent for."
|
||||
if (!matchingTokens.length) {
|
||||
// Get a token with the correct client id.
|
||||
const token = clientId === DEFAULT_CLIENT_ID
|
||||
const token = scopeData.clientId === DEFAULT_CLIENT_ID
|
||||
? this._tokens.find(t => t.refreshToken && !t.scope.includes('VSCODE_CLIENT_ID'))
|
||||
: this._tokens.find(t => t.refreshToken && t.scope.includes(`VSCODE_CLIENT_ID:${clientId}`));
|
||||
: this._tokens.find(t => t.refreshToken && t.scope.includes(`VSCODE_CLIENT_ID:${scopeData.clientId}`));
|
||||
|
||||
if (token) {
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Found a matching token with a different scopes '${token.scope}'. Attempting to get a new session using the existing session.`);
|
||||
try {
|
||||
const itoken = await this.refreshToken(token.refreshToken, scopeData);
|
||||
const itoken = await this.doRefreshToken(token.refreshToken, scopeData);
|
||||
matchingTokens.push(itoken);
|
||||
} catch (err) {
|
||||
this._logger.error(`Attempted to get a new session for scopes '${scopeData.scopeStr}' using the existing session with scopes '${token.scope}' but it failed due to: ${err.message ?? err}`);
|
||||
this._logger.error(`[${scopeData.scopeStr}] Attempted to get a new session using the existing session with scopes '${token.scope}' but it failed due to: ${err.message ?? err}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._logger.info(`Got ${matchingTokens.length} sessions for scopes: ${modifiedScopesStr}`);
|
||||
return Promise.all(matchingTokens.map(token => this.convertToSession(token, scopeData)));
|
||||
this._logger.info(`[${scopeData.scopeStr}] Got ${matchingTokens.length} sessions`);
|
||||
const results = await Promise.allSettled(matchingTokens.map(token => this.convertToSession(token, scopeData)));
|
||||
return results
|
||||
.filter(result => result.status === 'fulfilled')
|
||||
.map(result => (result as PromiseFulfilledResult<vscode.AuthenticationSession>).value);
|
||||
}
|
||||
|
||||
public async createSession(scopes: string[]): Promise<vscode.AuthenticationSession> {
|
||||
public createSession(scopes: string[]): Promise<vscode.AuthenticationSession> {
|
||||
let modifiedScopes = [...scopes];
|
||||
if (!modifiedScopes.includes('openid')) {
|
||||
modifiedScopes.push('openid');
|
||||
@@ -296,7 +299,12 @@ export class AzureActiveDirectoryService {
|
||||
tenant: this.getTenantId(scopes),
|
||||
};
|
||||
|
||||
this._logger.info(`Logging in for the following scopes: ${scopeData.scopeStr}`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] Queued creating session`);
|
||||
return this._sequencer.queue(scopeData.scopeStr, () => this.doCreateSession(scopeData));
|
||||
}
|
||||
|
||||
private async doCreateSession(scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
|
||||
this._logger.info(`[${scopeData.scopeStr}] Creating session`);
|
||||
|
||||
const runsRemote = vscode.env.remoteName !== undefined;
|
||||
const runsServerless = vscode.env.remoteName === undefined && vscode.env.uiKind === vscode.UIKind.Web;
|
||||
@@ -312,7 +320,7 @@ export class AzureActiveDirectoryService {
|
||||
try {
|
||||
return await this.createSessionWithLocalServer(scopeData);
|
||||
} catch (e) {
|
||||
this._logger.error(`Error creating session for scopes: ${scopeData.scopeStr} Error: ${e}`);
|
||||
this._logger.error(`[${scopeData.scopeStr}] Error creating session: ${e}`);
|
||||
|
||||
// If the error was about starting the server, try directly hitting the login endpoint instead
|
||||
if (e.message === 'Error listening to server' || e.message === 'Closed' || e.message === 'Timeout waiting for port') {
|
||||
@@ -324,6 +332,7 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
|
||||
private async createSessionWithLocalServer(scopeData: IScopeData) {
|
||||
this._logger.trace(`[${scopeData.scopeStr}] Starting login flow with local server`);
|
||||
const codeVerifier = generateCodeVerifier();
|
||||
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
||||
const qs = new URLSearchParams({
|
||||
@@ -352,11 +361,14 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
|
||||
const session = await this.exchangeCodeForSession(codeToExchange, codeVerifier, scopeData);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${session.id}' Sending change event for added session`);
|
||||
this._sessionChangeEmitter.fire({ added: [session], removed: [], changed: [] });
|
||||
this._logger.info(`[${scopeData.scopeStr}] '${session.id}' session successfully created!`);
|
||||
return session;
|
||||
}
|
||||
|
||||
private async createSessionWithoutLocalServer(scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
|
||||
this._logger.trace(`[${scopeData.scopeStr}] Starting login flow without local server`);
|
||||
let callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.microsoft-authentication`));
|
||||
const nonce = generateCodeVerifier();
|
||||
const callbackQuery = new URLSearchParams(callbackUri.query);
|
||||
@@ -418,25 +430,19 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
|
||||
public async removeSessionById(sessionId: string, writeToDisk: boolean = true): Promise<vscode.AuthenticationSession | undefined> {
|
||||
this._logger.info(`Logging out of session '${sessionId}'`);
|
||||
const tokenIndex = this._tokens.findIndex(token => token.sessionId === sessionId);
|
||||
if (tokenIndex === -1) {
|
||||
this._logger.info(`Session not found '${sessionId}'`);
|
||||
this._logger.warn(`'${sessionId}' Session not found to remove`);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const token = this._tokens.splice(tokenIndex, 1)[0];
|
||||
const session = await this.removeSessionByIToken(token, writeToDisk);
|
||||
|
||||
if (session) {
|
||||
this._sessionChangeEmitter.fire({ added: [], removed: [session], changed: [] });
|
||||
}
|
||||
|
||||
return session;
|
||||
this._logger.trace(`[${token.scope}] '${sessionId}' Queued removing session`);
|
||||
return this._sequencer.queue(token.scope, () => this.removeSessionByIToken(token, writeToDisk));
|
||||
}
|
||||
|
||||
public async clearSessions() {
|
||||
this._logger.info('Logging out of all sessions');
|
||||
this._logger.trace('Logging out of all sessions');
|
||||
this._tokens = [];
|
||||
await this._tokenStorage.deleteAll(item => this.sessionMatchesEndpoint(item));
|
||||
|
||||
@@ -445,9 +451,11 @@ export class AzureActiveDirectoryService {
|
||||
});
|
||||
|
||||
this._refreshTimeouts.clear();
|
||||
this._logger.trace('All sessions logged out');
|
||||
}
|
||||
|
||||
private async removeSessionByIToken(token: IToken, writeToDisk: boolean = true): Promise<vscode.AuthenticationSession | undefined> {
|
||||
this._logger.info(`[${token.scope}] '${token.sessionId}' Logging out of session`);
|
||||
this.removeSessionTimeout(token.sessionId);
|
||||
|
||||
if (writeToDisk) {
|
||||
@@ -460,9 +468,9 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
|
||||
const session = this.convertToSessionSync(token);
|
||||
this._logger.info(`Sending change event for session that was removed with scopes: ${token.scope}`);
|
||||
this._logger.trace(`[${token.scope}] '${token.sessionId}' Sending change event for session that was removed`);
|
||||
this._sessionChangeEmitter.fire({ added: [], removed: [session], changed: [] });
|
||||
this._logger.info(`Logged out of session '${token.sessionId}' with scopes: ${token.scope}`);
|
||||
this._logger.info(`[${token.scope}] '${token.sessionId}' Logged out of session successfully!`);
|
||||
return session;
|
||||
}
|
||||
|
||||
@@ -471,12 +479,14 @@ export class AzureActiveDirectoryService {
|
||||
//#region timeout
|
||||
|
||||
private setSessionTimeout(sessionId: string, refreshToken: string, scopeData: IScopeData, timeout: number) {
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${sessionId}' Setting refresh timeout for ${timeout} milliseconds`);
|
||||
this.removeSessionTimeout(sessionId);
|
||||
this._refreshTimeouts.set(sessionId, setTimeout(async () => {
|
||||
try {
|
||||
const refreshedToken = await this.refreshToken(refreshToken, scopeData, sessionId);
|
||||
this._logger.info('Triggering change session event...');
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${sessionId}' Sending change event for session that was refreshed`);
|
||||
this._sessionChangeEmitter.fire({ added: [], removed: [], changed: [this.convertToSessionSync(refreshedToken)] });
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${sessionId}' refresh timeout complete`);
|
||||
} catch (e) {
|
||||
if (e.message !== REFRESH_NETWORK_FAILURE) {
|
||||
vscode.window.showErrorMessage(vscode.l10n.t('You have been signed out because reading stored authentication information failed.'));
|
||||
@@ -500,12 +510,13 @@ export class AzureActiveDirectoryService {
|
||||
|
||||
private convertToTokenSync(json: ITokenResponse, scopeData: IScopeData, existingId?: string): IToken {
|
||||
let claims = undefined;
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${existingId ?? 'new'}' Attempting to parse token response.`);
|
||||
|
||||
try {
|
||||
if (json.id_token) {
|
||||
claims = JSON.parse(base64Decode(json.id_token.split('.')[1]));
|
||||
} else {
|
||||
this._logger.info('Attempting to parse access_token instead since no id_token was included in the response.');
|
||||
this._logger.warn(`[${scopeData.scopeStr}] '${existingId ?? 'new'}' Attempting to parse access_token instead since no id_token was included in the response.`);
|
||||
claims = JSON.parse(base64Decode(json.access_token.split('.')[1]));
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -520,6 +531,8 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
|
||||
const id = `${claims.tid}/${(claims.oid ?? (claims.altsecid ?? '' + claims.ipd ?? ''))}`;
|
||||
const sessionId = existingId || `${id}/${randomUUID()}`;
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${sessionId}' Token response parsed successfully.`);
|
||||
return {
|
||||
expiresIn: json.expires_in,
|
||||
expiresAt: json.expires_in ? Date.now() + json.expires_in * 1000 : undefined,
|
||||
@@ -527,7 +540,7 @@ export class AzureActiveDirectoryService {
|
||||
idToken: json.id_token,
|
||||
refreshToken: json.refresh_token,
|
||||
scope: scopeData.scopeStr,
|
||||
sessionId: existingId || `${id}/${randomUUID()}`,
|
||||
sessionId,
|
||||
account: {
|
||||
label,
|
||||
id,
|
||||
@@ -552,9 +565,7 @@ export class AzureActiveDirectoryService {
|
||||
|
||||
private async convertToSession(token: IToken, scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
|
||||
if (token.accessToken && (!token.expiresAt || token.expiresAt > Date.now())) {
|
||||
token.expiresAt
|
||||
? this._logger.info(`Token available from cache (for scopes ${token.scope}), expires in ${token.expiresAt - Date.now()} milliseconds`)
|
||||
: this._logger.info('Token available from cache (for scopes ${token.scope})');
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Token available from cache${token.expiresAt ? `, expires in ${token.expiresAt - Date.now()} milliseconds` : ''}.`);
|
||||
return {
|
||||
id: token.sessionId,
|
||||
accessToken: token.accessToken,
|
||||
@@ -565,7 +576,7 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
|
||||
try {
|
||||
this._logger.info(`Token expired or unavailable (for scopes ${token.scope}), trying refresh`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Token expired or unavailable, trying refresh`);
|
||||
const refreshedToken = await this.refreshToken(token.refreshToken, scopeData, token.sessionId);
|
||||
if (refreshedToken.accessToken) {
|
||||
return {
|
||||
@@ -588,18 +599,13 @@ export class AzureActiveDirectoryService {
|
||||
|
||||
//#region refresh logic
|
||||
|
||||
private async refreshToken(refreshToken: string, scopeData: IScopeData, sessionId?: string): Promise<IToken> {
|
||||
this._refreshingPromise = this.doRefreshToken(refreshToken, scopeData, sessionId);
|
||||
try {
|
||||
const result = await this._refreshingPromise;
|
||||
return result;
|
||||
} finally {
|
||||
this._refreshingPromise = undefined;
|
||||
}
|
||||
private refreshToken(refreshToken: string, scopeData: IScopeData, sessionId?: string): Promise<IToken> {
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${sessionId ?? 'new'}' Queued refreshing token`);
|
||||
return this._sequencer.queue(scopeData.scopeStr, () => this.doRefreshToken(refreshToken, scopeData, sessionId));
|
||||
}
|
||||
|
||||
private async doRefreshToken(refreshToken: string, scopeData: IScopeData, sessionId?: string): Promise<IToken> {
|
||||
this._logger.info(`Refreshing token for scopes: ${scopeData.scopeStr}`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${sessionId ?? 'new'}' Refreshing token`);
|
||||
const postData = new URLSearchParams({
|
||||
refresh_token: refreshToken,
|
||||
client_id: scopeData.clientId,
|
||||
@@ -614,7 +620,7 @@ export class AzureActiveDirectoryService {
|
||||
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
|
||||
}
|
||||
this.setToken(token, scopeData);
|
||||
this._logger.info(`Token refresh success for scopes: ${token.scope}`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Token refresh success`);
|
||||
return token;
|
||||
} catch (e) {
|
||||
if (e.message === REFRESH_NETWORK_FAILURE) {
|
||||
@@ -625,7 +631,7 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
this._logger.error(`Refreshing token failed (for scopes: ${scopeData.scopeStr}): ${e.message}`);
|
||||
this._logger.error(`[${scopeData.scopeStr}] '${sessionId ?? 'new'}' Refreshing token failed: ${e.message}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -690,6 +696,7 @@ export class AzureActiveDirectoryService {
|
||||
|
||||
const session = await this.exchangeCodeForSession(code, verifier, scopeData);
|
||||
this._sessionChangeEmitter.fire({ added: [session], removed: [], changed: [] });
|
||||
this._logger.info(`[${scopeData.scopeStr}] '${session.id}' session successfully created!`);
|
||||
resolve(session);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
@@ -705,6 +712,7 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
|
||||
private async handleCodeInputBox(inputBox: vscode.InputBox, verifier: string, scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
|
||||
this._logger.trace(`[${scopeData.scopeStr}] Starting login flow with input box`);
|
||||
inputBox.ignoreFocusOut = true;
|
||||
inputBox.title = vscode.l10n.t('Microsoft Authentication');
|
||||
inputBox.prompt = vscode.l10n.t('Provide the authorization code to complete the sign in flow.');
|
||||
@@ -716,7 +724,9 @@ export class AzureActiveDirectoryService {
|
||||
if (code) {
|
||||
inputBox.dispose();
|
||||
const session = await this.exchangeCodeForSession(code, verifier, scopeData);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${session.id}' sending session changed event because session was added.`);
|
||||
this._sessionChangeEmitter.fire({ added: [session], removed: [], changed: [] });
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${session.id}' session successfully created!`);
|
||||
resolve(session);
|
||||
}
|
||||
});
|
||||
@@ -730,7 +740,7 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
|
||||
private async exchangeCodeForSession(code: string, codeVerifier: string, scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
|
||||
this._logger.info(`Exchanging login code for token for scopes: ${scopeData.scopeStr}`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] Exchanging login code for session`);
|
||||
let token: IToken | undefined;
|
||||
try {
|
||||
const postData = new URLSearchParams({
|
||||
@@ -743,10 +753,10 @@ export class AzureActiveDirectoryService {
|
||||
}).toString();
|
||||
|
||||
const json = await this.fetchTokenResponse(postData, scopeData);
|
||||
this._logger.info(`Exchanging login code for token (for scopes: ${scopeData.scopeStr}) succeeded!`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] Exchanging code for token succeeded!`);
|
||||
token = this.convertToTokenSync(json, scopeData);
|
||||
} catch (e) {
|
||||
this._logger.error(`Error exchanging code for token (for scopes ${scopeData.scopeStr}): ${e}`);
|
||||
this._logger.error(`[${scopeData.scopeStr}] Error exchanging code for token: ${e}`);
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -754,7 +764,7 @@ export class AzureActiveDirectoryService {
|
||||
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
|
||||
}
|
||||
this.setToken(token, scopeData);
|
||||
this._logger.info(`Login successful for scopes: ${scopeData.scopeStr}`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Exchanging login code for session succeeded!`);
|
||||
return await this.convertToSession(token, scopeData);
|
||||
}
|
||||
|
||||
@@ -789,7 +799,7 @@ export class AzureActiveDirectoryService {
|
||||
|
||||
if (!result || result.status > 499) {
|
||||
if (attempts > 3) {
|
||||
this._logger.error(`Fetching token failed for scopes (${scopeData.scopeStr}): ${result ? await result.text() : errorMessage}`);
|
||||
this._logger.error(`[${scopeData.scopeStr}] Fetching token failed: ${result ? await result.text() : errorMessage}`);
|
||||
break;
|
||||
}
|
||||
// Exponential backoff
|
||||
@@ -813,7 +823,7 @@ export class AzureActiveDirectoryService {
|
||||
//#region storage operations
|
||||
|
||||
private setToken(token: IToken, scopeData: IScopeData): void {
|
||||
this._logger.info(`Setting token for scopes: ${scopeData.scopeStr}`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Setting token`);
|
||||
|
||||
const existingTokenIndex = this._tokens.findIndex(t => t.sessionId === token.sessionId);
|
||||
if (existingTokenIndex > -1) {
|
||||
@@ -823,41 +833,18 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
|
||||
// Don't await because setting the token is only useful for any new windows that open.
|
||||
this.storeToken(token, scopeData);
|
||||
void this.storeToken(token, scopeData);
|
||||
}
|
||||
|
||||
private async storeToken(token: IToken, scopeData: IScopeData): Promise<void> {
|
||||
if (!vscode.window.state.focused) {
|
||||
const shouldStore = await new Promise((resolve, _) => {
|
||||
// To handle the case where the window is not focused for a long time. We want to store the token
|
||||
// at some point so that the next time they _do_ interact with VS Code, they don't have to sign in again.
|
||||
const timer = setTimeout(
|
||||
() => resolve(true),
|
||||
// 5 hours + random extra 0-30 seconds so that each window doesn't try to store at the same time
|
||||
(18000000) + Math.floor(Math.random() * 30000)
|
||||
);
|
||||
const dispose = vscode.Disposable.from(
|
||||
vscode.window.onDidChangeWindowState(e => {
|
||||
if (e.focused) {
|
||||
resolve(true);
|
||||
dispose.dispose();
|
||||
clearTimeout(timer);
|
||||
}
|
||||
}),
|
||||
this._tokenStorage.onDidChangeInOtherWindow(e => {
|
||||
if (e.updated.includes(token.sessionId)) {
|
||||
resolve(false);
|
||||
dispose.dispose();
|
||||
clearTimeout(timer);
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
if (!shouldStore) {
|
||||
this._logger.info(`Not storing token for scopes ${scopeData.scopeStr} because it was added in another window`);
|
||||
return;
|
||||
if (this._pendingTokensToStore.has(token.sessionId)) {
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Window is not focused, replacing token to be stored`);
|
||||
} else {
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Window is not focused, pending storage of token`);
|
||||
}
|
||||
this._pendingTokensToStore.set(token.sessionId, token);
|
||||
return;
|
||||
}
|
||||
|
||||
await this._tokenStorage.store(token.sessionId, {
|
||||
@@ -867,7 +854,31 @@ export class AzureActiveDirectoryService {
|
||||
account: token.account,
|
||||
endpoint: this._env.activeDirectoryEndpointUrl,
|
||||
});
|
||||
this._logger.info(`Stored token for scopes: ${scopeData.scopeStr}`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Stored token`);
|
||||
}
|
||||
|
||||
private async storePendingTokens(): Promise<void> {
|
||||
if (this._pendingTokensToStore.size === 0) {
|
||||
this._logger.trace('No pending tokens to store');
|
||||
return;
|
||||
}
|
||||
|
||||
const tokens = [...this._pendingTokensToStore.values()];
|
||||
this._pendingTokensToStore.clear();
|
||||
|
||||
this._logger.trace(`Storing ${tokens.length} pending tokens...`);
|
||||
await Promise.allSettled(tokens.map(async token => {
|
||||
this._logger.trace(`[${token.scope}] '${token.sessionId}' Storing pending token`);
|
||||
await this._tokenStorage.store(token.sessionId, {
|
||||
id: token.sessionId,
|
||||
refreshToken: token.refreshToken,
|
||||
scope: token.scope,
|
||||
account: token.account,
|
||||
endpoint: this._env.activeDirectoryEndpointUrl,
|
||||
});
|
||||
this._logger.trace(`[${token.scope}] '${token.sessionId}' Stored pending token`);
|
||||
}));
|
||||
this._logger.trace('Done storing pending tokens');
|
||||
}
|
||||
|
||||
private async checkForUpdates(e: IDidChangeInOtherWindowEvent<IStoredSession>): Promise<void> {
|
||||
@@ -875,7 +886,7 @@ export class AzureActiveDirectoryService {
|
||||
const session = await this._tokenStorage.get(key);
|
||||
if (!session) {
|
||||
this._logger.error('session not found that was apparently just added');
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.sessionMatchesEndpoint(session)) {
|
||||
@@ -895,36 +906,46 @@ export class AzureActiveDirectoryService {
|
||||
clientId: this.getClientId(scopes),
|
||||
tenant: this.getTenantId(scopes),
|
||||
};
|
||||
this._logger.info(`Session added in another window with scopes: ${session.scope}`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${session.id}' Session added in another window`);
|
||||
const token = await this.refreshToken(session.refreshToken, scopeData, session.id);
|
||||
this._logger.info(`Sending change event for session that was added with scopes: ${scopeData.scopeStr}`);
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Sending change event for session that was added`);
|
||||
this._sessionChangeEmitter.fire({ added: [this.convertToSessionSync(token)], removed: [], changed: [] });
|
||||
return;
|
||||
this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Session added in another window added here`);
|
||||
continue;
|
||||
} catch (e) {
|
||||
// Network failures will automatically retry on next poll.
|
||||
if (e.message !== REFRESH_NETWORK_FAILURE) {
|
||||
vscode.window.showErrorMessage(vscode.l10n.t('You have been signed out because reading stored authentication information failed.'));
|
||||
await this.removeSessionById(session.id);
|
||||
}
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const { value } of e.removed) {
|
||||
this._logger.trace(`[${value.scope}] '${value.id}' Session removed in another window`);
|
||||
if (!this.sessionMatchesEndpoint(value)) {
|
||||
// If the session wasn't made for this login endpoint, ignore this update
|
||||
this._logger.trace(`[${value.scope}] '${value.id}' Session doesn't match endpoint. Skipping...`);
|
||||
continue;
|
||||
}
|
||||
|
||||
this._logger.info(`Session removed in another window with scopes: ${value.scope}`);
|
||||
await this.removeSessionById(value.id, false);
|
||||
this._logger.trace(`[${value.scope}] '${value.id}' Session removed in another window removed here`);
|
||||
}
|
||||
|
||||
// NOTE: We don't need to handle changed sessions because all that really would give us is a new refresh token
|
||||
// because access tokens are not stored in Secret Storage due to their short lifespan. This new refresh token
|
||||
// is not useful in this window because we really only care about the lifetime of the _access_ token which we
|
||||
// are already managing (see usages of `setSessionTimeout`).
|
||||
// However, in order to minimize the amount of times we store tokens, if a token was stored via another window,
|
||||
// we cancel any pending token storage operations.
|
||||
for (const sessionId of e.updated) {
|
||||
if (this._pendingTokensToStore.delete(sessionId)) {
|
||||
this._logger.trace(`'${sessionId}' Cancelled pending token storage because token was updated in another window`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sessionMatchesEndpoint(session: IStoredSession): boolean {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vscode';
|
||||
|
||||
export class SequencerByKey<TKey> {
|
||||
|
||||
private promiseMap = new Map<TKey, Promise<unknown>>();
|
||||
|
||||
queue<T>(key: TKey, promiseTask: () => Promise<T>): Promise<T> {
|
||||
const runningPromise = this.promiseMap.get(key) ?? Promise.resolve();
|
||||
const newPromise = runningPromise
|
||||
.catch(() => { })
|
||||
.then(promiseTask)
|
||||
.finally(() => {
|
||||
if (this.promiseMap.get(key) === newPromise) {
|
||||
this.promiseMap.delete(key);
|
||||
}
|
||||
});
|
||||
this.promiseMap.set(key, newPromise);
|
||||
return newPromise;
|
||||
}
|
||||
}
|
||||
|
||||
export class IntervalTimer extends Disposable {
|
||||
|
||||
private _token: any;
|
||||
|
||||
constructor() {
|
||||
super(() => this.cancel());
|
||||
this._token = -1;
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
if (this._token !== -1) {
|
||||
clearInterval(this._token);
|
||||
this._token = -1;
|
||||
}
|
||||
}
|
||||
|
||||
cancelAndSet(runner: () => void, interval: number): void {
|
||||
this.cancel();
|
||||
this._token = setInterval(() => {
|
||||
runner();
|
||||
}, interval);
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ async function initMicrosoftSovereignCloudAuthProvider(context: vscode.Extension
|
||||
scopes: JSON.stringify(scopes.map(s => s.replace(/[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/i, '{guid}'))),
|
||||
});
|
||||
|
||||
return await aadService.createSession(scopes.sort());
|
||||
return await aadService.createSession(scopes);
|
||||
} catch (e) {
|
||||
/* __GDPR__
|
||||
"loginFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users run into issues with the login flow." }
|
||||
@@ -138,7 +138,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
scopes: JSON.stringify(scopes.map(s => s.replace(/[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/i, '{guid}'))),
|
||||
});
|
||||
|
||||
return await loginService.createSession(scopes.sort());
|
||||
return await loginService.createSession(scopes);
|
||||
} catch (e) {
|
||||
/* __GDPR__
|
||||
"loginFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users run into issues with the login flow." }
|
||||
|
||||
@@ -228,7 +228,9 @@ function onKeypressHandler(e: KeyboardEvent) {
|
||||
if (e.ctrlKey || e.shiftKey) {
|
||||
return;
|
||||
}
|
||||
if (e.code === 'ArrowDown' || e.code === 'End' || e.code === 'ArrowUp' || e.code === 'Home') {
|
||||
if (e.code === 'ArrowDown' || e.code === 'ArrowUp' ||
|
||||
e.code === 'End' || e.code === 'Home' ||
|
||||
e.code === 'PageUp' || e.code === 'PageDown') {
|
||||
// These should change the scroll position, not adjust the selected cell in the notebook
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"vscode": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"update-grammar": "node ../node_modules/vscode-grammar-updater/bin textmate/perl.tmbundle Syntaxes/Perl.plist ./syntaxes/perl.tmLanguage.json Syntaxes/Perl%%206.tmLanguage ./syntaxes/perl6.tmLanguage.json"
|
||||
"update-grammar": "node ../node_modules/vscode-grammar-updater/bin textmate/perl.tmbundle Syntaxes/Perl.plist ./syntaxes/perl.tmLanguage.json Syntaxes/Perl%206.tmLanguage ./syntaxes/perl6.tmLanguage.json"
|
||||
},
|
||||
"contributes": {
|
||||
"languages": [
|
||||
@@ -31,18 +31,23 @@
|
||||
"configuration": "./perl.language-configuration.json"
|
||||
},
|
||||
{
|
||||
"id": "perl6",
|
||||
"id": "raku",
|
||||
"aliases": [
|
||||
"Perl 6",
|
||||
"Raku",
|
||||
"Perl6",
|
||||
"perl6"
|
||||
],
|
||||
"extensions": [
|
||||
".raku",
|
||||
".rakumod",
|
||||
".rakutest",
|
||||
".rakudoc",
|
||||
".nqp",
|
||||
".p6",
|
||||
".pl6",
|
||||
".pm6",
|
||||
".nqp"
|
||||
".pm6"
|
||||
],
|
||||
"firstLine": "(^#!.*\\bperl6\\b)|use\\s+v6",
|
||||
"firstLine": "(^#!.*\\bperl6\\b)|use\\s+v6|raku|=begin\\spod|my\\sclass",
|
||||
"configuration": "./perl6.language-configuration.json"
|
||||
}
|
||||
],
|
||||
@@ -56,7 +61,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"language": "perl6",
|
||||
"language": "raku",
|
||||
"scopeName": "source.perl.6",
|
||||
"path": "./syntaxes/perl6.tmLanguage.json"
|
||||
}
|
||||
|
||||
@@ -278,18 +278,14 @@
|
||||
}
|
||||
],
|
||||
"colors": {
|
||||
|
||||
"editor.background": "#000c18",
|
||||
"editor.foreground": "#6688cc",
|
||||
|
||||
// Base
|
||||
// "foreground": "",
|
||||
"focusBorder": "#596F99",
|
||||
// "contrastActiveBorder": "",
|
||||
// "contrastBorder": "",
|
||||
|
||||
// "widget.shadow": "",
|
||||
|
||||
"input.background": "#181f2f",
|
||||
// "input.border": "",
|
||||
// "input.foreground": "",
|
||||
@@ -300,17 +296,13 @@
|
||||
"inputValidation.warningBorder": "#5B7E7A",
|
||||
"inputValidation.errorBackground": "#A22D44",
|
||||
"inputValidation.errorBorder": "#AB395B",
|
||||
|
||||
"badge.background": "#0063a5",
|
||||
"progressBar.background": "#0063a5",
|
||||
|
||||
"dropdown.background": "#181f2f",
|
||||
// "dropdown.foreground": "",
|
||||
// "dropdown.border": "",
|
||||
|
||||
"button.background": "#2B3C5D",
|
||||
// "button.foreground": "",
|
||||
|
||||
"list.activeSelectionBackground": "#08286b",
|
||||
// "list.activeSelectionForeground": "",
|
||||
"quickInputList.focusBackground": "#08286b",
|
||||
@@ -318,12 +310,10 @@
|
||||
"list.inactiveSelectionBackground": "#152037",
|
||||
"list.dropBackground": "#041D52",
|
||||
"list.highlightForeground": "#0063a5",
|
||||
|
||||
"scrollbar.shadow": "#515E91AA",
|
||||
"scrollbarSlider.activeBackground": "#3B3F5188",
|
||||
"scrollbarSlider.background": "#1F2230AA",
|
||||
"scrollbarSlider.hoverBackground": "#3B3F5188",
|
||||
|
||||
// Editor
|
||||
"editorWidget.background": "#262641",
|
||||
"editorCursor.foreground": "#ddbb88",
|
||||
@@ -350,14 +340,12 @@
|
||||
// "editor.selectionHighlightBackground": "",
|
||||
// "editor.wordHighlightBackground": "",
|
||||
// "editor.wordHighlightStrongBackground": "",
|
||||
|
||||
// Editor: Suggest Widget
|
||||
// "editorSuggestWidget.background": "",
|
||||
// "editorSuggestWidget.border": "",
|
||||
// "editorSuggestWidget.foreground": "",
|
||||
// "editorSuggestWidget.highlightForeground": "",
|
||||
// "editorSuggestWidget.selectedBackground": "",
|
||||
|
||||
// Editor: Peek View
|
||||
"peekViewResult.background": "#060621",
|
||||
// "peekViewResult.lineForeground": "",
|
||||
@@ -371,7 +359,6 @@
|
||||
"peekViewResult.matchHighlightBackground": "#eeeeee44",
|
||||
// "peekViewTitleLabel.foreground": "",
|
||||
// "peekViewTitleDescription.foreground": "",
|
||||
|
||||
// Ports
|
||||
"ports.iconRunningProcessForeground": "#80a2c2",
|
||||
// Editor: Diff
|
||||
@@ -379,23 +366,18 @@
|
||||
// "diffEditor.insertedTextBorder": "",
|
||||
"diffEditor.removedTextBackground": "#892F4688",
|
||||
// "diffEditor.removedTextBorder": "",
|
||||
|
||||
|
||||
// Editor: Minimap
|
||||
"minimap.selectionHighlight": "#750000",
|
||||
|
||||
// Workbench: Title
|
||||
"titleBar.activeBackground": "#10192c",
|
||||
// "titleBar.activeForeground": "",
|
||||
// "titleBar.inactiveBackground": "",
|
||||
// "titleBar.inactiveForeground": "",
|
||||
|
||||
// Workbench: Editors
|
||||
// "editorGroupHeader.noTabsBackground": "",
|
||||
"editorGroup.border": "#2b2b4a",
|
||||
"editorGroup.dropBackground": "#25375daa",
|
||||
"editorGroupHeader.tabsBackground": "#1c1c2a",
|
||||
|
||||
// Workbench: Tabs
|
||||
"tab.border": "#2b2b4a",
|
||||
// "tab.activeBackground": "",
|
||||
@@ -403,26 +385,21 @@
|
||||
// "tab.activeForeground": "",
|
||||
// "tab.inactiveForeground": "",
|
||||
"tab.lastPinnedBorder": "#2b3c5d",
|
||||
|
||||
// Workbench: Activity Bar
|
||||
"activityBar.background": "#051336",
|
||||
// "activityBar.foreground": "",
|
||||
// "activityBarBadge.background": "",
|
||||
// "activityBarBadge.foreground": "",
|
||||
"activityBarItem.profilesBackground": "#082877",
|
||||
|
||||
// Workbench: Panel
|
||||
// "panel.background": "",
|
||||
"panel.border": "#2b2b4a",
|
||||
// "panelTitle.activeBorder": "",
|
||||
// "panelTitle.activeForeground": "",
|
||||
// "panelTitle.inactiveForeground": "",
|
||||
|
||||
// Workbench: Side Bar
|
||||
"sideBar.background": "#060621",
|
||||
// "sideBarTitle.foreground": "",
|
||||
"sideBarSectionHeader.background": "#10192c",
|
||||
|
||||
// Workbench: Status Bar
|
||||
"statusBar.background": "#10192c",
|
||||
"statusBar.noFolderBackground": "#10192c",
|
||||
@@ -433,20 +410,16 @@
|
||||
"statusBarItem.prominentHoverBackground": "#0063a5dd",
|
||||
// "statusBarItem.activeBackground": "",
|
||||
// "statusBarItem.hoverBackground": "",
|
||||
|
||||
// Workbench: Debug
|
||||
"debugToolBar.background": "#051336",
|
||||
"debugExceptionWidget.background": "#051336",
|
||||
"debugExceptionWidget.border": "#AB395B",
|
||||
|
||||
// Workbench: Quick Open
|
||||
"pickerGroup.border": "#596F99",
|
||||
"pickerGroup.foreground": "#596F99",
|
||||
|
||||
// Workbench: Extensions
|
||||
"extensionButton.prominentBackground": "#5f8b3b",
|
||||
"extensionButton.prominentHoverBackground": "#5f8b3bbb",
|
||||
|
||||
// Workbench: Terminal
|
||||
"terminal.ansiBlack": "#111111",
|
||||
"terminal.ansiRed": "#ff9da4",
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
"source.cpp keyword.operator.new",
|
||||
"keyword.operator.delete",
|
||||
"keyword.other.using",
|
||||
"keyword.other.directive.using",
|
||||
"keyword.other.operator",
|
||||
"entity.name.operator"
|
||||
],
|
||||
|
||||
@@ -406,6 +406,7 @@
|
||||
"source.cpp keyword.operator.new",
|
||||
"source.cpp keyword.operator.delete",
|
||||
"keyword.other.using",
|
||||
"keyword.other.directive.using",
|
||||
"keyword.other.operator"
|
||||
],
|
||||
"settings": {
|
||||
|
||||
@@ -442,6 +442,7 @@
|
||||
"source.cpp keyword.operator.new",
|
||||
"source.cpp keyword.operator.delete",
|
||||
"keyword.other.using",
|
||||
"keyword.other.directive.using",
|
||||
"keyword.other.operator",
|
||||
"entity.name.operator"
|
||||
],
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
"source.cpp keyword.operator.new",
|
||||
"source.cpp keyword.operator.delete",
|
||||
"keyword.other.using",
|
||||
"keyword.other.directive.using",
|
||||
"keyword.other.operator",
|
||||
"entity.name.operator"
|
||||
],
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
"ports.iconRunningProcessForeground": "#369432",
|
||||
"activityBar.background": "#221a0f",
|
||||
"activityBar.foreground": "#d3af86",
|
||||
"activityBarItem.profilesBackground": "#47351d",
|
||||
"sideBar.background": "#362712",
|
||||
"menu.background": "#362712",
|
||||
"menu.foreground": "#CCCCCC",
|
||||
@@ -124,6 +123,7 @@
|
||||
"keyword.operator.new.cpp",
|
||||
"keyword.operator.delete.cpp",
|
||||
"keyword.other.using",
|
||||
"keyword.other.directive.using",
|
||||
"keyword.other.operator"
|
||||
],
|
||||
"settings": {
|
||||
|
||||
@@ -269,6 +269,7 @@
|
||||
"keyword.operator.new.cpp",
|
||||
"keyword.operator.delete.cpp",
|
||||
"keyword.other.using",
|
||||
"keyword.other.directive.using",
|
||||
"keyword.other.operator"
|
||||
],
|
||||
"settings": {
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
"statusBar.noFolderBackground": "#001126",
|
||||
"statusBar.debuggingBackground": "#001126",
|
||||
"activityBar.background": "#001733",
|
||||
"activityBarItem.profilesBackground": "#003271",
|
||||
"progressBar.background": "#bbdaffcc",
|
||||
"badge.background": "#bbdaffcc",
|
||||
"badge.foreground": "#001733",
|
||||
|
||||
@@ -67,7 +67,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
}
|
||||
|
||||
const logger = new Logger(vscode.l10n.t('Port Forwarding'));
|
||||
const provider = new TunnelProvider(logger);
|
||||
const provider = new TunnelProvider(logger, context);
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand('tunnel-forwarding.showLog', () => logger.show()),
|
||||
@@ -120,6 +120,8 @@ class Logger {
|
||||
}
|
||||
}
|
||||
|
||||
const didWarnPublicKey = 'didWarnPublic';
|
||||
|
||||
class TunnelProvider implements vscode.TunnelProvider {
|
||||
private readonly tunnels = new Set<Tunnel>();
|
||||
private readonly stateChange = new vscode.EventEmitter<StateT>();
|
||||
@@ -136,10 +138,16 @@ class TunnelProvider implements vscode.TunnelProvider {
|
||||
|
||||
public readonly onDidStateChange = this.stateChange.event;
|
||||
|
||||
constructor(private readonly logger: Logger) { }
|
||||
constructor(private readonly logger: Logger, private readonly context: vscode.ExtensionContext) { }
|
||||
|
||||
/** @inheritdoc */
|
||||
public async provideTunnel(tunnelOptions: vscode.TunnelOptions): Promise<vscode.Tunnel> {
|
||||
public async provideTunnel(tunnelOptions: vscode.TunnelOptions): Promise<vscode.Tunnel | undefined> {
|
||||
if (tunnelOptions.privacy === TunnelPrivacyId.Public) {
|
||||
if (!(await this.consentPublicPort(tunnelOptions.remoteAddress.port))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const tunnel = new Tunnel(
|
||||
tunnelOptions.remoteAddress,
|
||||
(tunnelOptions.privacy as TunnelPrivacyId) || TunnelPrivacyId.Private,
|
||||
@@ -184,6 +192,31 @@ class TunnelProvider implements vscode.TunnelProvider {
|
||||
this.updateActivePortsIfRunning();
|
||||
}
|
||||
|
||||
private async consentPublicPort(portNumber: number) {
|
||||
const didWarn = this.context.globalState.get(didWarnPublicKey, false);
|
||||
if (didWarn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const continueOpt = vscode.l10n.t('Continue');
|
||||
const dontShowAgain = vscode.l10n.t("Don't show again");
|
||||
const r = await vscode.window.showWarningMessage(
|
||||
vscode.l10n.t("You're about to create a publicly forwarded port. Anyone on the internet will be able to connect to the service listening on port {0}. You should only proceed if this service is secure and non-sensitive.", portNumber),
|
||||
{ modal: true },
|
||||
continueOpt,
|
||||
dontShowAgain,
|
||||
);
|
||||
if (r === continueOpt) {
|
||||
// continue
|
||||
} else if (r === dontShowAgain) {
|
||||
await this.context.globalState.update(didWarnPublicKey, true);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private isInStateWithProcess(process: ChildProcessWithoutNullStreams) {
|
||||
return (
|
||||
(this.state.state === State.Starting || this.state.state === State.Active) &&
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
"restrictedConfigurations": [
|
||||
"typescript.tsdk",
|
||||
"typescript.tsserver.pluginPaths",
|
||||
"typescript.npm"
|
||||
"typescript.npm",
|
||||
"typescript.tsserver.nodePath"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -1132,7 +1133,7 @@
|
||||
"typescript.tsserver.maxTsServerMemory": {
|
||||
"type": "number",
|
||||
"default": 3072,
|
||||
"description": "%configuration.tsserver.maxTsServerMemory%",
|
||||
"markdownDescription": "%configuration.tsserver.maxTsServerMemory%",
|
||||
"scope": "window"
|
||||
},
|
||||
"typescript.tsserver.experimental.enableProjectDiagnostics": {
|
||||
@@ -1251,6 +1252,11 @@
|
||||
"description": "%configuration.tsserver.web.projectWideIntellisense.suppressSemanticErrors%",
|
||||
"scope": "window"
|
||||
},
|
||||
"typescript.tsserver.nodePath": {
|
||||
"type": "string",
|
||||
"description": "%configuration.tsserver.nodePath%",
|
||||
"scope": "window"
|
||||
},
|
||||
"typescript.experimental.tsserver.web.typeAcquisition.enabled": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
"configuration.tsserver.useSyntaxServer.always": "Use a lighter weight syntax server to handle all IntelliSense operations. This syntax server can only provide IntelliSense for opened files.",
|
||||
"configuration.tsserver.useSyntaxServer.never": "Don't use a dedicated syntax server. Use a single server to handle all IntelliSense operations.",
|
||||
"configuration.tsserver.useSyntaxServer.auto": "Spawn both a full server and a lighter weight server dedicated to syntax operations. The syntax server is used to speed up syntax operations and provide IntelliSense while projects are loading.",
|
||||
"configuration.tsserver.maxTsServerMemory": "The maximum amount of memory (in MB) to allocate to the TypeScript server process.",
|
||||
"configuration.tsserver.maxTsServerMemory": "The maximum amount of memory (in MB) to allocate to the TypeScript server process. To use a memory limit greater than 4 GB, use `#typescript.tsserver.nodePath#` to run TS Server with a custom Node installation.",
|
||||
"configuration.tsserver.experimental.enableProjectDiagnostics": "(Experimental) Enables project wide error reporting.",
|
||||
"typescript.locale": "Sets the locale used to report JavaScript and TypeScript errors. Defaults to use VS Code's locale.",
|
||||
"configuration.implicitProjectConfig.module": "Sets the module system for the program. See more: https://www.typescriptlang.org/tsconfig#module.",
|
||||
@@ -213,6 +213,7 @@
|
||||
"configuration.suggest.objectLiteralMethodSnippets.enabled": "Enable/disable snippet completions for methods in object literals. Requires using TypeScript 4.7+ in the workspace.",
|
||||
"configuration.tsserver.web.projectWideIntellisense.enabled": "Enable/disable project-wide IntelliSense on web. Requires that VS Code is running in a trusted context.",
|
||||
"configuration.tsserver.web.projectWideIntellisense.suppressSemanticErrors": "Suppresses semantic errors. This is needed when using external packages as these can't be included analyzed on web.",
|
||||
"configuration.tsserver.nodePath": "Run TS Server on a custom Node installation. This can be a path to a Node executable, or 'node' if you want VS Code to detect a Node installation.",
|
||||
"configuration.experimental.tsserver.web.typeAcquisition.enabled": "Enable/disable package acquisition on the web.",
|
||||
"walkthroughs.nodejsWelcome.title": "Get started with JavaScript and Node.js",
|
||||
"walkthroughs.nodejsWelcome.description": "Make the most of Visual Studio Code's first-class JavaScript experience.",
|
||||
|
||||
@@ -16,4 +16,13 @@ export class BrowserServiceConfigurationProvider extends BaseServiceConfiguratio
|
||||
protected readLocalTsdk(_configuration: vscode.WorkspaceConfiguration): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
// On browsers, we don't run TSServer on Node
|
||||
protected readLocalNodePath(_configuration: vscode.WorkspaceConfiguration): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override readGlobalNodePath(_configuration: vscode.WorkspaceConfiguration): string | null {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as child_process from 'child_process';
|
||||
import * as fs from 'fs';
|
||||
import { BaseServiceConfigurationProvider } from './configuration';
|
||||
import { RelativeWorkspacePathResolver } from '../utils/relativePathResolver';
|
||||
|
||||
export class ElectronServiceConfigurationProvider extends BaseServiceConfigurationProvider {
|
||||
|
||||
@@ -35,4 +38,65 @@ export class ElectronServiceConfigurationProvider extends BaseServiceConfigurati
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected readLocalNodePath(configuration: vscode.WorkspaceConfiguration): string | null {
|
||||
return this.validatePath(this.readLocalNodePathWorker(configuration));
|
||||
}
|
||||
|
||||
private readLocalNodePathWorker(configuration: vscode.WorkspaceConfiguration): string | null {
|
||||
const inspect = configuration.inspect('typescript.tsserver.nodePath');
|
||||
if (inspect?.workspaceValue && typeof inspect.workspaceValue === 'string') {
|
||||
if (inspect.workspaceValue === 'node') {
|
||||
return this.findNodePath();
|
||||
}
|
||||
const fixedPath = this.fixPathPrefixes(inspect.workspaceValue);
|
||||
if (!path.isAbsolute(fixedPath)) {
|
||||
const workspacePath = RelativeWorkspacePathResolver.asAbsoluteWorkspacePath(fixedPath);
|
||||
return workspacePath || null;
|
||||
}
|
||||
return fixedPath;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected readGlobalNodePath(configuration: vscode.WorkspaceConfiguration): string | null {
|
||||
return this.validatePath(this.readGlobalNodePathWorker(configuration));
|
||||
}
|
||||
|
||||
private readGlobalNodePathWorker(configuration: vscode.WorkspaceConfiguration): string | null {
|
||||
const inspect = configuration.inspect('typescript.tsserver.nodePath');
|
||||
if (inspect?.globalValue && typeof inspect.globalValue === 'string') {
|
||||
if (inspect.globalValue === 'node') {
|
||||
return this.findNodePath();
|
||||
}
|
||||
const fixedPath = this.fixPathPrefixes(inspect.globalValue);
|
||||
if (path.isAbsolute(fixedPath)) {
|
||||
return fixedPath;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private findNodePath(): string | null {
|
||||
try {
|
||||
const out = child_process.execFileSync('node', ['-e', 'console.log(process.execPath)'], {
|
||||
windowsHide: true,
|
||||
timeout: 2000,
|
||||
cwd: vscode.workspace.workspaceFolders?.[0].uri.fsPath,
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
return out.trim();
|
||||
} catch (error) {
|
||||
vscode.window.showWarningMessage(vscode.l10n.t("Could not detect a Node installation to run TS Server."));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private validatePath(nodePath: string | null): string | null {
|
||||
if (nodePath && (!fs.existsSync(nodePath) || fs.lstatSync(nodePath).isDirectory())) {
|
||||
vscode.window.showWarningMessage(vscode.l10n.t("The path {0} doesn\'t point to a valid Node installation to run TS Server. Falling back to bundled Node.", nodePath));
|
||||
return null;
|
||||
}
|
||||
return nodePath;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,8 @@ export interface TypeScriptServiceConfiguration {
|
||||
readonly watchOptions: Proto.WatchOptions | undefined;
|
||||
readonly includePackageJsonAutoImports: 'auto' | 'on' | 'off' | undefined;
|
||||
readonly enableTsServerTracing: boolean;
|
||||
readonly localNodePath: string | null;
|
||||
readonly globalNodePath: string | null;
|
||||
}
|
||||
|
||||
export function areServiceConfigurationsEqual(a: TypeScriptServiceConfiguration, b: TypeScriptServiceConfiguration): boolean {
|
||||
@@ -154,11 +156,15 @@ export abstract class BaseServiceConfigurationProvider implements ServiceConfigu
|
||||
watchOptions: this.readWatchOptions(configuration),
|
||||
includePackageJsonAutoImports: this.readIncludePackageJsonAutoImports(configuration),
|
||||
enableTsServerTracing: this.readEnableTsServerTracing(configuration),
|
||||
localNodePath: this.readLocalNodePath(configuration),
|
||||
globalNodePath: this.readGlobalNodePath(configuration),
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract readGlobalTsdk(configuration: vscode.WorkspaceConfiguration): string | null;
|
||||
protected abstract readLocalTsdk(configuration: vscode.WorkspaceConfiguration): string | null;
|
||||
protected abstract readLocalNodePath(configuration: vscode.WorkspaceConfiguration): string | null;
|
||||
protected abstract readGlobalNodePath(configuration: vscode.WorkspaceConfiguration): string | null;
|
||||
|
||||
protected readTsServerLogLevel(configuration: vscode.WorkspaceConfiguration): TsServerLogLevel {
|
||||
const setting = configuration.get<string>('typescript.tsserver.log', 'off');
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { TypeScriptServiceConfiguration } from '../configuration/configuration';
|
||||
import { setImmediate } from '../utils/async';
|
||||
import { Disposable } from '../utils/dispose';
|
||||
|
||||
|
||||
const useWorkspaceNodeStorageKey = 'typescript.useWorkspaceNode';
|
||||
const lastKnownWorkspaceNodeStorageKey = 'typescript.lastKnownWorkspaceNode';
|
||||
type UseWorkspaceNodeState = undefined | boolean;
|
||||
type LastKnownWorkspaceNodeState = undefined | string;
|
||||
|
||||
export class NodeVersionManager extends Disposable {
|
||||
private _currentVersion: string | undefined;
|
||||
|
||||
public constructor(
|
||||
private configuration: TypeScriptServiceConfiguration,
|
||||
private readonly workspaceState: vscode.Memento
|
||||
) {
|
||||
super();
|
||||
|
||||
this._currentVersion = this.configuration.globalNodePath || undefined;
|
||||
if (vscode.workspace.isTrusted) {
|
||||
const workspaceVersion = this.configuration.localNodePath;
|
||||
if (workspaceVersion) {
|
||||
const useWorkspaceNode = this.canUseWorkspaceNode(workspaceVersion);
|
||||
if (useWorkspaceNode === undefined) {
|
||||
setImmediate(() => {
|
||||
this.promptAndSetWorkspaceNode();
|
||||
});
|
||||
}
|
||||
else if (useWorkspaceNode) {
|
||||
this._currentVersion = workspaceVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._disposables.push(vscode.workspace.onDidGrantWorkspaceTrust(() => {
|
||||
const workspaceVersion = this.configuration.localNodePath;
|
||||
if (workspaceVersion) {
|
||||
const useWorkspaceNode = this.canUseWorkspaceNode(workspaceVersion);
|
||||
if (useWorkspaceNode === undefined) {
|
||||
setImmediate(() => {
|
||||
this.promptAndSetWorkspaceNode();
|
||||
});
|
||||
}
|
||||
else if (useWorkspaceNode) {
|
||||
this.updateActiveVersion(workspaceVersion);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private readonly _onDidPickNewVersion = this._register(new vscode.EventEmitter<void>());
|
||||
public readonly onDidPickNewVersion = this._onDidPickNewVersion.event;
|
||||
|
||||
public get currentVersion(): string | undefined {
|
||||
return this._currentVersion;
|
||||
}
|
||||
|
||||
public async updateConfiguration(nextConfiguration: TypeScriptServiceConfiguration) {
|
||||
const oldConfiguration = this.configuration;
|
||||
this.configuration = nextConfiguration;
|
||||
if (oldConfiguration.globalNodePath !== nextConfiguration.globalNodePath
|
||||
|| oldConfiguration.localNodePath !== nextConfiguration.localNodePath) {
|
||||
await this.computeNewVersion();
|
||||
}
|
||||
}
|
||||
|
||||
private async computeNewVersion() {
|
||||
let version = this.configuration.globalNodePath || undefined;
|
||||
const workspaceVersion = this.configuration.localNodePath;
|
||||
if (vscode.workspace.isTrusted && workspaceVersion) {
|
||||
const useWorkspaceNode = this.canUseWorkspaceNode(workspaceVersion);
|
||||
if (useWorkspaceNode === undefined) {
|
||||
version = await this.promptUseWorkspaceNode() || version;
|
||||
}
|
||||
else if (useWorkspaceNode) {
|
||||
version = workspaceVersion;
|
||||
}
|
||||
}
|
||||
this.updateActiveVersion(version);
|
||||
}
|
||||
|
||||
private async promptUseWorkspaceNode(): Promise<string | undefined> {
|
||||
const workspaceVersion = this.configuration.localNodePath;
|
||||
if (workspaceVersion === null) {
|
||||
throw new Error('Could not prompt to use workspace Node installation because no workspace Node installation is specified');
|
||||
}
|
||||
|
||||
const allow = vscode.l10n.t("Yes");
|
||||
const disallow = vscode.l10n.t("No");
|
||||
const dismiss = vscode.l10n.t("Not now");
|
||||
|
||||
const result = await vscode.window.showInformationMessage(vscode.l10n.t("This workspace wants to use the Node installation at '{0}' to run TS Server. Would you like to use it?", workspaceVersion),
|
||||
allow,
|
||||
disallow,
|
||||
dismiss,
|
||||
);
|
||||
|
||||
let version = undefined;
|
||||
switch (result) {
|
||||
case allow:
|
||||
await this.setUseWorkspaceNodeState(true, workspaceVersion);
|
||||
version = workspaceVersion;
|
||||
break;
|
||||
case disallow:
|
||||
await this.setUseWorkspaceNodeState(false, workspaceVersion);
|
||||
break;
|
||||
case dismiss:
|
||||
await this.setUseWorkspaceNodeState(undefined, workspaceVersion);
|
||||
break;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
private async promptAndSetWorkspaceNode(): Promise<void> {
|
||||
const version = await this.promptUseWorkspaceNode();
|
||||
if (version !== undefined) {
|
||||
this.updateActiveVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
private updateActiveVersion(pickedVersion: string | undefined): void {
|
||||
const oldVersion = this.currentVersion;
|
||||
this._currentVersion = pickedVersion;
|
||||
if (oldVersion !== pickedVersion) {
|
||||
this._onDidPickNewVersion.fire();
|
||||
}
|
||||
}
|
||||
|
||||
private canUseWorkspaceNode(nodeVersion: string): boolean | undefined {
|
||||
const lastKnownWorkspaceNode = this.workspaceState.get<LastKnownWorkspaceNodeState>(lastKnownWorkspaceNodeStorageKey);
|
||||
if (lastKnownWorkspaceNode === nodeVersion) {
|
||||
return this.workspaceState.get<UseWorkspaceNodeState>(useWorkspaceNodeStorageKey);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async setUseWorkspaceNodeState(allow: boolean | undefined, nodeVersion: string) {
|
||||
await this.workspaceState.update(lastKnownWorkspaceNodeStorageKey, nodeVersion);
|
||||
await this.workspaceState.update(useWorkspaceNodeStorageKey, allow);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import type * as Proto from './protocol/protocol';
|
||||
import { EventName } from './protocol/protocol.const';
|
||||
import { TypeScriptVersionManager } from './versionManager';
|
||||
import { TypeScriptVersion } from './versionProvider';
|
||||
import { NodeVersionManager } from './nodeManager';
|
||||
|
||||
export enum ExecutionTarget {
|
||||
Semantic,
|
||||
@@ -70,6 +71,7 @@ export interface TsServerProcessFactory {
|
||||
kind: TsServerProcessKind,
|
||||
configuration: TypeScriptServiceConfiguration,
|
||||
versionManager: TypeScriptVersionManager,
|
||||
nodeVersionManager: NodeVersionManager,
|
||||
tsServerLog: TsServerLog | undefined,
|
||||
): TsServerProcess;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import type * as Proto from './protocol/protocol';
|
||||
import { TsServerLog, TsServerProcess, TsServerProcessFactory, TsServerProcessKind } from './server';
|
||||
import { TypeScriptVersionManager } from './versionManager';
|
||||
import { TypeScriptVersion } from './versionProvider';
|
||||
import { NodeVersionManager } from './nodeManager';
|
||||
|
||||
type BrowserWatchEvent = {
|
||||
type: 'watchDirectory' | 'watchFile';
|
||||
@@ -40,6 +41,7 @@ export class WorkerServerProcessFactory implements TsServerProcessFactory {
|
||||
kind: TsServerProcessKind,
|
||||
_configuration: TypeScriptServiceConfiguration,
|
||||
_versionManager: TypeScriptVersionManager,
|
||||
_nodeVersionManager: NodeVersionManager,
|
||||
tsServerLog: TsServerLog | undefined,
|
||||
) {
|
||||
const tsServerPath = version.tsServerPath;
|
||||
|
||||
@@ -15,6 +15,7 @@ import type * as Proto from './protocol/protocol';
|
||||
import { TsServerLog, TsServerProcess, TsServerProcessFactory, TsServerProcessKind } from './server';
|
||||
import { TypeScriptVersionManager } from './versionManager';
|
||||
import { TypeScriptVersion } from './versionProvider';
|
||||
import { NodeVersionManager } from './nodeManager';
|
||||
|
||||
|
||||
const defaultSize: number = 8192;
|
||||
@@ -134,10 +135,12 @@ class Reader<T> extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
function generatePatchedEnv(env: any, modulePath: string): any {
|
||||
function generatePatchedEnv(env: any, modulePath: string, hasExecPath: boolean): any {
|
||||
const newEnv = Object.assign({}, env);
|
||||
|
||||
newEnv['ELECTRON_RUN_AS_NODE'] = '1';
|
||||
if (!hasExecPath) {
|
||||
newEnv['ELECTRON_RUN_AS_NODE'] = '1';
|
||||
}
|
||||
newEnv['NODE_PATH'] = path.join(modulePath, '..', '..', '..');
|
||||
|
||||
// Ensure we always have a PATH set
|
||||
@@ -253,6 +256,7 @@ export class ElectronServiceProcessFactory implements TsServerProcessFactory {
|
||||
kind: TsServerProcessKind,
|
||||
configuration: TypeScriptServiceConfiguration,
|
||||
versionManager: TypeScriptVersionManager,
|
||||
nodeVersionManager: NodeVersionManager,
|
||||
_tsserverLog: TsServerLog | undefined,
|
||||
): TsServerProcess {
|
||||
let tsServerPath = version.tsServerPath;
|
||||
@@ -263,20 +267,30 @@ export class ElectronServiceProcessFactory implements TsServerProcessFactory {
|
||||
tsServerPath = versionManager.currentVersion.tsServerPath;
|
||||
}
|
||||
|
||||
const useIpc = version.apiVersion?.gte(API.v460);
|
||||
const execPath = nodeVersionManager.currentVersion;
|
||||
|
||||
const env = generatePatchedEnv(process.env, tsServerPath, !!execPath);
|
||||
const runtimeArgs = [...args];
|
||||
const execArgv = getExecArgv(kind, configuration);
|
||||
const useIpc = !execPath && version.apiVersion?.gte(API.v460);
|
||||
if (useIpc) {
|
||||
runtimeArgs.push('--useNodeIpc');
|
||||
}
|
||||
|
||||
const childProcess = child_process.fork(tsServerPath, runtimeArgs, {
|
||||
silent: true,
|
||||
cwd: undefined,
|
||||
env: generatePatchedEnv(process.env, tsServerPath),
|
||||
execArgv: getExecArgv(kind, configuration),
|
||||
stdio: useIpc ? ['pipe', 'pipe', 'pipe', 'ipc'] : undefined,
|
||||
});
|
||||
const childProcess = execPath ?
|
||||
child_process.spawn(execPath, [...execArgv, tsServerPath, ...runtimeArgs], {
|
||||
shell: true,
|
||||
windowsHide: true,
|
||||
cwd: undefined,
|
||||
env,
|
||||
}) :
|
||||
child_process.fork(tsServerPath, runtimeArgs, {
|
||||
silent: true,
|
||||
cwd: undefined,
|
||||
env,
|
||||
execArgv,
|
||||
stdio: useIpc ? ['pipe', 'pipe', 'pipe', 'ipc'] : undefined,
|
||||
});
|
||||
|
||||
return useIpc ? new IpcChildServerProcess(childProcess) : new StdioChildServerProcess(childProcess);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { PluginManager } from './plugins';
|
||||
import { GetErrRoutingTsServer, ITypeScriptServer, SingleTsServer, SyntaxRoutingTsServer, TsServerDelegate, TsServerLog, TsServerProcessFactory, TsServerProcessKind } from './server';
|
||||
import { TypeScriptVersionManager } from './versionManager';
|
||||
import { ITypeScriptVersionProvider, TypeScriptVersion } from './versionProvider';
|
||||
import { NodeVersionManager } from './nodeManager';
|
||||
|
||||
const enum CompositeServerType {
|
||||
/** Run a single server that handles all commands */
|
||||
@@ -44,6 +45,7 @@ export class TypeScriptServerSpawner {
|
||||
public constructor(
|
||||
private readonly _versionProvider: ITypeScriptVersionProvider,
|
||||
private readonly _versionManager: TypeScriptVersionManager,
|
||||
private readonly _nodeVersionManager: NodeVersionManager,
|
||||
private readonly _logDirectoryProvider: ILogDirectoryProvider,
|
||||
private readonly _pluginPathsProvider: TypeScriptPluginPathsProvider,
|
||||
private readonly _logger: Logger,
|
||||
@@ -160,7 +162,7 @@ export class TypeScriptServerSpawner {
|
||||
}
|
||||
|
||||
this._logger.info(`<${kind}> Forking...`);
|
||||
const process = this._factory.fork(version, args, kind, configuration, this._versionManager, tsServerLog);
|
||||
const process = this._factory.fork(version, args, kind, configuration, this._versionManager, this._nodeVersionManager, tsServerLog);
|
||||
this._logger.info(`<${kind}> Starting...`);
|
||||
|
||||
return new SingleTsServer(
|
||||
|
||||
@@ -30,6 +30,7 @@ import { TelemetryProperties, TelemetryReporter, VSCodeTelemetryReporter } from
|
||||
import Tracer from './logging/tracer';
|
||||
import { ProjectType, inferredProjectCompilerOptions } from './tsconfig';
|
||||
import { Schemes } from './configuration/schemes';
|
||||
import { NodeVersionManager } from './tsServer/nodeManager';
|
||||
|
||||
|
||||
export interface TsDiagnostics {
|
||||
@@ -103,6 +104,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
private _configuration: TypeScriptServiceConfiguration;
|
||||
private readonly pluginPathsProvider: TypeScriptPluginPathsProvider;
|
||||
private readonly _versionManager: TypeScriptVersionManager;
|
||||
private readonly _nodeVersionManager: NodeVersionManager;
|
||||
|
||||
private readonly logger: Logger;
|
||||
private readonly tracer: Tracer;
|
||||
@@ -173,6 +175,11 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
this.restartTsServer();
|
||||
}));
|
||||
|
||||
this._nodeVersionManager = this._register(new NodeVersionManager(this._configuration, context.workspaceState));
|
||||
this._register(this._nodeVersionManager.onDidPickNewVersion(() => {
|
||||
this.restartTsServer();
|
||||
}));
|
||||
|
||||
this.bufferSyncSupport = new BufferSyncSupport(this, allModeIds, onCaseInsenitiveFileSystem);
|
||||
this.onReady(() => { this.bufferSyncSupport.listen(); });
|
||||
|
||||
@@ -192,6 +199,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
this.versionProvider.updateConfiguration(this._configuration);
|
||||
this._versionManager.updateConfiguration(this._configuration);
|
||||
this.pluginPathsProvider.updateConfiguration(this._configuration);
|
||||
this._nodeVersionManager.updateConfiguration(this._configuration);
|
||||
|
||||
if (this.serverState.type === ServerState.Type.Running) {
|
||||
if (!this._configuration.implicitProjectConfiguration.isEqualTo(oldConfiguration.implicitProjectConfiguration)) {
|
||||
@@ -212,8 +220,9 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
}
|
||||
return this.apiVersion.fullVersionString;
|
||||
});
|
||||
|
||||
this.diagnosticsManager = new DiagnosticsManager('typescript', this._configuration, this.telemetryReporter, onCaseInsenitiveFileSystem);
|
||||
this.typescriptServerSpawner = new TypeScriptServerSpawner(this.versionProvider, this._versionManager, this.logDirectoryProvider, this.pluginPathsProvider, this.logger, this.telemetryReporter, this.tracer, this.processFactory);
|
||||
this.typescriptServerSpawner = new TypeScriptServerSpawner(this.versionProvider, this._versionManager, this._nodeVersionManager, this.logDirectoryProvider, this.pluginPathsProvider, this.logger, this.telemetryReporter, this.tracer, this.processFactory);
|
||||
|
||||
this._register(this.pluginManager.onDidUpdateConfig(update => {
|
||||
this.configurePlugin(update.pluginId, update.config);
|
||||
@@ -387,6 +396,10 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||
}
|
||||
|
||||
this.info(`Using tsserver from: ${version.path}`);
|
||||
const nodePath = this._nodeVersionManager.currentVersion;
|
||||
if (nodePath) {
|
||||
this.info(`Using Node installation from ${nodePath} to run TS Server`);
|
||||
}
|
||||
|
||||
const apiVersion = version.apiVersion || API.defaultVersion;
|
||||
const mytoken = ++this.token;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"vscode": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"update-grammar": "node ../node_modules/vscode-grammar-updater/bin textmate/asp.vb.net.tmbundle Syntaxes/ASP%%20VB.net.plist ./syntaxes/asp-vb-net.tmlanguage.json"
|
||||
"update-grammar": "node ../node_modules/vscode-grammar-updater/bin textmate/asp.vb.net.tmbundle Syntaxes/ASP%20VB.net.plist ./syntaxes/asp-vb-net.tmlanguage.json"
|
||||
},
|
||||
"contributes": {
|
||||
"languages": [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-tests ./tsconfig.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonc-parser": "2.2.1"
|
||||
"jsonc-parser": "^3.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.x"
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# Example taken from https://en.wikipedia.org/wiki/Raku_(programming_language)
|
||||
class Point is rw {
|
||||
has $.x;
|
||||
has $.y;
|
||||
|
||||
method distance( Point $p ) {
|
||||
sqrt(($!x - $p.x) ** 2 + ($!y - $p.y) ** 2)
|
||||
}
|
||||
|
||||
method distance-to-center {
|
||||
self.distance: Point.new(x => 0, y => 0)
|
||||
}
|
||||
}
|
||||
|
||||
my $point = Point.new( x => 1.2, y => -3.7 );
|
||||
say "Point's location: (", $point.x, ', ', $point.y, ')';
|
||||
# OUTPUT: Point's location: (1.2, -3.7)
|
||||
|
||||
# Changing x and y (note methods "x" and "y" used as lvalues):
|
||||
$point.x = 3;
|
||||
$point.y = 4;
|
||||
say "Point's location: (", $point.x, ', ', $point.y, ')';
|
||||
# OUTPUT: Point's location: (3, 4)
|
||||
|
||||
my $other-point = Point.new(x => -5, y => 10);
|
||||
$point.distance($other-point); #=> 10
|
||||
$point.distance-to-center; #=> 5
|
||||
@@ -1,21 +1,7 @@
|
||||
[
|
||||
{
|
||||
"c": "%",
|
||||
"t": "text.bibtex comment.line.percentage.bibtex punctuation.definition.comment.bibtex",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668",
|
||||
"dark_modern": "comment: #6A9955",
|
||||
"hc_light": "comment: #515151",
|
||||
"light_modern": "comment: #008000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " a sample bibliography file",
|
||||
"t": "text.bibtex comment.line.percentage.bibtex",
|
||||
"c": "% a sample bibliography file",
|
||||
"t": "text.bibtex comment.block.bibtex",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
@@ -29,7 +15,7 @@
|
||||
},
|
||||
{
|
||||
"c": "%",
|
||||
"t": "text.bibtex comment.line.percentage.bibtex punctuation.definition.comment.bibtex",
|
||||
"t": "text.bibtex comment.block.bibtex",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
@@ -1386,8 +1372,8 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "%",
|
||||
"t": "text.bibtex comment.line.percentage.bibtex punctuation.definition.comment.bibtex",
|
||||
"c": "% The authors mentioned here are almost, but not quite,",
|
||||
"t": "text.bibtex comment.block.bibtex",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
@@ -1400,36 +1386,8 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " The authors mentioned here are almost, but not quite,",
|
||||
"t": "text.bibtex comment.line.percentage.bibtex",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668",
|
||||
"dark_modern": "comment: #6A9955",
|
||||
"hc_light": "comment: #515151",
|
||||
"light_modern": "comment: #008000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": "%",
|
||||
"t": "text.bibtex comment.line.percentage.bibtex punctuation.definition.comment.bibtex",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668",
|
||||
"dark_modern": "comment: #6A9955",
|
||||
"hc_light": "comment: #515151",
|
||||
"light_modern": "comment: #008000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"c": " entirely unrelated to Matt Groening.",
|
||||
"t": "text.bibtex comment.line.percentage.bibtex",
|
||||
"c": "% entirely unrelated to Matt Groening.",
|
||||
"t": "text.bibtex comment.block.bibtex",
|
||||
"r": {
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
[
|
||||
{
|
||||
"c": "using",
|
||||
"t": "source.cs keyword.other.using.cs",
|
||||
"t": "source.cs keyword.other.directive.using.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword.other.using: #C586C0",
|
||||
"light_plus": "keyword.other.using: #AF00DB",
|
||||
"dark_plus": "keyword.other.directive.using: #C586C0",
|
||||
"light_plus": "keyword.other.directive.using: #AF00DB",
|
||||
"dark_vs": "keyword: #569CD6",
|
||||
"light_vs": "keyword: #0000FF",
|
||||
"hc_black": "keyword.other.using: #C586C0",
|
||||
"dark_modern": "keyword.other.using: #C586C0",
|
||||
"hc_light": "keyword.other.using: #B5200D",
|
||||
"light_modern": "keyword.other.using: #AF00DB"
|
||||
"hc_black": "keyword.other.directive.using: #C586C0",
|
||||
"dark_modern": "keyword.other.directive.using: #C586C0",
|
||||
"hc_light": "keyword.other.directive.using: #B5200D",
|
||||
"light_modern": "keyword.other.directive.using: #AF00DB"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -57,16 +57,16 @@
|
||||
},
|
||||
{
|
||||
"c": "namespace",
|
||||
"t": "source.cs keyword.other.namespace.cs",
|
||||
"t": "source.cs storage.type.namespace.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
"dark_vs": "keyword: #569CD6",
|
||||
"light_vs": "keyword: #0000FF",
|
||||
"hc_black": "keyword: #569CD6",
|
||||
"dark_modern": "keyword: #569CD6",
|
||||
"hc_light": "keyword: #0F4A85",
|
||||
"light_modern": "keyword: #0000FF"
|
||||
"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",
|
||||
"dark_modern": "storage.type: #569CD6",
|
||||
"hc_light": "storage.type: #0F4A85",
|
||||
"light_modern": "storage.type: #0000FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -127,16 +127,16 @@
|
||||
},
|
||||
{
|
||||
"c": "class",
|
||||
"t": "source.cs keyword.other.class.cs",
|
||||
"t": "source.cs storage.type.class.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
"dark_vs": "keyword: #569CD6",
|
||||
"light_vs": "keyword: #0000FF",
|
||||
"hc_black": "keyword: #569CD6",
|
||||
"dark_modern": "keyword: #569CD6",
|
||||
"hc_light": "keyword: #0F4A85",
|
||||
"light_modern": "keyword: #0000FF"
|
||||
"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",
|
||||
"dark_modern": "storage.type: #569CD6",
|
||||
"hc_light": "storage.type: #0F4A85",
|
||||
"light_modern": "storage.type: #0000FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -211,7 +211,7 @@
|
||||
},
|
||||
{
|
||||
"c": "static",
|
||||
"t": "source.cs storage.modifier.cs",
|
||||
"t": "source.cs storage.modifier.static.cs",
|
||||
"r": {
|
||||
"dark_plus": "storage.modifier: #569CD6",
|
||||
"light_plus": "storage.modifier: #0000FF",
|
||||
@@ -239,7 +239,7 @@
|
||||
},
|
||||
{
|
||||
"c": "void",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.void.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -295,7 +295,7 @@
|
||||
},
|
||||
{
|
||||
"c": "string",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.string.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -421,7 +421,7 @@
|
||||
},
|
||||
{
|
||||
"c": "int",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.int.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -799,7 +799,7 @@
|
||||
},
|
||||
{
|
||||
"c": "const",
|
||||
"t": "source.cs storage.modifier.cs",
|
||||
"t": "source.cs storage.modifier.const.cs",
|
||||
"r": {
|
||||
"dark_plus": "storage.modifier: #569CD6",
|
||||
"light_plus": "storage.modifier: #0000FF",
|
||||
@@ -827,7 +827,7 @@
|
||||
},
|
||||
{
|
||||
"c": "double",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.double.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -1023,7 +1023,7 @@
|
||||
},
|
||||
{
|
||||
"c": "int",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.int.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -1177,7 +1177,7 @@
|
||||
},
|
||||
{
|
||||
"c": "double",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.double.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -1429,16 +1429,16 @@
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "source.cs punctuation.whitespace.comment.leading.cs",
|
||||
"t": "source.cs comment.line.double-slash.cs punctuation.whitespace.comment.leading.cs",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF",
|
||||
"dark_modern": "default: #CCCCCC",
|
||||
"hc_light": "default: #292929",
|
||||
"light_modern": "default: #3B3B3B"
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668",
|
||||
"dark_modern": "comment: #6A9955",
|
||||
"hc_light": "comment: #515151",
|
||||
"light_modern": "comment: #008000"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -1751,7 +1751,7 @@
|
||||
},
|
||||
{
|
||||
"c": "public",
|
||||
"t": "source.cs storage.modifier.cs",
|
||||
"t": "source.cs storage.modifier.public.cs",
|
||||
"r": {
|
||||
"dark_plus": "storage.modifier: #569CD6",
|
||||
"light_plus": "storage.modifier: #0000FF",
|
||||
@@ -1779,7 +1779,7 @@
|
||||
},
|
||||
{
|
||||
"c": "void",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.void.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -1947,16 +1947,16 @@
|
||||
},
|
||||
{
|
||||
"c": "new",
|
||||
"t": "source.cs keyword.other.new.cs",
|
||||
"t": "source.cs keyword.operator.expression.new.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
"dark_vs": "keyword: #569CD6",
|
||||
"light_vs": "keyword: #0000FF",
|
||||
"hc_black": "keyword: #569CD6",
|
||||
"dark_modern": "keyword: #569CD6",
|
||||
"hc_light": "keyword: #0F4A85",
|
||||
"light_modern": "keyword: #0000FF"
|
||||
"dark_plus": "keyword.operator.expression: #569CD6",
|
||||
"light_plus": "keyword.operator.expression: #0000FF",
|
||||
"dark_vs": "keyword.operator.expression: #569CD6",
|
||||
"light_vs": "keyword.operator.expression: #0000FF",
|
||||
"hc_black": "keyword.operator.expression: #569CD6",
|
||||
"dark_modern": "keyword.operator.expression: #569CD6",
|
||||
"hc_light": "keyword.operator.expression: #0F4A85",
|
||||
"light_modern": "keyword.operator.expression: #0000FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2003,7 +2003,7 @@
|
||||
},
|
||||
{
|
||||
"c": "int",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.int.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -2115,7 +2115,7 @@
|
||||
},
|
||||
{
|
||||
"c": "int",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.int.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -2255,16 +2255,16 @@
|
||||
},
|
||||
{
|
||||
"c": "new",
|
||||
"t": "source.cs keyword.other.new.cs",
|
||||
"t": "source.cs keyword.operator.expression.new.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
"dark_vs": "keyword: #569CD6",
|
||||
"light_vs": "keyword: #0000FF",
|
||||
"hc_black": "keyword: #569CD6",
|
||||
"dark_modern": "keyword: #569CD6",
|
||||
"hc_light": "keyword: #0F4A85",
|
||||
"light_modern": "keyword: #0000FF"
|
||||
"dark_plus": "keyword.operator.expression: #569CD6",
|
||||
"light_plus": "keyword.operator.expression: #0000FF",
|
||||
"dark_vs": "keyword.operator.expression: #569CD6",
|
||||
"light_vs": "keyword.operator.expression: #0000FF",
|
||||
"hc_black": "keyword.operator.expression: #569CD6",
|
||||
"dark_modern": "keyword.operator.expression: #569CD6",
|
||||
"hc_light": "keyword.operator.expression: #0F4A85",
|
||||
"light_modern": "keyword.operator.expression: #0000FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2311,7 +2311,7 @@
|
||||
},
|
||||
{
|
||||
"c": "int",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.int.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -2423,7 +2423,7 @@
|
||||
},
|
||||
{
|
||||
"c": "int",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.int.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
@@ -2521,16 +2521,16 @@
|
||||
},
|
||||
{
|
||||
"c": "new",
|
||||
"t": "source.cs keyword.other.new.cs",
|
||||
"t": "source.cs keyword.operator.expression.new.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
"dark_vs": "keyword: #569CD6",
|
||||
"light_vs": "keyword: #0000FF",
|
||||
"hc_black": "keyword: #569CD6",
|
||||
"dark_modern": "keyword: #569CD6",
|
||||
"hc_light": "keyword: #0F4A85",
|
||||
"light_modern": "keyword: #0000FF"
|
||||
"dark_plus": "keyword.operator.expression: #569CD6",
|
||||
"light_plus": "keyword.operator.expression: #0000FF",
|
||||
"dark_vs": "keyword.operator.expression: #569CD6",
|
||||
"light_vs": "keyword.operator.expression: #0000FF",
|
||||
"hc_black": "keyword.operator.expression: #569CD6",
|
||||
"dark_modern": "keyword.operator.expression: #569CD6",
|
||||
"hc_light": "keyword.operator.expression: #0F4A85",
|
||||
"light_modern": "keyword.operator.expression: #0000FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2577,7 +2577,7 @@
|
||||
},
|
||||
{
|
||||
"c": "int",
|
||||
"t": "source.cs keyword.type.cs",
|
||||
"t": "source.cs keyword.type.int.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
|
||||
@@ -43,16 +43,16 @@
|
||||
},
|
||||
{
|
||||
"c": "var",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs keyword.other.var.cs",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs storage.type.var.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
"dark_vs": "keyword: #569CD6",
|
||||
"light_vs": "keyword: #0000FF",
|
||||
"hc_black": "keyword: #569CD6",
|
||||
"dark_modern": "keyword: #569CD6",
|
||||
"hc_light": "keyword: #0F4A85",
|
||||
"light_modern": "keyword: #0000FF"
|
||||
"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",
|
||||
"dark_modern": "storage.type: #569CD6",
|
||||
"hc_light": "storage.type: #0F4A85",
|
||||
"light_modern": "storage.type: #0000FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -169,16 +169,16 @@
|
||||
},
|
||||
{
|
||||
"c": "var",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs keyword.other.var.cs",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs storage.type.var.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
"dark_vs": "keyword: #569CD6",
|
||||
"light_vs": "keyword: #0000FF",
|
||||
"hc_black": "keyword: #569CD6",
|
||||
"dark_modern": "keyword: #569CD6",
|
||||
"hc_light": "keyword: #0F4A85",
|
||||
"light_modern": "keyword: #0000FF"
|
||||
"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",
|
||||
"dark_modern": "storage.type: #569CD6",
|
||||
"hc_light": "storage.type: #0F4A85",
|
||||
"light_modern": "storage.type: #0000FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -505,16 +505,16 @@
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock punctuation.whitespace.comment.leading.cs",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock comment.line.double-slash.cs punctuation.whitespace.comment.leading.cs",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF",
|
||||
"dark_modern": "default: #CCCCCC",
|
||||
"hc_light": "default: #292929",
|
||||
"light_modern": "default: #3B3B3B"
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668",
|
||||
"dark_modern": "comment: #6A9955",
|
||||
"hc_light": "comment: #515151",
|
||||
"light_modern": "comment: #008000"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -561,16 +561,16 @@
|
||||
},
|
||||
{
|
||||
"c": "var",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock keyword.other.var.cs",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock storage.type.var.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
"dark_vs": "keyword: #569CD6",
|
||||
"light_vs": "keyword: #0000FF",
|
||||
"hc_black": "keyword: #569CD6",
|
||||
"dark_modern": "keyword: #569CD6",
|
||||
"hc_light": "keyword: #0F4A85",
|
||||
"light_modern": "keyword: #0000FF"
|
||||
"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",
|
||||
"dark_modern": "storage.type: #569CD6",
|
||||
"hc_light": "storage.type: #0F4A85",
|
||||
"light_modern": "storage.type: #0000FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -757,16 +757,16 @@
|
||||
},
|
||||
{
|
||||
"c": "var",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock keyword.other.var.cs",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock storage.type.var.cs",
|
||||
"r": {
|
||||
"dark_plus": "keyword: #569CD6",
|
||||
"light_plus": "keyword: #0000FF",
|
||||
"dark_vs": "keyword: #569CD6",
|
||||
"light_vs": "keyword: #0000FF",
|
||||
"hc_black": "keyword: #569CD6",
|
||||
"dark_modern": "keyword: #569CD6",
|
||||
"hc_light": "keyword: #0F4A85",
|
||||
"light_modern": "keyword: #0000FF"
|
||||
"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",
|
||||
"dark_modern": "storage.type: #569CD6",
|
||||
"hc_light": "storage.type: #0F4A85",
|
||||
"light_modern": "storage.type: #0000FF"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -939,16 +939,16 @@
|
||||
},
|
||||
{
|
||||
"c": " ",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock punctuation.whitespace.comment.leading.cs",
|
||||
"t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor meta.structure.razor.csharp.codeblock comment.line.double-slash.cs punctuation.whitespace.comment.leading.cs",
|
||||
"r": {
|
||||
"dark_plus": "default: #D4D4D4",
|
||||
"light_plus": "default: #000000",
|
||||
"dark_vs": "default: #D4D4D4",
|
||||
"light_vs": "default: #000000",
|
||||
"hc_black": "default: #FFFFFF",
|
||||
"dark_modern": "default: #CCCCCC",
|
||||
"hc_light": "default: #292929",
|
||||
"light_modern": "default: #3B3B3B"
|
||||
"dark_plus": "comment: #6A9955",
|
||||
"light_plus": "comment: #008000",
|
||||
"dark_vs": "comment: #6A9955",
|
||||
"light_vs": "comment: #008000",
|
||||
"hc_black": "comment: #7CA668",
|
||||
"dark_modern": "comment: #6A9955",
|
||||
"hc_light": "comment: #515151",
|
||||
"light_modern": "comment: #008000"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.15.13.tgz#f64277c341150c979e42b00e4ac289290c9df469"
|
||||
integrity sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==
|
||||
|
||||
jsonc-parser@2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc"
|
||||
integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==
|
||||
jsonc-parser@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76"
|
||||
integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==
|
||||
|
||||
+9
-9
@@ -94,14 +94,14 @@
|
||||
"vscode-oniguruma": "1.7.0",
|
||||
"vscode-regexpp": "^3.1.0",
|
||||
"vscode-textmate": "9.0.0",
|
||||
"xterm": "5.3.0-beta.61",
|
||||
"xterm-addon-canvas": "0.5.0-beta.22",
|
||||
"xterm-addon-image": "0.6.0-beta.14",
|
||||
"xterm-addon-search": "0.13.0-beta.20",
|
||||
"xterm-addon-serialize": "0.11.0-beta.20",
|
||||
"xterm-addon-unicode11": "0.6.0-beta.12",
|
||||
"xterm-addon-webgl": "0.16.0-beta.30",
|
||||
"xterm-headless": "5.3.0-beta.61",
|
||||
"xterm": "5.4.0-beta.17",
|
||||
"xterm-addon-canvas": "0.6.0-beta.16",
|
||||
"xterm-addon-image": "0.6.0-beta.21",
|
||||
"xterm-addon-search": "0.14.0-beta.15",
|
||||
"xterm-addon-serialize": "0.12.0-beta.15",
|
||||
"xterm-addon-unicode11": "0.7.0-beta.15",
|
||||
"xterm-addon-webgl": "0.17.0-beta.15",
|
||||
"xterm-headless": "5.4.0-beta.17",
|
||||
"yauzl": "^2.9.2",
|
||||
"yazl": "^2.4.3"
|
||||
},
|
||||
@@ -210,7 +210,7 @@
|
||||
"ts-loader": "^9.4.2",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsec": "0.2.7",
|
||||
"typescript": "^5.3.0-dev.20230905",
|
||||
"typescript": "^5.3.0-dev.20230911",
|
||||
"typescript-formatter": "7.1.0",
|
||||
"underscore": "^1.12.1",
|
||||
"util": "^0.12.4",
|
||||
|
||||
+8
-8
@@ -26,14 +26,14 @@
|
||||
"vscode-oniguruma": "1.7.0",
|
||||
"vscode-regexpp": "^3.1.0",
|
||||
"vscode-textmate": "9.0.0",
|
||||
"xterm": "5.3.0-beta.61",
|
||||
"xterm-addon-canvas": "0.5.0-beta.22",
|
||||
"xterm-addon-image": "0.6.0-beta.14",
|
||||
"xterm-addon-search": "0.13.0-beta.20",
|
||||
"xterm-addon-serialize": "0.11.0-beta.20",
|
||||
"xterm-addon-unicode11": "0.6.0-beta.12",
|
||||
"xterm-addon-webgl": "0.16.0-beta.30",
|
||||
"xterm-headless": "5.3.0-beta.61",
|
||||
"xterm": "5.4.0-beta.17",
|
||||
"xterm-addon-canvas": "0.6.0-beta.16",
|
||||
"xterm-addon-image": "0.6.0-beta.21",
|
||||
"xterm-addon-search": "0.14.0-beta.15",
|
||||
"xterm-addon-serialize": "0.12.0-beta.15",
|
||||
"xterm-addon-unicode11": "0.7.0-beta.15",
|
||||
"xterm-addon-webgl": "0.17.0-beta.15",
|
||||
"xterm-headless": "5.4.0-beta.17",
|
||||
"yauzl": "^2.9.2",
|
||||
"yazl": "^2.4.3"
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
"tas-client-umd": "0.1.8",
|
||||
"vscode-oniguruma": "1.7.0",
|
||||
"vscode-textmate": "9.0.0",
|
||||
"xterm": "5.3.0-beta.61",
|
||||
"xterm-addon-canvas": "0.5.0-beta.22",
|
||||
"xterm-addon-image": "0.6.0-beta.14",
|
||||
"xterm-addon-search": "0.13.0-beta.20",
|
||||
"xterm-addon-unicode11": "0.6.0-beta.12",
|
||||
"xterm-addon-webgl": "0.16.0-beta.30"
|
||||
"xterm": "5.4.0-beta.17",
|
||||
"xterm-addon-canvas": "0.6.0-beta.16",
|
||||
"xterm-addon-image": "0.6.0-beta.21",
|
||||
"xterm-addon-search": "0.14.0-beta.15",
|
||||
"xterm-addon-unicode11": "0.7.0-beta.15",
|
||||
"xterm-addon-webgl": "0.17.0-beta.15"
|
||||
}
|
||||
}
|
||||
|
||||
+24
-24
@@ -68,32 +68,32 @@ vscode-textmate@9.0.0:
|
||||
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-9.0.0.tgz#313c6c8792b0507aef35aeb81b6b370b37c44d6c"
|
||||
integrity sha512-Cl65diFGxz7gpwbav10HqiY/eVYTO1sjQpmRmV991Bj7wAoOAjGQ97PpQcXorDE2Uc4hnGWLY17xme+5t6MlSg==
|
||||
|
||||
xterm-addon-canvas@0.5.0-beta.22:
|
||||
version "0.5.0-beta.22"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.22.tgz#513f0c2b7cf96073f47627b27e8965c1b1a22431"
|
||||
integrity sha512-9F6ZI0DMRgffVfHkLkDwl5n8VscvCaV10tWI3skXOX7Y7Aws6OEeglkOPoU3IllofCU792kHKM4pPoToUxTltg==
|
||||
xterm-addon-canvas@0.6.0-beta.16:
|
||||
version "0.6.0-beta.16"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.6.0-beta.16.tgz#6d6a475824c3c0129f3cb38eaea69cf12386cc31"
|
||||
integrity sha512-uh90h+uozwrZbc/yMhbRnKIY7J34CTse6njibajdeK+0hQvj09HnBXgkvALImR/sEwyIz8SVtSL+OOZTlmAHIQ==
|
||||
|
||||
xterm-addon-image@0.6.0-beta.14:
|
||||
version "0.6.0-beta.14"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.14.tgz#75fc3f824123183a4bbb5306e22f8b2c6966b0a6"
|
||||
integrity sha512-D5Gh5JTKhHaPt1KwQNf6diF37KA4eToJw3XId1wy62tWmSqfq+QflhOGTfd+SnSQYCktU05ETzM+0tncIU62pQ==
|
||||
xterm-addon-image@0.6.0-beta.21:
|
||||
version "0.6.0-beta.21"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.21.tgz#e3708bc504c56a23ff31f12a2eeb335331a92aac"
|
||||
integrity sha512-8/PTaXVPa4kQ0xzVeuZZk10OpbZBj2cgfwhM2B0ChSPvwrk0lX+ksnXdtDKH3tg+JYvo7fIhNXtkr4NwWt7VJQ==
|
||||
|
||||
xterm-addon-search@0.13.0-beta.20:
|
||||
version "0.13.0-beta.20"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.20.tgz#8ddd0513e2a70fcefa325722100d2e1bfaf3b9cb"
|
||||
integrity sha512-wrx6187cJ1UenGL6ZeYv3jFvRPhhENTfbC+Hv1Fnww8LmsKhcj+0+Pm6yInNjX/9hNVsNzdqKyqNeEMoykyoyA==
|
||||
xterm-addon-search@0.14.0-beta.15:
|
||||
version "0.14.0-beta.15"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.14.0-beta.15.tgz#fcea611a04a8f4fd5dd3ec5e3403cce9cde72f0a"
|
||||
integrity sha512-wPk3FzOFIeEAgVMjNL6CHoAfPcmk3DWwf28AtICfJ512JVJ3d0o9mUEh853m08/eaJJikAMXMEgTGRgjNtZU3Q==
|
||||
|
||||
xterm-addon-unicode11@0.6.0-beta.12:
|
||||
version "0.6.0-beta.12"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.12.tgz#ac6df9d635325dc692e4c602e74a2fc27a09405c"
|
||||
integrity sha512-9wWWf/5nFafYgq0pn9EgAWnXaXGleVxfjNOqavpLRYFv0nw42QbaYyGvnGcxyYHM5Aqx/8rYE/DDVWZBqQZdYA==
|
||||
xterm-addon-unicode11@0.7.0-beta.15:
|
||||
version "0.7.0-beta.15"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.7.0-beta.15.tgz#07359424a862aedc456f35f95126739cd4fbe7de"
|
||||
integrity sha512-CdPuahtDiacsBO618XTNc+z3diWPVzvpVlk0NcIsUpcdsF+44rgRBFaD7mT4tfAFU1w1ibTzTfOakrFlYZuM0A==
|
||||
|
||||
xterm-addon-webgl@0.16.0-beta.30:
|
||||
version "0.16.0-beta.30"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.30.tgz#820d5c65f868b14ec4177bfb8a294931a53616bf"
|
||||
integrity sha512-39qPHPFmNENxcHf8/CzGHS6wzKMMegoRkHB1+scqtBhSxFaD8tX5Ye33HZIEdQ9nXe9xtr4FWVp77T+n9hdrew==
|
||||
xterm-addon-webgl@0.17.0-beta.15:
|
||||
version "0.17.0-beta.15"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.17.0-beta.15.tgz#53e15a170e4e9d8ddafb8971b2e63b4c596b9744"
|
||||
integrity sha512-3JJ8KumPzFut1yloNhIrvObBwqp8kbqBI/up77MIyGE/6WiGhgecUFPmT8rYUCv4g/GBXoMan755yOEUNkKtcg==
|
||||
|
||||
xterm@5.3.0-beta.61:
|
||||
version "5.3.0-beta.61"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.61.tgz#a6c27d90a5314da51d80deeb32f3bd77f1e1c8f6"
|
||||
integrity sha512-rJHpCc48GSpHnu0SSERynQ80D5ikvFVsqhv6JdmeONTrnAFRr134OglJRIpbi2YK8UPbV6F6Dfqm/AQh+9GZzA==
|
||||
xterm@5.4.0-beta.17:
|
||||
version "5.4.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.4.0-beta.17.tgz#7e7841b09339670c5ada967b73a1416d1b3dc9f7"
|
||||
integrity sha512-hTSJHkyH/m26nQJt1oNI1KJU18JVJpOy41pP9WRRFQx1KoHhYq4HMRl7LO42SJt6Vs0mig0UYkbEnRWfT4FCww==
|
||||
|
||||
+32
-32
@@ -667,45 +667,45 @@ wrappy@1:
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
xterm-addon-canvas@0.5.0-beta.22:
|
||||
version "0.5.0-beta.22"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.5.0-beta.22.tgz#513f0c2b7cf96073f47627b27e8965c1b1a22431"
|
||||
integrity sha512-9F6ZI0DMRgffVfHkLkDwl5n8VscvCaV10tWI3skXOX7Y7Aws6OEeglkOPoU3IllofCU792kHKM4pPoToUxTltg==
|
||||
xterm-addon-canvas@0.6.0-beta.16:
|
||||
version "0.6.0-beta.16"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-canvas/-/xterm-addon-canvas-0.6.0-beta.16.tgz#6d6a475824c3c0129f3cb38eaea69cf12386cc31"
|
||||
integrity sha512-uh90h+uozwrZbc/yMhbRnKIY7J34CTse6njibajdeK+0hQvj09HnBXgkvALImR/sEwyIz8SVtSL+OOZTlmAHIQ==
|
||||
|
||||
xterm-addon-image@0.6.0-beta.14:
|
||||
version "0.6.0-beta.14"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.14.tgz#75fc3f824123183a4bbb5306e22f8b2c6966b0a6"
|
||||
integrity sha512-D5Gh5JTKhHaPt1KwQNf6diF37KA4eToJw3XId1wy62tWmSqfq+QflhOGTfd+SnSQYCktU05ETzM+0tncIU62pQ==
|
||||
xterm-addon-image@0.6.0-beta.21:
|
||||
version "0.6.0-beta.21"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-image/-/xterm-addon-image-0.6.0-beta.21.tgz#e3708bc504c56a23ff31f12a2eeb335331a92aac"
|
||||
integrity sha512-8/PTaXVPa4kQ0xzVeuZZk10OpbZBj2cgfwhM2B0ChSPvwrk0lX+ksnXdtDKH3tg+JYvo7fIhNXtkr4NwWt7VJQ==
|
||||
|
||||
xterm-addon-search@0.13.0-beta.20:
|
||||
version "0.13.0-beta.20"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.13.0-beta.20.tgz#8ddd0513e2a70fcefa325722100d2e1bfaf3b9cb"
|
||||
integrity sha512-wrx6187cJ1UenGL6ZeYv3jFvRPhhENTfbC+Hv1Fnww8LmsKhcj+0+Pm6yInNjX/9hNVsNzdqKyqNeEMoykyoyA==
|
||||
xterm-addon-search@0.14.0-beta.15:
|
||||
version "0.14.0-beta.15"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.14.0-beta.15.tgz#fcea611a04a8f4fd5dd3ec5e3403cce9cde72f0a"
|
||||
integrity sha512-wPk3FzOFIeEAgVMjNL6CHoAfPcmk3DWwf28AtICfJ512JVJ3d0o9mUEh853m08/eaJJikAMXMEgTGRgjNtZU3Q==
|
||||
|
||||
xterm-addon-serialize@0.11.0-beta.20:
|
||||
version "0.11.0-beta.20"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.11.0-beta.20.tgz#e879b34d214761403f1081833f9221c6903bf0c3"
|
||||
integrity sha512-OXnC1SATaz7kEFjFWhyv9MJaXi8yHdPjazpGLNi11h33CRTKtCQiqqPBHU87dztnXmpEX6Jw0/jr3zlyXuAmnw==
|
||||
xterm-addon-serialize@0.12.0-beta.15:
|
||||
version "0.12.0-beta.15"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.12.0-beta.15.tgz#8e210d566c03b616823317a31dbce474a728b3c9"
|
||||
integrity sha512-4iF9pQ/q6831ayADPlngAM0aa/mhzvZ4XEd4UNJIgW7mpgoSTvnbh6d6lb37pNkpdDFIRLJv6rlqDjlh6EkoJg==
|
||||
|
||||
xterm-addon-unicode11@0.6.0-beta.12:
|
||||
version "0.6.0-beta.12"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.6.0-beta.12.tgz#ac6df9d635325dc692e4c602e74a2fc27a09405c"
|
||||
integrity sha512-9wWWf/5nFafYgq0pn9EgAWnXaXGleVxfjNOqavpLRYFv0nw42QbaYyGvnGcxyYHM5Aqx/8rYE/DDVWZBqQZdYA==
|
||||
xterm-addon-unicode11@0.7.0-beta.15:
|
||||
version "0.7.0-beta.15"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.7.0-beta.15.tgz#07359424a862aedc456f35f95126739cd4fbe7de"
|
||||
integrity sha512-CdPuahtDiacsBO618XTNc+z3diWPVzvpVlk0NcIsUpcdsF+44rgRBFaD7mT4tfAFU1w1ibTzTfOakrFlYZuM0A==
|
||||
|
||||
xterm-addon-webgl@0.16.0-beta.30:
|
||||
version "0.16.0-beta.30"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.16.0-beta.30.tgz#820d5c65f868b14ec4177bfb8a294931a53616bf"
|
||||
integrity sha512-39qPHPFmNENxcHf8/CzGHS6wzKMMegoRkHB1+scqtBhSxFaD8tX5Ye33HZIEdQ9nXe9xtr4FWVp77T+n9hdrew==
|
||||
xterm-addon-webgl@0.17.0-beta.15:
|
||||
version "0.17.0-beta.15"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.17.0-beta.15.tgz#53e15a170e4e9d8ddafb8971b2e63b4c596b9744"
|
||||
integrity sha512-3JJ8KumPzFut1yloNhIrvObBwqp8kbqBI/up77MIyGE/6WiGhgecUFPmT8rYUCv4g/GBXoMan755yOEUNkKtcg==
|
||||
|
||||
xterm-headless@5.3.0-beta.61:
|
||||
version "5.3.0-beta.61"
|
||||
resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.3.0-beta.61.tgz#28654550cb572709b99ea3eb8672d4568ae141c9"
|
||||
integrity sha512-yfkbPLUtKjE4K7DsZ204A1BuOKpu6Usqi6rIYWT4XRMi+LjnkTbBjGr2BSjyJ3Gmtm+cSgBD0SvRN+V3xNxbxA==
|
||||
xterm-headless@5.4.0-beta.17:
|
||||
version "5.4.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.4.0-beta.17.tgz#cb779eba8da66ecad6f4be41af649453bb3260e9"
|
||||
integrity sha512-ax2asr5QS4EnJAmRnKDDnAqESst+r2G/MckaYdxTDgX0pc997TU4B/JQ6c5BhxVLQvRwmotTm11/n909HiHadQ==
|
||||
|
||||
xterm@5.3.0-beta.61:
|
||||
version "5.3.0-beta.61"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0-beta.61.tgz#a6c27d90a5314da51d80deeb32f3bd77f1e1c8f6"
|
||||
integrity sha512-rJHpCc48GSpHnu0SSERynQ80D5ikvFVsqhv6JdmeONTrnAFRr134OglJRIpbi2YK8UPbV6F6Dfqm/AQh+9GZzA==
|
||||
xterm@5.4.0-beta.17:
|
||||
version "5.4.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.4.0-beta.17.tgz#7e7841b09339670c5ada967b73a1416d1b3dc9f7"
|
||||
integrity sha512-hTSJHkyH/m26nQJt1oNI1KJU18JVJpOy41pP9WRRFQx1KoHhYq4HMRl7LO42SJt6Vs0mig0UYkbEnRWfT4FCww==
|
||||
|
||||
yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
|
||||
@@ -35,7 +35,7 @@ if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
||||
:: Tests in the extension host
|
||||
|
||||
set API_TESTS_EXTRA_ARGS=--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=%VSCODECRASHDIR% --logsPath=%VSCODELOGSDIR% --no-cached-data --disable-updates --disable-keytar --disable-extensions --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
|
||||
set API_TESTS_EXTRA_ARGS=--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=%VSCODECRASHDIR% --logsPath=%VSCODELOGSDIR% --no-cached-data --disable-updates --use-inmemory-secretstorage --disable-extensions --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
|
||||
|
||||
echo.
|
||||
echo ### API tests (folder)
|
||||
|
||||
@@ -44,7 +44,7 @@ echo
|
||||
|
||||
# Tests in the extension host
|
||||
|
||||
API_TESTS_EXTRA_ARGS="--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=$VSCODECRASHDIR --logsPath=$VSCODELOGSDIR --no-cached-data --disable-updates --disable-keytar --disable-extensions --disable-workspace-trust --user-data-dir=$VSCODEUSERDATADIR"
|
||||
API_TESTS_EXTRA_ARGS="--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=$VSCODECRASHDIR --logsPath=$VSCODELOGSDIR --no-cached-data --disable-updates --use-inmemory-secretstorage --disable-extensions --disable-workspace-trust --user-data-dir=$VSCODEUSERDATADIR"
|
||||
|
||||
if [ -z "$INTEGRATION_TEST_APP_NAME" ]; then
|
||||
kill_app() { true; }
|
||||
|
||||
@@ -55,7 +55,7 @@ echo Storing log files into '%VSCODELOGSDIR%'
|
||||
|
||||
:: Tests in the extension host
|
||||
|
||||
set API_TESTS_EXTRA_ARGS=--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=%VSCODECRASHDIR% --logsPath=%VSCODELOGSDIR% --no-cached-data --disable-updates --disable-keytar --disable-inspect --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
|
||||
set API_TESTS_EXTRA_ARGS=--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=%VSCODECRASHDIR% --logsPath=%VSCODELOGSDIR% --no-cached-data --disable-updates --use-inmemory-secretstorage --disable-inspect --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
|
||||
|
||||
echo.
|
||||
echo ### API tests (folder)
|
||||
|
||||
@@ -68,7 +68,7 @@ else
|
||||
kill_app() { killall $INTEGRATION_TEST_APP_NAME || true; }
|
||||
fi
|
||||
|
||||
API_TESTS_EXTRA_ARGS="--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=$VSCODECRASHDIR --logsPath=$VSCODELOGSDIR --no-cached-data --disable-updates --disable-keytar --disable-workspace-trust --user-data-dir=$VSCODEUSERDATADIR"
|
||||
API_TESTS_EXTRA_ARGS="--disable-telemetry --skip-welcome --skip-release-notes --crash-reporter-directory=$VSCODECRASHDIR --logsPath=$VSCODELOGSDIR --no-cached-data --disable-updates --use-inmemory-secretstorage --disable-workspace-trust --user-data-dir=$VSCODEUSERDATADIR"
|
||||
|
||||
echo "Storing crash reports into '$VSCODECRASHDIR'."
|
||||
echo "Storing log files into '$VSCODELOGSDIR'."
|
||||
|
||||
@@ -123,3 +123,26 @@ export class IframeUtils {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sha-256 composed of `parentOrigin` and `salt` converted to base 32
|
||||
*/
|
||||
export async function parentOriginHash(parentOrigin: string, salt: string): Promise<string> {
|
||||
// This same code is also inlined at `src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html`
|
||||
if (!crypto.subtle) {
|
||||
throw new Error(`'crypto.subtle' is not available so webviews will not work. This is likely because the editor is not running in a secure context (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).`);
|
||||
}
|
||||
|
||||
const strData = JSON.stringify({ parentOrigin, salt });
|
||||
const encoder = new TextEncoder();
|
||||
const arrData = encoder.encode(strData);
|
||||
const hash = await crypto.subtle.digest('sha-256', arrData);
|
||||
return sha256AsBase32(hash);
|
||||
}
|
||||
|
||||
function sha256AsBase32(bytes: ArrayBuffer): string {
|
||||
const array = Array.from(new Uint8Array(bytes));
|
||||
const hexArray = array.map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
// sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32
|
||||
return BigInt(`0x${hexArray}`).toString(32).padStart(52, '0');
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as DomUtils from 'vs/base/browser/dom';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable, markAsSingleton, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { LinkedList } from 'vs/base/common/linkedList';
|
||||
|
||||
export namespace EventType {
|
||||
@@ -99,7 +99,7 @@ export class Gesture extends Disposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
if (!Gesture.INSTANCE) {
|
||||
Gesture.INSTANCE = new Gesture();
|
||||
Gesture.INSTANCE = markAsSingleton(new Gesture());
|
||||
}
|
||||
|
||||
const remove = Gesture.INSTANCE.targets.push(element);
|
||||
@@ -111,7 +111,7 @@ export class Gesture extends Disposable {
|
||||
return Disposable.None;
|
||||
}
|
||||
if (!Gesture.INSTANCE) {
|
||||
Gesture.INSTANCE = new Gesture();
|
||||
Gesture.INSTANCE = markAsSingleton(new Gesture());
|
||||
}
|
||||
|
||||
const remove = Gesture.INSTANCE.ignoreTargets.push(element);
|
||||
|
||||
@@ -248,7 +248,7 @@ class BranchNode implements ISplitView<ILayoutContext>, IDisposable {
|
||||
|
||||
readonly element: HTMLElement;
|
||||
readonly children: Node[] = [];
|
||||
private splitview: SplitView<ILayoutContext>;
|
||||
private splitview: SplitView<ILayoutContext, Node>;
|
||||
|
||||
private _size: number;
|
||||
get size(): number { return this._size; }
|
||||
@@ -511,14 +511,27 @@ class BranchNode implements ISplitView<ILayoutContext>, IDisposable {
|
||||
this.onDidChildrenChange();
|
||||
}
|
||||
|
||||
removeChild(index: number, sizing?: Sizing): void {
|
||||
removeChild(index: number, sizing?: Sizing): Node {
|
||||
index = validateIndex(index, this.children.length);
|
||||
|
||||
this.splitview.removeView(index, sizing);
|
||||
const result = this.splitview.removeView(index, sizing);
|
||||
this.children.splice(index, 1);
|
||||
|
||||
this.updateBoundarySashes();
|
||||
this.onDidChildrenChange();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
removeAllChildren(): Node[] {
|
||||
const result = this.splitview.removeAllViews();
|
||||
|
||||
this.children.splice(0, this.children.length);
|
||||
|
||||
this.updateBoundarySashes();
|
||||
this.onDidChildrenChange();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
moveChild(from: number, to: number): void {
|
||||
@@ -904,7 +917,10 @@ export interface INodeDescriptor {
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
function flipNode<T extends Node>(node: T, size: number, orthogonalSize: number): T {
|
||||
function flipNode(node: BranchNode, size: number, orthogonalSize: number): BranchNode;
|
||||
function flipNode(node: LeafNode, size: number, orthogonalSize: number): LeafNode;
|
||||
function flipNode(node: Node, size: number, orthogonalSize: number): Node;
|
||||
function flipNode(node: Node, size: number, orthogonalSize: number): Node {
|
||||
if (node instanceof BranchNode) {
|
||||
const result = new BranchNode(orthogonal(node.orientation), node.layoutController, node.styles, node.splitviewProportionalLayout, size, orthogonalSize, node.edgeSnapping);
|
||||
|
||||
@@ -925,9 +941,12 @@ function flipNode<T extends Node>(node: T, size: number, orthogonalSize: number)
|
||||
result.addChild(flipNode(child, orthogonalSize, newSize), newSize, 0, true);
|
||||
}
|
||||
|
||||
return result as T;
|
||||
node.dispose();
|
||||
return result;
|
||||
} else {
|
||||
return new LeafNode((node as LeafNode).view, orthogonal(node.orientation), node.layoutController, orthogonalSize) as T;
|
||||
const result = new LeafNode(node.view, orthogonal(node.orientation), node.layoutController, orthogonalSize);
|
||||
node.dispose();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1162,8 +1181,13 @@ export class GridView implements IDisposable {
|
||||
|
||||
if (parent instanceof BranchNode) {
|
||||
const node = new LeafNode(view, orthogonal(parent.orientation), this.layoutController, parent.orthogonalSize);
|
||||
parent.addChild(node, size, index);
|
||||
|
||||
try {
|
||||
parent.addChild(node, size, index);
|
||||
} catch (err) {
|
||||
node.dispose();
|
||||
throw err;
|
||||
}
|
||||
} else {
|
||||
const [, grandParent] = tail(pathToParent);
|
||||
const [, parentIndex] = tail(rest);
|
||||
@@ -1175,7 +1199,8 @@ export class GridView implements IDisposable {
|
||||
newSiblingSize = Sizing.Invisible(newSiblingCachedVisibleSize);
|
||||
}
|
||||
|
||||
grandParent.removeChild(parentIndex);
|
||||
const oldChild = grandParent.removeChild(parentIndex);
|
||||
oldChild.dispose();
|
||||
|
||||
const newParent = new BranchNode(parent.orientation, parent.layoutController, this.styles, this.proportionalLayout, parent.size, parent.orthogonalSize, grandParent.edgeSnapping);
|
||||
grandParent.addChild(newParent, parent.size, parentIndex);
|
||||
@@ -1218,6 +1243,7 @@ export class GridView implements IDisposable {
|
||||
}
|
||||
|
||||
parent.removeChild(index, sizing);
|
||||
node.dispose();
|
||||
|
||||
if (parent.children.length === 0) {
|
||||
throw new Error('Invalid grid state');
|
||||
@@ -1237,6 +1263,7 @@ export class GridView implements IDisposable {
|
||||
|
||||
// we must promote sibling to be the new root
|
||||
parent.removeChild(0);
|
||||
parent.dispose();
|
||||
this.root = sibling;
|
||||
this.boundarySashes = this.boundarySashes;
|
||||
this.trySet2x2();
|
||||
@@ -1246,19 +1273,20 @@ export class GridView implements IDisposable {
|
||||
const [, grandParent] = tail(pathToParent);
|
||||
const [, parentIndex] = tail(rest);
|
||||
|
||||
const sibling = parent.children[0];
|
||||
const isSiblingVisible = parent.isChildVisible(0);
|
||||
parent.removeChild(0);
|
||||
const sibling = parent.removeChild(0);
|
||||
|
||||
const sizes = grandParent.children.map((_, i) => grandParent.getChildSize(i));
|
||||
grandParent.removeChild(parentIndex, sizing);
|
||||
parent.dispose();
|
||||
|
||||
if (sibling instanceof BranchNode) {
|
||||
sizes.splice(parentIndex, 1, ...sibling.children.map(c => c.size));
|
||||
|
||||
for (let i = 0; i < sibling.children.length; i++) {
|
||||
const child = sibling.children[i];
|
||||
grandParent.addChild(child, child.size, parentIndex + i);
|
||||
const siblingChildren = sibling.removeAllChildren();
|
||||
|
||||
for (let i = 0; i < siblingChildren.length; i++) {
|
||||
grandParent.addChild(siblingChildren[i], siblingChildren[i].size, parentIndex + i);
|
||||
}
|
||||
} else {
|
||||
const newSibling = new LeafNode(sibling.view, orthogonal(sibling.orientation), this.layoutController, sibling.size);
|
||||
@@ -1266,6 +1294,8 @@ export class GridView implements IDisposable {
|
||||
grandParent.addChild(newSibling, sizing, parentIndex);
|
||||
}
|
||||
|
||||
sibling.dispose();
|
||||
|
||||
for (let i = 0; i < sizes.length; i++) {
|
||||
grandParent.resizeChild(i, sizes[i]);
|
||||
}
|
||||
@@ -1654,9 +1684,6 @@ export class GridView implements IDisposable {
|
||||
dispose(): void {
|
||||
this.onDidSashResetRelay.dispose();
|
||||
this.root.dispose();
|
||||
|
||||
if (this.element && this.element.parentElement) {
|
||||
this.element.parentElement.removeChild(this.element);
|
||||
}
|
||||
this.element.parentElement?.removeChild(this.element);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ export interface IView<TLayoutContext = undefined> {
|
||||
/**
|
||||
* A descriptor for a {@link SplitView} instance.
|
||||
*/
|
||||
export interface ISplitViewDescriptor<TLayoutContext = undefined> {
|
||||
export interface ISplitViewDescriptor<TLayoutContext = undefined, TView extends IView<TLayoutContext> = IView<TLayoutContext>> {
|
||||
|
||||
/**
|
||||
* The layout size of the {@link SplitView}.
|
||||
@@ -150,11 +150,11 @@ export interface ISplitViewDescriptor<TLayoutContext = undefined> {
|
||||
*
|
||||
* @defaultValue `true`
|
||||
*/
|
||||
readonly view: IView<TLayoutContext>;
|
||||
readonly view: TView;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface ISplitViewOptions<TLayoutContext = undefined> {
|
||||
export interface ISplitViewOptions<TLayoutContext = undefined, TView extends IView<TLayoutContext> = IView<TLayoutContext>> {
|
||||
|
||||
/**
|
||||
* Which axis the views align on.
|
||||
@@ -184,7 +184,7 @@ export interface ISplitViewOptions<TLayoutContext = undefined> {
|
||||
* An initial description of this {@link SplitView} instance, allowing
|
||||
* to initialze all views within the ctor.
|
||||
*/
|
||||
readonly descriptor?: ISplitViewDescriptor<TLayoutContext>;
|
||||
readonly descriptor?: ISplitViewDescriptor<TLayoutContext, TView>;
|
||||
|
||||
/**
|
||||
* The scrollbar visibility setting for whenever the views within
|
||||
@@ -207,7 +207,7 @@ interface ISashEvent {
|
||||
|
||||
type ViewItemSize = number | { cachedVisibleSize: number };
|
||||
|
||||
abstract class ViewItem<TLayoutContext> {
|
||||
abstract class ViewItem<TLayoutContext, TView extends IView<TLayoutContext>> {
|
||||
|
||||
private _size: number;
|
||||
set size(size: number) {
|
||||
@@ -259,7 +259,7 @@ abstract class ViewItem<TLayoutContext> {
|
||||
|
||||
constructor(
|
||||
protected container: HTMLElement,
|
||||
readonly view: IView<TLayoutContext>,
|
||||
readonly view: TView,
|
||||
size: ViewItemSize,
|
||||
private disposable: IDisposable
|
||||
) {
|
||||
@@ -285,7 +285,7 @@ abstract class ViewItem<TLayoutContext> {
|
||||
}
|
||||
}
|
||||
|
||||
class VerticalViewItem<TLayoutContext> extends ViewItem<TLayoutContext> {
|
||||
class VerticalViewItem<TLayoutContext, TView extends IView<TLayoutContext>> extends ViewItem<TLayoutContext, TView> {
|
||||
|
||||
layoutContainer(offset: number): void {
|
||||
this.container.style.top = `${offset}px`;
|
||||
@@ -293,7 +293,7 @@ class VerticalViewItem<TLayoutContext> extends ViewItem<TLayoutContext> {
|
||||
}
|
||||
}
|
||||
|
||||
class HorizontalViewItem<TLayoutContext> extends ViewItem<TLayoutContext> {
|
||||
class HorizontalViewItem<TLayoutContext, TView extends IView<TLayoutContext>> extends ViewItem<TLayoutContext, TView> {
|
||||
|
||||
layoutContainer(offset: number): void {
|
||||
this.container.style.left = `${offset}px`;
|
||||
@@ -413,7 +413,7 @@ export namespace Sizing {
|
||||
* - View swap/move support
|
||||
* - Alt key modifier behavior, macOS style
|
||||
*/
|
||||
export class SplitView<TLayoutContext = undefined> extends Disposable {
|
||||
export class SplitView<TLayoutContext = undefined, TView extends IView<TLayoutContext> = IView<TLayoutContext>> extends Disposable {
|
||||
|
||||
/**
|
||||
* This {@link SplitView}'s orientation.
|
||||
@@ -433,7 +433,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
|
||||
private layoutContext: TLayoutContext | undefined;
|
||||
private contentSize = 0;
|
||||
private proportions: (number | undefined)[] | undefined = undefined;
|
||||
private viewItems: ViewItem<TLayoutContext>[] = [];
|
||||
private viewItems: ViewItem<TLayoutContext, TView>[] = [];
|
||||
sashItems: ISashItem[] = []; // used in tests
|
||||
private sashDragState: ISashDragState | undefined;
|
||||
private state: State = State.Idle;
|
||||
@@ -549,7 +549,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
|
||||
/**
|
||||
* Create a new {@link SplitView} instance.
|
||||
*/
|
||||
constructor(container: HTMLElement, options: ISplitViewOptions<TLayoutContext> = {}) {
|
||||
constructor(container: HTMLElement, options: ISplitViewOptions<TLayoutContext, TView> = {}) {
|
||||
super();
|
||||
|
||||
this.orientation = options.orientation ?? Orientation.VERTICAL;
|
||||
@@ -636,7 +636,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
|
||||
* @param index The index to insert the view on.
|
||||
* @param skipLayout Whether layout should be skipped.
|
||||
*/
|
||||
addView(view: IView<TLayoutContext>, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {
|
||||
addView(view: TView, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {
|
||||
this.doAddView(view, size, index, skipLayout);
|
||||
}
|
||||
|
||||
@@ -646,7 +646,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
|
||||
* @param index The index where the {@link IView view} is located.
|
||||
* @param sizing Whether to distribute other {@link IView view}'s sizes.
|
||||
*/
|
||||
removeView(index: number, sizing?: Sizing): IView<TLayoutContext> {
|
||||
removeView(index: number, sizing?: Sizing): TView {
|
||||
if (this.state !== State.Idle) {
|
||||
throw new Error('Cant modify splitview');
|
||||
}
|
||||
@@ -695,6 +695,31 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
|
||||
return result;
|
||||
}
|
||||
|
||||
removeAllViews(): TView[] {
|
||||
if (this.state !== State.Idle) {
|
||||
throw new Error('Cant modify splitview');
|
||||
}
|
||||
|
||||
this.state = State.Busy;
|
||||
|
||||
const viewItems = this.viewItems.splice(0, this.viewItems.length);
|
||||
|
||||
for (const viewItem of viewItems) {
|
||||
viewItem.dispose();
|
||||
}
|
||||
|
||||
const sashItems = this.sashItems.splice(0, this.sashItems.length);
|
||||
|
||||
for (const sashItem of sashItems) {
|
||||
sashItem.disposable.dispose();
|
||||
}
|
||||
|
||||
this.relayout();
|
||||
this.state = State.Idle;
|
||||
|
||||
return viewItems.map(i => i.view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move a {@link IView view} to a different index.
|
||||
*
|
||||
@@ -951,7 +976,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private onViewChange(item: ViewItem<TLayoutContext>, size: number | undefined): void {
|
||||
private onViewChange(item: ViewItem<TLayoutContext, TView>, size: number | undefined): void {
|
||||
const index = this.viewItems.indexOf(item);
|
||||
|
||||
if (index < 0 || index >= this.viewItems.length) {
|
||||
@@ -1024,7 +1049,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
|
||||
* Distribute the entire {@link SplitView} size among all {@link IView views}.
|
||||
*/
|
||||
distributeViewSizes(): void {
|
||||
const flexibleViewItems: ViewItem<TLayoutContext>[] = [];
|
||||
const flexibleViewItems: ViewItem<TLayoutContext, TView>[] = [];
|
||||
let flexibleSize = 0;
|
||||
|
||||
for (const item of this.viewItems) {
|
||||
@@ -1058,7 +1083,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
|
||||
return this.viewItems[index].size;
|
||||
}
|
||||
|
||||
private doAddView(view: IView<TLayoutContext>, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {
|
||||
private doAddView(view: TView, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {
|
||||
if (this.state !== State.Idle) {
|
||||
throw new Error('Cant modify splitview');
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { Comparator } from './arrays';
|
||||
|
||||
export function findLast<T>(array: readonly T[], predicate: (item: T) => boolean): T | undefined {
|
||||
export function findLast<T>(array: readonly T[], predicate: (item: T) => boolean, fromIdx?: number): T | undefined {
|
||||
const idx = findLastIdx(array, predicate);
|
||||
if (idx === -1) {
|
||||
return undefined;
|
||||
@@ -13,8 +13,8 @@ export function findLast<T>(array: readonly T[], predicate: (item: T) => boolean
|
||||
return array[idx];
|
||||
}
|
||||
|
||||
export function findLastIdx<T>(array: readonly T[], predicate: (item: T) => boolean): number {
|
||||
for (let i = array.length - 1; i >= 0; i--) {
|
||||
export function findLastIdx<T>(array: readonly T[], predicate: (item: T) => boolean, fromIndex = array.length - 1): number {
|
||||
for (let i = fromIndex; i >= 0; i--) {
|
||||
const element = array[i];
|
||||
|
||||
if (predicate(element)) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { CancellationError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableMap, IDisposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { extUri as defaultExtUri, IExtUri } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { setTimeout0 } from 'vs/base/common/platform';
|
||||
@@ -182,7 +182,7 @@ export class Throttler implements IDisposable {
|
||||
|
||||
queue<T>(promiseFactory: ITask<Promise<T>>): Promise<T> {
|
||||
if (this.isDisposed) {
|
||||
throw new Error('Throttler is disposed');
|
||||
return Promise.reject(new Error('Throttler is disposed'));
|
||||
}
|
||||
|
||||
if (this.activePromise) {
|
||||
@@ -717,6 +717,9 @@ export class ResourceQueue implements IDisposable {
|
||||
|
||||
private readonly drainers = new Set<DeferredPromise<void>>();
|
||||
|
||||
private drainListeners: DisposableMap<number> | undefined = undefined;
|
||||
private drainListenerCount = 0;
|
||||
|
||||
async whenDrained(): Promise<void> {
|
||||
if (this.isDrained()) {
|
||||
return;
|
||||
@@ -744,12 +747,25 @@ export class ResourceQueue implements IDisposable {
|
||||
let queue = this.queues.get(key);
|
||||
if (!queue) {
|
||||
queue = new Queue<void>();
|
||||
Event.once(queue.onDrained)(() => {
|
||||
const drainListenerId = this.drainListenerCount++;
|
||||
const drainListener = Event.once(queue.onDrained)(() => {
|
||||
queue?.dispose();
|
||||
this.queues.delete(key);
|
||||
this.onDidQueueDrain();
|
||||
|
||||
this.drainListeners?.deleteAndDispose(drainListenerId);
|
||||
|
||||
if (this.drainListeners?.size === 0) {
|
||||
this.drainListeners.dispose();
|
||||
this.drainListeners = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.drainListeners) {
|
||||
this.drainListeners = new DisposableMap();
|
||||
}
|
||||
this.drainListeners.set(drainListenerId, drainListener);
|
||||
|
||||
this.queues.set(key, queue);
|
||||
}
|
||||
|
||||
@@ -786,6 +802,8 @@ export class ResourceQueue implements IDisposable {
|
||||
// promises when the resource queue is being
|
||||
// disposed.
|
||||
this.releaseDrainers();
|
||||
|
||||
this.drainListeners?.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ export namespace Event {
|
||||
* this.onInstallExtension = Event.buffer(service.onInstallExtension, true);
|
||||
* ```
|
||||
*/
|
||||
export function buffer<T>(event: Event<T>, flushAfterTimeout = false, _buffer: T[] = []): Event<T> {
|
||||
export function buffer<T>(event: Event<T>, flushAfterTimeout = false, _buffer: T[] = [], disposable?: DisposableStore): Event<T> {
|
||||
let buffer: T[] | null = _buffer.slice();
|
||||
|
||||
let listener: IDisposable | null = event(e => {
|
||||
@@ -405,6 +405,10 @@ export namespace Event {
|
||||
}
|
||||
});
|
||||
|
||||
if (disposable) {
|
||||
disposable.add(listener);
|
||||
}
|
||||
|
||||
const flush = () => {
|
||||
buffer?.forEach(e => emitter.fire(e));
|
||||
buffer = null;
|
||||
@@ -414,6 +418,9 @@ export namespace Event {
|
||||
onWillAddFirstListener() {
|
||||
if (!listener) {
|
||||
listener = event(e => emitter.fire(e));
|
||||
if (disposable) {
|
||||
disposable.add(listener);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -435,6 +442,10 @@ export namespace Event {
|
||||
}
|
||||
});
|
||||
|
||||
if (disposable) {
|
||||
disposable.add(emitter);
|
||||
}
|
||||
|
||||
return emitter.event;
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -539,6 +539,10 @@ export class DisposableMap<K, V extends IDisposable = IDisposable> implements ID
|
||||
return this._store.has(key);
|
||||
}
|
||||
|
||||
get size(): number {
|
||||
return this._store.size;
|
||||
}
|
||||
|
||||
get(key: K): V | undefined {
|
||||
return this._store.get(key);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ export interface IObservable<T, TChange = unknown> {
|
||||
* (see {@link ConvenientObservable.map}).
|
||||
*/
|
||||
map<TNew>(fn: (value: T, reader: IReader) => TNew): IObservable<TNew>;
|
||||
map<TNew>(owner: object, fn: (value: T, reader: IReader) => TNew): IObservable<TNew>;
|
||||
|
||||
/**
|
||||
* A human-readable name for debugging purposes.
|
||||
@@ -165,9 +166,15 @@ export abstract class ConvenientObservable<T, TChange> implements IObservable<T,
|
||||
}
|
||||
|
||||
/** @sealed */
|
||||
public map<TNew>(fn: (value: T, reader: IReader) => TNew): IObservable<TNew> {
|
||||
public map<TNew>(fn: (value: T, reader: IReader) => TNew): IObservable<TNew>;
|
||||
public map<TNew>(owner: object, fn: (value: T, reader: IReader) => TNew): IObservable<TNew>;
|
||||
public map<TNew>(fnOrOwner: object | ((value: T, reader: IReader) => TNew), fnOrUndefined?: (value: T, reader: IReader) => TNew): IObservable<TNew> {
|
||||
const owner = fnOrUndefined === undefined ? undefined : fnOrOwner as object;
|
||||
const fn = fnOrUndefined === undefined ? fnOrOwner as (value: T, reader: IReader) => TNew : fnOrUndefined;
|
||||
|
||||
return _derived(
|
||||
{
|
||||
owner,
|
||||
debugName: () => {
|
||||
const name = getFunctionName(fn);
|
||||
if (name !== undefined) {
|
||||
@@ -180,7 +187,10 @@ export abstract class ConvenientObservable<T, TChange> implements IObservable<T,
|
||||
if (match) {
|
||||
return `${this.debugName}.${match[2]}`;
|
||||
}
|
||||
return `${this.debugName} (mapped)`;
|
||||
if (!owner) {
|
||||
return `${this.debugName} (mapped)`;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
(reader) => fn(this.read(reader), reader),
|
||||
|
||||
@@ -26,7 +26,7 @@ export function derived<T>(computeFnOrOwner: ((reader: IReader) => T) | object,
|
||||
export function derivedOpts<T>(
|
||||
options: {
|
||||
owner?: object;
|
||||
debugName?: string | (() => string);
|
||||
debugName?: string | (() => string | undefined);
|
||||
equalityComparer?: EqualityComparer<T>;
|
||||
},
|
||||
computeFn: (reader: IReader) => T
|
||||
|
||||
@@ -118,7 +118,7 @@ export class PagedModel<T> implements IPagedModel<T> {
|
||||
});
|
||||
}
|
||||
|
||||
cancellationToken.onCancellationRequested(() => {
|
||||
const listener = cancellationToken.onCancellationRequested(() => {
|
||||
if (!page.cts) {
|
||||
return;
|
||||
}
|
||||
@@ -132,7 +132,8 @@ export class PagedModel<T> implements IPagedModel<T> {
|
||||
|
||||
page.promiseIndexes.add(index);
|
||||
|
||||
return page.promise.then(() => page.elements[indexInPage]);
|
||||
return page.promise.then(() => page.elements[indexInPage])
|
||||
.finally(() => listener.dispose());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -622,11 +622,15 @@ export function peekStream<T>(stream: ReadableStream<T>, maxChunks: number): Pro
|
||||
|
||||
// Error Listener
|
||||
const errorListener = (error: Error) => {
|
||||
streamListeners.dispose();
|
||||
|
||||
return reject(error);
|
||||
};
|
||||
|
||||
// End Listener
|
||||
const endListener = () => {
|
||||
streamListeners.dispose();
|
||||
|
||||
return resolve({ stream, buffer, ended: true });
|
||||
};
|
||||
|
||||
|
||||
@@ -107,12 +107,12 @@ function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions, tok
|
||||
let last = createCancelablePromise<void>(() => Promise.resolve());
|
||||
let extractedEntriesCount = 0;
|
||||
|
||||
token.onCancellationRequested(() => {
|
||||
const listener = token.onCancellationRequested(() => {
|
||||
last.cancel();
|
||||
zipfile.close();
|
||||
});
|
||||
|
||||
return new Promise((c, e) => {
|
||||
return new Promise<void>((c, e) => {
|
||||
const throttler = new Sequencer();
|
||||
|
||||
const readNextEntry = (token: CancellationToken) => {
|
||||
@@ -158,7 +158,7 @@ function extractZip(zipfile: ZipFile, targetPath: string, options: IOptions, tok
|
||||
|
||||
last = createCancelablePromise(token => throttler.queue(() => stream.then(stream => extractEntry(stream, fileName, mode, targetPath, options, token).then(() => readNextEntry(token)))).then(null, e));
|
||||
});
|
||||
});
|
||||
}).finally(() => listener.dispose());
|
||||
}
|
||||
|
||||
function openZip(zipFile: string, lazy: boolean = false): Promise<ZipFile> {
|
||||
|
||||
@@ -427,7 +427,6 @@ export class ChannelServer<TContext = string> implements IChannelServer<TContext
|
||||
|
||||
promise.then(data => {
|
||||
this.sendResponse(<IRawResponse>{ id, data, type: ResponseType.PromiseSuccess });
|
||||
this.activeRequests.delete(request.id);
|
||||
}, err => {
|
||||
if (err instanceof Error) {
|
||||
this.sendResponse(<IRawResponse>{
|
||||
@@ -440,7 +439,8 @@ export class ChannelServer<TContext = string> implements IChannelServer<TContext
|
||||
} else {
|
||||
this.sendResponse(<IRawResponse>{ id, data: err, type: ResponseType.PromiseErrorObj });
|
||||
}
|
||||
|
||||
}).finally(() => {
|
||||
disposable.dispose();
|
||||
this.activeRequests.delete(request.id);
|
||||
});
|
||||
|
||||
@@ -639,7 +639,10 @@ export class ChannelClient implements IChannelClient, IDisposable {
|
||||
this.activeRequests.add(disposable);
|
||||
});
|
||||
|
||||
return result.finally(() => { this.activeRequests.delete(disposable); });
|
||||
return result.finally(() => {
|
||||
disposable.dispose();
|
||||
this.activeRequests.delete(disposable);
|
||||
});
|
||||
}
|
||||
|
||||
private requestEvent(channelName: string, name: string, arg?: any): Event<any> {
|
||||
@@ -795,6 +798,8 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
private readonly _onDidRemoveConnection = new Emitter<Connection<TContext>>();
|
||||
readonly onDidRemoveConnection: Event<Connection<TContext>> = this._onDidRemoveConnection.event;
|
||||
|
||||
private disposables = new DisposableStore();
|
||||
|
||||
get connections(): Connection<TContext>[] {
|
||||
const result: Connection<TContext>[] = [];
|
||||
this._connections.forEach(ctx => result.push(ctx));
|
||||
@@ -802,10 +807,10 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
}
|
||||
|
||||
constructor(onDidClientConnect: Event<ClientConnectionEvent>) {
|
||||
onDidClientConnect(({ protocol, onDidClientDisconnect }) => {
|
||||
this.disposables.add(onDidClientConnect(({ protocol, onDidClientDisconnect }) => {
|
||||
const onFirstMessage = Event.once(protocol.onMessage);
|
||||
|
||||
onFirstMessage(msg => {
|
||||
this.disposables.add(onFirstMessage(msg => {
|
||||
const reader = new BufferReader(msg);
|
||||
const ctx = deserialize(reader) as TContext;
|
||||
|
||||
@@ -818,14 +823,14 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
this._connections.add(connection);
|
||||
this._onDidAddConnection.fire(connection);
|
||||
|
||||
onDidClientDisconnect(() => {
|
||||
this.disposables.add(onDidClientDisconnect(() => {
|
||||
channelServer.dispose();
|
||||
channelClient.dispose();
|
||||
this._connections.delete(connection);
|
||||
this._onDidRemoveConnection.fire(connection);
|
||||
});
|
||||
});
|
||||
});
|
||||
}));
|
||||
}));
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -879,7 +884,7 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
|
||||
private getMulticastEvent<T extends IChannel>(channelName: string, clientFilter: (client: Client<TContext>) => boolean, eventName: string, arg: any): Event<T> {
|
||||
const that = this;
|
||||
let disposables = new DisposableStore();
|
||||
let disposables: DisposableStore | undefined;
|
||||
|
||||
// Create an emitter which hooks up to all clients
|
||||
// as soon as first listener is added. It also
|
||||
@@ -922,7 +927,8 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
disposables.add(eventMultiplexer);
|
||||
},
|
||||
onDidRemoveLastListener: () => {
|
||||
disposables.dispose();
|
||||
disposables?.dispose();
|
||||
disposables = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -932,14 +938,21 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
registerChannel(channelName: string, channel: IServerChannel<TContext>): void {
|
||||
this.channels.set(channelName, channel);
|
||||
|
||||
this._connections.forEach(connection => {
|
||||
for (const connection of this._connections) {
|
||||
connection.channelServer.registerChannel(channelName, channel);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.channels.clear();
|
||||
this.disposables.dispose();
|
||||
|
||||
for (const connection of this._connections) {
|
||||
connection.channelClient.dispose();
|
||||
connection.channelServer.dispose();
|
||||
}
|
||||
|
||||
this._connections.clear();
|
||||
this.channels.clear();
|
||||
this._onDidAddConnection.dispose();
|
||||
this._onDidRemoveConnection.dispose();
|
||||
}
|
||||
@@ -1074,7 +1087,7 @@ export namespace ProxyChannel {
|
||||
|
||||
export interface ICreateServiceChannelOptions extends IProxyOptions { }
|
||||
|
||||
export function fromService<TContext>(service: unknown, options?: ICreateServiceChannelOptions): IServerChannel<TContext> {
|
||||
export function fromService<TContext>(service: unknown, disposables: DisposableStore, options?: ICreateServiceChannelOptions): IServerChannel<TContext> {
|
||||
const handler = service as { [key: string]: unknown };
|
||||
const disableMarshalling = options && options.disableMarshalling;
|
||||
|
||||
@@ -1083,7 +1096,7 @@ export namespace ProxyChannel {
|
||||
const mapEventNameToEvent = new Map<string, Event<unknown>>();
|
||||
for (const key in handler) {
|
||||
if (propertyIsEvent(key)) {
|
||||
mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event<unknown>, true));
|
||||
mapEventNameToEvent.set(key, Event.buffer(handler[key] as Event<unknown>, true, undefined, disposables));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,11 @@ import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { BufferReader, BufferWriter, ClientConnectionEvent, deserialize, IChannel, IMessagePassingProtocol, IPCClient, IPCServer, IServerChannel, ProxyChannel, serialize } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
class QueueProtocol implements IMessagePassingProtocol {
|
||||
|
||||
@@ -111,6 +113,8 @@ interface ITestService {
|
||||
|
||||
class TestService implements ITestService {
|
||||
|
||||
private disposables = new DisposableStore();
|
||||
|
||||
private readonly _onPong = new Emitter<string>();
|
||||
readonly onPong = this._onPong.event;
|
||||
|
||||
@@ -131,7 +135,7 @@ class TestService implements ITestService {
|
||||
return Promise.reject(canceled());
|
||||
}
|
||||
|
||||
return new Promise((_, e) => cancellationToken.onCancellationRequested(() => e(canceled())));
|
||||
return new Promise((_, e) => this.disposables.add(cancellationToken.onCancellationRequested(() => e(canceled()))));
|
||||
}
|
||||
|
||||
buffersLength(buffers: VSBuffer[]): Promise<number> {
|
||||
@@ -149,6 +153,10 @@ class TestService implements ITestService {
|
||||
context(context?: unknown): Promise<unknown> {
|
||||
return Promise.resolve(context);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.disposables.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class TestChannel implements IServerChannel {
|
||||
@@ -213,6 +221,8 @@ class TestChannelClient implements ITestService {
|
||||
|
||||
suite('Base IPC', function () {
|
||||
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
test('createProtocolPair', async function () {
|
||||
const [clientProtocol, serverProtocol] = createProtocolPair();
|
||||
|
||||
@@ -236,21 +246,16 @@ suite('Base IPC', function () {
|
||||
let ipcService: ITestService;
|
||||
|
||||
setup(function () {
|
||||
service = new TestService();
|
||||
const testServer = new TestIPCServer();
|
||||
service = store.add(new TestService());
|
||||
const testServer = store.add(new TestIPCServer());
|
||||
server = testServer;
|
||||
|
||||
server.registerChannel(TestChannelId, new TestChannel(service));
|
||||
|
||||
client = testServer.createConnection('client1');
|
||||
client = store.add(testServer.createConnection('client1'));
|
||||
ipcService = new TestChannelClient(client.getChannel(TestChannelId));
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
client.dispose();
|
||||
server.dispose();
|
||||
});
|
||||
|
||||
test('call success', async function () {
|
||||
const r = await ipcService.marco();
|
||||
return assert.strictEqual(r, 'polo');
|
||||
@@ -301,7 +306,7 @@ suite('Base IPC', function () {
|
||||
test('listen to events', async function () {
|
||||
const messages: string[] = [];
|
||||
|
||||
ipcService.onPong(msg => messages.push(msg));
|
||||
store.add(ipcService.onPong(msg => messages.push(msg)));
|
||||
await timeout(0);
|
||||
|
||||
assert.deepStrictEqual(messages, []);
|
||||
@@ -343,20 +348,21 @@ suite('Base IPC', function () {
|
||||
let service: TestService;
|
||||
let ipcService: ITestService;
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
setup(function () {
|
||||
service = new TestService();
|
||||
const testServer = new TestIPCServer();
|
||||
service = store.add(new TestService());
|
||||
const testServer = disposables.add(new TestIPCServer());
|
||||
server = testServer;
|
||||
|
||||
server.registerChannel(TestChannelId, ProxyChannel.fromService(service));
|
||||
server.registerChannel(TestChannelId, ProxyChannel.fromService(service, disposables));
|
||||
|
||||
client = testServer.createConnection('client1');
|
||||
client = disposables.add(testServer.createConnection('client1'));
|
||||
ipcService = ProxyChannel.toService(client.getChannel(TestChannelId));
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
client.dispose();
|
||||
server.dispose();
|
||||
disposables.clear();
|
||||
});
|
||||
|
||||
test('call success', async function () {
|
||||
@@ -376,7 +382,7 @@ suite('Base IPC', function () {
|
||||
test('listen to events', async function () {
|
||||
const messages: string[] = [];
|
||||
|
||||
ipcService.onPong(msg => messages.push(msg));
|
||||
disposables.add(ipcService.onPong(msg => messages.push(msg)));
|
||||
await timeout(0);
|
||||
|
||||
assert.deepStrictEqual(messages, []);
|
||||
@@ -409,20 +415,21 @@ suite('Base IPC', function () {
|
||||
let service: TestService;
|
||||
let ipcService: ITestService;
|
||||
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
setup(function () {
|
||||
service = new TestService();
|
||||
const testServer = new TestIPCServer();
|
||||
service = store.add(new TestService());
|
||||
const testServer = disposables.add(new TestIPCServer());
|
||||
server = testServer;
|
||||
|
||||
server.registerChannel(TestChannelId, ProxyChannel.fromService(service));
|
||||
server.registerChannel(TestChannelId, ProxyChannel.fromService(service, disposables));
|
||||
|
||||
client = testServer.createConnection('client1');
|
||||
client = disposables.add(testServer.createConnection('client1'));
|
||||
ipcService = ProxyChannel.toService(client.getChannel(TestChannelId), { context: 'Super Context' });
|
||||
});
|
||||
|
||||
teardown(function () {
|
||||
client.dispose();
|
||||
server.dispose();
|
||||
disposables.clear();
|
||||
});
|
||||
|
||||
test('call extra context', async function () {
|
||||
@@ -433,20 +440,20 @@ suite('Base IPC', function () {
|
||||
|
||||
suite('one to many', function () {
|
||||
test('all clients get pinged', async function () {
|
||||
const service = new TestService();
|
||||
const service = store.add(new TestService());
|
||||
const channel = new TestChannel(service);
|
||||
const server = new TestIPCServer();
|
||||
const server = store.add(new TestIPCServer());
|
||||
server.registerChannel('channel', channel);
|
||||
|
||||
let client1GotPinged = false;
|
||||
const client1 = server.createConnection('client1');
|
||||
const client1 = store.add(server.createConnection('client1'));
|
||||
const ipcService1 = new TestChannelClient(client1.getChannel('channel'));
|
||||
ipcService1.onPong(() => client1GotPinged = true);
|
||||
store.add(ipcService1.onPong(() => client1GotPinged = true));
|
||||
|
||||
let client2GotPinged = false;
|
||||
const client2 = server.createConnection('client2');
|
||||
const client2 = store.add(server.createConnection('client2'));
|
||||
const ipcService2 = new TestChannelClient(client2.getChannel('channel'));
|
||||
ipcService2.onPong(() => client2GotPinged = true);
|
||||
store.add(ipcService2.onPong(() => client2GotPinged = true));
|
||||
|
||||
await timeout(1);
|
||||
service.ping('hello');
|
||||
@@ -454,24 +461,20 @@ suite('Base IPC', function () {
|
||||
await timeout(1);
|
||||
assert(client1GotPinged, 'client 1 got pinged');
|
||||
assert(client2GotPinged, 'client 2 got pinged');
|
||||
|
||||
client1.dispose();
|
||||
client2.dispose();
|
||||
server.dispose();
|
||||
});
|
||||
|
||||
test('server gets pings from all clients (broadcast channel)', async function () {
|
||||
const server = new TestIPCServer();
|
||||
const server = store.add(new TestIPCServer());
|
||||
|
||||
const client1 = server.createConnection('client1');
|
||||
const clientService1 = new TestService();
|
||||
const clientService1 = store.add(new TestService());
|
||||
const clientChannel1 = new TestChannel(clientService1);
|
||||
client1.registerChannel('channel', clientChannel1);
|
||||
|
||||
const pings: string[] = [];
|
||||
const channel = server.getChannel('channel', () => true);
|
||||
const service = new TestChannelClient(channel);
|
||||
service.onPong(msg => pings.push(msg));
|
||||
store.add(service.onPong(msg => pings.push(msg)));
|
||||
|
||||
await timeout(1);
|
||||
clientService1.ping('hello 1');
|
||||
@@ -480,7 +483,7 @@ suite('Base IPC', function () {
|
||||
assert.deepStrictEqual(pings, ['hello 1']);
|
||||
|
||||
const client2 = server.createConnection('client2');
|
||||
const clientService2 = new TestService();
|
||||
const clientService2 = store.add(new TestService());
|
||||
const clientChannel2 = new TestChannel(clientService2);
|
||||
client2.registerChannel('channel', clientChannel2);
|
||||
|
||||
@@ -503,7 +506,6 @@ suite('Base IPC', function () {
|
||||
assert.deepStrictEqual(pings, ['hello 1', 'hello 2', 'hello again 2']);
|
||||
|
||||
client2.dispose();
|
||||
server.dispose();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -123,7 +123,7 @@ export class Storage extends Disposable implements IStorage {
|
||||
|
||||
private cache = new Map<string, string>();
|
||||
|
||||
private readonly flushDelayer = new ThrottledDelayer<void>(Storage.DEFAULT_FLUSH_DELAY);
|
||||
private readonly flushDelayer = this._register(new ThrottledDelayer<void>(Storage.DEFAULT_FLUSH_DELAY));
|
||||
|
||||
private pendingDeletes = new Set<string>();
|
||||
private pendingInserts = new Map<string, string>();
|
||||
@@ -392,6 +392,10 @@ export class Storage extends Disposable implements IStorage {
|
||||
}
|
||||
|
||||
private async doFlush(delay?: number): Promise<void> {
|
||||
if (this.options.hint === StorageHint.STORAGE_IN_MEMORY) {
|
||||
return this.flushPending(); // return early if in-memory
|
||||
}
|
||||
|
||||
return this.flushDelayer.trigger(() => this.flushPending(), delay);
|
||||
}
|
||||
|
||||
@@ -406,12 +410,6 @@ export class Storage extends Disposable implements IStorage {
|
||||
isInMemory(): boolean {
|
||||
return this.options.hint === StorageHint.STORAGE_IN_MEMORY;
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
this.flushDelayer.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class InMemoryStorageDatabase implements IStorageDatabase {
|
||||
|
||||
@@ -6,16 +6,19 @@
|
||||
import * as assert from 'assert';
|
||||
import { ActionBar, prepareActions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action, Separator } from 'vs/base/common/actions';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
suite('Actionbar', () => {
|
||||
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
test('prepareActions()', function () {
|
||||
const a1 = new Separator();
|
||||
const a2 = new Separator();
|
||||
const a3 = new Action('a3');
|
||||
const a3 = store.add(new Action('a3'));
|
||||
const a4 = new Separator();
|
||||
const a5 = new Separator();
|
||||
const a6 = new Action('a6');
|
||||
const a6 = store.add(new Action('a6'));
|
||||
const a7 = new Separator();
|
||||
|
||||
const actions = prepareActions([a1, a2, a3, a4, a5, a6, a7]);
|
||||
@@ -27,10 +30,10 @@ suite('Actionbar', () => {
|
||||
|
||||
test('hasAction()', function () {
|
||||
const container = document.createElement('div');
|
||||
const actionbar = new ActionBar(container);
|
||||
const actionbar = store.add(new ActionBar(container));
|
||||
|
||||
const a1 = new Action('a1');
|
||||
const a2 = new Action('a2');
|
||||
const a1 = store.add(new Action('a1'));
|
||||
const a2 = store.add(new Action('a2'));
|
||||
|
||||
actionbar.push(a1);
|
||||
assert.strictEqual(actionbar.hasAction(a1), true);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
suite('HighlightedLabel', () => {
|
||||
let label: HighlightedLabel;
|
||||
@@ -58,6 +59,7 @@ suite('HighlightedLabel', () => {
|
||||
escaped = HighlightedLabel.escapeNewLines('ACTION\r\n_TYPE2', highlights);
|
||||
assert.strictEqual(escaped, 'ACTION\u23CE_TYPE2');
|
||||
assert.deepStrictEqual(highlights, [{ start: 5, end: 8 }, { start: 10, end: 11 }]);
|
||||
|
||||
});
|
||||
|
||||
ensureNoDisposablesAreLeakedInTestSuite();
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
suite('ProgressBar', () => {
|
||||
let fixture: HTMLElement;
|
||||
@@ -29,4 +30,6 @@ suite('ProgressBar', () => {
|
||||
|
||||
bar.dispose();
|
||||
});
|
||||
|
||||
ensureNoDisposablesAreLeakedInTestSuite();
|
||||
});
|
||||
|
||||
@@ -8,6 +8,8 @@ import { createSerializedGrid, Direction, getRelativeLocation, Grid, GridNode, G
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
import { nodesToArrays, TestView } from './util';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
|
||||
// Simple example:
|
||||
//
|
||||
@@ -30,6 +32,8 @@ import { nodesToArrays, TestView } from './util';
|
||||
// +-3
|
||||
|
||||
suite('Grid', function () {
|
||||
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
let container: HTMLElement;
|
||||
|
||||
setup(function () {
|
||||
@@ -72,8 +76,8 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('empty', () => {
|
||||
const view1 = new TestView(100, Number.MAX_VALUE, 100, Number.MAX_VALUE);
|
||||
const gridview = new Grid(view1);
|
||||
const view1 = store.add(new TestView(100, Number.MAX_VALUE, 100, Number.MAX_VALUE));
|
||||
const gridview = store.add(new Grid(view1));
|
||||
container.appendChild(gridview.element);
|
||||
gridview.layout(800, 600);
|
||||
|
||||
@@ -81,59 +85,59 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('two views vertically', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
grid.layout(800, 600);
|
||||
assert.deepStrictEqual(view1.size, [800, 600]);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, 200, view1, Direction.Up);
|
||||
assert.deepStrictEqual(view1.size, [800, 400]);
|
||||
assert.deepStrictEqual(view2.size, [800, 200]);
|
||||
});
|
||||
|
||||
test('two views horizontally', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
assert.deepStrictEqual(view1.size, [800, 600]);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, 300, view1, Direction.Right);
|
||||
assert.deepStrictEqual(view1.size, [500, 600]);
|
||||
assert.deepStrictEqual(view2.size, [300, 600]);
|
||||
});
|
||||
|
||||
test('simple layout', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
assert.deepStrictEqual(view1.size, [800, 600]);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, 200, view1, Direction.Up);
|
||||
assert.deepStrictEqual(view1.size, [800, 400]);
|
||||
assert.deepStrictEqual(view2.size, [800, 200]);
|
||||
|
||||
const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, 200, view1, Direction.Right);
|
||||
assert.deepStrictEqual(view1.size, [600, 400]);
|
||||
assert.deepStrictEqual(view2.size, [800, 200]);
|
||||
assert.deepStrictEqual(view3.size, [200, 400]);
|
||||
|
||||
const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, 200, view2, Direction.Left);
|
||||
assert.deepStrictEqual(view1.size, [600, 400]);
|
||||
assert.deepStrictEqual(view2.size, [600, 200]);
|
||||
assert.deepStrictEqual(view3.size, [200, 400]);
|
||||
assert.deepStrictEqual(view4.size, [200, 200]);
|
||||
|
||||
const view5 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view5 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view5, 100, view1, Direction.Down);
|
||||
assert.deepStrictEqual(view1.size, [600, 300]);
|
||||
assert.deepStrictEqual(view2.size, [600, 200]);
|
||||
@@ -143,32 +147,32 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('another simple layout with automatic size distribution', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
assert.deepStrictEqual(view1.size, [800, 600]);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Distribute, view1, Direction.Left);
|
||||
assert.deepStrictEqual(view1.size, [400, 600]);
|
||||
assert.deepStrictEqual(view2.size, [400, 600]);
|
||||
|
||||
const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Distribute, view1, Direction.Right);
|
||||
assert.deepStrictEqual(view1.size, [266, 600]);
|
||||
assert.deepStrictEqual(view2.size, [266, 600]);
|
||||
assert.deepStrictEqual(view3.size, [268, 600]);
|
||||
|
||||
const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, Sizing.Distribute, view2, Direction.Down);
|
||||
assert.deepStrictEqual(view1.size, [266, 600]);
|
||||
assert.deepStrictEqual(view2.size, [266, 300]);
|
||||
assert.deepStrictEqual(view3.size, [268, 600]);
|
||||
assert.deepStrictEqual(view4.size, [266, 300]);
|
||||
|
||||
const view5 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view5 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view5, Sizing.Distribute, view3, Direction.Up);
|
||||
assert.deepStrictEqual(view1.size, [266, 600]);
|
||||
assert.deepStrictEqual(view2.size, [266, 300]);
|
||||
@@ -176,7 +180,7 @@ suite('Grid', function () {
|
||||
assert.deepStrictEqual(view4.size, [266, 300]);
|
||||
assert.deepStrictEqual(view5.size, [268, 300]);
|
||||
|
||||
const view6 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view6 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view6, Sizing.Distribute, view3, Direction.Down);
|
||||
assert.deepStrictEqual(view1.size, [266, 600]);
|
||||
assert.deepStrictEqual(view2.size, [266, 300]);
|
||||
@@ -187,32 +191,32 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('another simple layout with split size distribution', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
assert.deepStrictEqual(view1.size, [800, 600]);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Split, view1, Direction.Left);
|
||||
assert.deepStrictEqual(view1.size, [400, 600]);
|
||||
assert.deepStrictEqual(view2.size, [400, 600]);
|
||||
|
||||
const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Split, view1, Direction.Right);
|
||||
assert.deepStrictEqual(view1.size, [200, 600]);
|
||||
assert.deepStrictEqual(view2.size, [400, 600]);
|
||||
assert.deepStrictEqual(view3.size, [200, 600]);
|
||||
|
||||
const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, Sizing.Split, view2, Direction.Down);
|
||||
assert.deepStrictEqual(view1.size, [200, 600]);
|
||||
assert.deepStrictEqual(view2.size, [400, 300]);
|
||||
assert.deepStrictEqual(view3.size, [200, 600]);
|
||||
assert.deepStrictEqual(view4.size, [400, 300]);
|
||||
|
||||
const view5 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view5 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view5, Sizing.Split, view3, Direction.Up);
|
||||
assert.deepStrictEqual(view1.size, [200, 600]);
|
||||
assert.deepStrictEqual(view2.size, [400, 300]);
|
||||
@@ -220,7 +224,7 @@ suite('Grid', function () {
|
||||
assert.deepStrictEqual(view4.size, [400, 300]);
|
||||
assert.deepStrictEqual(view5.size, [200, 300]);
|
||||
|
||||
const view6 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view6 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view6, Sizing.Split, view3, Direction.Down);
|
||||
assert.deepStrictEqual(view1.size, [200, 600]);
|
||||
assert.deepStrictEqual(view2.size, [400, 300]);
|
||||
@@ -231,32 +235,32 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('3/2 layout with split', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
assert.deepStrictEqual(view1.size, [800, 600]);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Split, view1, Direction.Down);
|
||||
assert.deepStrictEqual(view1.size, [800, 300]);
|
||||
assert.deepStrictEqual(view2.size, [800, 300]);
|
||||
|
||||
const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Split, view2, Direction.Right);
|
||||
assert.deepStrictEqual(view1.size, [800, 300]);
|
||||
assert.deepStrictEqual(view2.size, [400, 300]);
|
||||
assert.deepStrictEqual(view3.size, [400, 300]);
|
||||
|
||||
const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, Sizing.Split, view1, Direction.Right);
|
||||
assert.deepStrictEqual(view1.size, [400, 300]);
|
||||
assert.deepStrictEqual(view2.size, [400, 300]);
|
||||
assert.deepStrictEqual(view3.size, [400, 300]);
|
||||
assert.deepStrictEqual(view4.size, [400, 300]);
|
||||
|
||||
const view5 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view5 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view5, Sizing.Split, view1, Direction.Right);
|
||||
assert.deepStrictEqual(view1.size, [200, 300]);
|
||||
assert.deepStrictEqual(view2.size, [400, 300]);
|
||||
@@ -266,19 +270,19 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('sizing should be correct after branch demotion #50564', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Split, view1, Direction.Right);
|
||||
|
||||
const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Split, view2, Direction.Down);
|
||||
|
||||
const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, Sizing.Split, view2, Direction.Right);
|
||||
assert.deepStrictEqual(view1.size, [400, 600]);
|
||||
assert.deepStrictEqual(view2.size, [200, 300]);
|
||||
@@ -292,19 +296,19 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('sizing should be correct after branch demotion #50675', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Distribute, view1, Direction.Down);
|
||||
|
||||
const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Distribute, view2, Direction.Down);
|
||||
|
||||
const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, Sizing.Distribute, view3, Direction.Right);
|
||||
assert.deepStrictEqual(view1.size, [800, 200]);
|
||||
assert.deepStrictEqual(view2.size, [800, 200]);
|
||||
@@ -318,8 +322,8 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('getNeighborViews should work on single view layout', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
@@ -336,16 +340,16 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('getNeighborViews should work on simple layout', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Distribute, view1, Direction.Down);
|
||||
|
||||
const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Distribute, view2, Direction.Down);
|
||||
|
||||
assert.deepStrictEqual(grid.getNeighborViews(view1, Direction.Up), []);
|
||||
@@ -380,22 +384,22 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('getNeighborViews should work on a complex layout', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Distribute, view1, Direction.Down);
|
||||
|
||||
const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Distribute, view2, Direction.Down);
|
||||
|
||||
const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, Sizing.Distribute, view2, Direction.Right);
|
||||
|
||||
const view5 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view5 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view5, Sizing.Distribute, view4, Direction.Down);
|
||||
|
||||
assert.deepStrictEqual(grid.getNeighborViews(view1, Direction.Up), []);
|
||||
@@ -421,19 +425,19 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('getNeighborViews should work on another simple layout', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Distribute, view1, Direction.Right);
|
||||
|
||||
const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Distribute, view2, Direction.Down);
|
||||
|
||||
const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, Sizing.Distribute, view2, Direction.Right);
|
||||
|
||||
assert.deepStrictEqual(grid.getNeighborViews(view4, Direction.Up), []);
|
||||
@@ -443,19 +447,19 @@ suite('Grid', function () {
|
||||
});
|
||||
|
||||
test('getNeighborViews should only return immediate neighbors', function () {
|
||||
const view1 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new Grid(view1);
|
||||
const view1 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new Grid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Distribute, view1, Direction.Right);
|
||||
|
||||
const view3 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Distribute, view2, Direction.Down);
|
||||
|
||||
const view4 = new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestView(50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, Sizing.Distribute, view2, Direction.Right);
|
||||
|
||||
assert.deepStrictEqual(grid.getNeighborViews(view1, Direction.Right), [view2, view3]);
|
||||
@@ -483,8 +487,10 @@ class TestViewDeserializer implements IViewDeserializer<TestSerializableView> {
|
||||
|
||||
private views = new Map<string, TestSerializableView>();
|
||||
|
||||
constructor(private readonly store: Pick<DisposableStore, 'add'>) { }
|
||||
|
||||
fromJSON(json: any): TestSerializableView {
|
||||
const view = new TestSerializableView(json.name, 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view = this.store.add(new TestSerializableView(json.name, 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
this.views.set(json.name, view);
|
||||
return view;
|
||||
}
|
||||
@@ -508,6 +514,7 @@ function nodesToNames(node: GridNode<TestSerializableView>): any {
|
||||
|
||||
suite('SerializableGrid', function () {
|
||||
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
let container: HTMLElement;
|
||||
|
||||
setup(function () {
|
||||
@@ -518,8 +525,8 @@ suite('SerializableGrid', function () {
|
||||
});
|
||||
|
||||
test('serialize empty', function () {
|
||||
const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new SerializableGrid(view1);
|
||||
const view1 = store.add(new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new SerializableGrid(view1));
|
||||
container.appendChild(grid.element);
|
||||
grid.layout(800, 600);
|
||||
|
||||
@@ -545,21 +552,21 @@ suite('SerializableGrid', function () {
|
||||
});
|
||||
|
||||
test('serialize simple layout', function () {
|
||||
const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new SerializableGrid(view1);
|
||||
const view1 = store.add(new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new SerializableGrid(view1));
|
||||
container.appendChild(grid.element);
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, 200, view1, Direction.Up);
|
||||
|
||||
const view3 = new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, 200, view1, Direction.Right);
|
||||
|
||||
const view4 = new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, 200, view2, Direction.Left);
|
||||
|
||||
const view5 = new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view5 = store.add(new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view5, 100, view1, Direction.Down);
|
||||
|
||||
assert.deepStrictEqual(grid.serialize(), {
|
||||
@@ -599,45 +606,45 @@ suite('SerializableGrid', function () {
|
||||
});
|
||||
|
||||
test('deserialize empty', function () {
|
||||
const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new SerializableGrid(view1);
|
||||
const view1 = store.add(new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new SerializableGrid(view1));
|
||||
container.appendChild(grid.element);
|
||||
grid.layout(800, 600);
|
||||
|
||||
const json = grid.serialize();
|
||||
grid.dispose();
|
||||
|
||||
const deserializer = new TestViewDeserializer();
|
||||
const grid2 = SerializableGrid.deserialize(json, deserializer);
|
||||
const deserializer = new TestViewDeserializer(store);
|
||||
const grid2 = store.add(SerializableGrid.deserialize(json, deserializer));
|
||||
grid2.layout(800, 600);
|
||||
|
||||
assert.deepStrictEqual(nodesToNames(grid2.getViews()), ['view1']);
|
||||
});
|
||||
|
||||
test('deserialize simple layout', function () {
|
||||
const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new SerializableGrid(view1);
|
||||
const view1 = store.add(new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new SerializableGrid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, 200, view1, Direction.Up);
|
||||
|
||||
const view3 = new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, 200, view1, Direction.Right);
|
||||
|
||||
const view4 = new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, 200, view2, Direction.Left);
|
||||
|
||||
const view5 = new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view5 = store.add(new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view5, 100, view1, Direction.Down);
|
||||
|
||||
const json = grid.serialize();
|
||||
grid.dispose();
|
||||
|
||||
const deserializer = new TestViewDeserializer();
|
||||
const grid2 = SerializableGrid.deserialize(json, deserializer);
|
||||
const deserializer = new TestViewDeserializer(store);
|
||||
const grid2 = store.add(SerializableGrid.deserialize(json, deserializer));
|
||||
|
||||
const view1Copy = deserializer.getView('view1');
|
||||
const view2Copy = deserializer.getView('view2');
|
||||
@@ -657,29 +664,29 @@ suite('SerializableGrid', function () {
|
||||
});
|
||||
|
||||
test('deserialize simple layout with scaling', function () {
|
||||
const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new SerializableGrid(view1);
|
||||
const view1 = store.add(new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new SerializableGrid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, 200, view1, Direction.Up);
|
||||
|
||||
const view3 = new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, 200, view1, Direction.Right);
|
||||
|
||||
const view4 = new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, 200, view2, Direction.Left);
|
||||
|
||||
const view5 = new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view5 = store.add(new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view5, 100, view1, Direction.Down);
|
||||
|
||||
const json = grid.serialize();
|
||||
grid.dispose();
|
||||
|
||||
const deserializer = new TestViewDeserializer();
|
||||
const grid2 = SerializableGrid.deserialize(json, deserializer);
|
||||
const deserializer = new TestViewDeserializer(store);
|
||||
const grid2 = store.add(SerializableGrid.deserialize(json, deserializer));
|
||||
|
||||
const view1Copy = deserializer.getView('view1');
|
||||
const view2Copy = deserializer.getView('view2');
|
||||
@@ -696,25 +703,25 @@ suite('SerializableGrid', function () {
|
||||
});
|
||||
|
||||
test('deserialize 4 view layout (ben issue #2)', function () {
|
||||
const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new SerializableGrid(view1);
|
||||
const view1 = store.add(new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new SerializableGrid(view1));
|
||||
container.appendChild(grid.element);
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Split, view1, Direction.Down);
|
||||
|
||||
const view3 = new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Split, view2, Direction.Down);
|
||||
|
||||
const view4 = new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, Sizing.Split, view3, Direction.Right);
|
||||
|
||||
const json = grid.serialize();
|
||||
grid.dispose();
|
||||
|
||||
const deserializer = new TestViewDeserializer();
|
||||
const grid2 = SerializableGrid.deserialize(json, deserializer);
|
||||
const deserializer = new TestViewDeserializer(store);
|
||||
const grid2 = store.add(SerializableGrid.deserialize(json, deserializer));
|
||||
|
||||
const view1Copy = deserializer.getView('view1');
|
||||
const view2Copy = deserializer.getView('view2');
|
||||
@@ -730,20 +737,20 @@ suite('SerializableGrid', function () {
|
||||
});
|
||||
|
||||
test('deserialize 2 view layout (ben issue #3)', function () {
|
||||
const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new SerializableGrid(view1);
|
||||
const view1 = store.add(new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new SerializableGrid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Split, view1, Direction.Right);
|
||||
|
||||
const json = grid.serialize();
|
||||
grid.dispose();
|
||||
|
||||
const deserializer = new TestViewDeserializer();
|
||||
const grid2 = SerializableGrid.deserialize(json, deserializer);
|
||||
const deserializer = new TestViewDeserializer(store);
|
||||
const grid2 = store.add(SerializableGrid.deserialize(json, deserializer));
|
||||
|
||||
const view1Copy = deserializer.getView('view1');
|
||||
const view2Copy = deserializer.getView('view2');
|
||||
@@ -755,16 +762,16 @@ suite('SerializableGrid', function () {
|
||||
});
|
||||
|
||||
test('deserialize simple view layout #50609', function () {
|
||||
const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new SerializableGrid(view1);
|
||||
const view1 = store.add(new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new SerializableGrid(view1));
|
||||
container.appendChild(grid.element);
|
||||
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, Sizing.Split, view1, Direction.Right);
|
||||
|
||||
const view3 = new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, Sizing.Split, view2, Direction.Down);
|
||||
|
||||
grid.removeView(view1, Sizing.Split);
|
||||
@@ -772,8 +779,8 @@ suite('SerializableGrid', function () {
|
||||
const json = grid.serialize();
|
||||
grid.dispose();
|
||||
|
||||
const deserializer = new TestViewDeserializer();
|
||||
const grid2 = SerializableGrid.deserialize(json, deserializer);
|
||||
const deserializer = new TestViewDeserializer(store);
|
||||
const grid2 = store.add(SerializableGrid.deserialize(json, deserializer));
|
||||
|
||||
const view2Copy = deserializer.getView('view2');
|
||||
const view3Copy = deserializer.getView('view3');
|
||||
@@ -835,7 +842,7 @@ suite('SerializableGrid', function () {
|
||||
}
|
||||
};
|
||||
|
||||
const grid = SerializableGrid.deserialize(serializedGrid, deserializer);
|
||||
const grid = store.add(SerializableGrid.deserialize(serializedGrid, deserializer));
|
||||
assert.strictEqual(views.length, 3);
|
||||
|
||||
// should not throw
|
||||
@@ -867,21 +874,21 @@ suite('SerializableGrid', function () {
|
||||
});
|
||||
|
||||
test('serialize should store visibility and previous size', function () {
|
||||
const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new SerializableGrid(view1);
|
||||
const view1 = store.add(new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new SerializableGrid(view1));
|
||||
container.appendChild(grid.element);
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, 200, view1, Direction.Up);
|
||||
|
||||
const view3 = new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, 200, view1, Direction.Right);
|
||||
|
||||
const view4 = new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, 200, view2, Direction.Left);
|
||||
|
||||
const view5 = new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view5 = store.add(new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view5, 100, view1, Direction.Down);
|
||||
|
||||
assert.deepStrictEqual(view1.size, [600, 300]);
|
||||
@@ -954,8 +961,8 @@ suite('SerializableGrid', function () {
|
||||
|
||||
grid.dispose();
|
||||
|
||||
const deserializer = new TestViewDeserializer();
|
||||
const grid2 = SerializableGrid.deserialize(json, deserializer);
|
||||
const deserializer = new TestViewDeserializer(store);
|
||||
const grid2 = store.add(SerializableGrid.deserialize(json, deserializer));
|
||||
|
||||
const view1Copy = deserializer.getView('view1');
|
||||
const view2Copy = deserializer.getView('view2');
|
||||
@@ -994,21 +1001,21 @@ suite('SerializableGrid', function () {
|
||||
});
|
||||
|
||||
test('serialize should store visibility and previous size even for first leaf', function () {
|
||||
const view1 = new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const grid = new SerializableGrid(view1);
|
||||
const view1 = store.add(new TestSerializableView('view1', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
const grid = store.add(new SerializableGrid(view1));
|
||||
container.appendChild(grid.element);
|
||||
grid.layout(800, 600);
|
||||
|
||||
const view2 = new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view2 = store.add(new TestSerializableView('view2', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view2, 200, view1, Direction.Up);
|
||||
|
||||
const view3 = new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view3 = store.add(new TestSerializableView('view3', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view3, 200, view1, Direction.Right);
|
||||
|
||||
const view4 = new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view4 = store.add(new TestSerializableView('view4', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view4, 200, view2, Direction.Left);
|
||||
|
||||
const view5 = new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE);
|
||||
const view5 = store.add(new TestSerializableView('view5', 50, Number.MAX_VALUE, 50, Number.MAX_VALUE));
|
||||
grid.addView(view5, 100, view1, Direction.Down);
|
||||
|
||||
assert.deepStrictEqual(view1.size, [600, 300]);
|
||||
@@ -1063,8 +1070,8 @@ suite('SerializableGrid', function () {
|
||||
|
||||
grid.dispose();
|
||||
|
||||
const deserializer = new TestViewDeserializer();
|
||||
const grid2 = SerializableGrid.deserialize(json, deserializer);
|
||||
const deserializer = new TestViewDeserializer(store);
|
||||
const grid2 = store.add(SerializableGrid.deserialize(json, deserializer));
|
||||
|
||||
const view1Copy = deserializer.getView('view1');
|
||||
const view2Copy = deserializer.getView('view2');
|
||||
|
||||
@@ -7,36 +7,41 @@ import * as assert from 'assert';
|
||||
import { $ } from 'vs/base/browser/dom';
|
||||
import { GridView, IView, Orientation, Sizing } from 'vs/base/browser/ui/grid/gridview';
|
||||
import { nodesToArrays, TestView } from './util';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
suite('Gridview', function () {
|
||||
let gridview: GridView;
|
||||
|
||||
setup(function () {
|
||||
gridview = new GridView();
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
function createGridView(): GridView {
|
||||
const gridview = store.add(new GridView());
|
||||
const container = $('.container');
|
||||
|
||||
container.style.position = 'absolute';
|
||||
container.style.width = `${200}px`;
|
||||
container.style.height = `${200}px`;
|
||||
container.appendChild(gridview.element);
|
||||
});
|
||||
|
||||
return gridview;
|
||||
}
|
||||
|
||||
test('empty gridview is empty', function () {
|
||||
const gridview = createGridView();
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), []);
|
||||
gridview.dispose();
|
||||
});
|
||||
|
||||
test('gridview addView', function () {
|
||||
const gridview = createGridView();
|
||||
|
||||
const view = new TestView(20, 20, 20, 20);
|
||||
const view = store.add(new TestView(20, 20, 20, 20));
|
||||
assert.throws(() => gridview.addView(view, 200, []), 'empty location');
|
||||
assert.throws(() => gridview.addView(view, 200, [1]), 'index overflow');
|
||||
assert.throws(() => gridview.addView(view, 200, [0, 0]), 'hierarchy overflow');
|
||||
|
||||
const views = [
|
||||
new TestView(20, 20, 20, 20),
|
||||
new TestView(20, 20, 20, 20),
|
||||
new TestView(20, 20, 20, 20)
|
||||
store.add(new TestView(20, 20, 20, 20)),
|
||||
store.add(new TestView(20, 20, 20, 20)),
|
||||
store.add(new TestView(20, 20, 20, 20))
|
||||
];
|
||||
|
||||
gridview.addView(views[0], 200, [0]);
|
||||
@@ -44,17 +49,16 @@ suite('Gridview', function () {
|
||||
gridview.addView(views[2], 200, [2]);
|
||||
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), views);
|
||||
|
||||
gridview.dispose();
|
||||
});
|
||||
|
||||
test('gridview addView nested', function () {
|
||||
const gridview = createGridView();
|
||||
|
||||
const views = [
|
||||
new TestView(20, 20, 20, 20),
|
||||
store.add(new TestView(20, 20, 20, 20)),
|
||||
[
|
||||
new TestView(20, 20, 20, 20),
|
||||
new TestView(20, 20, 20, 20)
|
||||
store.add(new TestView(20, 20, 20, 20)),
|
||||
store.add(new TestView(20, 20, 20, 20))
|
||||
]
|
||||
];
|
||||
|
||||
@@ -63,63 +67,61 @@ suite('Gridview', function () {
|
||||
gridview.addView((views[1] as TestView[])[1] as IView, 200, [1, 1]);
|
||||
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), views);
|
||||
|
||||
gridview.dispose();
|
||||
});
|
||||
|
||||
test('gridview addView deep nested', function () {
|
||||
const gridview = createGridView();
|
||||
|
||||
const view1 = new TestView(20, 20, 20, 20);
|
||||
const view1 = store.add(new TestView(20, 20, 20, 20));
|
||||
gridview.addView(view1 as IView, 200, [0]);
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), [view1]);
|
||||
|
||||
const view2 = new TestView(20, 20, 20, 20);
|
||||
const view2 = store.add(new TestView(20, 20, 20, 20));
|
||||
gridview.addView(view2 as IView, 200, [1]);
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), [view1, view2]);
|
||||
|
||||
const view3 = new TestView(20, 20, 20, 20);
|
||||
const view3 = store.add(new TestView(20, 20, 20, 20));
|
||||
gridview.addView(view3 as IView, 200, [1, 0]);
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), [view1, [view3, view2]]);
|
||||
|
||||
const view4 = new TestView(20, 20, 20, 20);
|
||||
const view4 = store.add(new TestView(20, 20, 20, 20));
|
||||
gridview.addView(view4 as IView, 200, [1, 0, 0]);
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), [view1, [[view4, view3], view2]]);
|
||||
|
||||
const view5 = new TestView(20, 20, 20, 20);
|
||||
const view5 = store.add(new TestView(20, 20, 20, 20));
|
||||
gridview.addView(view5 as IView, 200, [1, 0]);
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), [view1, [view5, [view4, view3], view2]]);
|
||||
|
||||
const view6 = new TestView(20, 20, 20, 20);
|
||||
const view6 = store.add(new TestView(20, 20, 20, 20));
|
||||
gridview.addView(view6 as IView, 200, [2]);
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), [view1, [view5, [view4, view3], view2], view6]);
|
||||
|
||||
const view7 = new TestView(20, 20, 20, 20);
|
||||
const view7 = store.add(new TestView(20, 20, 20, 20));
|
||||
gridview.addView(view7 as IView, 200, [1, 1]);
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), [view1, [view5, view7, [view4, view3], view2], view6]);
|
||||
|
||||
const view8 = new TestView(20, 20, 20, 20);
|
||||
const view8 = store.add(new TestView(20, 20, 20, 20));
|
||||
gridview.addView(view8 as IView, 200, [1, 1, 0]);
|
||||
assert.deepStrictEqual(nodesToArrays(gridview.getView()), [view1, [view5, [view8, view7], [view4, view3], view2], view6]);
|
||||
|
||||
gridview.dispose();
|
||||
});
|
||||
|
||||
test('simple layout', function () {
|
||||
const gridview = createGridView();
|
||||
gridview.layout(800, 600);
|
||||
|
||||
const view1 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view1 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view1, 200, [0]);
|
||||
assert.deepStrictEqual(view1.size, [800, 600]);
|
||||
assert.deepStrictEqual(gridview.getViewSize([0]), { width: 800, height: 600 });
|
||||
|
||||
const view2 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view2 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view2, 200, [0]);
|
||||
assert.deepStrictEqual(view1.size, [800, 400]);
|
||||
assert.deepStrictEqual(gridview.getViewSize([1]), { width: 800, height: 400 });
|
||||
assert.deepStrictEqual(view2.size, [800, 200]);
|
||||
assert.deepStrictEqual(gridview.getViewSize([0]), { width: 800, height: 200 });
|
||||
|
||||
const view3 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view3 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view3, 200, [1, 1]);
|
||||
assert.deepStrictEqual(view1.size, [600, 400]);
|
||||
assert.deepStrictEqual(gridview.getViewSize([1, 0]), { width: 600, height: 400 });
|
||||
@@ -128,7 +130,7 @@ suite('Gridview', function () {
|
||||
assert.deepStrictEqual(view3.size, [200, 400]);
|
||||
assert.deepStrictEqual(gridview.getViewSize([1, 1]), { width: 200, height: 400 });
|
||||
|
||||
const view4 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view4 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view4, 200, [0, 0]);
|
||||
assert.deepStrictEqual(view1.size, [600, 400]);
|
||||
assert.deepStrictEqual(gridview.getViewSize([1, 0]), { width: 600, height: 400 });
|
||||
@@ -139,7 +141,7 @@ suite('Gridview', function () {
|
||||
assert.deepStrictEqual(view4.size, [200, 200]);
|
||||
assert.deepStrictEqual(gridview.getViewSize([0, 0]), { width: 200, height: 200 });
|
||||
|
||||
const view5 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view5 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view5, 100, [1, 0, 1]);
|
||||
assert.deepStrictEqual(view1.size, [600, 300]);
|
||||
assert.deepStrictEqual(gridview.getViewSize([1, 0, 0]), { width: 600, height: 300 });
|
||||
@@ -154,32 +156,33 @@ suite('Gridview', function () {
|
||||
});
|
||||
|
||||
test('simple layout with automatic size distribution', function () {
|
||||
const gridview = createGridView();
|
||||
gridview.layout(800, 600);
|
||||
|
||||
const view1 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view1 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view1, Sizing.Distribute, [0]);
|
||||
assert.deepStrictEqual(view1.size, [800, 600]);
|
||||
assert.deepStrictEqual(gridview.getViewSize([0]), { width: 800, height: 600 });
|
||||
|
||||
const view2 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view2 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view2, Sizing.Distribute, [0]);
|
||||
assert.deepStrictEqual(view1.size, [800, 300]);
|
||||
assert.deepStrictEqual(view2.size, [800, 300]);
|
||||
|
||||
const view3 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view3 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view3, Sizing.Distribute, [1, 1]);
|
||||
assert.deepStrictEqual(view1.size, [400, 300]);
|
||||
assert.deepStrictEqual(view2.size, [800, 300]);
|
||||
assert.deepStrictEqual(view3.size, [400, 300]);
|
||||
|
||||
const view4 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view4 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view4, Sizing.Distribute, [0, 0]);
|
||||
assert.deepStrictEqual(view1.size, [400, 300]);
|
||||
assert.deepStrictEqual(view2.size, [400, 300]);
|
||||
assert.deepStrictEqual(view3.size, [400, 300]);
|
||||
assert.deepStrictEqual(view4.size, [400, 300]);
|
||||
|
||||
const view5 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view5 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view5, Sizing.Distribute, [1, 0, 1]);
|
||||
assert.deepStrictEqual(view1.size, [400, 150]);
|
||||
assert.deepStrictEqual(view2.size, [400, 300]);
|
||||
@@ -189,14 +192,15 @@ suite('Gridview', function () {
|
||||
});
|
||||
|
||||
test('addviews before layout call 1', function () {
|
||||
const gridview = createGridView();
|
||||
|
||||
const view1 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view1 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view1, 200, [0]);
|
||||
|
||||
const view2 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view2 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view2, 200, [0]);
|
||||
|
||||
const view3 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view3 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view3, 200, [1, 1]);
|
||||
|
||||
gridview.layout(800, 600);
|
||||
@@ -207,13 +211,14 @@ suite('Gridview', function () {
|
||||
});
|
||||
|
||||
test('addviews before layout call 2', function () {
|
||||
const view1 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const gridview = createGridView();
|
||||
const view1 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view1, 200, [0]);
|
||||
|
||||
const view2 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view2 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view2, 200, [0]);
|
||||
|
||||
const view3 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view3 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view3, 200, [0, 0]);
|
||||
|
||||
gridview.layout(800, 600);
|
||||
@@ -224,10 +229,11 @@ suite('Gridview', function () {
|
||||
});
|
||||
|
||||
test('flipping orientation should preserve absolute offsets', function () {
|
||||
const view1 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const gridview = createGridView();
|
||||
const view1 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view1, 200, [0]);
|
||||
|
||||
const view2 = new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY);
|
||||
const view2 = store.add(new TestView(50, Number.POSITIVE_INFINITY, 50, Number.POSITIVE_INFINITY));
|
||||
gridview.addView(view2, 200, [1]);
|
||||
|
||||
gridview.layout(800, 600, 100, 200);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user