mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 09:08:48 +01:00
Merge branch 'main' into joh/intense-heron
This commit is contained in:
@@ -21,8 +21,8 @@ jobs:
|
||||
uses: ./actions/locker
|
||||
with:
|
||||
daysSinceClose: 45
|
||||
appInsightsKey: ${{secrets.TRIAGE_ACTIONS_APP_INSIGHTS}}
|
||||
daysSinceUpdate: 3
|
||||
ignoredLabel: "*out-of-scope,accessibility"
|
||||
ignoreLabelUntil: "author-verification-requested"
|
||||
ignoredMilestones: "Backlog Candidates"
|
||||
labelUntil: "verified"
|
||||
|
||||
@@ -135,13 +135,22 @@ steps:
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
AZURE_STORAGE_ACCOUNT="ticino" \
|
||||
AZURE_STORAGE_ACCOUNT="vscodeweb" \
|
||||
AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
|
||||
AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
|
||||
AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \
|
||||
node build/azure-pipelines/upload-sourcemaps
|
||||
displayName: Upload sourcemaps to Azure
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
AZURE_STORAGE_ACCOUNT="ticino" \
|
||||
AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
|
||||
AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
|
||||
AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \
|
||||
node build/azure-pipelines/upload-sourcemaps
|
||||
displayName: Upload sourcemaps to Azure (Deprecated)
|
||||
|
||||
- script: ./build/azure-pipelines/common/extract-telemetry.sh
|
||||
displayName: Generate lists of telemetry events
|
||||
|
||||
|
||||
@@ -129,6 +129,15 @@ steps:
|
||||
node build/azure-pipelines/upload-cdn
|
||||
displayName: Upload to CDN
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
AZURE_STORAGE_ACCOUNT="vscodeweb" \
|
||||
AZURE_TENANT_ID="$(AZURE_TENANT_ID)" \
|
||||
AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
|
||||
AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \
|
||||
node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.main.js.map
|
||||
displayName: Upload sourcemaps (Web)
|
||||
|
||||
# upload only the workbench.web.main.js source maps because
|
||||
# we just compiled these bits in the previous step and the
|
||||
# general task to upload source maps has already been run
|
||||
@@ -139,7 +148,7 @@ steps:
|
||||
AZURE_CLIENT_ID="$(AZURE_CLIENT_ID)" \
|
||||
AZURE_CLIENT_SECRET="$(AZURE_CLIENT_SECRET)" \
|
||||
node build/azure-pipelines/upload-sourcemaps out-vscode-web-min out-vscode-web-min/vs/workbench/workbench.web.main.js.map
|
||||
displayName: Upload sourcemaps (Web)
|
||||
displayName: Upload sourcemaps (Deprecated)
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
|
||||
@@ -71,7 +71,7 @@ const compilations = [
|
||||
'.vscode/extensions/vscode-selfhost-test-provider/tsconfig.json',
|
||||
];
|
||||
|
||||
const getBaseUrl = out => `https://ticino.blob.core.windows.net/sourcemaps/${commit}/${out}`;
|
||||
const getBaseUrl = out => `https://main.vscode-cdn.net/sourcemaps/${commit}/${out}`;
|
||||
|
||||
const tasks = compilations.map(function (tsconfigFile) {
|
||||
const absolutePath = path.join(root, tsconfigFile);
|
||||
|
||||
@@ -439,7 +439,7 @@ function tweakProductForServerWeb(product) {
|
||||
const minifyTask = task.define(`minify-vscode-${type}`, task.series(
|
||||
optimizeTask,
|
||||
util.rimraf(`out-vscode-${type}-min`),
|
||||
optimize.minifyTask(`out-vscode-${type}`, `https://ticino.blob.core.windows.net/sourcemaps/${commit}/core`)
|
||||
optimize.minifyTask(`out-vscode-${type}`, `https://main.vscode-cdn.net/sourcemaps/${commit}/core`)
|
||||
));
|
||||
gulp.task(minifyTask);
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ const optimizeVSCodeTask = task.define('optimize-vscode', task.series(
|
||||
));
|
||||
gulp.task(optimizeVSCodeTask);
|
||||
|
||||
const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`;
|
||||
const sourceMappingURLBase = `https://main.vscode-cdn.net/sourcemaps/${commit}`;
|
||||
const minifyVSCodeTask = task.define('minify-vscode', task.series(
|
||||
optimizeVSCodeTask,
|
||||
util.rimraf('out-vscode-min'),
|
||||
|
||||
@@ -175,7 +175,7 @@ const optimizeVSCodeWebTask = task.define('optimize-vscode-web', task.series(
|
||||
const minifyVSCodeWebTask = task.define('minify-vscode-web', task.series(
|
||||
optimizeVSCodeWebTask,
|
||||
util.rimraf('out-vscode-web-min'),
|
||||
optimize.minifyTask('out-vscode-web', `https://ticino.blob.core.windows.net/sourcemaps/${commit}/core`)
|
||||
optimize.minifyTask('out-vscode-web', `https://main.vscode-cdn.net/sourcemaps/${commit}/core`)
|
||||
));
|
||||
gulp.task(minifyVSCodeWebTask);
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ const getVersion_1 = require("./getVersion");
|
||||
const fetch_1 = require("./fetch");
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
const commit = (0, getVersion_1.getVersion)(root);
|
||||
const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`;
|
||||
const sourceMappingURLBase = `https://main.vscode-cdn.net/sourcemaps/${commit}`;
|
||||
function minifyExtensionResources(input) {
|
||||
const jsonFilter = filter(['**/*.json', '**/*.code-snippets'], { restore: true });
|
||||
return input
|
||||
|
||||
@@ -28,7 +28,7 @@ import { fetchUrls, fetchGithub } from './fetch';
|
||||
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
const commit = getVersion(root);
|
||||
const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`;
|
||||
const sourceMappingURLBase = `https://main.vscode-cdn.net/sourcemaps/${commit}`;
|
||||
|
||||
function minifyExtensionResources(input: Stream): Stream {
|
||||
const jsonFilter = filter(['**/*.json', '**/*.code-snippets'], { restore: true });
|
||||
|
||||
@@ -3401,7 +3401,7 @@
|
||||
"@vscode/iconv-lite-umd": "0.7.0",
|
||||
"byline": "^5.0.0",
|
||||
"file-type": "16.5.4",
|
||||
"jschardet": "3.0.0",
|
||||
"jschardet": "3.1.2",
|
||||
"picomatch": "2.3.1",
|
||||
"vscode-uri": "^2.0.0",
|
||||
"which": "4.0.0"
|
||||
|
||||
@@ -182,10 +182,10 @@ isexe@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d"
|
||||
integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==
|
||||
|
||||
jschardet@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882"
|
||||
integrity sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==
|
||||
jschardet@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.1.2.tgz#9bf4364deba0677fe9e3bd9e29eda57febf2e9db"
|
||||
integrity sha512-mw3CBZGzW8nUBPYhFU2ztZ/kJ6NClQUQVpyzvFMfznZsoC///ZQ30J2RCUanNsr5yF22LqhgYr/lj807/ZleWA==
|
||||
|
||||
peek-readable@^4.1.0:
|
||||
version "4.1.0"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"license": "MIT",
|
||||
"description": "Dependencies shared by all extensions",
|
||||
"dependencies": {
|
||||
"typescript": "5.4.5"
|
||||
"typescript": "^5.5.0-dev.20240603"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "node ./postinstall.mjs"
|
||||
|
||||
-1
@@ -191,7 +191,6 @@ export default class FileConfigurationManager extends Disposable {
|
||||
includeCompletionsWithClassMemberSnippets: config.get<boolean>('suggest.classMemberSnippets.enabled', true),
|
||||
includeCompletionsWithObjectLiteralMethodSnippets: config.get<boolean>('suggest.objectLiteralMethodSnippets.enabled', true),
|
||||
autoImportFileExcludePatterns: this.getAutoImportFileExcludePatternsPreference(preferencesConfig, vscode.workspace.getWorkspaceFolder(document.uri)?.uri),
|
||||
// @ts-expect-error until 5.3 #56090
|
||||
preferTypeOnlyAutoImports: preferencesConfig.get<boolean>('preferTypeOnlyAutoImports', false),
|
||||
useLabelDetailsInCompletionEntries: true,
|
||||
allowIncompleteCompletions: true,
|
||||
|
||||
@@ -19,70 +19,5 @@ declare module '../../../../node_modules/typescript/lib/typescript' {
|
||||
interface Response {
|
||||
readonly _serverType?: ServerType;
|
||||
}
|
||||
|
||||
//#region MapCode
|
||||
export interface MapCodeRequestArgs extends FileRequestArgs {
|
||||
/**
|
||||
* The files and changes to try and apply/map.
|
||||
*/
|
||||
mapping: MapCodeRequestDocumentMapping;
|
||||
}
|
||||
|
||||
export interface MapCodeRequestDocumentMapping {
|
||||
/**
|
||||
* The specific code to map/insert/replace in the file.
|
||||
*/
|
||||
contents: string[];
|
||||
|
||||
/**
|
||||
* Areas of "focus" to inform the code mapper with. For example, cursor
|
||||
* location, current selection, viewport, etc. Nested arrays denote
|
||||
* priority: toplevel arrays are more important than inner arrays, and
|
||||
* inner array priorities are based on items within that array. Items
|
||||
* earlier in the arrays have higher priority.
|
||||
*/
|
||||
focusLocations?: TextSpan[][];
|
||||
}
|
||||
|
||||
export interface MapCodeRequest extends FileRequest {
|
||||
command: 'mapCode';
|
||||
arguments: MapCodeRequestArgs;
|
||||
}
|
||||
|
||||
export interface MapCodeResponse extends Response {
|
||||
body: FileCodeEdits[]
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Paste
|
||||
export interface GetPasteEditsRequest extends Request {
|
||||
command: 'getPasteEdits';
|
||||
arguments: GetPasteEditsRequestArgs;
|
||||
}
|
||||
|
||||
export interface GetPasteEditsRequestArgs extends FileRequestArgs {
|
||||
/** The text that gets pasted in a file. */
|
||||
pastedText: string[];
|
||||
/** Locations of where the `pastedText` gets added in a file. If the length of the `pastedText` and `pastedLocations` are not the same,
|
||||
* then the `pastedText` is combined into one and added at all the `pastedLocations`.
|
||||
*/
|
||||
pasteLocations: TextSpan[];
|
||||
/** The source location of each `pastedText`. If present, the length of `spans` must be equal to the length of `pastedText`. */
|
||||
copiedFrom?: {
|
||||
file: string;
|
||||
spans: TextSpan[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface GetPasteEditsResponse extends Response {
|
||||
body: PasteEditsAction;
|
||||
}
|
||||
export interface PasteEditsAction {
|
||||
edits: FileCodeEdits[];
|
||||
fixId?: {};
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -234,10 +234,10 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
typescript@5.4.5:
|
||||
version "5.4.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611"
|
||||
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
|
||||
typescript@^5.5.0-dev.20240603:
|
||||
version "5.5.0-dev.20240603"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.0-dev.20240603.tgz#a1b7311df5039a8abbaaa2213c21cac6ec547490"
|
||||
integrity sha512-gdm3Sh1A+Pjj9ZlfBEJY3o2rs3tvpcSbu3vYqcCijMe09BePQBtZlsuShuPn+zCnP+qBLxdKjFiw5v1tkna3tA==
|
||||
|
||||
vscode-grammar-updater@^1.1.0:
|
||||
version "1.1.0"
|
||||
|
||||
+9
-9
@@ -82,17 +82,17 @@
|
||||
"@vscode/windows-mutex": "^0.5.0",
|
||||
"@vscode/windows-process-tree": "^0.6.0",
|
||||
"@vscode/windows-registry": "^1.1.0",
|
||||
"@xterm/addon-image": "0.9.0-beta.17",
|
||||
"@xterm/addon-search": "0.16.0-beta.17",
|
||||
"@xterm/addon-serialize": "0.14.0-beta.17",
|
||||
"@xterm/addon-unicode11": "0.9.0-beta.17",
|
||||
"@xterm/addon-webgl": "0.19.0-beta.17",
|
||||
"@xterm/headless": "5.6.0-beta.17",
|
||||
"@xterm/xterm": "5.6.0-beta.17",
|
||||
"@xterm/addon-image": "0.9.0-beta.19",
|
||||
"@xterm/addon-search": "0.16.0-beta.19",
|
||||
"@xterm/addon-serialize": "0.14.0-beta.19",
|
||||
"@xterm/addon-unicode11": "0.9.0-beta.19",
|
||||
"@xterm/addon-webgl": "0.19.0-beta.19",
|
||||
"@xterm/headless": "5.6.0-beta.19",
|
||||
"@xterm/xterm": "5.6.0-beta.19",
|
||||
"graceful-fs": "4.2.11",
|
||||
"http-proxy-agent": "^7.0.0",
|
||||
"https-proxy-agent": "^7.0.2",
|
||||
"jschardet": "3.0.0",
|
||||
"jschardet": "3.1.2",
|
||||
"kerberos": "^2.0.1",
|
||||
"minimist": "^1.2.6",
|
||||
"native-is-elevated": "0.7.0",
|
||||
@@ -208,7 +208,7 @@
|
||||
"ts-loader": "^9.4.2",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsec": "0.2.7",
|
||||
"typescript": "^5.5.0-dev.20240521",
|
||||
"typescript": "^5.5.0-dev.20240603",
|
||||
"util": "^0.12.4",
|
||||
"vscode-nls-dev": "^3.3.1",
|
||||
"webpack": "^5.91.0",
|
||||
|
||||
+8
-8
@@ -14,18 +14,18 @@
|
||||
"@vscode/vscode-languagedetection": "1.0.21",
|
||||
"@vscode/windows-process-tree": "^0.6.0",
|
||||
"@vscode/windows-registry": "^1.1.0",
|
||||
"@xterm/addon-image": "0.9.0-beta.17",
|
||||
"@xterm/addon-search": "0.16.0-beta.17",
|
||||
"@xterm/addon-serialize": "0.14.0-beta.17",
|
||||
"@xterm/addon-unicode11": "0.9.0-beta.17",
|
||||
"@xterm/addon-webgl": "0.19.0-beta.17",
|
||||
"@xterm/headless": "5.6.0-beta.17",
|
||||
"@xterm/xterm": "5.6.0-beta.17",
|
||||
"@xterm/addon-image": "0.9.0-beta.19",
|
||||
"@xterm/addon-search": "0.16.0-beta.19",
|
||||
"@xterm/addon-serialize": "0.14.0-beta.19",
|
||||
"@xterm/addon-unicode11": "0.9.0-beta.19",
|
||||
"@xterm/addon-webgl": "0.19.0-beta.19",
|
||||
"@xterm/headless": "5.6.0-beta.19",
|
||||
"@xterm/xterm": "5.6.0-beta.19",
|
||||
"cookie": "^0.4.0",
|
||||
"graceful-fs": "4.2.11",
|
||||
"http-proxy-agent": "^7.0.0",
|
||||
"https-proxy-agent": "^7.0.2",
|
||||
"jschardet": "3.0.0",
|
||||
"jschardet": "3.1.2",
|
||||
"kerberos": "^2.0.1",
|
||||
"minimist": "^1.2.6",
|
||||
"native-watchdog": "^1.4.1",
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
"@microsoft/1ds-post-js": "^3.2.13",
|
||||
"@vscode/iconv-lite-umd": "0.7.0",
|
||||
"@vscode/vscode-languagedetection": "1.0.21",
|
||||
"@xterm/addon-image": "0.9.0-beta.17",
|
||||
"@xterm/addon-search": "0.16.0-beta.17",
|
||||
"@xterm/addon-serialize": "0.14.0-beta.17",
|
||||
"@xterm/addon-unicode11": "0.9.0-beta.17",
|
||||
"@xterm/addon-webgl": "0.19.0-beta.17",
|
||||
"@xterm/xterm": "5.6.0-beta.17",
|
||||
"jschardet": "3.0.0",
|
||||
"@xterm/addon-image": "0.9.0-beta.19",
|
||||
"@xterm/addon-search": "0.16.0-beta.19",
|
||||
"@xterm/addon-serialize": "0.14.0-beta.19",
|
||||
"@xterm/addon-unicode11": "0.9.0-beta.19",
|
||||
"@xterm/addon-webgl": "0.19.0-beta.19",
|
||||
"@xterm/xterm": "5.6.0-beta.19",
|
||||
"jschardet": "3.1.2",
|
||||
"tas-client-umd": "0.2.0",
|
||||
"vscode-oniguruma": "1.7.0",
|
||||
"vscode-textmate": "9.0.0"
|
||||
|
||||
+28
-28
@@ -48,40 +48,40 @@
|
||||
resolved "https://registry.yarnpkg.com/@vscode/vscode-languagedetection/-/vscode-languagedetection-1.0.21.tgz#89b48f293f6aa3341bb888c1118d16ff13b032d3"
|
||||
integrity sha512-zSUH9HYCw5qsCtd7b31yqkpaCU6jhtkKLkvOOA8yTrIRfBSOFb8PPhgmMicD7B/m+t4PwOJXzU1XDtrM9Fd3/g==
|
||||
|
||||
"@xterm/addon-image@0.9.0-beta.17":
|
||||
version "0.9.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.9.0-beta.17.tgz#343d0665a6060d4f893b4f2d32de6ccbbd00bb63"
|
||||
integrity sha512-g0r2hpBcLABY5as4llsMP36RHtkWooEn7tf+7U0/hTndJoCAvs4uGDqZNQigFgeAM3lJ4PnRYh4lfnEh9bGt8A==
|
||||
"@xterm/addon-image@0.9.0-beta.19":
|
||||
version "0.9.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.9.0-beta.19.tgz#3823382e5c55268998f0e0d8d77e8b7810925830"
|
||||
integrity sha512-LX9g03po3mXYE/HZFoKbdnIRvdD56Qw84FpQ9LCJGDsyx9SFIf47DXLS+lXCEpJ2hjKIing46BQxP+MDEayXDw==
|
||||
|
||||
"@xterm/addon-search@0.16.0-beta.17":
|
||||
version "0.16.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-search/-/addon-search-0.16.0-beta.17.tgz#7cb01c7f498405909d37040884ee22d1889a36d2"
|
||||
integrity sha512-wBfxmWOeqG6HHHE5mVamDJ75zBdHC35ERNy5/aTpQsQsyxrnV0Ks76c8ZVTaTu9wyBCAyx7UmZT42Ot80khY/g==
|
||||
"@xterm/addon-search@0.16.0-beta.19":
|
||||
version "0.16.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-search/-/addon-search-0.16.0-beta.19.tgz#46b3374eb312a1bff974a5df188b1ebf777ff49d"
|
||||
integrity sha512-iTJVUEsKSdL8SyhcDBqN6gYxhqv0wrwtP1QCUGLKNAAVDI7HKVgig3V9wToqRxYfOnu/anyU+u0qFUoKCRLnCg==
|
||||
|
||||
"@xterm/addon-serialize@0.14.0-beta.17":
|
||||
version "0.14.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.17.tgz#1cb8e35c0d118060a807adb340624fa7f80dd9c5"
|
||||
integrity sha512-/c3W39kdRgGGYDoYjXb5HrUC421qwPn6NryAT4WJuJWnyMtFbe2DPwKsTfHuCBPiPyovS3a9j950Md3O3YXDZA==
|
||||
"@xterm/addon-serialize@0.14.0-beta.19":
|
||||
version "0.14.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.19.tgz#c7a0a0e5f5b1bd94a35a775ec6224ba42282556c"
|
||||
integrity sha512-D+BiXQfuxDb3azAIBq1RJTQGZlvo459V6U/2s/3dKpTAvRybqCRMazuf8cLoffUoNcjTb3uSWpii9+MVVvHIrQ==
|
||||
|
||||
"@xterm/addon-unicode11@0.9.0-beta.17":
|
||||
version "0.9.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.17.tgz#b5558148029a796c6a6d78e2a8b7255f92a51530"
|
||||
integrity sha512-z7v8uojFVrO1aLSWtnz5MzSrfWRT8phde7kh9ufqHLBv7YYtMHxlPVjSuW8PZ2h4eY1LOZf6icUAzrmyJmJ7Kg==
|
||||
"@xterm/addon-unicode11@0.9.0-beta.19":
|
||||
version "0.9.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.19.tgz#529d8b22d9378cff8c31df1b7e76250b2f8079c3"
|
||||
integrity sha512-0Umiu9GkjwL/jaT85Rcfka9HVyJw3UhJsnOVOVZd/3YBZqMY2SZMHqz73W/qpXl5nz6vvyCWKbpkfddsJhpToA==
|
||||
|
||||
"@xterm/addon-webgl@0.19.0-beta.17":
|
||||
version "0.19.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.17.tgz#68ad9e68dd1cf581b391971de33f5c04966b0d8e"
|
||||
integrity sha512-X8ObRgoZl7UZTgdndM+mpSO3hLzAhWKoXXrGvUQg/7XabRKAPrQ2XvdyZm04nYwibE6Tpit2h5kkxjlVqupIig==
|
||||
"@xterm/addon-webgl@0.19.0-beta.19":
|
||||
version "0.19.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.19.tgz#655d1e27b1249c19352c65a8ea1d0bf319397b35"
|
||||
integrity sha512-Y5efISx8X5hpFAsPOTza1Fp0xiD8x+l3MuH+mv68v1El8tpna/MW5EM4oX25qYOsPDZY00mpmkBmPbAT5loMEg==
|
||||
|
||||
"@xterm/xterm@5.6.0-beta.17":
|
||||
version "5.6.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/xterm/-/xterm-5.6.0-beta.17.tgz#67ce2e2ff45bd6cc9f26d455d5522c6c4a122ed9"
|
||||
integrity sha512-+wAv8PhaGQSN9yXWIa8EFtT33pbrA4lZakMB1P05fr+DQ7zoH66QOAUoDY95uOf/4+S6Ihz8wzP2+FH8zETQEA==
|
||||
"@xterm/xterm@5.6.0-beta.19":
|
||||
version "5.6.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/xterm/-/xterm-5.6.0-beta.19.tgz#2cc292fc93b25c7c655ed6d1f0425a636b36747d"
|
||||
integrity sha512-mGoJxrUxAL4dueZEqw2e23KCrGNSvYaw5twTnccKqK7lITK/hDrosWCxb1jL1AjFf7bBzMxw9/dZdhWncKQQmw==
|
||||
|
||||
jschardet@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882"
|
||||
integrity sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==
|
||||
jschardet@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.1.2.tgz#9bf4364deba0677fe9e3bd9e29eda57febf2e9db"
|
||||
integrity sha512-mw3CBZGzW8nUBPYhFU2ztZ/kJ6NClQUQVpyzvFMfznZsoC///ZQ30J2RCUanNsr5yF22LqhgYr/lj807/ZleWA==
|
||||
|
||||
tas-client-umd@0.2.0:
|
||||
version "0.2.0"
|
||||
|
||||
+32
-32
@@ -122,40 +122,40 @@
|
||||
resolved "https://registry.yarnpkg.com/@vscode/windows-registry/-/windows-registry-1.1.0.tgz#03dace7c29c46f658588b9885b9580e453ad21f9"
|
||||
integrity sha512-5AZzuWJpGscyiMOed0IuyEwt6iKmV5Us7zuwCDCFYMIq7tsvooO9BUiciywsvuthGz6UG4LSpeDeCxvgMVhnIw==
|
||||
|
||||
"@xterm/addon-image@0.9.0-beta.17":
|
||||
version "0.9.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.9.0-beta.17.tgz#343d0665a6060d4f893b4f2d32de6ccbbd00bb63"
|
||||
integrity sha512-g0r2hpBcLABY5as4llsMP36RHtkWooEn7tf+7U0/hTndJoCAvs4uGDqZNQigFgeAM3lJ4PnRYh4lfnEh9bGt8A==
|
||||
"@xterm/addon-image@0.9.0-beta.19":
|
||||
version "0.9.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.9.0-beta.19.tgz#3823382e5c55268998f0e0d8d77e8b7810925830"
|
||||
integrity sha512-LX9g03po3mXYE/HZFoKbdnIRvdD56Qw84FpQ9LCJGDsyx9SFIf47DXLS+lXCEpJ2hjKIing46BQxP+MDEayXDw==
|
||||
|
||||
"@xterm/addon-search@0.16.0-beta.17":
|
||||
version "0.16.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-search/-/addon-search-0.16.0-beta.17.tgz#7cb01c7f498405909d37040884ee22d1889a36d2"
|
||||
integrity sha512-wBfxmWOeqG6HHHE5mVamDJ75zBdHC35ERNy5/aTpQsQsyxrnV0Ks76c8ZVTaTu9wyBCAyx7UmZT42Ot80khY/g==
|
||||
"@xterm/addon-search@0.16.0-beta.19":
|
||||
version "0.16.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-search/-/addon-search-0.16.0-beta.19.tgz#46b3374eb312a1bff974a5df188b1ebf777ff49d"
|
||||
integrity sha512-iTJVUEsKSdL8SyhcDBqN6gYxhqv0wrwtP1QCUGLKNAAVDI7HKVgig3V9wToqRxYfOnu/anyU+u0qFUoKCRLnCg==
|
||||
|
||||
"@xterm/addon-serialize@0.14.0-beta.17":
|
||||
version "0.14.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.17.tgz#1cb8e35c0d118060a807adb340624fa7f80dd9c5"
|
||||
integrity sha512-/c3W39kdRgGGYDoYjXb5HrUC421qwPn6NryAT4WJuJWnyMtFbe2DPwKsTfHuCBPiPyovS3a9j950Md3O3YXDZA==
|
||||
"@xterm/addon-serialize@0.14.0-beta.19":
|
||||
version "0.14.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.19.tgz#c7a0a0e5f5b1bd94a35a775ec6224ba42282556c"
|
||||
integrity sha512-D+BiXQfuxDb3azAIBq1RJTQGZlvo459V6U/2s/3dKpTAvRybqCRMazuf8cLoffUoNcjTb3uSWpii9+MVVvHIrQ==
|
||||
|
||||
"@xterm/addon-unicode11@0.9.0-beta.17":
|
||||
version "0.9.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.17.tgz#b5558148029a796c6a6d78e2a8b7255f92a51530"
|
||||
integrity sha512-z7v8uojFVrO1aLSWtnz5MzSrfWRT8phde7kh9ufqHLBv7YYtMHxlPVjSuW8PZ2h4eY1LOZf6icUAzrmyJmJ7Kg==
|
||||
"@xterm/addon-unicode11@0.9.0-beta.19":
|
||||
version "0.9.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.19.tgz#529d8b22d9378cff8c31df1b7e76250b2f8079c3"
|
||||
integrity sha512-0Umiu9GkjwL/jaT85Rcfka9HVyJw3UhJsnOVOVZd/3YBZqMY2SZMHqz73W/qpXl5nz6vvyCWKbpkfddsJhpToA==
|
||||
|
||||
"@xterm/addon-webgl@0.19.0-beta.17":
|
||||
version "0.19.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.17.tgz#68ad9e68dd1cf581b391971de33f5c04966b0d8e"
|
||||
integrity sha512-X8ObRgoZl7UZTgdndM+mpSO3hLzAhWKoXXrGvUQg/7XabRKAPrQ2XvdyZm04nYwibE6Tpit2h5kkxjlVqupIig==
|
||||
"@xterm/addon-webgl@0.19.0-beta.19":
|
||||
version "0.19.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.19.tgz#655d1e27b1249c19352c65a8ea1d0bf319397b35"
|
||||
integrity sha512-Y5efISx8X5hpFAsPOTza1Fp0xiD8x+l3MuH+mv68v1El8tpna/MW5EM4oX25qYOsPDZY00mpmkBmPbAT5loMEg==
|
||||
|
||||
"@xterm/headless@5.6.0-beta.17":
|
||||
version "5.6.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/headless/-/headless-5.6.0-beta.17.tgz#bff1d67c9c061c57adff22571e733d54e3aba2b7"
|
||||
integrity sha512-ehS7y/XRqX1ppx4RPiYc0vu0SdIQ91aA4lSN/2XNOf3IGdP0A38Q7a0T6mzqxRGZKiiyA0kTR1szr78wnY+wmA==
|
||||
"@xterm/headless@5.6.0-beta.19":
|
||||
version "5.6.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/headless/-/headless-5.6.0-beta.19.tgz#dbbd4dd420e24e9bdee6e533153f405bfc1ba89b"
|
||||
integrity sha512-zFTcftonaaMEbMqfQnFwos1YQCmqWnvIzSNXwmfIymkEvSxhsB03oynEjFwm48dT2filTcJXpYT91io4qvR+3g==
|
||||
|
||||
"@xterm/xterm@5.6.0-beta.17":
|
||||
version "5.6.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/xterm/-/xterm-5.6.0-beta.17.tgz#67ce2e2ff45bd6cc9f26d455d5522c6c4a122ed9"
|
||||
integrity sha512-+wAv8PhaGQSN9yXWIa8EFtT33pbrA4lZakMB1P05fr+DQ7zoH66QOAUoDY95uOf/4+S6Ihz8wzP2+FH8zETQEA==
|
||||
"@xterm/xterm@5.6.0-beta.19":
|
||||
version "5.6.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/xterm/-/xterm-5.6.0-beta.19.tgz#2cc292fc93b25c7c655ed6d1f0425a636b36747d"
|
||||
integrity sha512-mGoJxrUxAL4dueZEqw2e23KCrGNSvYaw5twTnccKqK7lITK/hDrosWCxb1jL1AjFf7bBzMxw9/dZdhWncKQQmw==
|
||||
|
||||
agent-base@^7.0.1, agent-base@^7.0.2, agent-base@^7.1.0:
|
||||
version "7.1.0"
|
||||
@@ -347,10 +347,10 @@ is-number@^7.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
jschardet@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882"
|
||||
integrity sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==
|
||||
jschardet@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.1.2.tgz#9bf4364deba0677fe9e3bd9e29eda57febf2e9db"
|
||||
integrity sha512-mw3CBZGzW8nUBPYhFU2ztZ/kJ6NClQUQVpyzvFMfznZsoC///ZQ30J2RCUanNsr5yF22LqhgYr/lj807/ZleWA==
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.1.0"
|
||||
|
||||
@@ -18,6 +18,7 @@ import * as platform from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
import { CodeWindow, ensureCodeWindow, mainWindow } from 'vs/base/browser/window';
|
||||
import { isPointWithinTriangle } from 'vs/base/common/numbers';
|
||||
|
||||
export interface IRegisteredCodeWindow {
|
||||
readonly window: CodeWindow;
|
||||
@@ -2408,3 +2409,53 @@ export function trackAttributes(from: Element, to: Element, filter?: string[]):
|
||||
|
||||
return disposables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for calculating the "safe triangle" occluded by hovers to avoid early dismissal.
|
||||
* @see https://www.smashingmagazine.com/2023/08/better-context-menus-safe-triangles/ for example
|
||||
*/
|
||||
export class SafeTriangle {
|
||||
// 4 triangles, 2 points (x, y) stored for each
|
||||
private triangles: number[] = [];
|
||||
|
||||
constructor(
|
||||
private readonly originX: number,
|
||||
private readonly originY: number,
|
||||
target: HTMLElement
|
||||
) {
|
||||
const { top, left, right, bottom } = target.getBoundingClientRect();
|
||||
const t = this.triangles;
|
||||
let i = 0;
|
||||
|
||||
t[i++] = left;
|
||||
t[i++] = top;
|
||||
t[i++] = right;
|
||||
t[i++] = top;
|
||||
|
||||
t[i++] = left;
|
||||
t[i++] = top;
|
||||
t[i++] = left;
|
||||
t[i++] = bottom;
|
||||
|
||||
t[i++] = right;
|
||||
t[i++] = top;
|
||||
t[i++] = right;
|
||||
t[i++] = bottom;
|
||||
|
||||
t[i++] = left;
|
||||
t[i++] = bottom;
|
||||
t[i++] = right;
|
||||
t[i++] = bottom;
|
||||
}
|
||||
|
||||
public contains(x: number, y: number) {
|
||||
const { triangles, originX, originY } = this;
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (isPointWithinTriangle(x, y, originX, originY, triangles[2 * i], triangles[2 * i + 1], triangles[2 * i + 2], triangles[2 * i + 3])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,9 +44,10 @@ export namespace Iterable {
|
||||
return iterable[Symbol.iterator]().next().value;
|
||||
}
|
||||
|
||||
export function some<T>(iterable: Iterable<T>, predicate: (t: T) => unknown): boolean {
|
||||
export function some<T>(iterable: Iterable<T>, predicate: (t: T, i: number) => unknown): boolean {
|
||||
let i = 0;
|
||||
for (const element of iterable) {
|
||||
if (predicate(element)) {
|
||||
if (predicate(element, i++)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,3 +69,30 @@ export class SlidingWindowAverage {
|
||||
return this._val;
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns whether the point is within the triangle formed by the following 6 x/y point pairs */
|
||||
export function isPointWithinTriangle(
|
||||
x: number, y: number,
|
||||
ax: number, ay: number,
|
||||
bx: number, by: number,
|
||||
cx: number, cy: number
|
||||
) {
|
||||
const v0x = cx - ax;
|
||||
const v0y = cy - ay;
|
||||
const v1x = bx - ax;
|
||||
const v1y = by - ay;
|
||||
const v2x = x - ax;
|
||||
const v2y = y - ay;
|
||||
|
||||
const dot00 = v0x * v0x + v0y * v0y;
|
||||
const dot01 = v0x * v1x + v0y * v1y;
|
||||
const dot02 = v0x * v2x + v0y * v2y;
|
||||
const dot11 = v1x * v1x + v1y * v1y;
|
||||
const dot12 = v1x * v2x + v1y * v2y;
|
||||
|
||||
const invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
|
||||
const u = (dot11 * dot02 - dot01 * dot12) * invDenom;
|
||||
const v = (dot00 * dot12 - dot01 * dot02) * invDenom;
|
||||
|
||||
return u >= 0 && v >= 0 && u + v < 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { isPointWithinTriangle } from 'vs/base/common/numbers';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
|
||||
|
||||
suite('isPointWithinTriangle', () => {
|
||||
ensureNoDisposablesAreLeakedInTestSuite();
|
||||
|
||||
test('should return true if the point is within the triangle', () => {
|
||||
const result = isPointWithinTriangle(0.25, 0.25, 0, 0, 1, 0, 0, 1);
|
||||
assert.ok(result);
|
||||
});
|
||||
|
||||
test('should return false if the point is outside the triangle', () => {
|
||||
const result = isPointWithinTriangle(2, 2, 0, 0, 1, 0, 0, 1);
|
||||
assert.ok(!result);
|
||||
});
|
||||
|
||||
test('should return true if the point is on the edge of the triangle', () => {
|
||||
const result = isPointWithinTriangle(0.5, 0, 0, 0, 1, 0, 0, 1);
|
||||
assert.ok(result);
|
||||
});
|
||||
});
|
||||
@@ -123,5 +123,5 @@ function detectLanguageId(modelService: IModelService, languageService: ILanguag
|
||||
}
|
||||
|
||||
function cssEscape(str: string): string {
|
||||
return str.replace(/[\11\12\14\15\40]/g, '/'); // HTML class names can not contain certain whitespace characters, use / instead, which doesn't exist in file names.
|
||||
return str.replace(/[\x11\x12\x14\x15\x40]/g, '/'); // HTML class names can not contain certain whitespace characters, use / instead, which doesn't exist in file names.
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
||||
private readonly _sessionStore: DisposableStore = new DisposableStore();
|
||||
|
||||
private _widgetState: StickyScrollWidgetState;
|
||||
private _foldingModel: FoldingModel | null = null;
|
||||
private _foldingModel: FoldingModel | undefined;
|
||||
private _maxStickyLines: number = Number.MAX_SAFE_INTEGER;
|
||||
|
||||
private _stickyRangeProjectedOnEditor: IRange | undefined;
|
||||
@@ -67,7 +67,7 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
||||
private _positionRevealed = false;
|
||||
private _onMouseDown = false;
|
||||
private _endLineNumbers: number[] = [];
|
||||
private _showEndForLine: number | null = null;
|
||||
private _showEndForLine: number | undefined;
|
||||
|
||||
constructor(
|
||||
private readonly _editor: ICodeEditor,
|
||||
@@ -84,7 +84,7 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
||||
this._register(this._stickyScrollWidget);
|
||||
this._register(this._stickyLineCandidateProvider);
|
||||
|
||||
this._widgetState = new StickyScrollWidgetState([], [], 0);
|
||||
this._widgetState = StickyScrollWidgetState.Empty;
|
||||
this._onDidResize();
|
||||
this._readConfiguration();
|
||||
const stickyScrollDomNode = this._stickyScrollWidget.getDomNode();
|
||||
@@ -291,14 +291,14 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
||||
this._renderStickyScroll();
|
||||
return;
|
||||
}
|
||||
if (this._showEndForLine !== null) {
|
||||
this._showEndForLine = null;
|
||||
if (this._showEndForLine !== undefined) {
|
||||
this._showEndForLine = undefined;
|
||||
this._renderStickyScroll();
|
||||
}
|
||||
}));
|
||||
this._register(dom.addDisposableListener(stickyScrollWidgetDomNode, dom.EventType.MOUSE_LEAVE, (e) => {
|
||||
if (this._showEndForLine !== null) {
|
||||
this._showEndForLine = null;
|
||||
if (this._showEndForLine !== undefined) {
|
||||
this._showEndForLine = undefined;
|
||||
this._renderStickyScroll();
|
||||
}
|
||||
}));
|
||||
@@ -415,14 +415,14 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
||||
this._editor.addOverlayWidget(this._stickyScrollWidget);
|
||||
this._sessionStore.add(this._editor.onDidScrollChange((e) => {
|
||||
if (e.scrollTopChanged) {
|
||||
this._showEndForLine = null;
|
||||
this._showEndForLine = undefined;
|
||||
this._renderStickyScroll();
|
||||
}
|
||||
}));
|
||||
this._sessionStore.add(this._editor.onDidLayoutChange(() => this._onDidResize()));
|
||||
this._sessionStore.add(this._editor.onDidChangeModelTokens((e) => this._onTokensChange(e)));
|
||||
this._sessionStore.add(this._stickyLineCandidateProvider.onDidChangeStickyScroll(() => {
|
||||
this._showEndForLine = null;
|
||||
this._showEndForLine = undefined;
|
||||
this._renderStickyScroll();
|
||||
}));
|
||||
this._enabled = true;
|
||||
@@ -431,7 +431,7 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
||||
const lineNumberOption = this._editor.getOption(EditorOption.lineNumbers);
|
||||
if (lineNumberOption.renderType === RenderLineNumbersType.Relative) {
|
||||
this._sessionStore.add(this._editor.onDidChangeCursorPosition(() => {
|
||||
this._showEndForLine = null;
|
||||
this._showEndForLine = undefined;
|
||||
this._renderStickyScroll(0);
|
||||
}));
|
||||
}
|
||||
@@ -479,32 +479,28 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
||||
this._maxStickyLines = Math.round(theoreticalLines * .25);
|
||||
}
|
||||
|
||||
private async _renderStickyScroll(rebuildFromLine?: number) {
|
||||
private async _renderStickyScroll(rebuildFromLine?: number): Promise<void> {
|
||||
const model = this._editor.getModel();
|
||||
if (!model || model.isTooLargeForTokenization()) {
|
||||
this._foldingModel = null;
|
||||
this._stickyScrollWidget.setState(undefined, null);
|
||||
this._resetState();
|
||||
return;
|
||||
}
|
||||
const stickyLineVersion = this._stickyLineCandidateProvider.getVersionId();
|
||||
if (stickyLineVersion === undefined || stickyLineVersion === model.getVersionId()) {
|
||||
this._foldingModel = await FoldingController.get(this._editor)?.getFoldingModel() ?? null;
|
||||
this._widgetState = this.findScrollWidgetState();
|
||||
this._stickyScrollVisibleContextKey.set(!(this._widgetState.startLineNumbers.length === 0));
|
||||
|
||||
const stickyWidgetVersion = this._stickyLineCandidateProvider.getVersionId();
|
||||
const shouldUpdateState = stickyWidgetVersion === undefined || stickyWidgetVersion === model.getVersionId();
|
||||
if (shouldUpdateState) {
|
||||
if (!this._focused) {
|
||||
this._stickyScrollWidget.setState(this._widgetState, this._foldingModel, rebuildFromLine);
|
||||
await this._updateState(rebuildFromLine);
|
||||
} else {
|
||||
// Suppose that previously the sticky scroll widget had height 0, then if there are visible lines, set the last line as focused
|
||||
if (this._focusedStickyElementIndex === -1) {
|
||||
this._stickyScrollWidget.setState(this._widgetState, this._foldingModel, rebuildFromLine);
|
||||
await this._updateState(rebuildFromLine);
|
||||
this._focusedStickyElementIndex = this._stickyScrollWidget.lineNumberCount - 1;
|
||||
if (this._focusedStickyElementIndex !== -1) {
|
||||
this._stickyScrollWidget.focusLineWithIndex(this._focusedStickyElementIndex);
|
||||
}
|
||||
} else {
|
||||
const focusedStickyElementLineNumber = this._stickyScrollWidget.lineNumbers[this._focusedStickyElementIndex];
|
||||
this._stickyScrollWidget.setState(this._widgetState, this._foldingModel, rebuildFromLine);
|
||||
await this._updateState(rebuildFromLine);
|
||||
// Suppose that after setting the state, there are no sticky lines, set the focused index to -1
|
||||
if (this._stickyScrollWidget.lineNumberCount === 0) {
|
||||
this._focusedStickyElementIndex = -1;
|
||||
@@ -522,6 +518,20 @@ export class StickyScrollController extends Disposable implements IEditorContrib
|
||||
}
|
||||
}
|
||||
}
|
||||
private async _updateState(rebuildFromLine?: number): Promise<void> {
|
||||
this._foldingModel = await FoldingController.get(this._editor)?.getFoldingModel() ?? undefined;
|
||||
this._widgetState = this.findScrollWidgetState();
|
||||
const stickyWidgetHasLines = this._widgetState.startLineNumbers.length > 0;
|
||||
this._stickyScrollVisibleContextKey.set(stickyWidgetHasLines);
|
||||
this._stickyScrollWidget.setState(this._widgetState, this._foldingModel, rebuildFromLine);
|
||||
}
|
||||
|
||||
private async _resetState(): Promise<void> {
|
||||
this._foldingModel = undefined;
|
||||
this._widgetState = StickyScrollWidgetState.Empty;
|
||||
this._stickyScrollVisibleContextKey.set(false);
|
||||
this._stickyScrollWidget.setState(undefined, undefined);
|
||||
}
|
||||
|
||||
findScrollWidgetState(): StickyScrollWidgetState {
|
||||
const lineHeight: number = this._editor.getOption(EditorOption.lineHeight);
|
||||
|
||||
@@ -35,6 +35,10 @@ export class StickyScrollWidgetState {
|
||||
&& equals(this.startLineNumbers, other.startLineNumbers)
|
||||
&& equals(this.endLineNumbers, other.endLineNumbers);
|
||||
}
|
||||
|
||||
static get Empty() {
|
||||
return new StickyScrollWidgetState([], [], 0);
|
||||
}
|
||||
}
|
||||
|
||||
const _ttPolicy = createTrustedTypesPolicy('stickyScrollViewLayer', { createHTML: value => value });
|
||||
@@ -126,7 +130,7 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
||||
return this._lineNumbers;
|
||||
}
|
||||
|
||||
setState(_state: StickyScrollWidgetState | undefined, foldingModel: FoldingModel | null, _rebuildFromLine?: number): void {
|
||||
setState(_state: StickyScrollWidgetState | undefined, foldingModel: FoldingModel | undefined, _rebuildFromLine?: number): void {
|
||||
if (_rebuildFromLine === undefined &&
|
||||
((!this._previousState && !_state) || (this._previousState && this._previousState.equals(_state)))
|
||||
) {
|
||||
@@ -205,7 +209,7 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
||||
}
|
||||
}
|
||||
|
||||
private async _renderRootNode(state: StickyScrollWidgetState | undefined, foldingModel: FoldingModel | null, rebuildFromLine: number): Promise<void> {
|
||||
private async _renderRootNode(state: StickyScrollWidgetState | undefined, foldingModel: FoldingModel | undefined, rebuildFromLine: number): Promise<void> {
|
||||
this._clearStickyLinesFromLine(rebuildFromLine);
|
||||
if (!state) {
|
||||
return;
|
||||
@@ -258,7 +262,7 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
||||
}));
|
||||
}
|
||||
|
||||
private _renderChildNode(index: number, line: number, foldingModel: FoldingModel | null, layoutInfo: EditorLayoutInfo): RenderedStickyLine | undefined {
|
||||
private _renderChildNode(index: number, line: number, foldingModel: FoldingModel | undefined, layoutInfo: EditorLayoutInfo): RenderedStickyLine | undefined {
|
||||
const viewModel = this._editor._getViewModel();
|
||||
if (!viewModel) {
|
||||
return;
|
||||
@@ -358,7 +362,7 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
|
||||
return stickyLine;
|
||||
}
|
||||
|
||||
private _renderFoldingIconForLine(foldingModel: FoldingModel | null, line: number): StickyFoldingIcon | undefined {
|
||||
private _renderFoldingIconForLine(foldingModel: FoldingModel | undefined, line: number): StickyFoldingIcon | undefined {
|
||||
const showFoldingControls: 'mouseover' | 'always' | 'never' = this._editor.getOption(EditorOption.showFoldingControls);
|
||||
if (!foldingModel || showFoldingControls === 'never') {
|
||||
return;
|
||||
|
||||
Vendored
+5
-5
@@ -5003,8 +5003,8 @@ declare namespace monaco.editor {
|
||||
screenReaderAnnounceInlineSuggestion: IEditorOption<EditorOption.screenReaderAnnounceInlineSuggestion, boolean>;
|
||||
autoClosingBrackets: IEditorOption<EditorOption.autoClosingBrackets, 'always' | 'languageDefined' | 'beforeWhitespace' | 'never'>;
|
||||
autoClosingComments: IEditorOption<EditorOption.autoClosingComments, 'always' | 'languageDefined' | 'beforeWhitespace' | 'never'>;
|
||||
autoClosingDelete: IEditorOption<EditorOption.autoClosingDelete, 'always' | 'never' | 'auto'>;
|
||||
autoClosingOvertype: IEditorOption<EditorOption.autoClosingOvertype, 'always' | 'never' | 'auto'>;
|
||||
autoClosingDelete: IEditorOption<EditorOption.autoClosingDelete, 'auto' | 'always' | 'never'>;
|
||||
autoClosingOvertype: IEditorOption<EditorOption.autoClosingOvertype, 'auto' | 'always' | 'never'>;
|
||||
autoClosingQuotes: IEditorOption<EditorOption.autoClosingQuotes, 'always' | 'languageDefined' | 'beforeWhitespace' | 'never'>;
|
||||
autoIndent: IEditorOption<EditorOption.autoIndent, EditorAutoIndentStrategy>;
|
||||
automaticLayout: IEditorOption<EditorOption.automaticLayout, boolean>;
|
||||
@@ -5016,7 +5016,7 @@ declare namespace monaco.editor {
|
||||
codeLensFontFamily: IEditorOption<EditorOption.codeLensFontFamily, string>;
|
||||
codeLensFontSize: IEditorOption<EditorOption.codeLensFontSize, number>;
|
||||
colorDecorators: IEditorOption<EditorOption.colorDecorators, boolean>;
|
||||
colorDecoratorActivatedOn: IEditorOption<EditorOption.colorDecoratorsActivatedOn, 'clickAndHover' | 'click' | 'hover'>;
|
||||
colorDecoratorActivatedOn: IEditorOption<EditorOption.colorDecoratorsActivatedOn, 'hover' | 'clickAndHover' | 'click'>;
|
||||
colorDecoratorsLimit: IEditorOption<EditorOption.colorDecoratorsLimit, number>;
|
||||
columnSelection: IEditorOption<EditorOption.columnSelection, boolean>;
|
||||
comments: IEditorOption<EditorOption.comments, Readonly<Required<IEditorCommentsOptions>>>;
|
||||
@@ -5124,13 +5124,13 @@ declare namespace monaco.editor {
|
||||
tabCompletion: IEditorOption<EditorOption.tabCompletion, 'on' | 'off' | 'onlySnippets'>;
|
||||
tabIndex: IEditorOption<EditorOption.tabIndex, number>;
|
||||
unicodeHighlight: IEditorOption<EditorOption.unicodeHighlighting, any>;
|
||||
unusualLineTerminators: IEditorOption<EditorOption.unusualLineTerminators, 'auto' | 'off' | 'prompt'>;
|
||||
unusualLineTerminators: IEditorOption<EditorOption.unusualLineTerminators, 'off' | 'auto' | 'prompt'>;
|
||||
useShadowDOM: IEditorOption<EditorOption.useShadowDOM, boolean>;
|
||||
useTabStops: IEditorOption<EditorOption.useTabStops, boolean>;
|
||||
wordBreak: IEditorOption<EditorOption.wordBreak, 'normal' | 'keepAll'>;
|
||||
wordSegmenterLocales: IEditorOption<EditorOption.wordSegmenterLocales, {}>;
|
||||
wordSeparators: IEditorOption<EditorOption.wordSeparators, string>;
|
||||
wordWrap: IEditorOption<EditorOption.wordWrap, 'on' | 'off' | 'wordWrapColumn' | 'bounded'>;
|
||||
wordWrap: IEditorOption<EditorOption.wordWrap, 'wordWrapColumn' | 'on' | 'off' | 'bounded'>;
|
||||
wordWrapBreakAfterCharacters: IEditorOption<EditorOption.wordWrapBreakAfterCharacters, string>;
|
||||
wordWrapBreakBeforeCharacters: IEditorOption<EditorOption.wordWrapBreakBeforeCharacters, string>;
|
||||
wordWrapColumn: IEditorOption<EditorOption.wordWrapColumn, number>;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { OperatingSystem } from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -215,7 +215,7 @@ export class DisposableTunnel {
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractTunnelService implements ITunnelService {
|
||||
export abstract class AbstractTunnelService extends Disposable implements ITunnelService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private _onTunnelOpened: Emitter<RemoteTunnel> = new Emitter();
|
||||
@@ -234,7 +234,7 @@ export abstract class AbstractTunnelService implements ITunnelService {
|
||||
public constructor(
|
||||
@ILogService protected readonly logService: ILogService,
|
||||
@IConfigurationService protected readonly configurationService: IConfigurationService
|
||||
) { }
|
||||
) { super(); }
|
||||
|
||||
get hasTunnelProvider(): boolean {
|
||||
return !!this._tunnelProvider;
|
||||
@@ -308,7 +308,8 @@ export abstract class AbstractTunnelService implements ITunnelService {
|
||||
return tunnels;
|
||||
}
|
||||
|
||||
async dispose(): Promise<void> {
|
||||
override async dispose(): Promise<void> {
|
||||
super.dispose();
|
||||
for (const portMap of this._tunnels.values()) {
|
||||
for (const { value } of portMap.values()) {
|
||||
await value.then(tunnel => typeof tunnel !== 'string' ? tunnel?.dispose() : undefined);
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
|
||||
import { DisposableMap } from 'vs/base/common/lifecycle';
|
||||
import { revive } from 'vs/base/common/marshalling';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Location } from 'vs/editor/common/languages';
|
||||
import { ExtHostChatVariablesShape, ExtHostContext, IChatVariableResolverProgressDto, MainContext, MainThreadChatVariablesShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ChatAgentLocation } from 'vs/workbench/contrib/chat/common/chatAgents';
|
||||
import { IChatRequestVariableValue, IChatVariableData, IChatVariableResolverProgress, IChatVariablesService } from 'vs/workbench/contrib/chat/common/chatVariables';
|
||||
import { IExtHostContext, extHostNamedCustomer } from 'vs/workbench/services/extensions/common/extHostCustomers';
|
||||
|
||||
@@ -50,8 +47,4 @@ export class MainThreadChatVariables implements MainThreadChatVariablesShape {
|
||||
$unregisterVariable(handle: number): void {
|
||||
this._variables.deleteAndDispose(handle);
|
||||
}
|
||||
|
||||
$attachContext(name: string, value: string | URI | Location | unknown, location: ChatAgentLocation.Panel): void {
|
||||
this._chatVariablesService.attachContext(name, revive(value), location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1429,10 +1429,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
createDynamicChatParticipant(id: string, dynamicProps: vscode.DynamicChatParticipantProps, handler: vscode.ChatExtendedRequestHandler): vscode.ChatParticipant {
|
||||
checkProposedApiEnabled(extension, 'chatParticipantPrivate');
|
||||
return extHostChatAgents2.createDynamicChatAgent(extension, id, dynamicProps, handler);
|
||||
},
|
||||
attachContext(name: string, value: string | vscode.Uri | vscode.Location | unknown, location: vscode.ChatLocation.Panel) {
|
||||
checkProposedApiEnabled(extension, 'chatVariableResolver');
|
||||
return extHostChatVariables.attachContext(name, value, location);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IRemoteConsoleLog } from 'vs/base/common/console';
|
||||
import { Location } from 'vs/editor/common/languages';
|
||||
import { SerializedError } from 'vs/base/common/errors';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||
@@ -1291,7 +1290,6 @@ export interface MainThreadChatVariablesShape extends IDisposable {
|
||||
$registerVariable(handle: number, data: IChatVariableData): void;
|
||||
$handleProgressChunk(requestId: string, progress: IChatVariableResolverProgressDto): Promise<number | void>;
|
||||
$unregisterVariable(handle: number): void;
|
||||
$attachContext(name: string, value: string | Dto<Location> | URI | unknown, location: ChatAgentLocation): void;
|
||||
}
|
||||
|
||||
export type IChatRequestVariableValueDto = Dto<IChatRequestVariableValue>;
|
||||
|
||||
@@ -64,10 +64,6 @@ export class ExtHostChatVariables implements ExtHostChatVariablesShape {
|
||||
this._proxy.$unregisterVariable(handle);
|
||||
});
|
||||
}
|
||||
|
||||
attachContext(name: string, value: string | vscode.Location | vscode.Uri | unknown, location: vscode.ChatLocation.Panel) {
|
||||
this._proxy.$attachContext(name, extHostTypes.Location.isLocation(value) ? typeConvert.Location.from(value) : value, typeConvert.ChatLocation.from(location));
|
||||
}
|
||||
}
|
||||
|
||||
class ChatVariableResolverResponseStream {
|
||||
|
||||
@@ -171,118 +171,77 @@ const configuration: IConfigurationNode = {
|
||||
type: 'boolean',
|
||||
default: true
|
||||
},
|
||||
'accessibility.signalOptions': {
|
||||
description: 'Configures the behavior of signals (audio cues and announcements) in the workbench. Includes volume, debounce position changes, and delays for different types of signals.',
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
'volume': {
|
||||
'description': localize('accessibility.signalOptions.volume', "The volume of the sounds in percent (0-100)."),
|
||||
'accessibility.signalOptions.volume': {
|
||||
'description': localize('accessibility.signalOptions.volume', "The volume of the sounds in percent (0-100)."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'maximum': 100,
|
||||
'default': 70,
|
||||
'tags': ['accessibility']
|
||||
},
|
||||
'accessibility.signalOptions.debouncePositionChanges': {
|
||||
'description': localize('accessibility.signalOptions.debouncePositionChanges', "Whether or not position changes should be debounced"),
|
||||
'type': 'boolean',
|
||||
'default': false,
|
||||
'tags': ['accessibility']
|
||||
},
|
||||
'accessibility.signalOptions.experimental.delays.general': {
|
||||
'type': 'object',
|
||||
'description': 'Delays for all signals besides error and warning at position',
|
||||
'additionalProperties': false,
|
||||
'properties': {
|
||||
'announcement': {
|
||||
'description': localize('accessibility.signalOptions.delays.general.announcement', "The delay in milliseconds before an announcement is made."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'maximum': 100,
|
||||
'default': 70,
|
||||
'default': 3000
|
||||
},
|
||||
'debouncePositionChanges': {
|
||||
'description': localize('accessibility.signalOptions.debouncePositionChanges', "Whether or not position changes should be debounced"),
|
||||
'type': 'boolean',
|
||||
'default': false,
|
||||
},
|
||||
'experimental.delays': {
|
||||
'type': 'object',
|
||||
'additionalProperties': false,
|
||||
'properties': {
|
||||
'general': {
|
||||
'type': 'object',
|
||||
'description': 'Delays for all signals besides error and warning at position',
|
||||
'additionalProperties': false,
|
||||
'properties': {
|
||||
'announcement': {
|
||||
'description': localize('accessibility.signalOptions.delays.general.announcement', "The delay in milliseconds before an announcement is made."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 3000
|
||||
},
|
||||
'sound': {
|
||||
'description': localize('accessibility.signalOptions.delays.general.sound', "The delay in milliseconds before a sound is played."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 400
|
||||
}
|
||||
},
|
||||
},
|
||||
'warningAtPosition': {
|
||||
'type': 'object',
|
||||
'additionalProperties': false,
|
||||
'properties': {
|
||||
'announcement': {
|
||||
'description': localize('accessibility.signalOptions.delays.warningAtPosition.announcement', "The delay in milliseconds before an announcement is made when there's a warning at the position."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 3000
|
||||
},
|
||||
'sound': {
|
||||
'description': localize('accessibility.signalOptions.delays.warningAtPosition.sound', "The delay in milliseconds before a sound is played when there's a warning at the position."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 1000
|
||||
}
|
||||
},
|
||||
},
|
||||
'errorAtPosition': {
|
||||
'type': 'object',
|
||||
'additionalProperties': false,
|
||||
'properties': {
|
||||
'announcement': {
|
||||
'description': localize('accessibility.signalOptions.delays.errorAtPosition.announcement', "The delay in milliseconds before an announcement is made when there's an error at the position."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 3000
|
||||
},
|
||||
'sound': {
|
||||
'description': localize('accessibility.signalOptions.delays.errorAtPosition.sound', "The delay in milliseconds before a sound is played when there's an error at the position."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 1000
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
'default': {
|
||||
'general': {
|
||||
'announcement': 3000,
|
||||
'sound': 400
|
||||
},
|
||||
'warningAtPosition': {
|
||||
'announcement': 3000,
|
||||
'sound': 1000
|
||||
},
|
||||
'errorAtPosition': {
|
||||
'announcement': 3000,
|
||||
'sound': 1000
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
'default': {
|
||||
'volume': 70,
|
||||
'debouncePositionChanges': false,
|
||||
'delays': {
|
||||
'general': {
|
||||
'announcement': 3000,
|
||||
'sound': 400
|
||||
},
|
||||
'warningAtPosition': {
|
||||
'announcement': 3000,
|
||||
'sound': 1000
|
||||
},
|
||||
'errorAtPosition': {
|
||||
'announcement': 3000,
|
||||
'sound': 1000
|
||||
}
|
||||
'sound': {
|
||||
'description': localize('accessibility.signalOptions.delays.general.sound', "The delay in milliseconds before a sound is played."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 400
|
||||
}
|
||||
},
|
||||
tags: ['accessibility']
|
||||
'tags': ['accessibility']
|
||||
},
|
||||
'accessibility.signalOptions.experimental.delays.warningAtPosition': {
|
||||
'type': 'object',
|
||||
'additionalProperties': false,
|
||||
'properties': {
|
||||
'announcement': {
|
||||
'description': localize('accessibility.signalOptions.delays.warningAtPosition.announcement', "The delay in milliseconds before an announcement is made when there's a warning at the position."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 3000
|
||||
},
|
||||
'sound': {
|
||||
'description': localize('accessibility.signalOptions.delays.warningAtPosition.sound', "The delay in milliseconds before a sound is played when there's a warning at the position."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 1000
|
||||
}
|
||||
},
|
||||
'tags': ['accessibility']
|
||||
},
|
||||
'accessibility.signalOptions.experimental.delays.errorAtPosition': {
|
||||
'type': 'object',
|
||||
'additionalProperties': false,
|
||||
'properties': {
|
||||
'announcement': {
|
||||
'description': localize('accessibility.signalOptions.delays.errorAtPosition.announcement', "The delay in milliseconds before an announcement is made when there's an error at the position."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 3000
|
||||
},
|
||||
'sound': {
|
||||
'description': localize('accessibility.signalOptions.delays.errorAtPosition.sound', "The delay in milliseconds before a sound is played when there's an error at the position."),
|
||||
'type': 'number',
|
||||
'minimum': 0,
|
||||
'default': 1000
|
||||
}
|
||||
},
|
||||
'tags': ['accessibility']
|
||||
},
|
||||
'accessibility.signals.lineHasBreakpoint': {
|
||||
...signalFeatureBase,
|
||||
@@ -804,10 +763,9 @@ export class DynamicSpeechAccessibilityConfiguration extends Disposable implemen
|
||||
Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMigration)
|
||||
.registerConfigurationMigrations([{
|
||||
key: 'audioCues.volume',
|
||||
migrateFn: (volume, accessor) => {
|
||||
const debouncePositionChanges = getDebouncePositionChangesFromConfig(accessor);
|
||||
migrateFn: (value, accessor) => {
|
||||
return [
|
||||
['accessibility.signalOptions', { value: debouncePositionChanges !== undefined ? { volume, debouncePositionChanges } : { volume } }],
|
||||
['accessibility.signalOptions.volume', { value }],
|
||||
['audioCues.volume', { value: undefined }]
|
||||
];
|
||||
}
|
||||
@@ -816,10 +774,9 @@ Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMi
|
||||
Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMigration)
|
||||
.registerConfigurationMigrations([{
|
||||
key: 'audioCues.debouncePositionChanges',
|
||||
migrateFn: (debouncePositionChanges, accessor) => {
|
||||
const volume = getVolumeFromConfig(accessor);
|
||||
migrateFn: (value) => {
|
||||
return [
|
||||
['accessibility.signalOptions', { value: volume !== undefined ? { volume, debouncePositionChanges } : { debouncePositionChanges } }],
|
||||
['accessibility.signalOptions.debouncePositionChanges', { value }],
|
||||
['audioCues.debouncePositionChanges', { value: undefined }]
|
||||
];
|
||||
}
|
||||
@@ -829,12 +786,18 @@ Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMi
|
||||
.registerConfigurationMigrations([{
|
||||
key: 'accessibility.signalOptions',
|
||||
migrateFn: (value, accessor) => {
|
||||
const delays = value.delays;
|
||||
if (!delays) {
|
||||
return [];
|
||||
}
|
||||
const delayGeneral = getDelaysFromConfig(accessor, 'general');
|
||||
const delayError = getDelaysFromConfig(accessor, 'errorAtPosition');
|
||||
const delayWarning = getDelaysFromConfig(accessor, 'warningAtPosition');
|
||||
const volume = getVolumeFromConfig(accessor);
|
||||
const debouncePositionChanges = getDebouncePositionChangesFromConfig(accessor);
|
||||
return [
|
||||
['accessibility.signalOptions', { value: { ...value, 'experimental.delays': delays, 'delays': undefined } }],
|
||||
['accessibility.signalOptions.volume', { value: volume }],
|
||||
['accessibility.signalOptions.debouncePositionChanges', { value: debouncePositionChanges }],
|
||||
['accessibility.signalOptions.experimental.delays.general', { value: delayGeneral }],
|
||||
['accessibility.signalOptions.experimental.delays.errorAtPosition', { value: delayError }],
|
||||
['accessibility.signalOptions.experimental.delays.warningAtPosition', { value: delayWarning }],
|
||||
['accessibility.signalOptions', { value: undefined }],
|
||||
];
|
||||
}
|
||||
}]);
|
||||
@@ -843,10 +806,9 @@ Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMi
|
||||
Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMigration)
|
||||
.registerConfigurationMigrations([{
|
||||
key: 'accessibility.signals.sounds.volume',
|
||||
migrateFn: (volume, accessor) => {
|
||||
const debouncePositionChanges = getDebouncePositionChangesFromConfig(accessor);
|
||||
migrateFn: (value) => {
|
||||
return [
|
||||
['accessibility.signalOptions', { value: debouncePositionChanges !== undefined ? { volume, debouncePositionChanges } : { volume } }],
|
||||
['accessibility.signalOptions.volume', { value }],
|
||||
['accessibility.signals.sounds.volume', { value: undefined }]
|
||||
];
|
||||
}
|
||||
@@ -855,21 +817,24 @@ Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMi
|
||||
Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMigration)
|
||||
.registerConfigurationMigrations([{
|
||||
key: 'accessibility.signals.debouncePositionChanges',
|
||||
migrateFn: (debouncePositionChanges, accessor) => {
|
||||
const volume = getVolumeFromConfig(accessor);
|
||||
migrateFn: (value) => {
|
||||
return [
|
||||
['accessibility.signalOptions', { value: volume !== undefined ? { volume, debouncePositionChanges } : { debouncePositionChanges } }],
|
||||
['accessibility.signalOptions.debouncePositionChanges', { value }],
|
||||
['accessibility.signals.debouncePositionChanges', { value: undefined }]
|
||||
];
|
||||
}
|
||||
}]);
|
||||
|
||||
function getDelaysFromConfig(accessor: (key: string) => any, type: 'general' | 'errorAtPosition' | 'warningAtPosition'): { announcement: number; sound: number } | undefined {
|
||||
return accessor(`accessibility.signalOptions.experimental.delays.${type}`) || accessor('accessibility.signalOptions')?.['experimental.delays']?.[`${type}`] || accessor('accessibility.signalOptions')?.['delays']?.[`${type}`];
|
||||
}
|
||||
|
||||
function getVolumeFromConfig(accessor: (key: string) => any): string | undefined {
|
||||
return accessor('accessibility.signalOptions')?.volume || accessor('accessibility.signals.sounds.volume') || accessor('audioCues.volume');
|
||||
return accessor('accessibility.signalOptions.volume') || accessor('accessibility.signalOptions')?.volume || accessor('accessibility.signals.sounds.volume') || accessor('audioCues.volume');
|
||||
}
|
||||
|
||||
function getDebouncePositionChangesFromConfig(accessor: (key: string) => any): number | undefined {
|
||||
return accessor('accessibility.signalOptions')?.debouncePositionChanges || accessor('accessibility.signals.debouncePositionChanges') || accessor('audioCues.debouncePositionChanges');
|
||||
return accessor('accessibility.signalOptions.debouncePositionChanges') || accessor('accessibility.signalOptions')?.debouncePositionChanges || accessor('accessibility.signals.debouncePositionChanges') || accessor('audioCues.debouncePositionChanges');
|
||||
}
|
||||
|
||||
Registry.as<IConfigurationMigrationRegistry>(WorkbenchExtensions.ConfigurationMigration)
|
||||
|
||||
@@ -30,9 +30,13 @@ import { IChatVariablesService } from 'vs/workbench/contrib/chat/common/chatVari
|
||||
import { AnythingQuickAccessProvider } from 'vs/workbench/contrib/search/browser/anythingQuickAccess';
|
||||
import { ISymbolQuickPickItem, SymbolsQuickAccessProvider } from 'vs/workbench/contrib/search/browser/symbolsQuickAccess';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { EditorType } from 'vs/editor/common/editorCommon';
|
||||
|
||||
export function registerChatContextActions() {
|
||||
registerAction2(AttachContextAction);
|
||||
registerAction2(AttachFileAction);
|
||||
registerAction2(AttachSelectionAction);
|
||||
}
|
||||
|
||||
export type IChatContextQuickPickItem = IFileQuickPickItem | IDynamicVariableQuickPickItem | IStaticVariableQuickPickItem | IGotoSymbolQuickPickItem | ISymbolQuickPickItem | IQuickAccessQuickPickItem;
|
||||
@@ -77,6 +81,58 @@ export interface IQuickAccessQuickPickItem extends IQuickPickItem {
|
||||
prefix: string;
|
||||
}
|
||||
|
||||
class AttachFileAction extends Action2 {
|
||||
|
||||
static readonly ID = 'workbench.action.chat.attachFile';
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: AttachFileAction.ID,
|
||||
title: localize2('workbench.action.chat.attachFile.label', "Attach File"),
|
||||
category: CHAT_CATEGORY,
|
||||
f1: false
|
||||
});
|
||||
}
|
||||
|
||||
override async run(accessor: ServicesAccessor, ...args: any[]): Promise<void> {
|
||||
const variablesService = accessor.get(IChatVariablesService);
|
||||
const textEditorService = accessor.get(IEditorService);
|
||||
|
||||
const activeUri = textEditorService.activeEditor?.resource;
|
||||
if (textEditorService.activeTextEditorControl?.getEditorType() === EditorType.ICodeEditor && activeUri && [Schemas.file, Schemas.vscodeRemote].includes(activeUri.scheme)) {
|
||||
variablesService.attachContext('file', activeUri, ChatAgentLocation.Panel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AttachSelectionAction extends Action2 {
|
||||
|
||||
static readonly ID = 'workbench.action.chat.attachSelection';
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: AttachSelectionAction.ID,
|
||||
title: localize2('workbench.action.chat.attachSelection.label', "Add Selection to Chat"),
|
||||
category: CHAT_CATEGORY,
|
||||
f1: false
|
||||
});
|
||||
}
|
||||
|
||||
override async run(accessor: ServicesAccessor, ...args: any[]): Promise<void> {
|
||||
const variablesService = accessor.get(IChatVariablesService);
|
||||
const textEditorService = accessor.get(IEditorService);
|
||||
|
||||
const activeEditor = textEditorService.activeTextEditorControl;
|
||||
const activeUri = textEditorService.activeEditor?.resource;
|
||||
if (textEditorService.activeTextEditorControl?.getEditorType() === EditorType.ICodeEditor && activeUri && [Schemas.file, Schemas.vscodeRemote].includes(activeUri.scheme)) {
|
||||
const selection = activeEditor?.getSelection();
|
||||
if (selection) {
|
||||
variablesService.attachContext('file', { uri: activeUri, range: selection }, ChatAgentLocation.Panel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class AttachContextAction extends Action2 {
|
||||
|
||||
static readonly ID = 'workbench.action.chat.attachContext';
|
||||
|
||||
@@ -105,6 +105,10 @@ interface IItemHeightChangeParams {
|
||||
height: number;
|
||||
}
|
||||
|
||||
interface IChatMarkdownRenderResult extends IMarkdownRenderResult {
|
||||
codeBlockCount: number;
|
||||
}
|
||||
|
||||
const forceVerboseLayoutTracing = false;
|
||||
|
||||
export interface IChatRendererDelegate {
|
||||
@@ -481,11 +485,12 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
|
||||
this.renderContentReferencesIfNeeded(element, templateData, templateData.elementDisposables);
|
||||
|
||||
let fileTreeIndex = 0;
|
||||
let codeBlockIndex = 0;
|
||||
value.forEach((data, index) => {
|
||||
const result = data.kind === 'treeData'
|
||||
? this.renderTreeData(data.treeData, element, templateData, fileTreeIndex++)
|
||||
: data.kind === 'markdownContent'
|
||||
? this.renderMarkdown(data.content, element, templateData, fillInIncompleteTokens)
|
||||
? this.renderMarkdown(data.content, element, templateData, fillInIncompleteTokens, codeBlockIndex)
|
||||
: data.kind === 'progressMessage' && onlyProgressMessagesAfterI(value, index) ? this.renderProgressMessage(data, false) // TODO render command
|
||||
: data.kind === 'progressTask' ? this.renderProgressTask(data, false, element, templateData)
|
||||
: data.kind === 'command' ? this.renderCommandButton(element, data)
|
||||
@@ -497,6 +502,10 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
|
||||
if (result) {
|
||||
templateData.value.appendChild(result.element);
|
||||
templateData.elementDisposables.add(result);
|
||||
|
||||
if ('codeBlockCount' in result) {
|
||||
codeBlockIndex += (result as IChatMarkdownRenderResult).codeBlockCount;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1119,13 +1128,13 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
|
||||
};
|
||||
}
|
||||
|
||||
private renderMarkdown(markdown: IMarkdownString, element: ChatTreeItem, templateData: IChatListItemTemplate, fillInIncompleteTokens = false): IMarkdownRenderResult {
|
||||
private renderMarkdown(markdown: IMarkdownString, element: ChatTreeItem, templateData: IChatListItemTemplate, fillInIncompleteTokens = false, codeBlockStartIndex = 0): IChatMarkdownRenderResult {
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
// We release editors in order so that it's more likely that the same editor will be assigned if this element is re-rendered right away, like it often is during progressive rendering
|
||||
const orderedDisposablesList: IDisposable[] = [];
|
||||
const codeblocks: IChatCodeBlockInfo[] = [];
|
||||
let codeBlockIndex = 0;
|
||||
let codeBlockIndex = codeBlockStartIndex;
|
||||
const result = this.renderer.render(markdown, {
|
||||
fillInIncompleteTokens,
|
||||
codeBlockRendererSync: (languageId, text) => {
|
||||
@@ -1193,6 +1202,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
|
||||
|
||||
orderedDisposablesList.reverse().forEach(d => disposables.add(d));
|
||||
return {
|
||||
codeBlockCount: codeBlockIndex - codeBlockStartIndex,
|
||||
element: result.element,
|
||||
dispose() {
|
||||
result.dispose();
|
||||
|
||||
+10
-27
@@ -29,8 +29,6 @@ import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLa
|
||||
import { OS } from 'vs/base/common/platform';
|
||||
import { status } from 'vs/base/browser/ui/aria/aria';
|
||||
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { Extensions, IConfigurationMigrationRegistry } from 'vs/workbench/common/configuration';
|
||||
import { LOG_MODE_ID, OUTPUT_MODE_ID } from 'vs/workbench/services/output/common/output';
|
||||
import { SEARCH_RESULT_LANGUAGE_ID } from 'vs/workbench/services/search/common/search';
|
||||
import { getDefaultHoverDelegate } from 'vs/base/browser/ui/hover/hoverDelegateFactory';
|
||||
@@ -39,23 +37,6 @@ import { ChatAgentLocation, IChatAgent, IChatAgentService } from 'vs/workbench/c
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
// TODO@joyceerhl remove this after a few iterations
|
||||
Registry.as<IConfigurationMigrationRegistry>(Extensions.ConfigurationMigration)
|
||||
.registerConfigurationMigrations([{
|
||||
key: 'workbench.editor.untitled.hint',
|
||||
migrateFn: (value, _accessor) => ([
|
||||
[emptyTextEditorHintSetting, { value }],
|
||||
['workbench.editor.untitled.hint', { value: undefined }]
|
||||
])
|
||||
},
|
||||
{
|
||||
key: 'accessibility.verbosity.untitledHint',
|
||||
migrateFn: (value, _accessor) => ([
|
||||
[AccessibilityVerbositySettingId.EmptyEditorHint, { value }],
|
||||
['accessibility.verbosity.untitledHint', { value: undefined }]
|
||||
])
|
||||
}]);
|
||||
|
||||
export interface IEmptyTextEditorHintOptions {
|
||||
readonly clickable?: boolean;
|
||||
}
|
||||
@@ -218,6 +199,12 @@ class EmptyTextEditorHintContentWidget implements IContentWidget {
|
||||
return EmptyTextEditorHintContentWidget.ID;
|
||||
}
|
||||
|
||||
private _disableHint() {
|
||||
this.configurationService.updateValue(emptyTextEditorHintSetting, 'hidden');
|
||||
this.dispose();
|
||||
this.editor.focus();
|
||||
}
|
||||
|
||||
private _getHintInlineChat(providers: IChatAgent[]) {
|
||||
const providerName = (providers.length === 1 ? providers[0].fullName : undefined) ?? this.productService.nameShort;
|
||||
|
||||
@@ -257,6 +244,7 @@ class EmptyTextEditorHintContentWidget implements IContentWidget {
|
||||
const hintPart = $('a', undefined, fragment);
|
||||
hintPart.style.fontStyle = 'italic';
|
||||
hintPart.style.cursor = 'pointer';
|
||||
this.toDispose.add(dom.addDisposableListener(label.element, dom.EventType.CONTEXT_MENU, () => this._disableHint()));
|
||||
this.toDispose.add(dom.addDisposableListener(hintPart, dom.EventType.CLICK, handleClick));
|
||||
return hintPart;
|
||||
} else {
|
||||
@@ -275,6 +263,7 @@ class EmptyTextEditorHintContentWidget implements IContentWidget {
|
||||
|
||||
if (this.options.clickable) {
|
||||
label.element.style.cursor = 'pointer';
|
||||
this.toDispose.add(dom.addDisposableListener(label.element, dom.EventType.CONTEXT_MENU, () => this._disableHint()));
|
||||
this.toDispose.add(dom.addDisposableListener(label.element, dom.EventType.CLICK, handleClick));
|
||||
}
|
||||
|
||||
@@ -297,7 +286,7 @@ class EmptyTextEditorHintContentWidget implements IContentWidget {
|
||||
hintElement.appendChild(rendered);
|
||||
}
|
||||
|
||||
return { ariaLabel, hintHandler, hintElement };
|
||||
return { ariaLabel, hintElement };
|
||||
}
|
||||
|
||||
private _getHintDefault() {
|
||||
@@ -315,7 +304,7 @@ class EmptyTextEditorHintContentWidget implements IContentWidget {
|
||||
chooseEditorOnClickOrTap(event.browserEvent);
|
||||
break;
|
||||
case '3':
|
||||
dontShowOnClickOrTap();
|
||||
this._disableHint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -360,12 +349,6 @@ class EmptyTextEditorHintContentWidget implements IContentWidget {
|
||||
}
|
||||
};
|
||||
|
||||
const dontShowOnClickOrTap = () => {
|
||||
this.configurationService.updateValue(emptyTextEditorHintSetting, 'hidden');
|
||||
this.dispose();
|
||||
this.editor.focus();
|
||||
};
|
||||
|
||||
const hintMsg = localize({
|
||||
key: 'message',
|
||||
comment: [
|
||||
|
||||
@@ -264,7 +264,7 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi
|
||||
}
|
||||
|
||||
private createTriggerBreakpointInput(container: HTMLElement) {
|
||||
const breakpoints = this.debugService.getModel().getBreakpoints().filter(bp => bp !== this.breakpoint);
|
||||
const breakpoints = this.debugService.getModel().getBreakpoints().filter(bp => bp !== this.breakpoint && !bp.logMessage);
|
||||
const breakpointOptions: ISelectOptionItem[] = [
|
||||
{ text: nls.localize('noTriggerByBreakpoint', 'None'), isDisabled: true },
|
||||
...breakpoints.map(bp => ({
|
||||
@@ -433,12 +433,12 @@ export class BreakpointWidget extends ZoneWidget implements IPrivateBreakpointWi
|
||||
if (success) {
|
||||
// if there is already a breakpoint on this location - remove it.
|
||||
|
||||
let condition = this.breakpoint?.condition;
|
||||
let hitCondition = this.breakpoint?.hitCondition;
|
||||
let logMessage = this.breakpoint?.logMessage;
|
||||
let triggeredBy = this.breakpoint?.triggeredBy;
|
||||
let mode = this.breakpoint?.mode;
|
||||
let modeLabel = this.breakpoint?.modeLabel;
|
||||
let condition: string | undefined = undefined;
|
||||
let hitCondition: string | undefined = undefined;
|
||||
let logMessage: string | undefined = undefined;
|
||||
let triggeredBy: string | undefined = undefined;
|
||||
let mode: string | undefined = undefined;
|
||||
let modeLabel: string | undefined = undefined;
|
||||
|
||||
this.rememberInput();
|
||||
|
||||
|
||||
@@ -1643,7 +1643,7 @@ registerAction2(class extends Action2 {
|
||||
} else if (breakpoint instanceof DataBreakpoint) {
|
||||
await debugService.removeDataBreakpoints(breakpoint.getId());
|
||||
} else if (breakpoint instanceof InstructionBreakpoint) {
|
||||
await debugService.removeInstructionBreakpoints(breakpoint.instructionReference);
|
||||
await debugService.removeInstructionBreakpoints(breakpoint.instructionReference, breakpoint.offset);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { addDisposableListener, isKeyboardEvent } from 'vs/base/browser/dom';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
@@ -208,7 +209,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
|
||||
|
||||
private toDispose: IDisposable[];
|
||||
private hoverWidget: DebugHoverWidget;
|
||||
private hoverPosition: Position | null = null;
|
||||
private hoverPosition?: { position: Position; event: IMouseEvent };
|
||||
private mouseDown = false;
|
||||
private exceptionWidgetVisible: IContextKey<boolean>;
|
||||
private gutterIsHovered = false;
|
||||
@@ -341,7 +342,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
|
||||
|
||||
if (debugHoverWasVisible && this.hoverPosition) {
|
||||
// If the debug hover was visible immediately show the editor hover for the alt transition to be smooth
|
||||
this.showEditorHover(this.hoverPosition, false);
|
||||
this.showEditorHover(this.hoverPosition.position, false);
|
||||
}
|
||||
|
||||
const onKeyUp = new DomEmitter(ownerDocument, 'keyup');
|
||||
@@ -361,14 +362,14 @@ export class DebugEditorContribution implements IDebugEditorContribution {
|
||||
});
|
||||
}
|
||||
|
||||
async showHover(position: Position, focus: boolean): Promise<void> {
|
||||
async showHover(position: Position, focus: boolean, mouseEvent?: IMouseEvent): Promise<void> {
|
||||
// normally will already be set in `showHoverScheduler`, but public callers may hit this directly:
|
||||
this.preventDefaultEditorHover();
|
||||
|
||||
const sf = this.debugService.getViewModel().focusedStackFrame;
|
||||
const model = this.editor.getModel();
|
||||
if (sf && model && this.uriIdentityService.extUri.isEqual(sf.source.uri, model.uri)) {
|
||||
const result = await this.hoverWidget.showAt(position, focus);
|
||||
const result = await this.hoverWidget.showAt(position, focus, mouseEvent);
|
||||
if (result === ShowDebugHoverResult.NOT_AVAILABLE) {
|
||||
// When no expression available fallback to editor hover
|
||||
this.showEditorHover(position, focus);
|
||||
@@ -438,7 +439,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
|
||||
private get showHoverScheduler() {
|
||||
const scheduler = new RunOnceScheduler(() => {
|
||||
if (this.hoverPosition && !this.altPressed) {
|
||||
this.showHover(this.hoverPosition, false);
|
||||
this.showHover(this.hoverPosition.position, false, this.hoverPosition.event);
|
||||
}
|
||||
}, this.hoverDelay);
|
||||
this.toDispose.push(scheduler);
|
||||
@@ -493,8 +494,8 @@ export class DebugEditorContribution implements IDebugEditorContribution {
|
||||
}
|
||||
|
||||
if (target.type === MouseTargetType.CONTENT_TEXT) {
|
||||
if (target.position && !Position.equals(target.position, this.hoverPosition)) {
|
||||
this.hoverPosition = target.position;
|
||||
if (target.position && !Position.equals(target.position, this.hoverPosition?.position || null) && !this.hoverWidget.isInSafeTriangle(mouseEvent.event.posx, mouseEvent.event.posy)) {
|
||||
this.hoverPosition = { position: target.position, event: mouseEvent.event };
|
||||
// Disable the editor hover during the request to avoid flickering
|
||||
this.preventDefaultEditorHover();
|
||||
this.showHoverScheduler.schedule(this.hoverDelay);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
@@ -83,6 +84,7 @@ export class DebugHoverWidget implements IContentWidget {
|
||||
readonly allowEditorOverflow = true;
|
||||
|
||||
private _isVisible: boolean;
|
||||
private safeTriangle?: dom.SafeTriangle;
|
||||
private showCancellationSource?: CancellationTokenSource;
|
||||
private domNode!: HTMLElement;
|
||||
private tree!: AsyncDataTree<IExpression, IExpression, any>;
|
||||
@@ -228,7 +230,15 @@ export class DebugHoverWidget implements IContentWidget {
|
||||
return this.domNode;
|
||||
}
|
||||
|
||||
async showAt(position: Position, focus: boolean): Promise<void | ShowDebugHoverResult> {
|
||||
/**
|
||||
* Gets whether the given coordinates are in the safe triangle formed from
|
||||
* the position at which the hover was initiated.
|
||||
*/
|
||||
isInSafeTriangle(x: number, y: number) {
|
||||
return this._isVisible && !!this.safeTriangle?.contains(x, y);
|
||||
}
|
||||
|
||||
async showAt(position: Position, focus: boolean, mouseEvent?: IMouseEvent): Promise<void | ShowDebugHoverResult> {
|
||||
this.showCancellationSource?.cancel();
|
||||
const cancellationSource = this.showCancellationSource = new CancellationTokenSource();
|
||||
const session = this.debugService.getViewModel().focusedSession;
|
||||
@@ -269,7 +279,7 @@ export class DebugHoverWidget implements IContentWidget {
|
||||
options: DebugHoverWidget._HOVER_HIGHLIGHT_DECORATION_OPTIONS
|
||||
}]);
|
||||
|
||||
return this.doShow(result.range.getStartPosition(), expression, focus);
|
||||
return this.doShow(result.range.getStartPosition(), expression, focus, mouseEvent);
|
||||
}
|
||||
|
||||
private static readonly _HOVER_HIGHLIGHT_DECORATION_OPTIONS = ModelDecorationOptions.register({
|
||||
@@ -277,7 +287,7 @@ export class DebugHoverWidget implements IContentWidget {
|
||||
className: 'hoverHighlight'
|
||||
});
|
||||
|
||||
private async doShow(position: Position, expression: IExpression, focus: boolean, forceValueHover = false): Promise<void> {
|
||||
private async doShow(position: Position, expression: IExpression, focus: boolean, mouseEvent: IMouseEvent | undefined): Promise<void> {
|
||||
if (!this.domNode) {
|
||||
this.create();
|
||||
}
|
||||
@@ -285,7 +295,7 @@ export class DebugHoverWidget implements IContentWidget {
|
||||
this.showAtPosition = position;
|
||||
this._isVisible = true;
|
||||
|
||||
if (!expression.hasChildren || forceValueHover) {
|
||||
if (!expression.hasChildren) {
|
||||
this.complexValueContainer.hidden = true;
|
||||
this.valueContainer.hidden = false;
|
||||
renderExpressionValue(expression, this.valueContainer, {
|
||||
@@ -312,6 +322,7 @@ export class DebugHoverWidget implements IContentWidget {
|
||||
this.tree.scrollTop = 0;
|
||||
this.tree.scrollLeft = 0;
|
||||
this.complexValueContainer.hidden = false;
|
||||
this.safeTriangle = mouseEvent && new dom.SafeTriangle(mouseEvent.posx, mouseEvent.posy, this.domNode);
|
||||
|
||||
if (focus) {
|
||||
this.editor.render();
|
||||
|
||||
@@ -816,7 +816,7 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
|
||||
},
|
||||
['interactiveWindow.executeWithShiftEnter']: {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
default: false,
|
||||
markdownDescription: localize('interactiveWindow.executeWithShiftEnter', "Execute the interactive window (REPL) input box with shift+enter, so that enter can be used to create a newline.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -697,6 +697,14 @@ export class NotebookService extends Disposable implements INotebookService {
|
||||
return result;
|
||||
}
|
||||
|
||||
tryGetDataProviderSync(viewType: string): SimpleNotebookProviderInfo | undefined {
|
||||
const selected = this.notebookProviderInfoStore.get(viewType);
|
||||
if (!selected) {
|
||||
return undefined;
|
||||
}
|
||||
return this._notebookProviders.get(selected.id);
|
||||
}
|
||||
|
||||
|
||||
private _persistMementos(): void {
|
||||
this._memento.saveMemento();
|
||||
|
||||
@@ -436,7 +436,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Themable {
|
||||
}
|
||||
|
||||
table, thead, tr, th, td, tbody {
|
||||
border: none !important;
|
||||
border: none;
|
||||
border-color: transparent;
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
|
||||
@@ -15,6 +15,7 @@ import { assertType } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IWriteFileOptions, IFileStatWithMetadata } from 'vs/platform/files/common/files';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IRevertOptions, ISaveOptions, IUntypedEditorInput } from 'vs/workbench/common/editor';
|
||||
import { EditorModel } from 'vs/workbench/common/editor/editorModel';
|
||||
@@ -197,7 +198,8 @@ export class NotebookFileWorkingCopyModel extends Disposable implements IStoredF
|
||||
private readonly _notebookModel: NotebookTextModel,
|
||||
private readonly _notebookService: INotebookService,
|
||||
private readonly _configurationService: IConfigurationService,
|
||||
private readonly _telemetryService: ITelemetryService
|
||||
private readonly _telemetryService: ITelemetryService,
|
||||
private readonly _logService: ILogService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -237,13 +239,22 @@ export class NotebookFileWorkingCopyModel extends Disposable implements IStoredF
|
||||
}
|
||||
|
||||
private async setSaveDelegate() {
|
||||
const serializer = await this.getNotebookSerializer();
|
||||
this.save = async (options: IWriteFileOptions, token: CancellationToken) => {
|
||||
if (token.isCancellationRequested) {
|
||||
throw new CancellationError();
|
||||
}
|
||||
// make sure we wait for a serializer to resolve before we try to handle saves in the EH
|
||||
await this.getNotebookSerializer();
|
||||
|
||||
this.save = async (options: IWriteFileOptions, token: CancellationToken) => {
|
||||
try {
|
||||
let serializer = this._notebookService.tryGetDataProviderSync(this.notebookModel.viewType)?.serializer;
|
||||
|
||||
if (!serializer) {
|
||||
this._logService.warn('No serializer found for notebook model, checking if provider still needs to be resolved');
|
||||
serializer = await this.getNotebookSerializer();
|
||||
}
|
||||
|
||||
if (token.isCancellationRequested) {
|
||||
throw new CancellationError();
|
||||
}
|
||||
|
||||
const stat = await serializer.save(this._notebookModel.uri, this._notebookModel.versionId, options, token);
|
||||
return stat;
|
||||
} catch (error) {
|
||||
@@ -358,7 +369,8 @@ export class NotebookFileWorkingCopyModelFactory implements IStoredFileWorkingCo
|
||||
private readonly _viewType: string,
|
||||
@INotebookService private readonly _notebookService: INotebookService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@ILogService private readonly _logService: ILogService
|
||||
) { }
|
||||
|
||||
async createModel(resource: URI, stream: VSBufferReadableStream, token: CancellationToken): Promise<NotebookFileWorkingCopyModel> {
|
||||
@@ -376,7 +388,7 @@ export class NotebookFileWorkingCopyModelFactory implements IStoredFileWorkingCo
|
||||
}
|
||||
|
||||
const notebookModel = this._notebookService.createNotebookTextModel(info.viewType, resource, data, info.serializer.options);
|
||||
return new NotebookFileWorkingCopyModel(notebookModel, this._notebookService, this._configurationService, this._telemetryService);
|
||||
return new NotebookFileWorkingCopyModel(notebookModel, this._notebookService, this._configurationService, this._telemetryService, this._logService);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class NotebookModelReferenceCollection extends ReferenceCollection<Promise<IReso
|
||||
const workingCopyTypeId = NotebookWorkingCopyTypeIdentifier.create(viewType);
|
||||
let workingCopyManager = this._workingCopyManagers.get(workingCopyTypeId);
|
||||
if (!workingCopyManager) {
|
||||
const factory = new NotebookFileWorkingCopyModelFactory(viewType, this._notebookService, this._configurationService, this._telemetryService);
|
||||
const factory = new NotebookFileWorkingCopyModelFactory(viewType, this._notebookService, this._configurationService, this._telemetryService, this._logService);
|
||||
workingCopyManager = <IFileWorkingCopyManager<NotebookFileWorkingCopyModel, NotebookFileWorkingCopyModel>><any>this._instantiationService.createInstance(
|
||||
FileWorkingCopyManager,
|
||||
workingCopyTypeId,
|
||||
|
||||
@@ -65,6 +65,7 @@ export interface INotebookService {
|
||||
|
||||
registerNotebookSerializer(viewType: string, extensionData: NotebookExtensionDescription, serializer: INotebookSerializer): IDisposable;
|
||||
withNotebookDataProvider(viewType: string): Promise<SimpleNotebookProviderInfo>;
|
||||
tryGetDataProviderSync(viewType: string): SimpleNotebookProviderInfo | undefined;
|
||||
|
||||
getOutputMimeTypeInfo(textModel: NotebookTextModel, kernelProvides: readonly string[] | undefined, output: IOutputDto): readonly IOrderedMimeType[];
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import { TestConfigurationService } from 'vs/platform/configuration/test/common/
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { IFileStatWithMetadata } from 'vs/platform/files/common/files';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { CellKind, IOutputDto, NotebookData, NotebookSetting, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
@@ -28,7 +29,10 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
let disposables: DisposableStore;
|
||||
let instantiationService: TestInstantiationService;
|
||||
const configurationService = new TestConfigurationService();
|
||||
const telemetryService = new class extends mock<ITelemetryService>() { };
|
||||
const telemetryService = new class extends mock<ITelemetryService>() {
|
||||
override publicLogError2() { }
|
||||
};
|
||||
const logservice = new class extends mock<ILogService>() { };
|
||||
|
||||
teardown(() => disposables.dispose());
|
||||
|
||||
@@ -65,7 +69,8 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
}
|
||||
),
|
||||
configurationService,
|
||||
telemetryService
|
||||
telemetryService,
|
||||
logservice
|
||||
));
|
||||
|
||||
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
|
||||
@@ -88,7 +93,8 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
}
|
||||
),
|
||||
configurationService,
|
||||
telemetryService
|
||||
telemetryService,
|
||||
logservice
|
||||
));
|
||||
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
|
||||
assert.strictEqual(callCount, 1);
|
||||
@@ -123,7 +129,8 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
}
|
||||
),
|
||||
configurationService,
|
||||
telemetryService
|
||||
telemetryService,
|
||||
logservice
|
||||
));
|
||||
|
||||
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
|
||||
@@ -147,6 +154,7 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
),
|
||||
configurationService,
|
||||
telemetryService,
|
||||
logservice
|
||||
|
||||
));
|
||||
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
|
||||
@@ -181,7 +189,8 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
}
|
||||
),
|
||||
configurationService,
|
||||
telemetryService
|
||||
telemetryService,
|
||||
logservice
|
||||
));
|
||||
|
||||
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
|
||||
@@ -204,7 +213,8 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
}
|
||||
),
|
||||
configurationService,
|
||||
telemetryService
|
||||
telemetryService,
|
||||
logservice
|
||||
));
|
||||
await model.snapshot(SnapshotContext.Save, CancellationToken.None);
|
||||
assert.strictEqual(callCount, 1);
|
||||
@@ -239,7 +249,8 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
}
|
||||
),
|
||||
configurationService,
|
||||
telemetryService
|
||||
telemetryService,
|
||||
logservice
|
||||
));
|
||||
|
||||
try {
|
||||
@@ -282,7 +293,8 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
notebook,
|
||||
notebookService,
|
||||
configurationService,
|
||||
telemetryService
|
||||
telemetryService,
|
||||
logservice
|
||||
));
|
||||
|
||||
// the save method should not be set if the serializer is not yet resolved
|
||||
@@ -299,11 +311,25 @@ suite('NotebookFileWorkingCopyModel', function () {
|
||||
|
||||
function mockNotebookService(notebook: NotebookTextModel, notebookSerializer: Promise<INotebookSerializer> | INotebookSerializer) {
|
||||
return new class extends mock<INotebookService>() {
|
||||
private serializer: INotebookSerializer | undefined = undefined;
|
||||
override async withNotebookDataProvider(viewType: string): Promise<SimpleNotebookProviderInfo> {
|
||||
const serializer = await notebookSerializer;
|
||||
this.serializer = await notebookSerializer;
|
||||
return new SimpleNotebookProviderInfo(
|
||||
notebook.viewType,
|
||||
serializer,
|
||||
this.serializer,
|
||||
{
|
||||
id: new ExtensionIdentifier('test'),
|
||||
location: undefined
|
||||
}
|
||||
);
|
||||
}
|
||||
override tryGetDataProviderSync(viewType: string): SimpleNotebookProviderInfo | undefined {
|
||||
if (!this.serializer) {
|
||||
return undefined;
|
||||
}
|
||||
return new SimpleNotebookProviderInfo(
|
||||
notebook.viewType,
|
||||
this.serializer,
|
||||
{
|
||||
id: new ExtensionIdentifier('test'),
|
||||
location: undefined
|
||||
|
||||
@@ -136,7 +136,7 @@ export class FolderMatchRenderer extends Disposable implements ICompressibleTree
|
||||
SearchContext.FileFocusKey.bindTo(contextKeyServiceMain).set(false);
|
||||
SearchContext.FolderFocusKey.bindTo(contextKeyServiceMain).set(true);
|
||||
|
||||
const instantiationService = this.instantiationService.createChild(new ServiceCollection([IContextKeyService, contextKeyServiceMain]));
|
||||
const instantiationService = this._register(this.instantiationService.createChild(new ServiceCollection([IContextKeyService, contextKeyServiceMain])));
|
||||
const actions = disposables.add(instantiationService.createInstance(MenuWorkbenchToolBar, actionBarContainer, MenuId.SearchActionMenu, {
|
||||
menuOptions: {
|
||||
shouldForwardArgs: true
|
||||
|
||||
@@ -237,8 +237,8 @@ export class SearchView extends ViewPane {
|
||||
this.inputPatternExclusionsFocused = Constants.SearchContext.PatternExcludesFocusedKey.bindTo(this.contextKeyService);
|
||||
this.isEditableItem = Constants.SearchContext.IsEditableItemKey.bindTo(this.contextKeyService);
|
||||
|
||||
this.instantiationService = this.instantiationService.createChild(
|
||||
new ServiceCollection([IContextKeyService, this.contextKeyService]));
|
||||
this.instantiationService = this._register(this.instantiationService.createChild(
|
||||
new ServiceCollection([IContextKeyService, this.contextKeyService])));
|
||||
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('search.sortOrder')) {
|
||||
|
||||
@@ -141,7 +141,7 @@ export class SearchEditor extends AbstractTextCodeEditor<SearchEditorViewState>
|
||||
|
||||
this.createQueryEditor(
|
||||
this.queryEditorContainer,
|
||||
this.instantiationService.createChild(new ServiceCollection([IContextKeyService, scopedContextKeyService])),
|
||||
this._register(this.instantiationService.createChild(new ServiceCollection([IContextKeyService, scopedContextKeyService]))),
|
||||
SearchContext.InputBoxFocusedKey.bindTo(scopedContextKeyService)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -269,6 +269,9 @@ export async function showRunRecentQuickPick(
|
||||
return;
|
||||
}
|
||||
const [item] = quickPick.activeItems;
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
if ('command' in item && item.command && item.command.marker) {
|
||||
if (!terminalScrollStateSaved) {
|
||||
xterm.markTracker.saveScrollState();
|
||||
|
||||
+20
-2
@@ -29,9 +29,14 @@ import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal
|
||||
import 'vs/css!./media/terminalInitialHint';
|
||||
import { TerminalInitialHintSettingId } from 'vs/workbench/contrib/terminalContrib/chat/common/terminalInitialHintConfiguration';
|
||||
import { ChatAgentLocation, IChatAgent, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
const enum Constants {
|
||||
InitialHintHideStorageKey = 'terminal.initialHint.hide'
|
||||
}
|
||||
|
||||
export class InitialHintAddon extends Disposable implements ITerminalAddon {
|
||||
private readonly _onDidRequestCreateHint = this._register(new Emitter<void>());
|
||||
get onDidRequestCreateHint(): Event<void> { return this._onDidRequestCreateHint.event; }
|
||||
@@ -90,11 +95,22 @@ export class TerminalInitialHintContribution extends Disposable implements ITerm
|
||||
@ITerminalGroupService private readonly _terminalGroupService: ITerminalGroupService,
|
||||
@ITerminalEditorService private readonly _terminalEditorService: ITerminalEditorService,
|
||||
@IChatAgentService private readonly _chatAgentService: IChatAgentService,
|
||||
@IStorageService private readonly _storageService: IStorageService,
|
||||
) {
|
||||
super();
|
||||
|
||||
// Reset hint state when config changes
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(TerminalInitialHintSettingId.Enabled)) {
|
||||
this._storageService.remove(Constants.InitialHintHideStorageKey, StorageScope.APPLICATION);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
xtermOpen(xterm: IXtermTerminal & { raw: RawXtermTerminal }): void {
|
||||
if (this._storageService.getBoolean(Constants.InitialHintHideStorageKey, StorageScope.APPLICATION, false)) {
|
||||
return;
|
||||
}
|
||||
if (this._terminalGroupService.instances.length + this._terminalEditorService.instances.length !== 1) {
|
||||
// only show for the first terminal
|
||||
return;
|
||||
@@ -108,7 +124,7 @@ export class TerminalInitialHintContribution extends Disposable implements ITerm
|
||||
private _createHint(): void {
|
||||
const instance = this._instance instanceof TerminalInstance ? this._instance : undefined;
|
||||
const commandDetectionCapability = instance?.capabilities.get(TerminalCapability.CommandDetection);
|
||||
if (!instance || !this._xterm || this._hintWidget || !commandDetectionCapability || commandDetectionCapability.promptInputModel.value || instance.reconnectionProperties) {
|
||||
if (!instance || !this._xterm || this._hintWidget || !commandDetectionCapability || commandDetectionCapability.promptInputModel.value || !!instance.shellLaunchConfig.attachPersistentProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -199,7 +215,8 @@ class TerminalInitialHintWidget extends Disposable {
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@ITerminalService private readonly terminalService: ITerminalService
|
||||
@ITerminalService private readonly terminalService: ITerminalService,
|
||||
@IStorageService private readonly _storageService: IStorageService
|
||||
) {
|
||||
super();
|
||||
this.toDispose.add(_instance.onDidFocus(() => {
|
||||
@@ -229,6 +246,7 @@ class TerminalInitialHintWidget extends Disposable {
|
||||
let ariaLabel = `Ask ${providerName} something or start typing to dismiss.`;
|
||||
|
||||
const handleClick = () => {
|
||||
this._storageService.store(Constants.InitialHintHideStorageKey, true, StorageScope.APPLICATION, StorageTarget.USER);
|
||||
this.telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', {
|
||||
id: 'terminalInlineChat.hintAction',
|
||||
from: 'hint'
|
||||
|
||||
@@ -223,9 +223,11 @@ export class TreeProjection extends Disposable implements ITestTreeProjection {
|
||||
break;
|
||||
}
|
||||
|
||||
// The first element will cause the root to be hidden
|
||||
// Removing the first element will cause the root to be hidden.
|
||||
// Changing first-level elements will need the root to re-render if
|
||||
// there are no other controllers with items.
|
||||
const parent = toRemove.parent;
|
||||
const affectsRootElement = toRemove.depth === 1 && parent?.children.size === 1;
|
||||
const affectsRootElement = toRemove.depth === 1 && (parent?.children.size === 1 || !Iterable.some(this.rootsWithChildren, (_, i) => i === 1));
|
||||
this.changedParents.add(affectsRootElement ? null : parent);
|
||||
|
||||
const queue: Iterable<TestExplorerTreeElement>[] = [[toRemove]];
|
||||
|
||||
+48
@@ -267,4 +267,52 @@ suite('Workbench - Testing Explorer Hierarchal by Location Projection', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
test('fixes #213316 (single root)', async () => {
|
||||
harness.flush();
|
||||
assert.deepStrictEqual(harness.tree.getRendered(), [
|
||||
{ e: 'a' }, { e: 'b' }
|
||||
]);
|
||||
harness.pushDiff({
|
||||
op: TestDiffOpType.Remove,
|
||||
itemId: new TestId(['ctrlId', 'id-a']).toString(),
|
||||
});
|
||||
harness.flush();
|
||||
assert.deepStrictEqual(harness.tree.getRendered(), [
|
||||
{ e: 'b' }
|
||||
]);
|
||||
});
|
||||
|
||||
test('fixes #213316 (multi root)', async () => {
|
||||
harness.pushDiff({
|
||||
op: TestDiffOpType.Add,
|
||||
item: { controllerId: 'ctrl2', expand: TestItemExpandState.Expanded, item: new TestTestItem(new TestId(['ctrlId2']), 'c').toTestItem() },
|
||||
}, {
|
||||
op: TestDiffOpType.Add,
|
||||
item: { controllerId: 'ctrl2', expand: TestItemExpandState.NotExpandable, item: new TestTestItem(new TestId(['ctrlId2', 'id-c']), 'ca').toTestItem() },
|
||||
});
|
||||
harness.flush();
|
||||
assert.deepStrictEqual(harness.flush(), [
|
||||
{ e: 'c', children: [{ e: 'ca' }] },
|
||||
{ e: 'root', children: [{ e: 'a' }, { e: 'b' }] }
|
||||
]);
|
||||
|
||||
harness.pushDiff({
|
||||
op: TestDiffOpType.Remove,
|
||||
itemId: new TestId(['ctrlId', 'id-a']).toString(),
|
||||
});
|
||||
harness.flush();
|
||||
assert.deepStrictEqual(harness.tree.getRendered(), [
|
||||
{ e: 'c', children: [{ e: 'ca' }] },
|
||||
{ e: 'root', children: [{ e: 'b' }] }
|
||||
]);
|
||||
|
||||
harness.pushDiff({
|
||||
op: TestDiffOpType.Remove,
|
||||
itemId: new TestId(['ctrlId', 'id-b']).toString(),
|
||||
});
|
||||
harness.flush();
|
||||
assert.deepStrictEqual(harness.tree.getRendered(), [
|
||||
{ e: 'ca' }
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -465,6 +465,6 @@ function handleParentFolder(key: string, selectors: string[]): string {
|
||||
}
|
||||
|
||||
function escapeCSS(str: string) {
|
||||
str = str.replace(/[\11\12\14\15\40]/g, '/'); // HTML class names can not contain certain whitespace characters, use / instead, which doesn't exist in file names.
|
||||
str = str.replace(/[\x11\x12\x14\x15\x40]/g, '/'); // HTML class names can not contain certain whitespace characters, use / instead, which doesn't exist in file names.
|
||||
return mainWindow.CSS.escape(str);
|
||||
}
|
||||
|
||||
@@ -68,11 +68,11 @@ export class TunnelService extends AbstractTunnelService {
|
||||
super(logService, configurationService);
|
||||
|
||||
// Destroy any shared process tunnels that might still be active
|
||||
lifecycleService.onDidShutdown(() => {
|
||||
this._register(lifecycleService.onDidShutdown(() => {
|
||||
this._activeSharedProcessTunnels.forEach((id) => {
|
||||
this._sharedProcessTunnelService.destroyTunnel(id);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
public isPortPrivileged(port: number): boolean {
|
||||
|
||||
@@ -19,15 +19,6 @@ declare module 'vscode' {
|
||||
* @param icon An icon to display when selecting context in the picker UI.
|
||||
*/
|
||||
export function registerChatVariableResolver(id: string, name: string, userDescription: string, modelDescription: string | undefined, isSlow: boolean | undefined, resolver: ChatVariableResolver, fullName?: string, icon?: ThemeIcon): Disposable;
|
||||
|
||||
/**
|
||||
* Attaches a chat context with the specified name, value, and location.
|
||||
*
|
||||
* @param name - The name of the chat context.
|
||||
* @param value - The value of the chat context.
|
||||
* @param location - The location of the chat context.
|
||||
*/
|
||||
export function attachContext(name: string, value: string | Uri | Location | unknown, location: ChatLocation.Panel): void;
|
||||
}
|
||||
|
||||
export interface ChatVariableValue {
|
||||
|
||||
@@ -1982,40 +1982,40 @@
|
||||
resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e"
|
||||
integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==
|
||||
|
||||
"@xterm/addon-image@0.9.0-beta.17":
|
||||
version "0.9.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.9.0-beta.17.tgz#343d0665a6060d4f893b4f2d32de6ccbbd00bb63"
|
||||
integrity sha512-g0r2hpBcLABY5as4llsMP36RHtkWooEn7tf+7U0/hTndJoCAvs4uGDqZNQigFgeAM3lJ4PnRYh4lfnEh9bGt8A==
|
||||
"@xterm/addon-image@0.9.0-beta.19":
|
||||
version "0.9.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-image/-/addon-image-0.9.0-beta.19.tgz#3823382e5c55268998f0e0d8d77e8b7810925830"
|
||||
integrity sha512-LX9g03po3mXYE/HZFoKbdnIRvdD56Qw84FpQ9LCJGDsyx9SFIf47DXLS+lXCEpJ2hjKIing46BQxP+MDEayXDw==
|
||||
|
||||
"@xterm/addon-search@0.16.0-beta.17":
|
||||
version "0.16.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-search/-/addon-search-0.16.0-beta.17.tgz#7cb01c7f498405909d37040884ee22d1889a36d2"
|
||||
integrity sha512-wBfxmWOeqG6HHHE5mVamDJ75zBdHC35ERNy5/aTpQsQsyxrnV0Ks76c8ZVTaTu9wyBCAyx7UmZT42Ot80khY/g==
|
||||
"@xterm/addon-search@0.16.0-beta.19":
|
||||
version "0.16.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-search/-/addon-search-0.16.0-beta.19.tgz#46b3374eb312a1bff974a5df188b1ebf777ff49d"
|
||||
integrity sha512-iTJVUEsKSdL8SyhcDBqN6gYxhqv0wrwtP1QCUGLKNAAVDI7HKVgig3V9wToqRxYfOnu/anyU+u0qFUoKCRLnCg==
|
||||
|
||||
"@xterm/addon-serialize@0.14.0-beta.17":
|
||||
version "0.14.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.17.tgz#1cb8e35c0d118060a807adb340624fa7f80dd9c5"
|
||||
integrity sha512-/c3W39kdRgGGYDoYjXb5HrUC421qwPn6NryAT4WJuJWnyMtFbe2DPwKsTfHuCBPiPyovS3a9j950Md3O3YXDZA==
|
||||
"@xterm/addon-serialize@0.14.0-beta.19":
|
||||
version "0.14.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.19.tgz#c7a0a0e5f5b1bd94a35a775ec6224ba42282556c"
|
||||
integrity sha512-D+BiXQfuxDb3azAIBq1RJTQGZlvo459V6U/2s/3dKpTAvRybqCRMazuf8cLoffUoNcjTb3uSWpii9+MVVvHIrQ==
|
||||
|
||||
"@xterm/addon-unicode11@0.9.0-beta.17":
|
||||
version "0.9.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.17.tgz#b5558148029a796c6a6d78e2a8b7255f92a51530"
|
||||
integrity sha512-z7v8uojFVrO1aLSWtnz5MzSrfWRT8phde7kh9ufqHLBv7YYtMHxlPVjSuW8PZ2h4eY1LOZf6icUAzrmyJmJ7Kg==
|
||||
"@xterm/addon-unicode11@0.9.0-beta.19":
|
||||
version "0.9.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.19.tgz#529d8b22d9378cff8c31df1b7e76250b2f8079c3"
|
||||
integrity sha512-0Umiu9GkjwL/jaT85Rcfka9HVyJw3UhJsnOVOVZd/3YBZqMY2SZMHqz73W/qpXl5nz6vvyCWKbpkfddsJhpToA==
|
||||
|
||||
"@xterm/addon-webgl@0.19.0-beta.17":
|
||||
version "0.19.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.17.tgz#68ad9e68dd1cf581b391971de33f5c04966b0d8e"
|
||||
integrity sha512-X8ObRgoZl7UZTgdndM+mpSO3hLzAhWKoXXrGvUQg/7XabRKAPrQ2XvdyZm04nYwibE6Tpit2h5kkxjlVqupIig==
|
||||
"@xterm/addon-webgl@0.19.0-beta.19":
|
||||
version "0.19.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.19.tgz#655d1e27b1249c19352c65a8ea1d0bf319397b35"
|
||||
integrity sha512-Y5efISx8X5hpFAsPOTza1Fp0xiD8x+l3MuH+mv68v1El8tpna/MW5EM4oX25qYOsPDZY00mpmkBmPbAT5loMEg==
|
||||
|
||||
"@xterm/headless@5.6.0-beta.17":
|
||||
version "5.6.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/headless/-/headless-5.6.0-beta.17.tgz#bff1d67c9c061c57adff22571e733d54e3aba2b7"
|
||||
integrity sha512-ehS7y/XRqX1ppx4RPiYc0vu0SdIQ91aA4lSN/2XNOf3IGdP0A38Q7a0T6mzqxRGZKiiyA0kTR1szr78wnY+wmA==
|
||||
"@xterm/headless@5.6.0-beta.19":
|
||||
version "5.6.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/headless/-/headless-5.6.0-beta.19.tgz#dbbd4dd420e24e9bdee6e533153f405bfc1ba89b"
|
||||
integrity sha512-zFTcftonaaMEbMqfQnFwos1YQCmqWnvIzSNXwmfIymkEvSxhsB03oynEjFwm48dT2filTcJXpYT91io4qvR+3g==
|
||||
|
||||
"@xterm/xterm@5.6.0-beta.17":
|
||||
version "5.6.0-beta.17"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/xterm/-/xterm-5.6.0-beta.17.tgz#67ce2e2ff45bd6cc9f26d455d5522c6c4a122ed9"
|
||||
integrity sha512-+wAv8PhaGQSN9yXWIa8EFtT33pbrA4lZakMB1P05fr+DQ7zoH66QOAUoDY95uOf/4+S6Ihz8wzP2+FH8zETQEA==
|
||||
"@xterm/xterm@5.6.0-beta.19":
|
||||
version "5.6.0-beta.19"
|
||||
resolved "https://registry.yarnpkg.com/@xterm/xterm/-/xterm-5.6.0-beta.19.tgz#2cc292fc93b25c7c655ed6d1f0425a636b36747d"
|
||||
integrity sha512-mGoJxrUxAL4dueZEqw2e23KCrGNSvYaw5twTnccKqK7lITK/hDrosWCxb1jL1AjFf7bBzMxw9/dZdhWncKQQmw==
|
||||
|
||||
"@xtuc/ieee754@^1.2.0":
|
||||
version "1.2.0"
|
||||
@@ -6229,10 +6229,10 @@ js-yaml@^3.13.0:
|
||||
argparse "^1.0.7"
|
||||
esprima "^4.0.0"
|
||||
|
||||
jschardet@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.0.0.tgz#898d2332e45ebabbdb6bf2feece9feea9a99e882"
|
||||
integrity sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==
|
||||
jschardet@3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-3.1.2.tgz#9bf4364deba0677fe9e3bd9e29eda57febf2e9db"
|
||||
integrity sha512-mw3CBZGzW8nUBPYhFU2ztZ/kJ6NClQUQVpyzvFMfznZsoC///ZQ30J2RCUanNsr5yF22LqhgYr/lj807/ZleWA==
|
||||
|
||||
jsdoc-type-pratt-parser@~4.0.0:
|
||||
version "4.0.0"
|
||||
@@ -10055,10 +10055,10 @@ typescript@^4.7.4:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6"
|
||||
integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==
|
||||
|
||||
typescript@^5.5.0-dev.20240521:
|
||||
version "5.5.0-dev.20240521"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.0-dev.20240521.tgz#a53f71ad2f5e4c4401a56c35993474b77813364c"
|
||||
integrity sha512-52WLKX9mbRmStK1lb30KM78dSo5ssgQT8WQERYiv8JihXir4HUgwlgTz4crExojzpsGjFGFJROL/bZrhXUiOEQ==
|
||||
typescript@^5.5.0-dev.20240603:
|
||||
version "5.5.0-dev.20240603"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.0-dev.20240603.tgz#a1b7311df5039a8abbaaa2213c21cac6ec547490"
|
||||
integrity sha512-gdm3Sh1A+Pjj9ZlfBEJY3o2rs3tvpcSbu3vYqcCijMe09BePQBtZlsuShuPn+zCnP+qBLxdKjFiw5v1tkna3tA==
|
||||
|
||||
typical@^4.0.0:
|
||||
version "4.0.0"
|
||||
|
||||
Reference in New Issue
Block a user