mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-04-01 09:30:31 -04:00
Merge from vscode a416c77e56ef0314ae00633faa04878151610de8 (#8600)
* Merge from vscode a416c77e56ef0314ae00633faa04878151610de8 * distro * fix tests * fix tests
This commit is contained in:
@@ -50,10 +50,6 @@
|
||||
"name": "vs/workbench/contrib/comments",
|
||||
"project": "vscode-workbench"
|
||||
},
|
||||
{
|
||||
"name": "vs/workbench/contrib/testCustomEditors",
|
||||
"project": "vscode-workbench"
|
||||
},
|
||||
{
|
||||
"name": "vs/workbench/contrib/debug",
|
||||
"project": "vscode-workbench"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema#",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "Configures an attached to container",
|
||||
"allowComments": true,
|
||||
"type": "object",
|
||||
@@ -18,6 +18,10 @@
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"$ref": "vscode://schemas/settings/machine",
|
||||
"description": "Machine specific settings that should be copied into the container."
|
||||
},
|
||||
"remoteEnv": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema#",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "Defines a dev container",
|
||||
"allowComments": true,
|
||||
"type": "object",
|
||||
@@ -84,6 +84,13 @@
|
||||
"type": "boolean",
|
||||
"description": "Controls whether on Linux the container's user should be updated with the local user's UID and GID. On by default."
|
||||
},
|
||||
"mounts": {
|
||||
"type": "array",
|
||||
"description": "Mount points to set up when creating the container. See Docker's documentation for the --mount option for the supported syntax.",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"runArgs": {
|
||||
"type": "array",
|
||||
"description": "The arguments required when starting in the container.",
|
||||
|
||||
@@ -13,5 +13,4 @@ Supported image formats:
|
||||
- `*.bmp`
|
||||
- `*.gif`
|
||||
- `*.ico`
|
||||
- `*.tga`
|
||||
- `*.webp`
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "image-preview",
|
||||
"displayName": "%displayName%",
|
||||
"description": "%description%",
|
||||
"extensionKind": "ui",
|
||||
"extensionKind": ["ui", "workspace"],
|
||||
"version": "1.0.0",
|
||||
"publisher": "vscode",
|
||||
"icon": "icon.png",
|
||||
|
||||
@@ -10,8 +10,16 @@ import { xhr, XHRResponse, getErrorStatusDescription } from 'request-light';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
import { workspace, window, languages, commands, ExtensionContext, extensions, Uri, LanguageConfiguration, Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken, ProviderResult, TextEdit, Range, Disposable } from 'vscode';
|
||||
import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification, HandleDiagnosticsSignature, ResponseError, DocumentRangeFormattingParams, DocumentRangeFormattingRequest } from 'vscode-languageclient';
|
||||
import {
|
||||
workspace, window, languages, commands, ExtensionContext, extensions, Uri, LanguageConfiguration,
|
||||
Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken,
|
||||
ProviderResult, TextEdit, Range, Position, Disposable, CompletionItem, CompletionList, CompletionContext
|
||||
} from 'vscode';
|
||||
import {
|
||||
LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType,
|
||||
DidChangeConfigurationNotification, HandleDiagnosticsSignature, ResponseError, DocumentRangeFormattingParams,
|
||||
DocumentRangeFormattingRequest, ProvideCompletionItemsSignature
|
||||
} from 'vscode-languageclient';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
|
||||
import { hash } from './utils/hash';
|
||||
@@ -36,6 +44,10 @@ namespace SchemaAssociationNotification {
|
||||
export const type: NotificationType<ISchemaAssociations, any> = new NotificationType('json/schemaAssociations');
|
||||
}
|
||||
|
||||
namespace ResultLimitReachedNotification {
|
||||
export const type: NotificationType<string, any> = new NotificationType('json/resultLimitReached');
|
||||
}
|
||||
|
||||
interface IPackageInfo {
|
||||
name: string;
|
||||
version: string;
|
||||
@@ -132,6 +144,29 @@ export function activate(context: ExtensionContext) {
|
||||
}
|
||||
|
||||
next(uri, diagnostics);
|
||||
},
|
||||
// testing the replace / insert mode
|
||||
provideCompletionItem(document: TextDocument, position: Position, context: CompletionContext, token: CancellationToken, next: ProvideCompletionItemsSignature): ProviderResult<CompletionItem[] | CompletionList> {
|
||||
function updateRanges(item: CompletionItem) {
|
||||
const range = item.range;
|
||||
if (range && range.end.isAfter(position) && range.start.isBeforeOrEqual(position)) {
|
||||
item.range2 = { inserting: new Range(range.start, position), replacing: range };
|
||||
item.range = undefined;
|
||||
}
|
||||
}
|
||||
function updateProposals(r: CompletionItem[] | CompletionList | null | undefined): CompletionItem[] | CompletionList | null | undefined {
|
||||
if (r) {
|
||||
(Array.isArray(r) ? r : r.items).forEach(updateRanges);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
const isThenable = <T>(obj: ProviderResult<T>): obj is Thenable<T> => obj && (<any>obj)['then'];
|
||||
|
||||
const r = next(document, position, context, token);
|
||||
if (isThenable<CompletionItem[] | CompletionList | null | undefined>(r)) {
|
||||
return r.then(updateProposals);
|
||||
}
|
||||
return updateProposals(r);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -239,6 +274,12 @@ export function activate(context: ExtensionContext) {
|
||||
updateFormatterRegistration();
|
||||
toDispose.push({ dispose: () => rangeFormatting && rangeFormatting.dispose() });
|
||||
toDispose.push(workspace.onDidChangeConfiguration(e => e.affectsConfiguration('html.format.enable') && updateFormatterRegistration()));
|
||||
|
||||
|
||||
client.onNotification(ResultLimitReachedNotification.type, message => {
|
||||
window.showInformationMessage(`${message}\nUse setting 'json.maxItemsComputed' to configure the limit.`);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
let languageConfiguration: LanguageConfiguration = {
|
||||
@@ -320,6 +361,8 @@ function getSchemaAssociation(_context: ExtensionContext): ISchemaAssociations {
|
||||
function getSettings(): Settings {
|
||||
let httpSettings = workspace.getConfiguration('http');
|
||||
|
||||
let resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get('json.maxItemsComputed')))) || 5000;
|
||||
|
||||
let settings: Settings = {
|
||||
http: {
|
||||
proxy: httpSettings.get('proxy'),
|
||||
@@ -327,7 +370,7 @@ function getSettings(): Settings {
|
||||
},
|
||||
json: {
|
||||
schemas: [],
|
||||
resultLimit: 5000
|
||||
resultLimit
|
||||
}
|
||||
};
|
||||
let schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null);
|
||||
@@ -422,5 +465,4 @@ function readJSONFile(location: string) {
|
||||
console.log(`Problems reading ${location}: ${e}`);
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,113 +1,125 @@
|
||||
{
|
||||
"name": "json-language-features",
|
||||
"displayName": "%displayName%",
|
||||
"description": "%description%",
|
||||
"version": "1.0.0",
|
||||
"publisher": "vscode",
|
||||
"license": "MIT",
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"engines": {
|
||||
"vscode": "0.10.x"
|
||||
},
|
||||
"icon": "icons/json.png",
|
||||
"activationEvents": [
|
||||
"onLanguage:json",
|
||||
"onLanguage:jsonc"
|
||||
],
|
||||
"main": "./client/out/jsonMain",
|
||||
"enableProposedApi": true,
|
||||
"scripts": {
|
||||
"compile": "gulp compile-extension:json-language-features-client compile-extension:json-language-features-server",
|
||||
"watch": "gulp watch-extension:json-language-features-client watch-extension:json-language-features-server",
|
||||
"postinstall": "cd server && yarn install",
|
||||
"install-client-next": "yarn add vscode-languageclient@next"
|
||||
},
|
||||
"categories": [
|
||||
"Programming Languages"
|
||||
],
|
||||
"contributes": {
|
||||
"configuration": {
|
||||
"id": "json",
|
||||
"order": 20,
|
||||
"type": "object",
|
||||
"title": "JSON",
|
||||
"properties": {
|
||||
"json.schemas": {
|
||||
"type": "array",
|
||||
"scope": "resource",
|
||||
"description": "%json.schemas.desc%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"fileMatch": [
|
||||
"/myfile"
|
||||
],
|
||||
"url": "schemaURL"
|
||||
},
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"default": "/user.schema.json",
|
||||
"description": "%json.schemas.url.desc%"
|
||||
},
|
||||
"fileMatch": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"default": "MyFile.json",
|
||||
"description": "%json.schemas.fileMatch.item.desc%"
|
||||
},
|
||||
"minItems": 1,
|
||||
"description": "%json.schemas.fileMatch.desc%"
|
||||
},
|
||||
"schema": {
|
||||
"$ref": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "%json.schemas.schema.desc%"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"json.format.enable": {
|
||||
"type": "boolean",
|
||||
"scope": "window",
|
||||
"default": true,
|
||||
"description": "%json.format.enable.desc%"
|
||||
},
|
||||
"json.trace.server": {
|
||||
"type": "string",
|
||||
"scope": "window",
|
||||
"enum": [
|
||||
"off",
|
||||
"messages",
|
||||
"verbose"
|
||||
],
|
||||
"default": "off",
|
||||
"description": "%json.tracing.desc%"
|
||||
},
|
||||
"json.colorDecorators.enable": {
|
||||
"type": "boolean",
|
||||
"scope": "window",
|
||||
"default": true,
|
||||
"description": "%json.colorDecorators.enable.desc%",
|
||||
"deprecationMessage": "%json.colorDecorators.enable.deprecationMessage%"
|
||||
}
|
||||
}
|
||||
"name": "json-language-features",
|
||||
"displayName": "%displayName%",
|
||||
"description": "%description%",
|
||||
"version": "1.0.0",
|
||||
"publisher": "vscode",
|
||||
"license": "MIT",
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"engines": {
|
||||
"vscode": "0.10.x"
|
||||
},
|
||||
"configurationDefaults": {
|
||||
"[json]": {
|
||||
"editor.quickSuggestions": {
|
||||
"strings": true
|
||||
"icon": "icons/json.png",
|
||||
"activationEvents": [
|
||||
"onLanguage:json",
|
||||
"onLanguage:jsonc"
|
||||
],
|
||||
"main": "./client/out/jsonMain",
|
||||
"enableProposedApi": true,
|
||||
"scripts": {
|
||||
"compile": "gulp compile-extension:json-language-features-client compile-extension:json-language-features-server",
|
||||
"watch": "gulp watch-extension:json-language-features-client watch-extension:json-language-features-server",
|
||||
"postinstall": "cd server && yarn install",
|
||||
"install-client-next": "yarn add vscode-languageclient@next"
|
||||
},
|
||||
"categories": [
|
||||
"Programming Languages"
|
||||
],
|
||||
"contributes": {
|
||||
"configuration": {
|
||||
"id": "json",
|
||||
"order": 20,
|
||||
"type": "object",
|
||||
"title": "JSON",
|
||||
"properties": {
|
||||
"json.schemas": {
|
||||
"type": "array",
|
||||
"scope": "resource",
|
||||
"description": "%json.schemas.desc%",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"fileMatch": [
|
||||
"/myfile"
|
||||
],
|
||||
"url": "schemaURL"
|
||||
},
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"default": "/user.schema.json",
|
||||
"description": "%json.schemas.url.desc%"
|
||||
},
|
||||
"fileMatch": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"default": "MyFile.json",
|
||||
"description": "%json.schemas.fileMatch.item.desc%"
|
||||
},
|
||||
"minItems": 1,
|
||||
"description": "%json.schemas.fileMatch.desc%"
|
||||
},
|
||||
"schema": {
|
||||
"$ref": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "%json.schemas.schema.desc%"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"json.format.enable": {
|
||||
"type": "boolean",
|
||||
"scope": "window",
|
||||
"default": true,
|
||||
"description": "%json.format.enable.desc%"
|
||||
},
|
||||
"json.trace.server": {
|
||||
"type": "string",
|
||||
"scope": "window",
|
||||
"enum": [
|
||||
"off",
|
||||
"messages",
|
||||
"verbose"
|
||||
],
|
||||
"default": "off",
|
||||
"description": "%json.tracing.desc%"
|
||||
},
|
||||
"json.colorDecorators.enable": {
|
||||
"type": "boolean",
|
||||
"scope": "window",
|
||||
"default": true,
|
||||
"description": "%json.colorDecorators.enable.desc%",
|
||||
"deprecationMessage": "%json.colorDecorators.enable.deprecationMessage%"
|
||||
},
|
||||
"json.maxItemsComputed": {
|
||||
"type": "number",
|
||||
"default": 5000,
|
||||
"description": "%json.maxItemsComputed.desc%"
|
||||
}
|
||||
}
|
||||
},
|
||||
"configurationDefaults": {
|
||||
"[json]": {
|
||||
"editor.quickSuggestions": {
|
||||
"strings": true
|
||||
},
|
||||
"editor.suggest.insertMode": "replace"
|
||||
},
|
||||
"[jsonc]": {
|
||||
"editor.quickSuggestions": {
|
||||
"strings": true
|
||||
},
|
||||
"editor.suggest.insertMode": "replace"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"request-light": "^0.2.5",
|
||||
"vscode-extension-telemetry": "0.1.1",
|
||||
"vscode-languageclient": "^6.0.0-next.3",
|
||||
"vscode-nls": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.11.7"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"request-light": "^0.2.5",
|
||||
"vscode-extension-telemetry": "0.1.1",
|
||||
"vscode-languageclient": "^6.0.0-next.3",
|
||||
"vscode-nls": "^4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.11.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,6 @@
|
||||
"json.colorDecorators.enable.desc": "Enables or disables color decorators",
|
||||
"json.colorDecorators.enable.deprecationMessage": "The setting `json.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`.",
|
||||
"json.schemaResolutionErrorMessage": "Unable to resolve schema.",
|
||||
"json.clickToRetry": "Click to retry."
|
||||
"json.clickToRetry": "Click to retry.",
|
||||
"json.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons)."
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ The server supports the following settings:
|
||||
- `fileMatch`: an array of file names or paths (separated by `/`). `*` can be used as a wildcard.
|
||||
- `url`: The URL of the schema, optional when also a schema is provided.
|
||||
- `schema`: The schema content.
|
||||
- `resultLimit`: The max number foldig ranges and otline symbols to be computed (for performance reasons)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -153,6 +154,16 @@ Notification:
|
||||
- method: 'json/schemaContent'
|
||||
- params: `string` the URL of the schema that has changed.
|
||||
|
||||
### Item Limit
|
||||
|
||||
If the setting `resultLimit` is set, the JSON language server will limit the number of folding ranges and document symbols computed.
|
||||
When the limit is reached, a notification `json/resultLimitReached` is sent that can be shown that camn be shown to the user.
|
||||
|
||||
Notification:
|
||||
- method: 'json/resultLimitReached'
|
||||
- params: a human readable string to show to the user.
|
||||
|
||||
|
||||
## Try
|
||||
|
||||
The JSON language server is shipped with [Visual Studio Code](https://code.visualstudio.com/) as part of the built-in VSCode extension `json-language-features`. The server is started when the first JSON file is opened. The [VSCode JSON documentation](https://code.visualstudio.com/docs/languages/json) for detailed information on the user experience and has more information on how to configure the language support.
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"dependencies": {
|
||||
"jsonc-parser": "^2.2.0",
|
||||
"request-light": "^0.2.5",
|
||||
"vscode-json-languageservice": "^3.4.7",
|
||||
"vscode-json-languageservice": "^3.4.9",
|
||||
"vscode-languageserver": "^6.0.0-next.3",
|
||||
"vscode-uri": "^2.1.1"
|
||||
},
|
||||
|
||||
@@ -35,6 +35,10 @@ namespace SchemaContentChangeNotification {
|
||||
export const type: NotificationType<string, any> = new NotificationType('json/schemaContent');
|
||||
}
|
||||
|
||||
namespace ResultLimitReachedNotification {
|
||||
export const type: NotificationType<string, any> = new NotificationType('json/resultLimitReached');
|
||||
}
|
||||
|
||||
namespace ForceValidateRequest {
|
||||
export const type: RequestType<string, Diagnostic[], any, any> = new RequestType('json/validate');
|
||||
}
|
||||
@@ -211,7 +215,7 @@ namespace LimitExceededWarnings {
|
||||
} else {
|
||||
warning = { features: { [name]: name } };
|
||||
warning.timeout = setTimeout(() => {
|
||||
connection.window.showInformationMessage(`${posix.basename(uri)}: For performance reasons, ${Object.keys(warning.features).join(' and ')} have been limited to ${resultLimit} items.`);
|
||||
connection.sendNotification(ResultLimitReachedNotification.type, `${posix.basename(uri)}: For performance reasons, ${Object.keys(warning.features).join(' and ')} have been limited to ${resultLimit} items.`);
|
||||
warning.timeout = undefined;
|
||||
}, 2000);
|
||||
pendingWarnings[uri] = warning;
|
||||
|
||||
@@ -80,10 +80,10 @@ request-light@^0.2.5:
|
||||
https-proxy-agent "^2.2.3"
|
||||
vscode-nls "^4.1.1"
|
||||
|
||||
vscode-json-languageservice@^3.4.7:
|
||||
version "3.4.7"
|
||||
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.4.7.tgz#8d85f3c1d46a1e58e9867d747552fb8c83d934fd"
|
||||
integrity sha512-y3MN2+/yph3yoIHGmHu4ScYpm285L58XVvfGkd49xTQzLja4apxSbwzsYcP9QsqS0W7KuvoyiPhqksiudoMwjg==
|
||||
vscode-json-languageservice@^3.4.9:
|
||||
version "3.4.9"
|
||||
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.4.9.tgz#7ce485bb0f9a07b4d879c988baac9be2222909ad"
|
||||
integrity sha512-4VCpZ9ooea/Zc/MTnj1ccc9C7rqcoinKVQLhLoi6jw6yueSf4y4tg/YIUiPPVMlEAG7ZCPS+NVmqxisQ+mOsSw==
|
||||
dependencies:
|
||||
jsonc-parser "^2.2.0"
|
||||
vscode-languageserver-textdocument "^1.0.0-next.4"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Markdown contributions to package.json",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -29,4 +29,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,8 +249,11 @@ export class MarkdownEngine {
|
||||
if (uri.path[0] === '/') {
|
||||
const root = vscode.workspace.getWorkspaceFolder(this.currentDocument!);
|
||||
if (root) {
|
||||
uri = uri.with({
|
||||
path: path.join(root.uri.fsPath, uri.path),
|
||||
const fileUri = vscode.Uri.file(path.join(root.uri.fsPath, uri.fsPath));
|
||||
uri = fileUri.with({
|
||||
scheme: uri.scheme,
|
||||
fragment: uri.fragment,
|
||||
query: uri.query,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.1",
|
||||
"description": "Dependencies shared by all extensions",
|
||||
"dependencies": {
|
||||
"typescript": "3.7.3-insiders.20191123"
|
||||
"typescript": "3.7.3"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "node ./postinstall"
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:search-result ./tsconfig.json"
|
||||
},
|
||||
"contributes": {
|
||||
"configurationDefaults": {
|
||||
"[search-result]": {
|
||||
"editor.lineNumbers": "off"
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"command": "searchResult.rerunSearch",
|
||||
@@ -28,6 +33,15 @@
|
||||
"light": "./src/media/refresh-light.svg",
|
||||
"dark": "./src/media/refresh-dark.svg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "searchResult.rerunSearchWithContext",
|
||||
"title": "%searchResult.rerunSearchWithContext.title%",
|
||||
"category": "Search Result",
|
||||
"icon": {
|
||||
"light": "./src/media/refresh-light.svg",
|
||||
"dark": "./src/media/refresh-dark.svg"
|
||||
}
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
@@ -35,6 +49,7 @@
|
||||
{
|
||||
"command": "searchResult.rerunSearch",
|
||||
"when": "editorLangId == search-result",
|
||||
"alt": "searchResult.rerunSearchWithContext",
|
||||
"group": "navigation"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"displayName": "Search Result",
|
||||
"description": "Provides syntax highlighting and language features for tabbed search results.",
|
||||
"searchResult.rerunSearch.title": "Search Again"
|
||||
"searchResult.rerunSearch.title": "Search Again",
|
||||
"searchResult.rerunSearchWithContext.title": "Search Again (With Context)"
|
||||
}
|
||||
|
||||
@@ -7,81 +7,93 @@ import * as vscode from 'vscode';
|
||||
import * as pathUtils from 'path';
|
||||
|
||||
const FILE_LINE_REGEX = /^(\S.*):$/;
|
||||
const RESULT_LINE_REGEX = /^(\s+)(\d+):(\s+)(.*)$/;
|
||||
const RESULT_LINE_REGEX = /^(\s+)(\d+)(:| )(\s+)(.*)$/;
|
||||
const SEARCH_RESULT_SELECTOR = { language: 'search-result' };
|
||||
const DIRECTIVES = ['# Query:', '# Flags:', '# Including:', '# Excluding:', '# ContextLines:'];
|
||||
const FLAGS = ['RegExp', 'CaseSensitive', 'IgnoreExcludeSettings', 'WordMatch'];
|
||||
|
||||
let cachedLastParse: { version: number, parse: ParsedSearchResults } | undefined;
|
||||
|
||||
export function activate() {
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand('searchResult.rerunSearch', () => vscode.commands.executeCommand('search.action.rerunEditorSearch')),
|
||||
vscode.commands.registerCommand('searchResult.rerunSearchWithContext', () => vscode.commands.executeCommand('search.action.rerunEditorSearchWithContext')),
|
||||
|
||||
vscode.commands.registerCommand('searchResult.rerunSearch', () => vscode.commands.executeCommand('search.action.rerunEditorSearch'));
|
||||
vscode.languages.registerDocumentSymbolProvider(SEARCH_RESULT_SELECTOR, {
|
||||
provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.DocumentSymbol[] {
|
||||
const results = parseSearchResults(document, token)
|
||||
.filter(isFileLine)
|
||||
.map(line => new vscode.DocumentSymbol(
|
||||
line.path,
|
||||
'',
|
||||
vscode.SymbolKind.File,
|
||||
line.allLocations.map(({ originSelectionRange }) => originSelectionRange!).reduce((p, c) => p.union(c), line.location.originSelectionRange!),
|
||||
line.location.originSelectionRange!,
|
||||
));
|
||||
|
||||
vscode.languages.registerDocumentSymbolProvider(SEARCH_RESULT_SELECTOR, {
|
||||
provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.DocumentSymbol[] {
|
||||
const results = parseSearchResults(document, token)
|
||||
.filter(isFileLine)
|
||||
.map(line => new vscode.DocumentSymbol(
|
||||
line.path,
|
||||
'',
|
||||
vscode.SymbolKind.File,
|
||||
line.allLocations.map(({ originSelectionRange }) => originSelectionRange!).reduce((p, c) => p.union(c), line.location.originSelectionRange!),
|
||||
line.location.originSelectionRange!,
|
||||
));
|
||||
|
||||
return results;
|
||||
}
|
||||
});
|
||||
|
||||
vscode.languages.registerCompletionItemProvider(SEARCH_RESULT_SELECTOR, {
|
||||
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
|
||||
|
||||
const line = document.lineAt(position.line);
|
||||
if (position.line > 3) { return []; }
|
||||
if (position.character === 0 || (position.character === 1 && line.text === '#')) {
|
||||
const header = Array.from({ length: 4 }).map((_, i) => document.lineAt(i).text);
|
||||
|
||||
return ['# Query:', '# Flags:', '# Including:', '# Excluding:']
|
||||
.filter(suggestion => header.every(line => line.indexOf(suggestion) === -1))
|
||||
.map(flag => ({ label: flag, insertText: (flag.slice(position.character)) + ' ' }));
|
||||
return results;
|
||||
}
|
||||
}),
|
||||
|
||||
if (line.text.indexOf('# Flags:') === -1) { return []; }
|
||||
vscode.languages.registerCompletionItemProvider(SEARCH_RESULT_SELECTOR, {
|
||||
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
|
||||
|
||||
return ['RegExp', 'CaseSensitive', 'IgnoreExcludeSettings', 'WordMatch']
|
||||
.filter(flag => line.text.indexOf(flag) === -1)
|
||||
.map(flag => ({ label: flag, insertText: flag + ' ' }));
|
||||
}
|
||||
}, '#');
|
||||
const line = document.lineAt(position.line);
|
||||
if (position.line > 3) { return []; }
|
||||
if (position.character === 0 || (position.character === 1 && line.text === '#')) {
|
||||
const header = Array.from({ length: DIRECTIVES.length }).map((_, i) => document.lineAt(i).text);
|
||||
|
||||
vscode.languages.registerDefinitionProvider(SEARCH_RESULT_SELECTOR, {
|
||||
provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.DefinitionLink[] {
|
||||
const lineResult = parseSearchResults(document, token)[position.line];
|
||||
if (!lineResult) { return []; }
|
||||
if (lineResult.type === 'file') {
|
||||
// TODO: The multi-match peek UX isnt very smooth.
|
||||
// return lineResult.allLocations.length > 1 ? lineResult.allLocations : [lineResult.location];
|
||||
return [];
|
||||
return DIRECTIVES
|
||||
.filter(suggestion => header.every(line => line.indexOf(suggestion) === -1))
|
||||
.map(flag => ({ label: flag, insertText: (flag.slice(position.character)) + ' ' }));
|
||||
}
|
||||
|
||||
if (line.text.indexOf('# Flags:') === -1) { return []; }
|
||||
|
||||
return FLAGS
|
||||
.filter(flag => line.text.indexOf(flag) === -1)
|
||||
.map(flag => ({ label: flag, insertText: flag + ' ' }));
|
||||
}
|
||||
}, '#'),
|
||||
|
||||
return [lineResult.location];
|
||||
}
|
||||
});
|
||||
vscode.languages.registerDefinitionProvider(SEARCH_RESULT_SELECTOR, {
|
||||
provideDefinition(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.DefinitionLink[] {
|
||||
const lineResult = parseSearchResults(document, token)[position.line];
|
||||
if (!lineResult) { return []; }
|
||||
if (lineResult.type === 'file') {
|
||||
// TODO: The multi-match peek UX isnt very smooth.
|
||||
// return lineResult.allLocations.length > 1 ? lineResult.allLocations : [lineResult.location];
|
||||
return [];
|
||||
}
|
||||
|
||||
vscode.languages.registerDocumentLinkProvider(SEARCH_RESULT_SELECTOR, {
|
||||
async provideDocumentLinks(document: vscode.TextDocument, token: vscode.CancellationToken): Promise<vscode.DocumentLink[]> {
|
||||
return parseSearchResults(document, token)
|
||||
.filter(({ type }) => type === 'file')
|
||||
.map(({ location }) => ({ range: location.originSelectionRange!, target: location.targetUri }));
|
||||
}
|
||||
});
|
||||
const translateRangeSidewaysBy = (r: vscode.Range, n: number) =>
|
||||
r.with({ start: new vscode.Position(r.start.line, Math.max(0, n - r.start.character)), end: new vscode.Position(r.end.line, Math.max(0, n - r.end.character)) });
|
||||
|
||||
vscode.window.onDidChangeActiveTextEditor(e => {
|
||||
if (e?.document.languageId === 'search-result') {
|
||||
// Clear the parse whenever we open a new editor.
|
||||
// Conservative because things like the URI might remain constant even if the contents change, and re-parsing even large files is relatively fast.
|
||||
cachedLastParse = undefined;
|
||||
}
|
||||
});
|
||||
return [{
|
||||
...lineResult.location,
|
||||
targetSelectionRange: translateRangeSidewaysBy(lineResult.location.targetSelectionRange!, position.character - 1)
|
||||
}];
|
||||
}
|
||||
}),
|
||||
|
||||
vscode.languages.registerDocumentLinkProvider(SEARCH_RESULT_SELECTOR, {
|
||||
async provideDocumentLinks(document: vscode.TextDocument, token: vscode.CancellationToken): Promise<vscode.DocumentLink[]> {
|
||||
return parseSearchResults(document, token)
|
||||
.filter(({ type }) => type === 'file')
|
||||
.map(({ location }) => ({ range: location.originSelectionRange!, target: location.targetUri }));
|
||||
}
|
||||
}),
|
||||
|
||||
vscode.window.onDidChangeActiveTextEditor(e => {
|
||||
if (e?.document.languageId === 'search-result') {
|
||||
// Clear the parse whenever we open a new editor.
|
||||
// Conservative because things like the URI might remain constant even if the contents change, and re-parsing even large files is relatively fast.
|
||||
cachedLastParse = undefined;
|
||||
}
|
||||
}),
|
||||
|
||||
{ dispose() { cachedLastParse = undefined; } }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -160,13 +172,14 @@ function parseSearchResults(document: vscode.TextDocument, token: vscode.Cancell
|
||||
|
||||
const resultLine = RESULT_LINE_REGEX.exec(line);
|
||||
if (resultLine) {
|
||||
const [, indentation, _lineNumber, resultIndentation] = resultLine;
|
||||
const [, indentation, _lineNumber, seperator, resultIndentation] = resultLine;
|
||||
const lineNumber = +_lineNumber - 1;
|
||||
const resultStart = (indentation + _lineNumber + ':' + resultIndentation).length;
|
||||
const resultStart = (indentation + _lineNumber + seperator + resultIndentation).length;
|
||||
const metadataOffset = (indentation + _lineNumber + seperator).length;
|
||||
|
||||
const location: vscode.LocationLink = {
|
||||
targetRange: new vscode.Range(Math.max(lineNumber - 3, 0), 0, lineNumber + 3, line.length),
|
||||
targetSelectionRange: new vscode.Range(lineNumber, 0, lineNumber, line.length),
|
||||
targetSelectionRange: new vscode.Range(lineNumber, metadataOffset, lineNumber, metadataOffset),
|
||||
targetUri: currentTarget,
|
||||
originSelectionRange: new vscode.Range(i, resultStart, i, line.length),
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"scopeName": "text.searchResult",
|
||||
"patterns": [
|
||||
{
|
||||
"match": "^# (Query|Flags|Including|Excluding): .*$",
|
||||
"match": "^# (Query|Flags|Including|Excluding|ContextLines): .*$",
|
||||
"name": "comment"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -8,31 +8,43 @@ import * as jsoncParser from 'jsonc-parser';
|
||||
|
||||
export function activate(context: vscode.ExtensionContext): any {
|
||||
|
||||
const tokenModifiers = ['static', 'abstract', 'deprecated'];
|
||||
const tokenTypes = ['strings', 'types', 'structs', 'classes', 'functions', 'variables'];
|
||||
const tokenTypes = ['type', 'struct', 'class', 'interface', 'enum', 'parameterType', 'function', 'variable'];
|
||||
const tokenModifiers = ['static', 'abstract', 'deprecated', 'declaration', 'documentation', 'member', 'async'];
|
||||
|
||||
const legend = new vscode.SemanticTokensLegend(tokenTypes, tokenModifiers);
|
||||
|
||||
const semanticHighlightProvider: vscode.SemanticTokensProvider = {
|
||||
provideSemanticTokens(document: vscode.TextDocument): vscode.ProviderResult<vscode.SemanticTokens> {
|
||||
const builder = new vscode.SemanticTokensBuilder();
|
||||
|
||||
function addToken(value: string, startLine: number, startCharacter: number, length: number) {
|
||||
const [type, ...modifiers] = value.split('.');
|
||||
|
||||
let tokenType = legend.tokenTypes.indexOf(type);
|
||||
if (tokenType === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tokenModifiers = 0;
|
||||
for (let i = 0; i < modifiers.length; i++) {
|
||||
const index = legend.tokenModifiers.indexOf(modifiers[i]);
|
||||
if (index !== -1) {
|
||||
tokenModifiers = tokenModifiers | 1 << index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
builder.push(startLine, startCharacter, length, tokenType, tokenModifiers);
|
||||
}
|
||||
|
||||
const visitor: jsoncParser.JSONVisitor = {
|
||||
onObjectProperty: (property: string, _offset: number, length: number, startLine: number, startCharacter: number) => {
|
||||
const [type, ...modifiers] = property.split('.');
|
||||
let tokenType = legend.tokenTypes.indexOf(type);
|
||||
if (tokenType === -1) {
|
||||
tokenType = 0;
|
||||
onObjectProperty: (property: string, _offset: number, _length: number, startLine: number, startCharacter: number) => {
|
||||
addToken(property, startLine, startCharacter, property.length + 2);
|
||||
},
|
||||
onLiteralValue: (value: any, _offset: number, length: number, startLine: number, startCharacter: number) => {
|
||||
if (typeof value === 'string') {
|
||||
addToken(value, startLine, startCharacter, length);
|
||||
}
|
||||
|
||||
let tokenModifiers = 0;
|
||||
for (let i = 0; i < modifiers.length; i++) {
|
||||
const index = legend.tokenModifiers.indexOf(modifiers[i]);
|
||||
if (index !== -1) {
|
||||
tokenModifiers = tokenModifiers | 1 << index;
|
||||
}
|
||||
}
|
||||
|
||||
builder.push(startLine, startCharacter, length, tokenType, tokenModifiers);
|
||||
}
|
||||
};
|
||||
jsoncParser.visit(document.getText(), visitor);
|
||||
@@ -42,6 +54,6 @@ export function activate(context: vscode.ExtensionContext): any {
|
||||
};
|
||||
|
||||
|
||||
context.subscriptions.push(vscode.languages.registerSemanticTokensProvider({ pattern: '**/color-test.json' }, semanticHighlightProvider, legend));
|
||||
context.subscriptions.push(vscode.languages.registerSemanticTokensProvider({ pattern: '**/*semantic-test.json' }, semanticHighlightProvider, legend));
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
typescript@3.7.3-insiders.20191123:
|
||||
version "3.7.3-insiders.20191123"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3-insiders.20191123.tgz#f3bef33a2a3f6e02f11bcc0c20b6f0de526f17fd"
|
||||
integrity sha512-b+tLx4D0a6SeuaCa7iehdgkRKHsS67FkioQWw+0REjVNOYZ+AqJ0NjlnomK1hEUvSzSNrH9Du+m+Yiv7JlVpSg==
|
||||
typescript@3.7.3:
|
||||
version "3.7.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69"
|
||||
integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "azuredatastudio",
|
||||
"version": "1.14.0",
|
||||
"distro": "68a9088c1675337aaa88e0e9853ea68c32a0409f",
|
||||
"distro": "c2d125e08e84d4212f7b634dd8c0deaaca2bf4bd",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
@@ -77,7 +77,7 @@
|
||||
"vscode-ripgrep": "^1.5.7",
|
||||
"vscode-sqlite3": "4.0.9",
|
||||
"vscode-textmate": "4.4.0",
|
||||
"xterm": "4.3.0-beta.28",
|
||||
"xterm": "4.3.0-beta.28.vscode.1",
|
||||
"xterm-addon-search": "0.4.0-beta4",
|
||||
"xterm-addon-web-links": "0.2.1",
|
||||
"xterm-addon-webgl": "0.4.0-beta.11",
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"vscode-proxy-agent": "^0.5.2",
|
||||
"vscode-ripgrep": "^1.5.7",
|
||||
"vscode-textmate": "4.4.0",
|
||||
"xterm": "4.3.0-beta.28",
|
||||
"xterm": "4.3.0-beta.28.vscode.1",
|
||||
"xterm-addon-search": "0.4.0-beta4",
|
||||
"xterm-addon-web-links": "0.2.1",
|
||||
"xterm-addon-webgl": "0.4.0-beta.11",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"onigasm-umd": "2.2.5",
|
||||
"semver-umd": "^5.5.3",
|
||||
"vscode-textmate": "4.4.0",
|
||||
"xterm": "4.3.0-beta.28",
|
||||
"xterm": "4.3.0-beta.28.vscode.1",
|
||||
"xterm-addon-search": "0.4.0-beta4",
|
||||
"xterm-addon-web-links": "0.2.1",
|
||||
"xterm-addon-webgl": "0.4.0-beta.11"
|
||||
|
||||
@@ -46,7 +46,7 @@ xterm-addon-webgl@0.4.0-beta.11:
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.4.0-beta.11.tgz#0e4a7242e2353cf74aba55e5a5bdc0b4ec87ad10"
|
||||
integrity sha512-AteDxm1RFy1WnjY9r5iJSETozLebvUkR+jextdZk/ASsK21vsYK0DuVWwRI8afgiN2hUVhxcxuHEJUOV+CJDQA==
|
||||
|
||||
xterm@4.3.0-beta.28:
|
||||
version "4.3.0-beta.28"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.3.0-beta.28.tgz#80f7c4ba8f6ee3c953e6f33f8ce5aef08d5a8354"
|
||||
integrity sha512-WWZ4XCvce5h+klL6ObwtMauJff/n2KGGOwJJkDbJhrAjVy2a77GKgAedJTDDFGgKJ6ix1d7puHtVSSKflIVaDQ==
|
||||
xterm@4.3.0-beta.28.vscode.1:
|
||||
version "4.3.0-beta.28.vscode.1"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.3.0-beta.28.vscode.1.tgz#89b85398b5801708e833d08bf92b2124fa128943"
|
||||
integrity sha512-JNHNZyDtAWnybJTrenPzD6g/yXpHOvPqmjau91Up4onRbjQYMSNlth17SqaES68DKn/+4kcIl2c/RG5SXJjvGw==
|
||||
|
||||
@@ -433,10 +433,10 @@ xterm-addon-webgl@0.4.0-beta.11:
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.4.0-beta.11.tgz#0e4a7242e2353cf74aba55e5a5bdc0b4ec87ad10"
|
||||
integrity sha512-AteDxm1RFy1WnjY9r5iJSETozLebvUkR+jextdZk/ASsK21vsYK0DuVWwRI8afgiN2hUVhxcxuHEJUOV+CJDQA==
|
||||
|
||||
xterm@4.3.0-beta.28:
|
||||
version "4.3.0-beta.28"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.3.0-beta.28.tgz#80f7c4ba8f6ee3c953e6f33f8ce5aef08d5a8354"
|
||||
integrity sha512-WWZ4XCvce5h+klL6ObwtMauJff/n2KGGOwJJkDbJhrAjVy2a77GKgAedJTDDFGgKJ6ix1d7puHtVSSKflIVaDQ==
|
||||
xterm@4.3.0-beta.28.vscode.1:
|
||||
version "4.3.0-beta.28.vscode.1"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.3.0-beta.28.vscode.1.tgz#89b85398b5801708e833d08bf92b2124fa128943"
|
||||
integrity sha512-JNHNZyDtAWnybJTrenPzD6g/yXpHOvPqmjau91Up4onRbjQYMSNlth17SqaES68DKn/+4kcIl2c/RG5SXJjvGw==
|
||||
|
||||
yauzl@^2.9.2:
|
||||
version "2.10.0"
|
||||
|
||||
@@ -77,7 +77,7 @@ export class QueryTextEditor extends BaseTextEditor {
|
||||
if (!this._selected) {
|
||||
options.renderLineHighlight = 'none';
|
||||
options.parameterHints = { enabled: false };
|
||||
options.matchBrackets = false;
|
||||
options.matchBrackets = 'never';
|
||||
}
|
||||
if (this._hideLineNumbers) {
|
||||
options.lineNumbers = 'off';
|
||||
|
||||
@@ -972,6 +972,7 @@ export const EventHelper = {
|
||||
export interface IFocusTracker extends Disposable {
|
||||
onDidFocus: Event<void>;
|
||||
onDidBlur: Event<void>;
|
||||
refreshState?(): void;
|
||||
}
|
||||
|
||||
export function saveParentsScrollTop(node: Element): number[] {
|
||||
@@ -1000,6 +1001,8 @@ class FocusTracker extends Disposable implements IFocusTracker {
|
||||
private readonly _onDidBlur = this._register(new Emitter<void>());
|
||||
public readonly onDidBlur: Event<void> = this._onDidBlur.event;
|
||||
|
||||
private _refreshStateHandler: () => void;
|
||||
|
||||
constructor(element: HTMLElement | Window) {
|
||||
super();
|
||||
let hasFocus = isAncestor(document.activeElement, <HTMLElement>element);
|
||||
@@ -1026,9 +1029,24 @@ class FocusTracker extends Disposable implements IFocusTracker {
|
||||
}
|
||||
};
|
||||
|
||||
this._refreshStateHandler = () => {
|
||||
let currentNodeHasFocus = isAncestor(document.activeElement, <HTMLElement>element);
|
||||
if (currentNodeHasFocus !== hasFocus) {
|
||||
if (hasFocus) {
|
||||
onBlur();
|
||||
} else {
|
||||
onFocus();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this._register(domEvent(element, EventType.FOCUS, true)(onFocus));
|
||||
this._register(domEvent(element, EventType.BLUR, true)(onBlur));
|
||||
}
|
||||
|
||||
refreshState() {
|
||||
this._refreshStateHandler();
|
||||
}
|
||||
}
|
||||
|
||||
export function trackFocus(element: HTMLElement | Window): IFocusTracker {
|
||||
|
||||
@@ -15,7 +15,6 @@ import { cloneAndChange } from 'vs/base/common/objects';
|
||||
import { escape } from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { renderCodicons } from 'vs/base/browser/ui/codiconLabel/codiconLabel';
|
||||
|
||||
export interface MarkdownRenderOptions extends FormattedTextRenderOptions {
|
||||
codeBlockRenderer?: (modeId: string, value: string) => Promise<string>;
|
||||
@@ -73,10 +72,6 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
|
||||
|
||||
const renderer = new marked.Renderer();
|
||||
renderer.image = (href: string, title: string, text: string) => {
|
||||
if (href && href.indexOf('vscode-icon://codicon/') === 0) {
|
||||
return renderCodicons(`$(${URI.parse(href).path.substr(1)})`);
|
||||
}
|
||||
|
||||
let dimensions: string[] = [];
|
||||
let attributes: string[] = [];
|
||||
if (href) {
|
||||
|
||||
@@ -396,7 +396,6 @@
|
||||
.codicon-debug-breakpoint-function:before { content: "\eb88" }
|
||||
.codicon-debug-breakpoint-function-disabled:before { content: "\eb88" }
|
||||
.codicon-debug-breakpoint-stackframe-active:before { content: "\eb89" }
|
||||
.codicon-debug-breakpoint-stackframe-dot:before { content: "\eb8a" }
|
||||
.codicon-debug-breakpoint-stackframe:before { content: "\eb8b" }
|
||||
.codicon-debug-breakpoint-stackframe-focused:before { content: "\eb8b" }
|
||||
.codicon-debug-breakpoint-unsupported:before { content: "\eb8c" }
|
||||
|
||||
@@ -604,8 +604,8 @@ export class SerializableGrid<T extends ISerializableView> extends Grid<T> {
|
||||
export type GridNodeDescriptor = { size?: number, groups?: GridNodeDescriptor[] };
|
||||
export type GridDescriptor = { orientation: Orientation, groups?: GridNodeDescriptor[] };
|
||||
|
||||
export function sanitizeGridNodeDescriptor(nodeDescriptor: GridNodeDescriptor): void {
|
||||
if (nodeDescriptor.groups && nodeDescriptor.groups.length <= 1) {
|
||||
export function sanitizeGridNodeDescriptor(nodeDescriptor: GridNodeDescriptor, rootNode: boolean): void {
|
||||
if (!rootNode && nodeDescriptor.groups && nodeDescriptor.groups.length <= 1) {
|
||||
nodeDescriptor.groups = undefined;
|
||||
}
|
||||
|
||||
@@ -617,7 +617,7 @@ export function sanitizeGridNodeDescriptor(nodeDescriptor: GridNodeDescriptor):
|
||||
let totalDefinedSizeCount = 0;
|
||||
|
||||
for (const child of nodeDescriptor.groups) {
|
||||
sanitizeGridNodeDescriptor(child);
|
||||
sanitizeGridNodeDescriptor(child, false);
|
||||
|
||||
if (child.size) {
|
||||
totalDefinedSize += child.size;
|
||||
@@ -665,7 +665,7 @@ function getDimensions(node: ISerializedNode, orientation: Orientation): { width
|
||||
}
|
||||
|
||||
export function createSerializedGrid(gridDescriptor: GridDescriptor): ISerializedGrid {
|
||||
sanitizeGridNodeDescriptor(gridDescriptor);
|
||||
sanitizeGridNodeDescriptor(gridDescriptor, true);
|
||||
|
||||
const root = createSerializedNode(gridDescriptor);
|
||||
const { width, height } = getDimensions(root, gridDescriptor.orientation);
|
||||
|
||||
@@ -1086,6 +1086,8 @@ export class GridView implements IDisposable {
|
||||
throw new Error('Invalid JSON: \'width\' property must be a number.');
|
||||
} else if (typeof json.height !== 'number') {
|
||||
throw new Error('Invalid JSON: \'height\' property must be a number.');
|
||||
} else if (json.root?.type !== 'branch') {
|
||||
throw new Error('Invalid JSON: \'root\' property must have \'type\' value of branch.');
|
||||
}
|
||||
|
||||
const orientation = json.orientation;
|
||||
|
||||
@@ -9,6 +9,7 @@ import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlighte
|
||||
import { IMatch } from 'vs/base/common/filters';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Range } from 'vs/base/common/range';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
|
||||
export interface IIconLabelCreationOptions {
|
||||
supportHighlights?: boolean;
|
||||
@@ -165,15 +166,17 @@ class Label {
|
||||
|
||||
private label: string | string[] | undefined = undefined;
|
||||
private singleLabel: HTMLElement | undefined = undefined;
|
||||
private options: IIconLabelValueOptions | undefined;
|
||||
|
||||
constructor(private container: HTMLElement) { }
|
||||
|
||||
setLabel(label: string | string[], options?: IIconLabelValueOptions): void {
|
||||
if (this.label === label) {
|
||||
if (this.label === label && equals(this.options, options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.label = label;
|
||||
this.options = options;
|
||||
|
||||
if (typeof label === 'string') {
|
||||
if (!this.singleLabel) {
|
||||
@@ -226,15 +229,17 @@ class LabelWithHighlights {
|
||||
|
||||
private label: string | string[] | undefined = undefined;
|
||||
private singleLabel: HighlightedLabel | undefined = undefined;
|
||||
private options: IIconLabelValueOptions | undefined;
|
||||
|
||||
constructor(private container: HTMLElement, private supportCodicons: boolean) { }
|
||||
|
||||
setLabel(label: string | string[], options?: IIconLabelValueOptions): void {
|
||||
if (this.label === label) {
|
||||
if (this.label === label && equals(this.options, options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.label = label;
|
||||
this.options = options;
|
||||
|
||||
if (typeof label === 'string') {
|
||||
if (!this.singleLabel) {
|
||||
|
||||
@@ -1189,14 +1189,16 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
|
||||
if (compressedNode) {
|
||||
for (let i = 0; i < compressedNode.elements.length; i++) {
|
||||
const id = getId(compressedNode.elements[i].element as T);
|
||||
const element = compressedNode.elements[compressedNode.elements.length - 1].element as T;
|
||||
|
||||
if (oldSelection.has(id)) {
|
||||
selection.push(compressedNode.elements[compressedNode.elements.length - 1].element as T);
|
||||
// github.com/microsoft/vscode/issues/85938
|
||||
if (oldSelection.has(id) && selection.indexOf(element) === -1) {
|
||||
selection.push(element);
|
||||
didChangeSelection = true;
|
||||
}
|
||||
|
||||
if (oldFocus.has(id)) {
|
||||
focus.push(compressedNode.elements[compressedNode.elements.length - 1].element as T);
|
||||
if (oldFocus.has(id) && focus.indexOf(element) === -1) {
|
||||
focus.push(element);
|
||||
didChangeFocus = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,6 +199,13 @@ export function detectEncodingByBOMFromBuffer(buffer: Buffer | VSBuffer | null,
|
||||
return null;
|
||||
}
|
||||
|
||||
// we explicitly ignore a specific set of encodings from auto guessing
|
||||
// - ASCII: we never want this encoding (most UTF-8 files would happily detect as
|
||||
// ASCII files and then you could not type non-ASCII characters anymore)
|
||||
// - UTF-16: we have our own detection logic for UTF-16
|
||||
// - UTF-32: we do not support this encoding in VSCode
|
||||
const IGNORE_ENCODINGS = ['ascii', 'utf-16', 'utf-32'];
|
||||
|
||||
/**
|
||||
* Guesses the encoding from buffer.
|
||||
*/
|
||||
@@ -210,15 +217,9 @@ async function guessEncodingByBuffer(buffer: Buffer): Promise<string | null> {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Ignore 'ascii' as guessed encoding because that
|
||||
// is almost never what we want, rather fallback
|
||||
// to the configured encoding then. Otherwise,
|
||||
// opening a ascii-only file with auto guessing
|
||||
// enabled will put the file into 'ascii' mode
|
||||
// and thus typing any special characters is
|
||||
// not possible anymore.
|
||||
if (guessed.encoding.toLowerCase() === 'ascii') {
|
||||
return null;
|
||||
const enc = guessed.encoding.toLowerCase();
|
||||
if (0 <= IGNORE_ENCODINGS.indexOf(enc)) {
|
||||
return null; // see comment above why we ignore some encodings
|
||||
}
|
||||
|
||||
return toIconvLiteEncoding(guessed.encoding);
|
||||
|
||||
@@ -9,11 +9,10 @@ import { StandardWheelEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent
|
||||
import { RunOnceScheduler, TimeoutTimer } from 'vs/base/common/async';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { HitTestContext, IViewZoneData, MouseTarget, MouseTargetFactory } from 'vs/editor/browser/controller/mouseTarget';
|
||||
import { HitTestContext, IViewZoneData, MouseTarget, MouseTargetFactory, PointerHandlerLastRenderData } from 'vs/editor/browser/controller/mouseTarget';
|
||||
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
|
||||
import { ClientCoordinates, EditorMouseEvent, EditorMouseEventFactory, GlobalEditorMouseMoveMonitor, createEditorPagePosition } from 'vs/editor/browser/editorDom';
|
||||
import { ViewController } from 'vs/editor/browser/view/viewController';
|
||||
import { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';
|
||||
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
@@ -46,9 +45,9 @@ export interface IPointerHandlerHelper {
|
||||
focusTextArea(): void;
|
||||
|
||||
/**
|
||||
* Get the last rendered information of the cursors.
|
||||
* Get the last rendered information for cursors & textarea.
|
||||
*/
|
||||
getLastViewCursorsRenderData(): IViewCursorRenderData[];
|
||||
getLastRenderData(): PointerHandlerLastRenderData;
|
||||
|
||||
shouldSuppressMouseDownOnViewZone(viewZoneId: string): boolean;
|
||||
shouldSuppressMouseDownOnWidget(widgetId: string): boolean;
|
||||
@@ -158,13 +157,11 @@ export class MouseHandler extends ViewEventHandler {
|
||||
return null;
|
||||
}
|
||||
|
||||
const lastViewCursorsRenderData = this.viewHelper.getLastViewCursorsRenderData();
|
||||
return this.mouseTargetFactory.createMouseTarget(lastViewCursorsRenderData, editorPos, pos, null);
|
||||
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), editorPos, pos, null);
|
||||
}
|
||||
|
||||
protected _createMouseTarget(e: EditorMouseEvent, testEventTarget: boolean): editorBrowser.IMouseTarget {
|
||||
const lastViewCursorsRenderData = this.viewHelper.getLastViewCursorsRenderData();
|
||||
return this.mouseTargetFactory.createMouseTarget(lastViewCursorsRenderData, e.editorPos, e.pos, testEventTarget ? e.target : null);
|
||||
return this.mouseTargetFactory.createMouseTarget(this.viewHelper.getLastRenderData(), e.editorPos, e.pos, testEventTarget ? e.target : null);
|
||||
}
|
||||
|
||||
private _getMouseColumn(e: EditorMouseEvent): number {
|
||||
|
||||
@@ -89,6 +89,13 @@ interface IHitTestResult {
|
||||
hitTarget: Element | null;
|
||||
}
|
||||
|
||||
export class PointerHandlerLastRenderData {
|
||||
constructor(
|
||||
public readonly lastViewCursorsRenderData: IViewCursorRenderData[],
|
||||
public readonly lastTextareaPosition: Position | null
|
||||
) { }
|
||||
}
|
||||
|
||||
export class MouseTarget implements IMouseTarget {
|
||||
|
||||
public readonly element: Element | null;
|
||||
@@ -232,19 +239,19 @@ export class HitTestContext {
|
||||
public readonly viewDomNode: HTMLElement;
|
||||
public readonly lineHeight: number;
|
||||
public readonly typicalHalfwidthCharacterWidth: number;
|
||||
public readonly lastViewCursorsRenderData: IViewCursorRenderData[];
|
||||
public readonly lastRenderData: PointerHandlerLastRenderData;
|
||||
|
||||
private readonly _context: ViewContext;
|
||||
private readonly _viewHelper: IPointerHandlerHelper;
|
||||
|
||||
constructor(context: ViewContext, viewHelper: IPointerHandlerHelper, lastViewCursorsRenderData: IViewCursorRenderData[]) {
|
||||
constructor(context: ViewContext, viewHelper: IPointerHandlerHelper, lastRenderData: PointerHandlerLastRenderData) {
|
||||
this.model = context.model;
|
||||
const options = context.configuration.options;
|
||||
this.layoutInfo = options.get(EditorOption.layoutInfo);
|
||||
this.viewDomNode = viewHelper.viewDomNode;
|
||||
this.lineHeight = options.get(EditorOption.lineHeight);
|
||||
this.typicalHalfwidthCharacterWidth = options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth;
|
||||
this.lastViewCursorsRenderData = lastViewCursorsRenderData;
|
||||
this.lastRenderData = lastRenderData;
|
||||
this._context = context;
|
||||
this._viewHelper = viewHelper;
|
||||
}
|
||||
@@ -462,8 +469,8 @@ export class MouseTargetFactory {
|
||||
return false;
|
||||
}
|
||||
|
||||
public createMouseTarget(lastViewCursorsRenderData: IViewCursorRenderData[], editorPos: EditorPagePosition, pos: PageCoordinates, target: HTMLElement | null): IMouseTarget {
|
||||
const ctx = new HitTestContext(this._context, this._viewHelper, lastViewCursorsRenderData);
|
||||
public createMouseTarget(lastRenderData: PointerHandlerLastRenderData, editorPos: EditorPagePosition, pos: PageCoordinates, target: HTMLElement | null): IMouseTarget {
|
||||
const ctx = new HitTestContext(this._context, this._viewHelper, lastRenderData);
|
||||
const request = new HitTestRequest(ctx, editorPos, pos, target);
|
||||
try {
|
||||
const r = MouseTargetFactory._createMouseTarget(ctx, request, false);
|
||||
@@ -544,7 +551,7 @@ export class MouseTargetFactory {
|
||||
|
||||
if (request.target) {
|
||||
// Check if we've hit a painted cursor
|
||||
const lastViewCursorsRenderData = ctx.lastViewCursorsRenderData;
|
||||
const lastViewCursorsRenderData = ctx.lastRenderData.lastViewCursorsRenderData;
|
||||
|
||||
for (const d of lastViewCursorsRenderData) {
|
||||
|
||||
@@ -560,7 +567,7 @@ export class MouseTargetFactory {
|
||||
// first or last rendered view line dom node, therefore help it out
|
||||
// and first check if we are on top of a cursor
|
||||
|
||||
const lastViewCursorsRenderData = ctx.lastViewCursorsRenderData;
|
||||
const lastViewCursorsRenderData = ctx.lastRenderData.lastViewCursorsRenderData;
|
||||
const mouseContentHorizontalOffset = request.mouseContentHorizontalOffset;
|
||||
const mouseVerticalOffset = request.mouseVerticalOffset;
|
||||
|
||||
@@ -602,7 +609,10 @@ export class MouseTargetFactory {
|
||||
private static _hitTestTextArea(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
|
||||
// Is it the textarea?
|
||||
if (ElementPath.isTextArea(request.targetPath)) {
|
||||
return request.fulfill(MouseTargetType.TEXTAREA);
|
||||
if (ctx.lastRenderData.lastTextareaPosition) {
|
||||
return request.fulfill(MouseTargetType.CONTENT_TEXT, ctx.lastRenderData.lastTextareaPosition);
|
||||
}
|
||||
return request.fulfill(MouseTargetType.TEXTAREA, ctx.lastRenderData.lastTextareaPosition);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,12 @@ export class TextAreaHandler extends ViewPart {
|
||||
private _visibleTextArea: VisibleTextAreaData | null;
|
||||
private _selections: Selection[];
|
||||
|
||||
/**
|
||||
* The position at which the textarea was rendered.
|
||||
* This is useful for hit-testing and determining the mouse position.
|
||||
*/
|
||||
private _lastRenderPosition: Position | null;
|
||||
|
||||
public readonly textArea: FastDomNode<HTMLTextAreaElement>;
|
||||
public readonly textAreaCover: FastDomNode<HTMLElement>;
|
||||
private readonly _textAreaInput: TextAreaInput;
|
||||
@@ -104,6 +110,7 @@ export class TextAreaHandler extends ViewPart {
|
||||
|
||||
this._visibleTextArea = null;
|
||||
this._selections = [new Selection(1, 1, 1, 1)];
|
||||
this._lastRenderPosition = null;
|
||||
|
||||
// Text Area (The focus will always be in the textarea when the cursor is blinking)
|
||||
this.textArea = createFastDomNode(document.createElement('textarea'));
|
||||
@@ -413,13 +420,18 @@ export class TextAreaHandler extends ViewPart {
|
||||
this._textAreaInput.refreshFocusState();
|
||||
}
|
||||
|
||||
public getLastRenderData(): Position | null {
|
||||
return this._lastRenderPosition;
|
||||
}
|
||||
|
||||
// --- end view API
|
||||
|
||||
private _primaryCursorPosition: Position = new Position(1, 1);
|
||||
private _primaryCursorVisibleRange: HorizontalPosition | null = null;
|
||||
|
||||
public prepareRender(ctx: RenderingContext): void {
|
||||
const primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);
|
||||
this._primaryCursorVisibleRange = ctx.visibleRangeForPosition(primaryCursorPosition);
|
||||
this._primaryCursorPosition = new Position(this._selections[0].positionLineNumber, this._selections[0].positionColumn);
|
||||
this._primaryCursorVisibleRange = ctx.visibleRangeForPosition(this._primaryCursorPosition);
|
||||
}
|
||||
|
||||
public render(ctx: RestrictedRenderingContext): void {
|
||||
@@ -431,6 +443,7 @@ export class TextAreaHandler extends ViewPart {
|
||||
if (this._visibleTextArea) {
|
||||
// The text area is visible for composition reasons
|
||||
this._renderInsideEditor(
|
||||
null,
|
||||
this._visibleTextArea.top - this._scrollTop,
|
||||
this._contentLeft + this._visibleTextArea.left - this._scrollLeft,
|
||||
this._visibleTextArea.width,
|
||||
@@ -465,6 +478,7 @@ export class TextAreaHandler extends ViewPart {
|
||||
// For the popup emoji input, we will make the text area as high as the line height
|
||||
// We will also make the fontSize and lineHeight the correct dimensions to help with the placement of these pickers
|
||||
this._renderInsideEditor(
|
||||
this._primaryCursorPosition,
|
||||
top, left,
|
||||
canUseZeroSizeTextarea ? 0 : 1, this._lineHeight
|
||||
);
|
||||
@@ -472,12 +486,14 @@ export class TextAreaHandler extends ViewPart {
|
||||
}
|
||||
|
||||
this._renderInsideEditor(
|
||||
this._primaryCursorPosition,
|
||||
top, left,
|
||||
canUseZeroSizeTextarea ? 0 : 1, canUseZeroSizeTextarea ? 0 : 1
|
||||
);
|
||||
}
|
||||
|
||||
private _renderInsideEditor(top: number, left: number, width: number, height: number): void {
|
||||
private _renderInsideEditor(renderedPosition: Position | null, top: number, left: number, width: number, height: number): void {
|
||||
this._lastRenderPosition = renderedPosition;
|
||||
const ta = this.textArea;
|
||||
const tac = this.textAreaCover;
|
||||
|
||||
@@ -495,6 +511,7 @@ export class TextAreaHandler extends ViewPart {
|
||||
}
|
||||
|
||||
private _renderAtTopLeft(): void {
|
||||
this._lastRenderPosition = null;
|
||||
const ta = this.textArea;
|
||||
const tac = this.textAreaCover;
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
|
||||
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { IThemeService, getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { PointerHandlerLastRenderData } from 'vs/editor/browser/controller/mouseTarget';
|
||||
|
||||
|
||||
export interface IContentWidgetData {
|
||||
@@ -244,8 +245,10 @@ export class View extends ViewEventHandler {
|
||||
this.focus();
|
||||
},
|
||||
|
||||
getLastViewCursorsRenderData: () => {
|
||||
return this.viewCursors.getLastRenderData() || [];
|
||||
getLastRenderData: (): PointerHandlerLastRenderData => {
|
||||
const lastViewCursorsRenderData = this.viewCursors.getLastRenderData() || [];
|
||||
const lastTextareaPosition = this._textAreaHandler.getLastRenderData();
|
||||
return new PointerHandlerLastRenderData(lastViewCursorsRenderData, lastTextareaPosition);
|
||||
},
|
||||
shouldSuppressMouseDownOnViewZone: (viewZoneId: string) => {
|
||||
return this.viewZones.shouldSuppressMouseDownOnViewZone(viewZoneId);
|
||||
|
||||
@@ -57,7 +57,7 @@ export abstract class AbstractLineHighlightOverlay extends DynamicViewOverlay {
|
||||
const renderSelections = isRenderedUsingBorder ? this._selections.slice(0, 1) : this._selections;
|
||||
|
||||
const cursorsLineNumbers = renderSelections.map(s => s.positionLineNumber);
|
||||
cursorsLineNumbers.sort();
|
||||
cursorsLineNumbers.sort((a, b) => a - b);
|
||||
if (!arrays.equals(this._cursorLineNumbers, cursorsLineNumbers)) {
|
||||
this._cursorLineNumbers = cursorsLineNumbers;
|
||||
hasChanged = true;
|
||||
|
||||
@@ -874,6 +874,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
||||
|
||||
public onHide(): void {
|
||||
this._modelData?.view.refreshFocusState();
|
||||
this._focusTracker.refreshState();
|
||||
}
|
||||
|
||||
public getContribution<T extends editorCommon.IEditorContribution>(id: string): T {
|
||||
@@ -1806,6 +1807,12 @@ class CodeEditorWidgetFocusTracker extends Disposable {
|
||||
public hasFocus(): boolean {
|
||||
return this._hasFocus;
|
||||
}
|
||||
|
||||
public refreshState(): void {
|
||||
if (this._domFocusTracker.refreshState) {
|
||||
this._domFocusTracker.refreshState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const squigglyStart = encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 6 3' enable-background='new 0 0 6 3' height='3' width='6'><g fill='`);
|
||||
|
||||
@@ -130,12 +130,13 @@ class VisualEditorState {
|
||||
this.inlineDiffMargins = [];
|
||||
for (let i = 0, length = newDecorations.zones.length; i < length; i++) {
|
||||
const viewZone = <editorBrowser.IViewZone>newDecorations.zones[i];
|
||||
viewZone.suppressMouseDown = false;
|
||||
viewZone.suppressMouseDown = true;
|
||||
let zoneId = viewChangeAccessor.addZone(viewZone);
|
||||
this._zones.push(zoneId);
|
||||
this._zonesMap[String(zoneId)] = true;
|
||||
|
||||
if (newDecorations.zones[i].diff && viewZone.marginDomNode && this._clipboardService) {
|
||||
viewZone.suppressMouseDown = false;
|
||||
this.inlineDiffMargins.push(new InlineDiffMargin(zoneId, viewZone.marginDomNode, editor, newDecorations.zones[i].diff!, this._contextMenuService, this._clipboardService));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,6 +263,13 @@ function migrateOptions(options: IEditorOptions): void {
|
||||
} else if (<any>autoIndent === false) {
|
||||
options.autoIndent = 'advanced';
|
||||
}
|
||||
|
||||
const matchBrackets = options.matchBrackets;
|
||||
if (<any>matchBrackets === true) {
|
||||
options.matchBrackets = 'always';
|
||||
} else if (<any>matchBrackets === false) {
|
||||
options.matchBrackets = 'never';
|
||||
}
|
||||
}
|
||||
|
||||
function deepCloneAndMigrateOptions(_options: IEditorOptions): IEditorOptions {
|
||||
|
||||
@@ -481,9 +481,9 @@ export interface IEditorOptions {
|
||||
showFoldingControls?: 'always' | 'mouseover';
|
||||
/**
|
||||
* Enable highlighting of matching brackets.
|
||||
* Defaults to true.
|
||||
* Defaults to 'always'.
|
||||
*/
|
||||
matchBrackets?: boolean;
|
||||
matchBrackets?: 'never' | 'near' | 'always';
|
||||
/**
|
||||
* Enable rendering of whitespace.
|
||||
* Defaults to none.
|
||||
@@ -2277,7 +2277,7 @@ class EditorRulers extends SimpleEditorOption<EditorOption.rulers, number[]> {
|
||||
for (let value of input) {
|
||||
rulers.push(EditorIntOption.clampedInt(value, 0, 0, 10000));
|
||||
}
|
||||
rulers.sort();
|
||||
rulers.sort((a, b) => a - b);
|
||||
return rulers;
|
||||
}
|
||||
return this.defaultValue;
|
||||
@@ -3364,9 +3364,11 @@ export const EditorOptions = {
|
||||
EditorOption.links, 'links', true,
|
||||
{ description: nls.localize('links', "Controls whether the editor should detect links and make them clickable.") }
|
||||
)),
|
||||
matchBrackets: register(new EditorBooleanOption(
|
||||
EditorOption.matchBrackets, 'matchBrackets', true,
|
||||
{ description: nls.localize('matchBrackets', "Highlight matching brackets when one of them is selected.") }
|
||||
matchBrackets: register(new EditorStringEnumOption(
|
||||
EditorOption.matchBrackets, 'matchBrackets',
|
||||
'always' as 'never' | 'near' | 'always',
|
||||
['always', 'near', 'never'] as const,
|
||||
{ description: nls.localize('matchBrackets', "Highlight matching brackets.") }
|
||||
)),
|
||||
minimap: register(new EditorMinimap()),
|
||||
mouseStyle: register(new EditorStringEnumOption(
|
||||
|
||||
@@ -898,7 +898,7 @@ export interface ITextModel {
|
||||
* @param position The position at which to start the search.
|
||||
* @internal
|
||||
*/
|
||||
findEnclosingBrackets(position: IPosition): [Range, Range] | null;
|
||||
findEnclosingBrackets(position: IPosition, maxDuration?: number): [Range, Range] | null;
|
||||
|
||||
/**
|
||||
* Given a `position`, if the position is on top or near a bracket,
|
||||
|
||||
@@ -34,6 +34,7 @@ import { withUndefinedAsNull } from 'vs/base/common/types';
|
||||
import { VSBufferReadableStream, VSBuffer } from 'vs/base/common/buffer';
|
||||
import { TokensStore, MultilineTokens, countEOL, MultilineTokens2, TokensStore2 } from 'vs/editor/common/model/tokensStore';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { Constants } from 'vs/base/common/uint';
|
||||
|
||||
function createTextBufferBuilder() {
|
||||
return new PieceTreeTextBufferBuilder();
|
||||
@@ -2341,16 +2342,21 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
return null;
|
||||
}
|
||||
|
||||
public findEnclosingBrackets(_position: IPosition): [Range, Range] | null {
|
||||
public findEnclosingBrackets(_position: IPosition, maxDuration = Constants.MAX_SAFE_SMALL_INTEGER): [Range, Range] | null {
|
||||
const position = this.validatePosition(_position);
|
||||
const lineCount = this.getLineCount();
|
||||
const savedCounts = new Map<number, number[]>();
|
||||
|
||||
let counts: number[] = [];
|
||||
const resetCounts = (modeBrackets: RichEditBrackets | null) => {
|
||||
counts = [];
|
||||
for (let i = 0, len = modeBrackets ? modeBrackets.brackets.length : 0; i < len; i++) {
|
||||
counts[i] = 0;
|
||||
const resetCounts = (languageId: number, modeBrackets: RichEditBrackets | null) => {
|
||||
if (!savedCounts.has(languageId)) {
|
||||
let tmp = [];
|
||||
for (let i = 0, len = modeBrackets ? modeBrackets.brackets.length : 0; i < len; i++) {
|
||||
tmp[i] = 0;
|
||||
}
|
||||
savedCounts.set(languageId, tmp);
|
||||
}
|
||||
counts = savedCounts.get(languageId)!;
|
||||
};
|
||||
const searchInRange = (modeBrackets: RichEditBrackets, lineNumber: number, lineText: string, searchStartOffset: number, searchEndOffset: number): [Range, Range] | null => {
|
||||
while (true) {
|
||||
@@ -2380,7 +2386,12 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
|
||||
let languageId: LanguageId = -1;
|
||||
let modeBrackets: RichEditBrackets | null = null;
|
||||
const startTime = Date.now();
|
||||
for (let lineNumber = position.lineNumber; lineNumber <= lineCount; lineNumber++) {
|
||||
const elapsedTime = Date.now() - startTime;
|
||||
if (elapsedTime > maxDuration) {
|
||||
return null;
|
||||
}
|
||||
const lineTokens = this._getLineTokens(lineNumber);
|
||||
const tokenCount = lineTokens.getCount();
|
||||
const lineText = this._buffer.getLineContent(lineNumber);
|
||||
@@ -2396,7 +2407,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
if (languageId !== tokenLanguageId) {
|
||||
languageId = tokenLanguageId;
|
||||
modeBrackets = LanguageConfigurationRegistry.getBracketsSupport(languageId);
|
||||
resetCounts(modeBrackets);
|
||||
resetCounts(languageId, modeBrackets);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2415,7 +2426,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
||||
}
|
||||
languageId = tokenLanguageId;
|
||||
modeBrackets = LanguageConfigurationRegistry.getBracketsSupport(languageId);
|
||||
resetCounts(modeBrackets);
|
||||
resetCounts(languageId, modeBrackets);
|
||||
}
|
||||
|
||||
const searchInToken = (!!modeBrackets && !ignoreBracketsInToken(lineTokens.getStandardTokenType(tokenIndex)));
|
||||
|
||||
@@ -121,7 +121,7 @@ export interface IEncodedTokens {
|
||||
getMetadata(tokenIndex: number): number;
|
||||
|
||||
clear(): void;
|
||||
acceptDeleteRange(startDeltaLine: number, startCharacter: number, endDeltaLine: number, endCharacter: number): void;
|
||||
acceptDeleteRange(horizontalShiftForFirstLineTokens: number, startDeltaLine: number, startCharacter: number, endDeltaLine: number, endCharacter: number): void;
|
||||
acceptInsertText(deltaLine: number, character: number, eolCount: number, firstLineLength: number, lastLineLength: number, firstCharCode: number): void;
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ export class SparseEncodedTokens implements IEncodedTokens {
|
||||
this._tokenCount = 0;
|
||||
}
|
||||
|
||||
public acceptDeleteRange(startDeltaLine: number, startCharacter: number, endDeltaLine: number, endCharacter: number): void {
|
||||
public acceptDeleteRange(horizontalShiftForFirstLineTokens: number, startDeltaLine: number, startCharacter: number, endDeltaLine: number, endCharacter: number): void {
|
||||
// This is a bit complex, here are the cases I used to think about this:
|
||||
//
|
||||
// 1. The token starts before the deletion range
|
||||
@@ -292,9 +292,13 @@ export class SparseEncodedTokens implements IEncodedTokens {
|
||||
tokenDeltaLine -= deletedLineCount;
|
||||
} else if (tokenDeltaLine === endDeltaLine && tokenStartCharacter >= endCharacter) {
|
||||
// 4. (continued) The token starts after the deletion range, on the last line where a deletion occurs
|
||||
if (horizontalShiftForFirstLineTokens && tokenDeltaLine === 0) {
|
||||
tokenStartCharacter += horizontalShiftForFirstLineTokens;
|
||||
tokenEndCharacter += horizontalShiftForFirstLineTokens;
|
||||
}
|
||||
tokenDeltaLine -= deletedLineCount;
|
||||
tokenStartCharacter -= endCharacter;
|
||||
tokenEndCharacter -= endCharacter;
|
||||
tokenStartCharacter -= (endCharacter - startCharacter);
|
||||
tokenEndCharacter -= (endCharacter - startCharacter);
|
||||
} else {
|
||||
throw new Error(`Not possible!`);
|
||||
}
|
||||
@@ -373,8 +377,8 @@ export class SparseEncodedTokens implements IEncodedTokens {
|
||||
}
|
||||
}
|
||||
// => the token must move and keep its size constant
|
||||
tokenDeltaLine += eolCount;
|
||||
if (tokenDeltaLine === deltaLine) {
|
||||
tokenDeltaLine += eolCount;
|
||||
// this token is on the line where the insertion is taking place
|
||||
if (eolCount === 0) {
|
||||
tokenStartCharacter += firstLineLength;
|
||||
@@ -384,6 +388,8 @@ export class SparseEncodedTokens implements IEncodedTokens {
|
||||
tokenStartCharacter = lastLineLength + (tokenStartCharacter - character);
|
||||
tokenEndCharacter = tokenStartCharacter + tokenLength;
|
||||
}
|
||||
} else {
|
||||
tokenDeltaLine += eolCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,9 +533,9 @@ export class MultilineTokens2 {
|
||||
const deletedBefore = -firstLineIndex;
|
||||
this.startLineNumber -= deletedBefore;
|
||||
|
||||
this.tokens.acceptDeleteRange(0, 0, lastLineIndex, range.endColumn - 1);
|
||||
this.tokens.acceptDeleteRange(range.startColumn - 1, 0, 0, lastLineIndex, range.endColumn - 1);
|
||||
} else {
|
||||
this.tokens.acceptDeleteRange(firstLineIndex, range.startColumn - 1, lastLineIndex, range.endColumn - 1);
|
||||
this.tokens.acceptDeleteRange(0, firstLineIndex, range.startColumn - 1, lastLineIndex, range.endColumn - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -652,11 +652,15 @@ class ModelSemanticColoring extends Disposable {
|
||||
this._isDisposed = false;
|
||||
this._model = model;
|
||||
this._semanticStyling = stylingProvider;
|
||||
this._fetchSemanticTokens = this._register(new RunOnceScheduler(() => this._fetchSemanticTokensNow(), 500));
|
||||
this._fetchSemanticTokens = this._register(new RunOnceScheduler(() => this._fetchSemanticTokensNow(), 300));
|
||||
this._currentResponse = null;
|
||||
this._currentRequestCancellationTokenSource = null;
|
||||
|
||||
this._register(this._model.onDidChangeContent(e => this._fetchSemanticTokens.schedule()));
|
||||
this._register(this._model.onDidChangeContent(e => {
|
||||
if (!this._fetchSemanticTokens.isScheduled()) {
|
||||
this._fetchSemanticTokens.schedule();
|
||||
}
|
||||
}));
|
||||
this._register(SemanticTokensProviderRegistry.onDidChange(e => this._fetchSemanticTokens.schedule()));
|
||||
if (themeService) {
|
||||
// workaround for tests which use undefined... :/
|
||||
@@ -887,7 +891,9 @@ class ModelSemanticColoring extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
this._fetchSemanticTokens.schedule();
|
||||
if (!this._fetchSemanticTokens.isScheduled()) {
|
||||
this._fetchSemanticTokens.schedule();
|
||||
}
|
||||
}
|
||||
|
||||
this._model.setSemanticTokens(result);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
import { activeContrastBorder, editorBackground, editorForeground, registerColor, editorWarningForeground, editorInfoForeground, editorWarningBorder, editorInfoBorder, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { activeContrastBorder, editorBackground, editorForeground, registerColor, editorWarningForeground, editorInfoForeground, editorWarningBorder, editorInfoBorder, contrastBorder, editorFindMatchHighlight } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
/**
|
||||
@@ -15,7 +15,7 @@ export const editorLineHighlight = registerColor('editor.lineHighlightBackground
|
||||
export const editorLineHighlightBorder = registerColor('editor.lineHighlightBorder', { dark: '#282828', light: '#eeeeee', hc: '#f38518' }, nls.localize('lineHighlightBorderBox', 'Background color for the border around the line at the cursor position.'));
|
||||
export const editorRangeHighlight = registerColor('editor.rangeHighlightBackground', { dark: '#ffffff0b', light: '#fdff0033', hc: null }, nls.localize('rangeHighlight', 'Background color of highlighted ranges, like by quick open and find features. The color must not be opaque so as not to hide underlying decorations.'), true);
|
||||
export const editorRangeHighlightBorder = registerColor('editor.rangeHighlightBorder', { dark: null, light: null, hc: activeContrastBorder }, nls.localize('rangeHighlightBorder', 'Background color of the border around highlighted ranges.'), true);
|
||||
export const editorSymbolHighlight = registerColor('editor.symbolHighlightBackground', { dark: editorRangeHighlight, light: editorRangeHighlight, hc: null }, nls.localize('symbolHighlight', 'Background color of highlighted symbol, like for go to definition or go next/previous symbol. The color must not be opaque so as not to hide underlying decorations.'), true);
|
||||
export const editorSymbolHighlight = registerColor('editor.symbolHighlightBackground', { dark: editorFindMatchHighlight, light: editorFindMatchHighlight, hc: null }, nls.localize('symbolHighlight', 'Background color of highlighted symbol, like for go to definition or go next/previous symbol. The color must not be opaque so as not to hide underlying decorations.'), true);
|
||||
export const editorSymbolHighlightBorder = registerColor('editor.symbolHighlightBorder', { dark: null, light: null, hc: activeContrastBorder }, nls.localize('symbolHighlightBorder', 'Background color of the border around highlighted symbols.'), true);
|
||||
|
||||
export const editorCursorForeground = registerColor('editorCursor.foreground', { dark: '#AEAFAD', light: Color.black, hc: Color.white }, nls.localize('caret', 'Color of the editor cursor.'));
|
||||
|
||||
@@ -116,7 +116,7 @@ export class BracketMatchingController extends Disposable implements editorCommo
|
||||
private _lastVersionId: number;
|
||||
private _decorations: string[];
|
||||
private readonly _updateBracketsSoon: RunOnceScheduler;
|
||||
private _matchBrackets: boolean;
|
||||
private _matchBrackets: 'never' | 'near' | 'always';
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor
|
||||
@@ -132,7 +132,7 @@ export class BracketMatchingController extends Disposable implements editorCommo
|
||||
this._updateBracketsSoon.schedule();
|
||||
this._register(editor.onDidChangeCursorPosition((e) => {
|
||||
|
||||
if (!this._matchBrackets) {
|
||||
if (this._matchBrackets === 'never') {
|
||||
// Early exit if nothing needs to be done!
|
||||
// Leave some form of early exit check here if you wish to continue being a cursor position change listener ;)
|
||||
return;
|
||||
@@ -153,12 +153,13 @@ export class BracketMatchingController extends Disposable implements editorCommo
|
||||
this._updateBracketsSoon.schedule();
|
||||
}));
|
||||
this._register(editor.onDidChangeConfiguration((e) => {
|
||||
this._matchBrackets = this._editor.getOption(EditorOption.matchBrackets);
|
||||
if (!this._matchBrackets && this._decorations.length > 0) {
|
||||
// Remove existing decorations if bracket matching is off
|
||||
if (e.hasChanged(EditorOption.matchBrackets)) {
|
||||
this._matchBrackets = this._editor.getOption(EditorOption.matchBrackets);
|
||||
this._decorations = this._editor.deltaDecorations(this._decorations, []);
|
||||
this._lastBracketsData = [];
|
||||
this._lastVersionId = 0;
|
||||
this._updateBracketsSoon.schedule();
|
||||
}
|
||||
this._updateBracketsSoon.schedule();
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -262,7 +263,7 @@ export class BracketMatchingController extends Disposable implements editorCommo
|
||||
});
|
||||
|
||||
private _updateBrackets(): void {
|
||||
if (!this._matchBrackets) {
|
||||
if (this._matchBrackets === 'never') {
|
||||
return;
|
||||
}
|
||||
this._recomputeBrackets();
|
||||
@@ -332,8 +333,8 @@ export class BracketMatchingController extends Disposable implements editorCommo
|
||||
} else {
|
||||
let brackets = model.matchBracket(position);
|
||||
let options = BracketMatchingController._DECORATION_OPTIONS_WITH_OVERVIEW_RULER;
|
||||
if (!brackets) {
|
||||
brackets = model.findEnclosingBrackets(position);
|
||||
if (!brackets && this._matchBrackets === 'always') {
|
||||
brackets = model.findEnclosingBrackets(position, 20 /* give at most 20ms to compute */);
|
||||
options = BracketMatchingController._DECORATION_OPTIONS_WITHOUT_OVERVIEW_RULER;
|
||||
}
|
||||
newData[newDataLen++] = new BracketsData(position, brackets, options);
|
||||
|
||||
@@ -148,19 +148,29 @@ export class ContextMenuController implements IEditorContribution {
|
||||
// translate them into other actions
|
||||
for (let group of groups) {
|
||||
const [, actions] = group;
|
||||
let addedItems = 0;
|
||||
for (const action of actions) {
|
||||
if (action instanceof SubmenuItemAction) {
|
||||
const subActions = this._getMenuActions(model, action.item.submenu);
|
||||
if (subActions.length > 0) {
|
||||
result.push(new ContextSubMenu(action.label, subActions));
|
||||
addedItems++;
|
||||
}
|
||||
} else {
|
||||
result.push(action);
|
||||
addedItems++;
|
||||
}
|
||||
}
|
||||
result.push(new Separator());
|
||||
|
||||
if (addedItems) {
|
||||
result.push(new Separator());
|
||||
}
|
||||
}
|
||||
result.pop(); // remove last separator
|
||||
|
||||
if (result.length) {
|
||||
result.pop(); // remove last separator
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ const PART_WIDTH = 275;
|
||||
const FIND_INPUT_AREA_WIDTH = PART_WIDTH - 54;
|
||||
|
||||
let MAX_MATCHES_COUNT_WIDTH = 69;
|
||||
let FIND_ALL_CONTROLS_WIDTH = 17/** Find Input margin-left */ + (MAX_MATCHES_COUNT_WIDTH + 3 + 1) /** Match Results */ + 23 /** Button */ * 4 + 2/** sash */;
|
||||
// let FIND_ALL_CONTROLS_WIDTH = 17/** Find Input margin-left */ + (MAX_MATCHES_COUNT_WIDTH + 3 + 1) /** Match Results */ + 23 /** Button */ * 4 + 2/** sash */;
|
||||
|
||||
const FIND_INPUT_AREA_HEIGHT = 33; // The height of Find Widget when Replace Input is not visible.
|
||||
const ctrlEnterReplaceAllWarningPromptedKey = 'ctrlEnterReplaceAll.windows.donotask';
|
||||
@@ -706,10 +706,12 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
|
||||
if (this._resized) {
|
||||
this._findInput.inputBox.layout();
|
||||
let findInputWidth = this._findInput.inputBox.width;
|
||||
let findInputWidth = this._findInput.inputBox.element.clientWidth;
|
||||
if (findInputWidth > 0) {
|
||||
this._replaceInput.width = findInputWidth;
|
||||
}
|
||||
} else if (this._isReplaceVisible) {
|
||||
this._replaceInput.width = dom.getTotalWidth(this._findInput.domNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1159,13 +1161,11 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
return;
|
||||
}
|
||||
|
||||
const inputBoxWidth = width - FIND_ALL_CONTROLS_WIDTH;
|
||||
const maxWidth = parseFloat(dom.getComputedStyle(this._domNode).maxWidth!) || 0;
|
||||
if (width > maxWidth) {
|
||||
return;
|
||||
}
|
||||
this._domNode.style.width = `${width}px`;
|
||||
this._findInput.inputBox.width = inputBoxWidth;
|
||||
if (this._isReplaceVisible) {
|
||||
this._replaceInput.width = dom.getTotalWidth(this._findInput.domNode);
|
||||
}
|
||||
@@ -1197,10 +1197,8 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
*/
|
||||
}
|
||||
|
||||
const inputBoxWidth = width - FIND_ALL_CONTROLS_WIDTH;
|
||||
|
||||
this._domNode.style.width = `${width}px`;
|
||||
this._findInput.inputBox.width = inputBoxWidth;
|
||||
if (this._isReplaceVisible) {
|
||||
this._replaceInput.width = dom.getTotalWidth(this._findInput.domNode);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ReferencesModel, OneReference } from 'vs/editor/contrib/gotoSymbol/referencesModel';
|
||||
import { RawContextKey, IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { createDecorator, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
@@ -155,10 +155,7 @@ registerEditorCommand(new class extends EditorCommand {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'editor.gotoNextSymbolFromResult',
|
||||
precondition: ContextKeyExpr.and(
|
||||
ctxHasSymbols,
|
||||
ContextKeyExpr.equals('config.editor.gotoLocation.multiple', 'goto')
|
||||
),
|
||||
precondition: ctxHasSymbols,
|
||||
kbOpts: {
|
||||
weight: KeybindingWeight.EditorContrib,
|
||||
primary: KeyCode.F12
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
.monaco-editor .parameter-hints-widget .body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.monaco-editor .parameter-hints-widget .signature {
|
||||
@@ -72,6 +73,7 @@
|
||||
|
||||
.monaco-editor .parameter-hints-widget.multiple .controls {
|
||||
display: flex;
|
||||
padding: 0 2px;
|
||||
}
|
||||
|
||||
.monaco-editor .parameter-hints-widget.multiple .button {
|
||||
@@ -95,6 +97,7 @@
|
||||
height: 12px;
|
||||
line-height: 12px;
|
||||
opacity: 0.5;
|
||||
font-family: var(--monaco-monospace-font);
|
||||
}
|
||||
|
||||
.monaco-editor .parameter-hints-widget .signature .parameter.active {
|
||||
|
||||
168
src/vs/editor/test/common/model/tokensStore.test.ts
Normal file
168
src/vs/editor/test/common/model/tokensStore.test.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { MultilineTokens2, SparseEncodedTokens } from 'vs/editor/common/model/tokensStore';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { TextModel } from 'vs/editor/common/model/textModel';
|
||||
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
|
||||
import { MetadataConsts, TokenMetadata } from 'vs/editor/common/modes';
|
||||
|
||||
suite('TokensStore', () => {
|
||||
|
||||
const SEMANTIC_COLOR = 5;
|
||||
|
||||
function parseTokensState(state: string[]): { text: string; tokens: MultilineTokens2; } {
|
||||
let text: string[] = [];
|
||||
let tokens: number[] = [];
|
||||
let baseLine = 1;
|
||||
for (let i = 0; i < state.length; i++) {
|
||||
const line = state[i];
|
||||
|
||||
let startOffset = 0;
|
||||
let lineText = '';
|
||||
while (true) {
|
||||
const firstPipeOffset = line.indexOf('|', startOffset);
|
||||
if (firstPipeOffset === -1) {
|
||||
break;
|
||||
}
|
||||
const secondPipeOffset = line.indexOf('|', firstPipeOffset + 1);
|
||||
if (secondPipeOffset === -1) {
|
||||
break;
|
||||
}
|
||||
if (firstPipeOffset + 1 === secondPipeOffset) {
|
||||
// skip ||
|
||||
lineText += line.substring(startOffset, secondPipeOffset + 1);
|
||||
startOffset = secondPipeOffset + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
lineText += line.substring(startOffset, firstPipeOffset);
|
||||
const tokenStartCharacter = lineText.length;
|
||||
const tokenLength = secondPipeOffset - firstPipeOffset - 1;
|
||||
const metadata = (SEMANTIC_COLOR << MetadataConsts.FOREGROUND_OFFSET);
|
||||
|
||||
if (tokens.length === 0) {
|
||||
baseLine = i + 1;
|
||||
}
|
||||
tokens.push(i + 1 - baseLine, tokenStartCharacter, tokenStartCharacter + tokenLength, metadata);
|
||||
|
||||
lineText += line.substr(firstPipeOffset + 1, tokenLength);
|
||||
startOffset = secondPipeOffset + 1;
|
||||
}
|
||||
|
||||
lineText += line.substring(startOffset);
|
||||
|
||||
text.push(lineText);
|
||||
}
|
||||
|
||||
return {
|
||||
text: text.join('\n'),
|
||||
tokens: new MultilineTokens2(baseLine, new SparseEncodedTokens(new Uint32Array(tokens)))
|
||||
};
|
||||
}
|
||||
|
||||
function extractState(model: TextModel): string[] {
|
||||
let result: string[] = [];
|
||||
for (let lineNumber = 1; lineNumber <= model.getLineCount(); lineNumber++) {
|
||||
const lineTokens = model.getLineTokens(lineNumber);
|
||||
const lineContent = model.getLineContent(lineNumber);
|
||||
|
||||
let lineText = '';
|
||||
for (let i = 0; i < lineTokens.getCount(); i++) {
|
||||
const tokenStartCharacter = lineTokens.getStartOffset(i);
|
||||
const tokenEndCharacter = lineTokens.getEndOffset(i);
|
||||
const metadata = lineTokens.getMetadata(i);
|
||||
const color = TokenMetadata.getForeground(metadata);
|
||||
const tokenText = lineContent.substring(tokenStartCharacter, tokenEndCharacter);
|
||||
if (color === SEMANTIC_COLOR) {
|
||||
lineText += `|${tokenText}|`;
|
||||
} else {
|
||||
lineText += tokenText;
|
||||
}
|
||||
}
|
||||
|
||||
result.push(lineText);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// function extractState
|
||||
|
||||
function testTokensAdjustment(rawInitialState: string[], edits: IIdentifiedSingleEditOperation[], rawFinalState: string[]) {
|
||||
const initialState = parseTokensState(rawInitialState);
|
||||
const model = TextModel.createFromString(initialState.text);
|
||||
model.setSemanticTokens([initialState.tokens]);
|
||||
|
||||
model.applyEdits(edits);
|
||||
|
||||
const actualState = extractState(model);
|
||||
assert.deepEqual(actualState, rawFinalState);
|
||||
|
||||
model.dispose();
|
||||
}
|
||||
|
||||
test('issue #86303 - color shifting between different tokens', () => {
|
||||
testTokensAdjustment(
|
||||
[
|
||||
`import { |URI| } from 'vs/base/common/uri';`,
|
||||
`const foo = |URI|.parse('hey');`
|
||||
],
|
||||
[
|
||||
{ range: new Range(2, 9, 2, 10), text: '' }
|
||||
],
|
||||
[
|
||||
`import { |URI| } from 'vs/base/common/uri';`,
|
||||
`const fo = |URI|.parse('hey');`
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
test('deleting a newline', () => {
|
||||
testTokensAdjustment(
|
||||
[
|
||||
`import { |URI| } from 'vs/base/common/uri';`,
|
||||
`const foo = |URI|.parse('hey');`
|
||||
],
|
||||
[
|
||||
{ range: new Range(1, 42, 2, 1), text: '' }
|
||||
],
|
||||
[
|
||||
`import { |URI| } from 'vs/base/common/uri';const foo = |URI|.parse('hey');`
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
test('inserting a newline', () => {
|
||||
testTokensAdjustment(
|
||||
[
|
||||
`import { |URI| } from 'vs/base/common/uri';const foo = |URI|.parse('hey');`
|
||||
],
|
||||
[
|
||||
{ range: new Range(1, 42, 1, 42), text: '\n' }
|
||||
],
|
||||
[
|
||||
`import { |URI| } from 'vs/base/common/uri';`,
|
||||
`const foo = |URI|.parse('hey');`
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
test('deleting a newline 2', () => {
|
||||
testTokensAdjustment(
|
||||
[
|
||||
`import { `,
|
||||
` |URI| } from 'vs/base/common/uri';const foo = |URI|.parse('hey');`
|
||||
],
|
||||
[
|
||||
{ range: new Range(1, 10, 2, 5), text: '' }
|
||||
],
|
||||
[
|
||||
`import { |URI| } from 'vs/base/common/uri';const foo = |URI|.parse('hey');`
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
4
src/vs/monaco.d.ts
vendored
4
src/vs/monaco.d.ts
vendored
@@ -2880,9 +2880,9 @@ declare namespace monaco.editor {
|
||||
showFoldingControls?: 'always' | 'mouseover';
|
||||
/**
|
||||
* Enable highlighting of matching brackets.
|
||||
* Defaults to true.
|
||||
* Defaults to 'always'.
|
||||
*/
|
||||
matchBrackets?: boolean;
|
||||
matchBrackets?: 'never' | 'near' | 'always';
|
||||
/**
|
||||
* Enable rendering of whitespace.
|
||||
* Defaults to none.
|
||||
|
||||
@@ -819,3 +819,18 @@ export function etag(stat: { mtime: number | undefined, size: number | undefined
|
||||
|
||||
return stat.mtime.toString(29) + stat.size.toString(31);
|
||||
}
|
||||
|
||||
|
||||
export function whenProviderRegistered(file: URI, fileService: IFileService): Promise<void> {
|
||||
if (fileService.canHandleResource(URI.from({ scheme: file.scheme }))) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return new Promise((c, e) => {
|
||||
const disposable = fileService.onDidChangeFileSystemProviderRegistrations(e => {
|
||||
if (e.scheme === file.scheme && e.added) {
|
||||
disposable.dispose();
|
||||
c();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
|
||||
import { ILogService, LogLevel, AbstractLogService, ILoggerService, ILogger } from 'vs/platform/log/common/log';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IFileService, whenProviderRegistered } from 'vs/platform/files/common/files';
|
||||
import { Queue } from 'vs/base/common/async';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { dirname, joinPath, basename } from 'vs/base/common/resources';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
|
||||
|
||||
const MAX_FILE_SIZE = 1024 * 1024 * 5;
|
||||
|
||||
@@ -163,6 +164,7 @@ export class FileLoggerService extends Disposable implements ILoggerService {
|
||||
constructor(
|
||||
@ILogService private logService: ILogService,
|
||||
@IInstantiationService private instantiationService: IInstantiationService,
|
||||
@IFileService private fileService: IFileService,
|
||||
) {
|
||||
super();
|
||||
this._register(logService.onDidChangeLogLevel(level => this.loggers.forEach(logger => logger.setLevel(level))));
|
||||
@@ -171,8 +173,9 @@ export class FileLoggerService extends Disposable implements ILoggerService {
|
||||
getLogger(resource: URI): ILogger {
|
||||
let logger = this.loggers.get(resource.toString());
|
||||
if (!logger) {
|
||||
logger = this.instantiationService.createInstance(FileLogService, basename(resource), resource, this.logService.getLevel());
|
||||
logger = new BufferLogService, this.logService.getLevel();
|
||||
this.loggers.set(resource.toString(), logger);
|
||||
whenProviderRegistered(resource, this.fileService).then(() => (<BufferLogService>logger).logger = this.instantiationService.createInstance(FileLogService, basename(resource), resource, this.logService.getLevel()));
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
||||
@@ -306,8 +306,8 @@ export const editorFindRangeHighlightBorder = registerColor('editor.findRangeHig
|
||||
*
|
||||
* Distinct from normal editor find match to allow for better differentiation
|
||||
*/
|
||||
export const searchEditorFindMatch = registerColor('searchEditor.findMatchBackground', { light: transparent(editorFindMatchHighlight, 0.5), dark: transparent(editorFindMatchHighlight, 0.5), hc: editorFindMatchHighlight }, nls.localize('searchEditor.queryMatch', "Color of the Search Editor query matches."));
|
||||
export const searchEditorFindMatchBorder = registerColor('searchEditor.findMatchBorder', { light: transparent(editorFindMatchHighlightBorder, 0.5), dark: transparent(editorFindMatchHighlightBorder, 0.5), hc: editorFindMatchHighlightBorder }, nls.localize('searchEditor.editorFindMatchBorder', "Border color of the Search Editor query matches."));
|
||||
export const searchEditorFindMatch = registerColor('searchEditor.findMatchBackground', { light: transparent(editorFindMatchHighlight, 0.66), dark: transparent(editorFindMatchHighlight, 0.66), hc: editorFindMatchHighlight }, nls.localize('searchEditor.queryMatch', "Color of the Search Editor query matches."));
|
||||
export const searchEditorFindMatchBorder = registerColor('searchEditor.findMatchBorder', { light: transparent(editorFindMatchHighlightBorder, 0.66), dark: transparent(editorFindMatchHighlightBorder, 0.66), hc: editorFindMatchHighlightBorder }, nls.localize('searchEditor.editorFindMatchBorder', "Border color of the Search Editor query matches."));
|
||||
|
||||
/**
|
||||
* Editor hover
|
||||
|
||||
@@ -320,40 +320,45 @@ export function getTokenClassificationRegistry(): ITokenClassificationRegistry {
|
||||
return tokenClassificationRegistry;
|
||||
}
|
||||
|
||||
export const comments = registerTokenType('comments', nls.localize('comments', "Style for comments."), [['comment']]);
|
||||
export const strings = registerTokenType('strings', nls.localize('strings', "Style for strings."), [['string']]);
|
||||
export const keywords = registerTokenType('keywords', nls.localize('keywords', "Style for keywords."), [['keyword.control']]);
|
||||
export const numbers = registerTokenType('numbers', nls.localize('numbers', "Style for numbers."), [['constant.numeric']]);
|
||||
export const regexp = registerTokenType('regexp', nls.localize('regexp', "Style for expressions."), [['constant.regexp']]);
|
||||
export const operators = registerTokenType('operators', nls.localize('operator', "Style for operators."), [['keyword.operator']]);
|
||||
// default token types
|
||||
|
||||
export const namespaces = registerTokenType('namespaces', nls.localize('namespace', "Style for namespaces."), [['entity.name.namespace']]);
|
||||
registerTokenType('comment', nls.localize('comment', "Style for comments."), [['comment']]);
|
||||
registerTokenType('string', nls.localize('string', "Style for strings."), [['string']]);
|
||||
registerTokenType('keyword', nls.localize('keyword', "Style for keywords."), [['keyword.control']]);
|
||||
registerTokenType('number', nls.localize('number', "Style for numbers."), [['constant.numeric']]);
|
||||
registerTokenType('regexp', nls.localize('regexp', "Style for expressions."), [['constant.regexp']]);
|
||||
registerTokenType('operator', nls.localize('operator', "Style for operators."), [['keyword.operator']]);
|
||||
|
||||
export const types = registerTokenType('types', nls.localize('types', "Style for types."), [['entity.name.type'], ['entity.name.class'], ['support.type'], ['support.class']]);
|
||||
export const structs = registerTokenType('structs', nls.localize('struct', "Style for structs."), [['storage.type.struct']], types);
|
||||
export const classes = registerTokenType('classes', nls.localize('class', "Style for classes."), [['entity.name.class']], types);
|
||||
export const interfaces = registerTokenType('interfaces', nls.localize('interface', "Style for interfaces."), undefined, types);
|
||||
export const enums = registerTokenType('enums', nls.localize('enum', "Style for enums."), undefined, types);
|
||||
export const parameterTypes = registerTokenType('parameterTypes', nls.localize('parameterType', "Style for parameter types."), undefined, types);
|
||||
registerTokenType('namespace', nls.localize('namespace', "Style for namespaces."), [['entity.name.namespace']]);
|
||||
|
||||
export const functions = registerTokenType('functions', nls.localize('functions', "Style for functions"), [['entity.name.function'], ['support.function']]);
|
||||
export const macros = registerTokenType('macros', nls.localize('macro', "Style for macros."), undefined, functions);
|
||||
registerTokenType('type', nls.localize('type', "Style for types."), [['entity.name.type'], ['entity.name.class'], ['support.type'], ['support.class']]);
|
||||
registerTokenType('struct', nls.localize('struct', "Style for structs."), [['storage.type.struct']], 'type');
|
||||
registerTokenType('class', nls.localize('class', "Style for classes."), [['entity.name.class']], 'type');
|
||||
registerTokenType('interface', nls.localize('interface', "Style for interfaces."), undefined, 'type');
|
||||
registerTokenType('enum', nls.localize('enum', "Style for enums."), undefined, 'type');
|
||||
registerTokenType('parameterType', nls.localize('parameterType', "Style for parameter types."), undefined, 'type');
|
||||
|
||||
export const variables = registerTokenType('variables', nls.localize('variables', "Style for variables."), [['variable'], ['entity.name.variable']]);
|
||||
export const constants = registerTokenType('constants', nls.localize('constants', "Style for constants."), undefined, variables);
|
||||
export const parameters = registerTokenType('parameters', nls.localize('parameters', "Style for parameters."), undefined, variables);
|
||||
export const property = registerTokenType('properties', nls.localize('properties', "Style for properties."), undefined, variables);
|
||||
registerTokenType('function', nls.localize('function', "Style for functions"), [['entity.name.function'], ['support.function']]);
|
||||
registerTokenType('macro', nls.localize('macro', "Style for macros."), undefined, 'function');
|
||||
|
||||
export const labels = registerTokenType('labels', nls.localize('labels', "Style for labels. "), undefined);
|
||||
registerTokenType('variable', nls.localize('variable', "Style for variables."), [['variable'], ['entity.name.variable']]);
|
||||
registerTokenType('constant', nls.localize('constant', "Style for constants."), undefined, 'variable');
|
||||
registerTokenType('parameter', nls.localize('parameter', "Style for parameters."), undefined, 'variable');
|
||||
registerTokenType('property', nls.localize('propertie', "Style for properties."), undefined, 'variable');
|
||||
|
||||
registerTokenType('label', nls.localize('labels', "Style for labels. "), undefined);
|
||||
|
||||
// default token modifiers
|
||||
|
||||
registerTokenModifier('declaration', nls.localize('declaration', "Style for all symbol declarations."), undefined);
|
||||
registerTokenModifier('documentation', nls.localize('documentation', "Style to use for references in documentation."), undefined);
|
||||
registerTokenModifier('member', nls.localize('member', "Style to use for member functions, variables (fields) and types."), undefined);
|
||||
registerTokenModifier('static', nls.localize('static', "Style to use for symbols that are static."), undefined);
|
||||
registerTokenModifier('abstract', nls.localize('abstract', "Style to use for symbols that are abstract."), undefined);
|
||||
registerTokenModifier('deprecated', nls.localize('deprecated', "Style to use for symbols that are deprecated."), undefined);
|
||||
registerTokenModifier('modification', nls.localize('modification', "Style to use for write accesses."), undefined);
|
||||
registerTokenModifier('async', nls.localize('async', "Style to use for symbols that are async."), undefined);
|
||||
|
||||
export const m_declaration = registerTokenModifier('declaration', nls.localize('declaration', "Style for all symbol declarations."), undefined);
|
||||
export const m_documentation = registerTokenModifier('documentation', nls.localize('documentation', "Style to use for references in documentation."), undefined);
|
||||
export const m_member = registerTokenModifier('member', nls.localize('member', "Style to use for member functions, variables (fields) and types."), undefined);
|
||||
export const m_static = registerTokenModifier('static', nls.localize('static', "Style to use for symbols that are static."), undefined);
|
||||
export const m_abstract = registerTokenModifier('abstract', nls.localize('abstract', "Style to use for symbols that are abstract."), undefined);
|
||||
export const m_deprecated = registerTokenModifier('deprecated', nls.localize('deprecated', "Style to use for symbols that are deprecated."), undefined);
|
||||
export const m_modification = registerTokenModifier('modification', nls.localize('modification', "Style to use for write accesses."), undefined);
|
||||
export const m_async = registerTokenModifier('async', nls.localize('async', "Style to use for symbols that are async."), undefined);
|
||||
|
||||
function bitCount(u: number) {
|
||||
// https://blogs.msdn.microsoft.com/jeuge/2005/06/08/bit-fiddling-3/
|
||||
|
||||
@@ -18,6 +18,7 @@ import { startsWith } from 'vs/base/common/strings';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { Queue } from 'vs/base/common/async';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
export interface ISyncPreviewResult {
|
||||
readonly added: ISyncExtension[];
|
||||
@@ -26,6 +27,10 @@ export interface ISyncPreviewResult {
|
||||
readonly remote: ISyncExtension[] | null;
|
||||
}
|
||||
|
||||
interface ILastSyncUserData extends IUserData {
|
||||
skippedExtensions: ISyncExtension[] | undefined;
|
||||
}
|
||||
|
||||
export class ExtensionsSynchroniser extends Disposable implements ISynchroniser {
|
||||
|
||||
private static EXTERNAL_USER_DATA_EXTENSIONS_KEY: string = 'extensions';
|
||||
@@ -122,14 +127,16 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
|
||||
|
||||
private async doSync(): Promise<void> {
|
||||
const lastSyncData = await this.getLastSyncUserData();
|
||||
let remoteData = await this.userDataSyncStoreService.read(ExtensionsSynchroniser.EXTERNAL_USER_DATA_EXTENSIONS_KEY, lastSyncData);
|
||||
const lastSyncExtensions: ISyncExtension[] | null = lastSyncData ? JSON.parse(lastSyncData.content!) : null;
|
||||
let skippedExtensions: ISyncExtension[] = lastSyncData ? lastSyncData.skippedExtensions || [] : [];
|
||||
|
||||
const lastSyncExtensions: ISyncExtension[] = lastSyncData ? JSON.parse(lastSyncData.content!) : null;
|
||||
let remoteData = await this.userDataSyncStoreService.read(ExtensionsSynchroniser.EXTERNAL_USER_DATA_EXTENSIONS_KEY, lastSyncData);
|
||||
const remoteExtensions: ISyncExtension[] = remoteData.content ? JSON.parse(remoteData.content) : null;
|
||||
|
||||
const localExtensions = await this.getLocalExtensions();
|
||||
|
||||
this.logService.trace('Extensions: Merging remote extensions with local extensions...');
|
||||
const { added, removed, updated, remote } = this.merge(localExtensions, remoteExtensions, lastSyncExtensions);
|
||||
const { added, removed, updated, remote } = this.merge(localExtensions, remoteExtensions, lastSyncExtensions, skippedExtensions);
|
||||
|
||||
if (!added.length && !removed.length && !updated.length && !remote) {
|
||||
this.logService.trace('Extensions: No changes found during synchronizing extensions.');
|
||||
@@ -137,7 +144,7 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
|
||||
|
||||
if (added.length || removed.length || updated.length) {
|
||||
this.logService.info('Extensions: Updating local extensions...');
|
||||
await this.updateLocalExtensions(added, removed, updated);
|
||||
skippedExtensions = await this.updateLocalExtensions(added, removed, updated, skippedExtensions);
|
||||
}
|
||||
|
||||
if (remote) {
|
||||
@@ -151,7 +158,7 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
|
||||
) {
|
||||
// update last sync
|
||||
this.logService.info('Extensions: Updating last synchronised extensions...');
|
||||
await this.updateLastSyncValue(remoteData);
|
||||
await this.updateLastSyncValue({ ...remoteData, skippedExtensions });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +168,7 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
|
||||
* - Overwrite local with remote changes. Removed, Added, Updated.
|
||||
* - Update remote with those local extension which are newly added or updated or removed and untouched in remote.
|
||||
*/
|
||||
private merge(localExtensions: ISyncExtension[], remoteExtensions: ISyncExtension[] | null, lastSyncExtensions: ISyncExtension[] | null): { added: ISyncExtension[], removed: IExtensionIdentifier[], updated: ISyncExtension[], remote: ISyncExtension[] | null } {
|
||||
private merge(localExtensions: ISyncExtension[], remoteExtensions: ISyncExtension[] | null, lastSyncExtensions: ISyncExtension[] | null, skippedExtensions: ISyncExtension[]): { added: ISyncExtension[], removed: IExtensionIdentifier[], updated: ISyncExtension[], remote: ISyncExtension[] | null } {
|
||||
const ignoredExtensions = this.configurationService.getValue<string[]>('sync.ignoredExtensions') || [];
|
||||
// First time sync
|
||||
if (!remoteExtensions) {
|
||||
@@ -187,6 +194,7 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
|
||||
const remoteExtensionsMap = remoteExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>());
|
||||
const newRemoteExtensionsMap = remoteExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>());
|
||||
const lastSyncExtensionsMap = lastSyncExtensions ? lastSyncExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>()) : null;
|
||||
const skippedExtensionsMap = skippedExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>());
|
||||
const ignoredExtensionsSet = ignoredExtensions.reduce((set, id) => {
|
||||
const uuid = uuids.get(id.toLowerCase());
|
||||
return set.add(uuid ? `uuid:${uuid}` : `id:${id.toLowerCase()}`);
|
||||
@@ -273,8 +281,8 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
|
||||
|
||||
// Locally removed extensions
|
||||
for (const key of values(baseToLocal.removed)) {
|
||||
// If not updated in remote
|
||||
if (!baseToRemote.updated.has(key)) {
|
||||
// If not skipped and not updated in remote
|
||||
if (!skippedExtensionsMap.has(key) && !baseToRemote.updated.has(key)) {
|
||||
newRemoteExtensionsMap.delete(key);
|
||||
}
|
||||
}
|
||||
@@ -308,13 +316,17 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
|
||||
return { added, removed, updated };
|
||||
}
|
||||
|
||||
private async updateLocalExtensions(added: ISyncExtension[], removed: IExtensionIdentifier[], updated: ISyncExtension[]): Promise<void> {
|
||||
private async updateLocalExtensions(added: ISyncExtension[], removed: IExtensionIdentifier[], updated: ISyncExtension[], skippedExtensions: ISyncExtension[]): Promise<ISyncExtension[]> {
|
||||
const removeFromSkipped: IExtensionIdentifier[] = [];
|
||||
const addToSkipped: ISyncExtension[] = [];
|
||||
|
||||
if (removed.length) {
|
||||
const installedExtensions = await this.extensionManagementService.getInstalled(ExtensionType.User);
|
||||
const extensionsToRemove = installedExtensions.filter(({ identifier }) => removed.some(r => areSameExtensions(identifier, r)));
|
||||
await Promise.all(extensionsToRemove.map(e => {
|
||||
this.logService.info('Extensions: Removing local extension.', e.identifier.id);
|
||||
return this.extensionManagementService.uninstall(e);
|
||||
await Promise.all(extensionsToRemove.map(async extensionToRemove => {
|
||||
this.logService.info('Extensions: Removing local extension.', extensionToRemove.identifier.id);
|
||||
await this.extensionManagementService.uninstall(extensionToRemove);
|
||||
removeFromSkipped.push(extensionToRemove.identifier);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -323,18 +335,41 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
|
||||
const extension = await this.extensionGalleryService.getCompatibleExtension(e.identifier, e.version);
|
||||
if (extension) {
|
||||
this.logService.info('Extensions: Installing local extension.', e.identifier.id, extension.version);
|
||||
await this.extensionManagementService.installFromGallery(extension);
|
||||
try {
|
||||
await this.extensionManagementService.installFromGallery(extension);
|
||||
removeFromSkipped.push(extension.identifier);
|
||||
} catch (error) {
|
||||
addToSkipped.push(e);
|
||||
this.logService.error(error);
|
||||
this.logService.info(localize('skip extension', "Skipping synchronising extension {0}", extension.displayName || extension.identifier.id));
|
||||
}
|
||||
} else {
|
||||
addToSkipped.push(e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
const newSkippedExtensions: ISyncExtension[] = [];
|
||||
for (const skippedExtension of skippedExtensions) {
|
||||
if (!removeFromSkipped.some(e => areSameExtensions(e, skippedExtension.identifier))) {
|
||||
newSkippedExtensions.push(skippedExtension);
|
||||
}
|
||||
}
|
||||
for (const skippedExtension of addToSkipped) {
|
||||
if (!newSkippedExtensions.some(e => areSameExtensions(e.identifier, skippedExtension.identifier))) {
|
||||
newSkippedExtensions.push(skippedExtension);
|
||||
}
|
||||
}
|
||||
return newSkippedExtensions;
|
||||
}
|
||||
|
||||
private async getLocalExtensions(): Promise<ISyncExtension[]> {
|
||||
const installedExtensions = await this.extensionManagementService.getInstalled(ExtensionType.User);
|
||||
return installedExtensions.map(({ identifier }) => ({ identifier, enabled: true }));
|
||||
return installedExtensions
|
||||
.map(({ identifier }) => ({ identifier, enabled: true }));
|
||||
}
|
||||
|
||||
private async getLastSyncUserData(): Promise<IUserData | null> {
|
||||
private async getLastSyncUserData(): Promise<ILastSyncUserData | null> {
|
||||
try {
|
||||
const content = await this.fileService.readFile(this.lastSyncExtensionsResource);
|
||||
return JSON.parse(content.value.toString());
|
||||
@@ -343,14 +378,14 @@ export class ExtensionsSynchroniser extends Disposable implements ISynchroniser
|
||||
}
|
||||
}
|
||||
|
||||
private async updateLastSyncValue(lastSyncUserData: ILastSyncUserData): Promise<void> {
|
||||
await this.fileService.writeFile(this.lastSyncExtensionsResource, VSBuffer.fromString(JSON.stringify(lastSyncUserData)));
|
||||
}
|
||||
|
||||
private async writeToRemote(extensions: ISyncExtension[], ref: string | null): Promise<IUserData> {
|
||||
const content = JSON.stringify(extensions);
|
||||
ref = await this.userDataSyncStoreService.write(ExtensionsSynchroniser.EXTERNAL_USER_DATA_EXTENSIONS_KEY, content, ref);
|
||||
return { content, ref };
|
||||
}
|
||||
|
||||
private async updateLastSyncValue(remoteUserData: IUserData): Promise<void> {
|
||||
await this.fileService.writeFile(this.lastSyncExtensionsResource, VSBuffer.fromString(JSON.stringify(remoteUserData)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { parse, ParseError } from 'vs/base/common/json';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { CancelablePromise, createCancelablePromise, ThrottledDelayer } from 'vs/base/common/async';
|
||||
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { joinPath, dirname } from 'vs/base/common/resources';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { OS, OperatingSystem } from 'vs/base/common/platform';
|
||||
@@ -46,7 +46,6 @@ export class KeybindingsSynchroniser extends Disposable implements ISynchroniser
|
||||
private _onDidChangStatus: Emitter<SyncStatus> = this._register(new Emitter<SyncStatus>());
|
||||
readonly onDidChangeStatus: Event<SyncStatus> = this._onDidChangStatus.event;
|
||||
|
||||
private readonly throttledDelayer: ThrottledDelayer<void>;
|
||||
private _onDidChangeLocal: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChangeLocal: Event<void> = this._onDidChangeLocal.event;
|
||||
|
||||
@@ -62,24 +61,8 @@ export class KeybindingsSynchroniser extends Disposable implements ISynchroniser
|
||||
) {
|
||||
super();
|
||||
this.lastSyncKeybindingsResource = joinPath(this.environmentService.userRoamingDataHome, '.lastSyncKeybindings.json');
|
||||
this.throttledDelayer = this._register(new ThrottledDelayer<void>(500));
|
||||
this._register(this.fileService.watch(this.environmentService.keybindingsResource));
|
||||
this._register(Event.filter(this.fileService.onFileChanges, e => e.contains(this.environmentService.keybindingsResource))(() => this.throttledDelayer.trigger(() => this.onDidChangeKeybindings())));
|
||||
}
|
||||
|
||||
private async onDidChangeKeybindings(): Promise<void> {
|
||||
const localFileContent = await this.getLocalContent();
|
||||
const lastSyncData = await this.getLastSyncUserData();
|
||||
if (localFileContent && lastSyncData) {
|
||||
if (localFileContent.value.toString() !== lastSyncData.content) {
|
||||
this._onDidChangeLocal.fire();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!localFileContent || !lastSyncData) {
|
||||
this._onDidChangeLocal.fire();
|
||||
return;
|
||||
}
|
||||
this._register(this.fileService.watch(dirname(this.environmentService.keybindingsResource)));
|
||||
this._register(Event.filter(this.fileService.onFileChanges, e => e.contains(this.environmentService.keybindingsResource))(() => this._onDidChangeLocal.fire()));
|
||||
}
|
||||
|
||||
private setStatus(status: SyncStatus): void {
|
||||
|
||||
@@ -10,10 +10,10 @@ import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { parse, ParseError } from 'vs/base/common/json';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { CancelablePromise, createCancelablePromise, ThrottledDelayer } from 'vs/base/common/async';
|
||||
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import { joinPath, dirname } from 'vs/base/common/resources';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
@@ -37,7 +37,6 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
|
||||
private _onDidChangStatus: Emitter<SyncStatus> = this._register(new Emitter<SyncStatus>());
|
||||
readonly onDidChangeStatus: Event<SyncStatus> = this._onDidChangStatus.event;
|
||||
|
||||
private readonly throttledDelayer: ThrottledDelayer<void>;
|
||||
private _onDidChangeLocal: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChangeLocal: Event<void> = this._onDidChangeLocal.event;
|
||||
|
||||
@@ -53,23 +52,8 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
|
||||
) {
|
||||
super();
|
||||
this.lastSyncSettingsResource = joinPath(this.environmentService.userRoamingDataHome, '.lastSyncSettings.json');
|
||||
this.throttledDelayer = this._register(new ThrottledDelayer<void>(500));
|
||||
this._register(Event.filter(this.fileService.onFileChanges, e => e.contains(this.environmentService.settingsResource))(() => this.throttledDelayer.trigger(() => this.onDidChangeSettings())));
|
||||
}
|
||||
|
||||
private async onDidChangeSettings(): Promise<void> {
|
||||
const localFileContent = await this.getLocalFileContent();
|
||||
const lastSyncData = await this.getLastSyncUserData();
|
||||
if (localFileContent && lastSyncData) {
|
||||
if (localFileContent.value.toString() !== lastSyncData.content) {
|
||||
this._onDidChangeLocal.fire();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!localFileContent || !lastSyncData) {
|
||||
this._onDidChangeLocal.fire();
|
||||
return;
|
||||
}
|
||||
this._register(this.fileService.watch(dirname(this.environmentService.settingsResource)));
|
||||
this._register(Event.filter(this.fileService.onFileChanges, e => e.contains(this.environmentService.settingsResource))(() => this._onDidChangeLocal.fire()));
|
||||
}
|
||||
|
||||
private setStatus(status: SyncStatus): void {
|
||||
|
||||
236
src/vs/vscode.d.ts
vendored
236
src/vs/vscode.d.ts
vendored
@@ -8084,6 +8084,172 @@ declare module 'vscode' {
|
||||
waitUntil(thenable: Thenable<any>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired when files are going to be created.
|
||||
*
|
||||
* To make modifications to the workspace before the files are created,
|
||||
* call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a
|
||||
* thenable that resolves to a [workspace edit](#WorkspaceEdit).
|
||||
*/
|
||||
export interface FileWillCreateEvent {
|
||||
|
||||
/**
|
||||
* The files that are going to be created.
|
||||
*/
|
||||
readonly files: ReadonlyArray<Uri>;
|
||||
|
||||
/**
|
||||
* Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit).
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch and not
|
||||
* in an asynchronous manner:
|
||||
*
|
||||
* ```ts
|
||||
* workspace.onWillCreateFiles(event => {
|
||||
* // async, will *throw* an error
|
||||
* setTimeout(() => event.waitUntil(promise));
|
||||
*
|
||||
* // sync, OK
|
||||
* event.waitUntil(promise);
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<WorkspaceEdit>): void;
|
||||
|
||||
/**
|
||||
* Allows to pause the event until the provided thenable resolves.
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch.
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<any>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired after files are created.
|
||||
*/
|
||||
export interface FileCreateEvent {
|
||||
|
||||
/**
|
||||
* The files that got created.
|
||||
*/
|
||||
readonly files: ReadonlyArray<Uri>;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired when files are going to be deleted.
|
||||
*
|
||||
* To make modifications to the workspace before the files are deleted,
|
||||
* call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a
|
||||
* thenable that resolves to a [workspace edit](#WorkspaceEdit).
|
||||
*/
|
||||
export interface FileWillDeleteEvent {
|
||||
|
||||
/**
|
||||
* The files that are going to be deleted.
|
||||
*/
|
||||
readonly files: ReadonlyArray<Uri>;
|
||||
|
||||
/**
|
||||
* Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit).
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch and not
|
||||
* in an asynchronous manner:
|
||||
*
|
||||
* ```ts
|
||||
* workspace.onWillCreateFiles(event => {
|
||||
* // async, will *throw* an error
|
||||
* setTimeout(() => event.waitUntil(promise));
|
||||
*
|
||||
* // sync, OK
|
||||
* event.waitUntil(promise);
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<WorkspaceEdit>): void;
|
||||
|
||||
/**
|
||||
* Allows to pause the event until the provided thenable resolves.
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch.
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<any>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired after files are deleted.
|
||||
*/
|
||||
export interface FileDeleteEvent {
|
||||
|
||||
/**
|
||||
* The files that got deleted.
|
||||
*/
|
||||
readonly files: ReadonlyArray<Uri>;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired when files are going to be renamed.
|
||||
*
|
||||
* To make modifications to the workspace before the files are renamed,
|
||||
* call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a
|
||||
* thenable that resolves to a [workspace edit](#WorkspaceEdit).
|
||||
*/
|
||||
export interface FileWillRenameEvent {
|
||||
|
||||
/**
|
||||
* The files that are going to be renamed.
|
||||
*/
|
||||
readonly files: ReadonlyArray<{ oldUri: Uri, newUri: Uri }>;
|
||||
|
||||
/**
|
||||
* Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit).
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch and not
|
||||
* in an asynchronous manner:
|
||||
*
|
||||
* ```ts
|
||||
* workspace.onWillCreateFiles(event => {
|
||||
* // async, will *throw* an error
|
||||
* setTimeout(() => event.waitUntil(promise));
|
||||
*
|
||||
* // sync, OK
|
||||
* event.waitUntil(promise);
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<WorkspaceEdit>): void;
|
||||
|
||||
/**
|
||||
* Allows to pause the event until the provided thenable resolves.
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch.
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<any>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired after files are renamed.
|
||||
*/
|
||||
export interface FileRenameEvent {
|
||||
|
||||
/**
|
||||
* The files that got renamed.
|
||||
*/
|
||||
readonly files: ReadonlyArray<{ oldUri: Uri, newUri: Uri }>;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An event describing a change to the set of [workspace folders](#workspace.workspaceFolders).
|
||||
*/
|
||||
@@ -8433,6 +8599,76 @@ declare module 'vscode' {
|
||||
*/
|
||||
export const onDidSaveTextDocument: Event<TextDocument>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files are being created.
|
||||
*
|
||||
* *Note 1:* This event is triggered by user gestures, like creating a file from the
|
||||
* explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api. This event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*
|
||||
* *Note 2:* When this event is fired, edits to files thare are being created cannot be applied.
|
||||
*/
|
||||
export const onWillCreateFiles: Event<FileWillCreateEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files have been created.
|
||||
*
|
||||
* *Note:* This event is triggered by user gestures, like creating a file from the
|
||||
* explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*/
|
||||
export const onDidCreateFiles: Event<FileCreateEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files are being deleted.
|
||||
*
|
||||
* *Note 1:* This event is triggered by user gestures, like deleting a file from the
|
||||
* explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*
|
||||
* *Note 2:* When deleting a folder with children only one event is fired.
|
||||
*/
|
||||
export const onWillDeleteFiles: Event<FileWillDeleteEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files have been deleted.
|
||||
*
|
||||
* *Note 1:* This event is triggered by user gestures, like deleting a file from the
|
||||
* explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*
|
||||
* *Note 2:* When deleting a folder with children only one event is fired.
|
||||
*/
|
||||
export const onDidDeleteFiles: Event<FileDeleteEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files are being renamed.
|
||||
*
|
||||
* *Note 1:* This event is triggered by user gestures, like renaming a file from the
|
||||
* explorer, and from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*
|
||||
* *Note 2:* When renaming a folder with children only one event is fired.
|
||||
*/
|
||||
export const onWillRenameFiles: Event<FileWillRenameEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files have been renamed.
|
||||
*
|
||||
* *Note 1:* This event is triggered by user gestures, like renaming a file from the
|
||||
* explorer, and from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*
|
||||
* *Note 2:* When renaming a folder with children only one event is fired.
|
||||
*/
|
||||
export const onDidRenameFiles: Event<FileRenameEvent>;
|
||||
|
||||
/**
|
||||
* Get a workspace configuration object.
|
||||
*
|
||||
|
||||
494
src/vs/vscode.proposed.d.ts
vendored
494
src/vs/vscode.proposed.d.ts
vendored
@@ -68,7 +68,7 @@ declare module 'vscode' {
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Alex - semantic tokens
|
||||
//#region Semantic tokens: https://github.com/microsoft/vscode/issues/86415
|
||||
|
||||
export class SemanticTokensLegend {
|
||||
public readonly tokenTypes: string[];
|
||||
@@ -83,15 +83,13 @@ declare module 'vscode' {
|
||||
build(): Uint32Array;
|
||||
}
|
||||
|
||||
/**
|
||||
* A certain token (at index `i` is encoded using 5 uint32 integers):
|
||||
* - at index `5*i` - `deltaLine`: token line number, relative to `SemanticColoringArea.line`
|
||||
* - at index `5*i+1` - `deltaStart`: token start character offset inside the line (relative to 0 or the previous token if they are on the same line)
|
||||
* - at index `5*i+2` - `length`: the length of the token
|
||||
* - at index `5*i+3` - `tokenType`: will be looked up in `SemanticColoringLegend.tokenTypes`
|
||||
* - at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticColoringLegend.tokenModifiers`
|
||||
*/
|
||||
export class SemanticTokens {
|
||||
/**
|
||||
* The result id of the tokens.
|
||||
*
|
||||
* On a next call to `provideSemanticTokens`, if VS Code still holds in memory this result,
|
||||
* the result id will be passed in as `SemanticTokensRequestOptions.previousResultId`.
|
||||
*/
|
||||
readonly resultId?: string;
|
||||
readonly data: Uint32Array;
|
||||
|
||||
@@ -99,6 +97,12 @@ declare module 'vscode' {
|
||||
}
|
||||
|
||||
export class SemanticTokensEdits {
|
||||
/**
|
||||
* The result id of the tokens.
|
||||
*
|
||||
* On a next call to `provideSemanticTokens`, if VS Code still holds in memory this result,
|
||||
* the result id will be passed in as `SemanticTokensRequestOptions.previousResultId`.
|
||||
*/
|
||||
readonly resultId?: string;
|
||||
readonly edits: SemanticTokensEdit[];
|
||||
|
||||
@@ -115,6 +119,11 @@ declare module 'vscode' {
|
||||
|
||||
export interface SemanticTokensRequestOptions {
|
||||
readonly ranges?: readonly Range[];
|
||||
/**
|
||||
* The previous result id that the editor still holds in memory.
|
||||
*
|
||||
* Only when this is set it is safe for a `SemanticTokensProvider` to return `SemanticTokensEdits`.
|
||||
*/
|
||||
readonly previousResultId?: string;
|
||||
}
|
||||
|
||||
@@ -123,6 +132,102 @@ declare module 'vscode' {
|
||||
* semantic tokens.
|
||||
*/
|
||||
export interface SemanticTokensProvider {
|
||||
/**
|
||||
* A file can contain many tokens, perhaps even hundreds of thousands tokens. Therefore, to improve
|
||||
* the memory consumption around describing semantic tokens, we have decided to avoid allocating objects
|
||||
* and we have decided to represent tokens from a file as an array of integers.
|
||||
*
|
||||
*
|
||||
* In short, each token takes 5 integers to represent, so a specific token i in the file consists of the following fields:
|
||||
* - at index `5*i` - `deltaLine`: token line number, relative to the previous token
|
||||
* - at index `5*i+1` - `deltaStart`: token start character, relative to the previous token (relative to 0 or the previous token's start if they are on the same line)
|
||||
* - at index `5*i+2` - `length`: the length of the token. A token cannot be multiline.
|
||||
* - at index `5*i+3` - `tokenType`: will be looked up in `SemanticTokensLegend.tokenTypes`
|
||||
* - at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticTokensLegend.tokenModifiers`
|
||||
*
|
||||
*
|
||||
* Here is an example for encoding a file with 3 tokens:
|
||||
* ```
|
||||
* [ { line: 2, startChar: 5, length: 3, tokenType: "properties", tokenModifiers: ["private", "static"] },
|
||||
* { line: 2, startChar: 10, length: 4, tokenType: "types", tokenModifiers: [] },
|
||||
* { line: 5, startChar: 2, length: 7, tokenType: "classes", tokenModifiers: [] } ]
|
||||
* ```
|
||||
*
|
||||
* 1. First of all, a legend must be devised. This legend must be provided up-front and capture all possible token types.
|
||||
* For this example, we will choose the following legend which is passed in when registering the provider:
|
||||
* ```
|
||||
* { tokenTypes: ['', 'properties', 'types', 'classes'],
|
||||
* tokenModifiers: ['', 'private', 'static'] }
|
||||
* ```
|
||||
*
|
||||
* 2. The first transformation is to encode `tokenType` and `tokenModifiers` as integers using the legend. Token types are looked
|
||||
* up by index, so a `tokenType` value of `1` means `tokenTypes[1]`. Multiple token modifiers can be set by using bit flags,
|
||||
* so a `tokenModifier` value of `6` is first viewed as binary `0b110`, which means `[tokenModifiers[1], tokenModifiers[2]]` because
|
||||
* bits 1 and 2 are set. Using this legend, the tokens now are:
|
||||
* ```
|
||||
* [ { line: 2, startChar: 5, length: 3, tokenType: 1, tokenModifiers: 6 }, // 6 is 0b110
|
||||
* { line: 2, startChar: 10, length: 4, tokenType: 2, tokenModifiers: 0 },
|
||||
* { line: 5, startChar: 2, length: 7, tokenType: 3, tokenModifiers: 0 } ]
|
||||
* ```
|
||||
*
|
||||
* 3. Then, we will encode each token relative to the previous token in the file:
|
||||
* ```
|
||||
* [ { deltaLine: 2, deltaStartChar: 5, length: 3, tokenType: 1, tokenModifiers: 6 },
|
||||
* // this token is on the same line as the first one, so the startChar is made relative
|
||||
* { deltaLine: 0, deltaStartChar: 5, length: 4, tokenType: 2, tokenModifiers: 0 },
|
||||
* // this token is on a different line than the second one, so the startChar remains unchanged
|
||||
* { deltaLine: 3, deltaStartChar: 2, length: 7, tokenType: 3, tokenModifiers: 0 } ]
|
||||
* ```
|
||||
*
|
||||
* 4. Finally, the integers are organized in a single array, which is a memory friendly representation:
|
||||
* ```
|
||||
* // 1st token, 2nd token, 3rd token
|
||||
* [ 2,5,3,1,6, 0,5,4,2,0, 3,2,7,3,0 ]
|
||||
* ```
|
||||
*
|
||||
* In principle, each call to `provideSemanticTokens` expects a complete representations of the semantic tokens.
|
||||
* It is possible to simply return all the tokens at each call.
|
||||
*
|
||||
* But oftentimes, a small edit in the file will result in a small change to the above delta-based represented tokens.
|
||||
* (In fact, that is why the above tokens are delta-encoded relative to their corresponding previous tokens).
|
||||
* In such a case, if VS Code passes in the previous result id, it is possible for an advanced tokenization provider
|
||||
* to return a delta to the integers array.
|
||||
*
|
||||
* To continue with the previous example, suppose a new line has been pressed at the beginning of the file, such that
|
||||
* all the tokens are now one line lower, and that a new token has appeared since the last result on line 4.
|
||||
* For example, the tokens might look like:
|
||||
* ```
|
||||
* [ { line: 3, startChar: 5, length: 3, tokenType: "properties", tokenModifiers: ["private", "static"] },
|
||||
* { line: 3, startChar: 10, length: 4, tokenType: "types", tokenModifiers: [] },
|
||||
* { line: 4, startChar: 3, length: 5, tokenType: "properties", tokenModifiers: ["static"] },
|
||||
* { line: 6, startChar: 2, length: 7, tokenType: "classes", tokenModifiers: [] } ]
|
||||
* ```
|
||||
*
|
||||
* The integer encoding of all new tokens would be:
|
||||
* ```
|
||||
* [ 3,5,3,1,6, 0,5,4,2,0, 1,3,5,1,2, 2,2,7,3,0 ]
|
||||
* ```
|
||||
*
|
||||
* A smart tokens provider can return a `resultId` to `SemanticTokens`. Then, if the editor still has in memory the previous
|
||||
* result, the editor will pass in options the previous result id at `SemanticTokensRequestOptions.previousResultId`. Only when
|
||||
* the editor passes in the previous result id, it is safe and smart for a smart tokens provider can compute a diff from the
|
||||
* previous result to the new result.
|
||||
*
|
||||
* *NOTE*: It is illegal to return `SemanticTokensEdits` if `options.previousResultId` is not set!
|
||||
*
|
||||
* ```
|
||||
* [ 2,5,3,1,6, 0,5,4,2,0, 3,2,7,3,0 ]
|
||||
* [ 3,5,3,1,6, 0,5,4,2,0, 1,3,5,1,2, 2,2,7,3,0 ]
|
||||
* ```
|
||||
* and return as simple integer edits the diff:
|
||||
* ```
|
||||
* { edits: [
|
||||
* { start: 0, deleteCount: 1, data: [3] } // replace integer at offset 0 with 3
|
||||
* { start: 10, deleteCount: 1, data: [1,3,5,1,2,2] } // replace integer at offset 10 with [1,3,5,1,2,2]
|
||||
* ]}
|
||||
* ```
|
||||
* All indices expressed in the returned diff represent indices in the old result array, so they all refer to the previous result state.
|
||||
*/
|
||||
provideSemanticTokens(document: TextDocument, options: SemanticTokensRequestOptions, token: CancellationToken): ProviderResult<SemanticTokens | SemanticTokensEdits>;
|
||||
}
|
||||
|
||||
@@ -171,7 +276,7 @@ declare module 'vscode' {
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Rob: search provider
|
||||
//#region TextSearchProvider: https://github.com/microsoft/vscode/issues/59921
|
||||
|
||||
/**
|
||||
* The parameters of a query for text search.
|
||||
@@ -315,32 +420,6 @@ declare module 'vscode' {
|
||||
limitHit?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters of a query for file search.
|
||||
*/
|
||||
export interface FileSearchQuery {
|
||||
/**
|
||||
* The search pattern to match against file paths.
|
||||
*/
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options that apply to file search.
|
||||
*/
|
||||
export interface FileSearchOptions extends SearchOptions {
|
||||
/**
|
||||
* The maximum number of results to be returned.
|
||||
*/
|
||||
maxResults?: number;
|
||||
|
||||
/**
|
||||
* A CancellationToken that represents the session for this search query. If the provider chooses to, this object can be used as the key for a cache,
|
||||
* and searches with the same session object can search the same cache. When the token is cancelled, the session is complete and the cache can be cleared.
|
||||
*/
|
||||
session?: CancellationToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* A preview of the text result.
|
||||
*/
|
||||
@@ -400,6 +479,50 @@ declare module 'vscode' {
|
||||
|
||||
export type TextSearchResult = TextSearchMatch | TextSearchContext;
|
||||
|
||||
/**
|
||||
* A TextSearchProvider provides search results for text results inside files in the workspace.
|
||||
*/
|
||||
export interface TextSearchProvider {
|
||||
/**
|
||||
* Provide results that match the given text pattern.
|
||||
* @param query The parameters for this query.
|
||||
* @param options A set of options to consider while searching.
|
||||
* @param progress A progress callback that must be invoked for all results.
|
||||
* @param token A cancellation token.
|
||||
*/
|
||||
provideTextSearchResults(query: TextSearchQuery, options: TextSearchOptions, progress: Progress<TextSearchResult>, token: CancellationToken): ProviderResult<TextSearchComplete>;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region FileSearchProvider: https://github.com/microsoft/vscode/issues/73524
|
||||
|
||||
/**
|
||||
* The parameters of a query for file search.
|
||||
*/
|
||||
export interface FileSearchQuery {
|
||||
/**
|
||||
* The search pattern to match against file paths.
|
||||
*/
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options that apply to file search.
|
||||
*/
|
||||
export interface FileSearchOptions extends SearchOptions {
|
||||
/**
|
||||
* The maximum number of results to be returned.
|
||||
*/
|
||||
maxResults?: number;
|
||||
|
||||
/**
|
||||
* A CancellationToken that represents the session for this search query. If the provider chooses to, this object can be used as the key for a cache,
|
||||
* and searches with the same session object can search the same cache. When the token is cancelled, the session is complete and the cache can be cleared.
|
||||
*/
|
||||
session?: CancellationToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* A FileSearchProvider provides search results for files in the given folder that match a query string. It can be invoked by quickopen or other extensions.
|
||||
*
|
||||
@@ -419,20 +542,34 @@ declare module 'vscode' {
|
||||
provideFileSearchResults(query: FileSearchQuery, options: FileSearchOptions, token: CancellationToken): ProviderResult<Uri[]>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A TextSearchProvider provides search results for text results inside files in the workspace.
|
||||
*/
|
||||
export interface TextSearchProvider {
|
||||
export namespace workspace {
|
||||
/**
|
||||
* Provide results that match the given text pattern.
|
||||
* @param query The parameters for this query.
|
||||
* @param options A set of options to consider while searching.
|
||||
* @param progress A progress callback that must be invoked for all results.
|
||||
* @param token A cancellation token.
|
||||
* Register a search provider.
|
||||
*
|
||||
* Only one provider can be registered per scheme.
|
||||
*
|
||||
* @param scheme The provider will be invoked for workspace folders that have this file scheme.
|
||||
* @param provider The provider.
|
||||
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
|
||||
*/
|
||||
provideTextSearchResults(query: TextSearchQuery, options: TextSearchOptions, progress: Progress<TextSearchResult>, token: CancellationToken): ProviderResult<TextSearchComplete>;
|
||||
export function registerFileSearchProvider(scheme: string, provider: FileSearchProvider): Disposable;
|
||||
|
||||
/**
|
||||
* Register a text search provider.
|
||||
*
|
||||
* Only one provider can be registered per scheme.
|
||||
*
|
||||
* @param scheme The provider will be invoked for workspace folders that have this file scheme.
|
||||
* @param provider The provider.
|
||||
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
|
||||
*/
|
||||
export function registerTextSearchProvider(scheme: string, provider: TextSearchProvider): Disposable;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region findTextInFiles: https://github.com/microsoft/vscode/issues/59924
|
||||
|
||||
/**
|
||||
* Options that can be set on a findTextInFiles search.
|
||||
*/
|
||||
@@ -497,28 +634,6 @@ declare module 'vscode' {
|
||||
}
|
||||
|
||||
export namespace workspace {
|
||||
/**
|
||||
* Register a search provider.
|
||||
*
|
||||
* Only one provider can be registered per scheme.
|
||||
*
|
||||
* @param scheme The provider will be invoked for workspace folders that have this file scheme.
|
||||
* @param provider The provider.
|
||||
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
|
||||
*/
|
||||
export function registerFileSearchProvider(scheme: string, provider: FileSearchProvider): Disposable;
|
||||
|
||||
/**
|
||||
* Register a text search provider.
|
||||
*
|
||||
* Only one provider can be registered per scheme.
|
||||
*
|
||||
* @param scheme The provider will be invoked for workspace folders that have this file scheme.
|
||||
* @param provider The provider.
|
||||
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
|
||||
*/
|
||||
export function registerTextSearchProvider(scheme: string, provider: TextSearchProvider): Disposable;
|
||||
|
||||
/**
|
||||
* Search text in files across all [workspace folders](#workspace.workspaceFolders) in the workspace.
|
||||
* @param query The query parameters for the search - the search string, whether it's case-sensitive, or a regex, or matches whole words.
|
||||
@@ -647,7 +762,7 @@ declare module 'vscode' {
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Rob, Matt: logging
|
||||
//#region LogLevel: https://github.com/microsoft/vscode/issues/85992
|
||||
|
||||
/**
|
||||
* The severity level of a log message
|
||||
@@ -869,247 +984,6 @@ declare module 'vscode' {
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region mjbvz,joh: https://github.com/Microsoft/vscode/issues/43768
|
||||
|
||||
/**
|
||||
* An event that is fired when files are going to be created.
|
||||
*
|
||||
* To make modifications to the workspace before the files are created,
|
||||
* call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a
|
||||
* thenable that resolves to a [workspace edit](#WorkspaceEdit).
|
||||
*/
|
||||
export interface FileWillCreateEvent {
|
||||
|
||||
/**
|
||||
* The files that are going to be created.
|
||||
*/
|
||||
readonly files: ReadonlyArray<Uri>;
|
||||
|
||||
/**
|
||||
* Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit).
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch and not
|
||||
* in an asynchronous manner:
|
||||
*
|
||||
* ```ts
|
||||
* workspace.onWillCreateFiles(event => {
|
||||
* // async, will *throw* an error
|
||||
* setTimeout(() => event.waitUntil(promise));
|
||||
*
|
||||
* // sync, OK
|
||||
* event.waitUntil(promise);
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<WorkspaceEdit>): void;
|
||||
|
||||
/**
|
||||
* Allows to pause the event until the provided thenable resolves.
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch.
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<any>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired after files are created.
|
||||
*/
|
||||
export interface FileCreateEvent {
|
||||
|
||||
/**
|
||||
* The files that got created.
|
||||
*/
|
||||
readonly files: ReadonlyArray<Uri>;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired when files are going to be deleted.
|
||||
*
|
||||
* To make modifications to the workspace before the files are deleted,
|
||||
* call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a
|
||||
* thenable that resolves to a [workspace edit](#WorkspaceEdit).
|
||||
*/
|
||||
export interface FileWillDeleteEvent {
|
||||
|
||||
/**
|
||||
* The files that are going to be deleted.
|
||||
*/
|
||||
readonly files: ReadonlyArray<Uri>;
|
||||
|
||||
/**
|
||||
* Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit).
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch and not
|
||||
* in an asynchronous manner:
|
||||
*
|
||||
* ```ts
|
||||
* workspace.onWillCreateFiles(event => {
|
||||
* // async, will *throw* an error
|
||||
* setTimeout(() => event.waitUntil(promise));
|
||||
*
|
||||
* // sync, OK
|
||||
* event.waitUntil(promise);
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<WorkspaceEdit>): void;
|
||||
|
||||
/**
|
||||
* Allows to pause the event until the provided thenable resolves.
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch.
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<any>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired after files are deleted.
|
||||
*/
|
||||
export interface FileDeleteEvent {
|
||||
|
||||
/**
|
||||
* The files that got deleted.
|
||||
*/
|
||||
readonly files: ReadonlyArray<Uri>;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired when files are going to be renamed.
|
||||
*
|
||||
* To make modifications to the workspace before the files are renamed,
|
||||
* call the [`waitUntil](#FileWillCreateEvent.waitUntil)-function with a
|
||||
* thenable that resolves to a [workspace edit](#WorkspaceEdit).
|
||||
*/
|
||||
export interface FileWillRenameEvent {
|
||||
|
||||
/**
|
||||
* The files that are going to be renamed.
|
||||
*/
|
||||
readonly files: ReadonlyArray<{ oldUri: Uri, newUri: Uri }>;
|
||||
|
||||
/**
|
||||
* Allows to pause the event and to apply a [workspace edit](#WorkspaceEdit).
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch and not
|
||||
* in an asynchronous manner:
|
||||
*
|
||||
* ```ts
|
||||
* workspace.onWillCreateFiles(event => {
|
||||
* // async, will *throw* an error
|
||||
* setTimeout(() => event.waitUntil(promise));
|
||||
*
|
||||
* // sync, OK
|
||||
* event.waitUntil(promise);
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<WorkspaceEdit>): void;
|
||||
|
||||
/**
|
||||
* Allows to pause the event until the provided thenable resolves.
|
||||
*
|
||||
* *Note:* This function can only be called during event dispatch.
|
||||
*
|
||||
* @param thenable A thenable that delays saving.
|
||||
*/
|
||||
waitUntil(thenable: Thenable<any>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* An event that is fired after files are renamed.
|
||||
*/
|
||||
export interface FileRenameEvent {
|
||||
|
||||
/**
|
||||
* The files that got renamed.
|
||||
*/
|
||||
readonly files: ReadonlyArray<{ oldUri: Uri, newUri: Uri }>;
|
||||
}
|
||||
|
||||
export namespace workspace {
|
||||
|
||||
/**
|
||||
* An event that is emitted when files are being created.
|
||||
*
|
||||
* *Note 1:* This event is triggered by user gestures, like creating a file from the
|
||||
* explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api. This event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*
|
||||
* *Note 2:* When this event is fired, edits to files thare are being created cannot be applied.
|
||||
*/
|
||||
export const onWillCreateFiles: Event<FileWillCreateEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files have been created.
|
||||
*
|
||||
* *Note:* This event is triggered by user gestures, like creating a file from the
|
||||
* explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*/
|
||||
export const onDidCreateFiles: Event<FileCreateEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files are being deleted.
|
||||
*
|
||||
* *Note 1:* This event is triggered by user gestures, like deleting a file from the
|
||||
* explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*
|
||||
* *Note 2:* When deleting a folder with children only one event is fired.
|
||||
*/
|
||||
export const onWillDeleteFiles: Event<FileWillDeleteEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files have been deleted.
|
||||
*
|
||||
* *Note 1:* This event is triggered by user gestures, like deleting a file from the
|
||||
* explorer, or from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*
|
||||
* *Note 2:* When deleting a folder with children only one event is fired.
|
||||
*/
|
||||
export const onDidDeleteFiles: Event<FileDeleteEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files are being renamed.
|
||||
*
|
||||
* *Note 1:* This event is triggered by user gestures, like renaming a file from the
|
||||
* explorer, and from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*
|
||||
* *Note 2:* When renaming a folder with children only one event is fired.
|
||||
*/
|
||||
export const onWillRenameFiles: Event<FileWillRenameEvent>;
|
||||
|
||||
/**
|
||||
* An event that is emitted when files have been renamed.
|
||||
*
|
||||
* *Note 1:* This event is triggered by user gestures, like renaming a file from the
|
||||
* explorer, and from the [`workspace.applyEdit`](#workspace.applyEdit)-api, but this event is *not* fired when
|
||||
* files change on disk, e.g triggered by another application, or when using the
|
||||
* [`workspace.fs`](#FileSystem)-api.
|
||||
*
|
||||
* *Note 2:* When renaming a folder with children only one event is fired.
|
||||
*/
|
||||
export const onDidRenameFiles: Event<FileRenameEvent>;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Alex - OnEnter enhancement
|
||||
export interface OnEnterRule {
|
||||
/**
|
||||
|
||||
@@ -141,7 +141,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
} else if (dto.type === 'function') {
|
||||
this.debugService.addFunctionBreakpoint(dto.functionName, dto.id);
|
||||
} else if (dto.type === 'data') {
|
||||
this.debugService.addDataBreakpoint(dto.label, dto.dataId, dto.canPersist);
|
||||
this.debugService.addDataBreakpoint(dto.label, dto.dataId, dto.canPersist, dto.accessTypes);
|
||||
}
|
||||
}
|
||||
return Promise.resolve();
|
||||
@@ -336,7 +336,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
condition: dbp.condition,
|
||||
hitCondition: dbp.hitCondition,
|
||||
logMessage: dbp.logMessage,
|
||||
label: dbp.label,
|
||||
label: dbp.description,
|
||||
canPersist: dbp.canPersist
|
||||
};
|
||||
} else {
|
||||
|
||||
@@ -271,18 +271,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
webviewInput.webview.options = options;
|
||||
webviewInput.webview.extension = extension;
|
||||
|
||||
const model = await this._customEditorService.models.loadOrCreate(webviewInput.getResource(), webviewInput.viewType);
|
||||
|
||||
model.onUndo(edits => { this._proxy.$undoEdits(handle, edits.map(x => x.data)); });
|
||||
model.onApplyEdit(edits => {
|
||||
const editsToApply = edits.filter(x => x.source !== webviewInput).map(x => x.data);
|
||||
if (editsToApply.length) {
|
||||
this._proxy.$applyEdits(handle, editsToApply);
|
||||
}
|
||||
});
|
||||
model.onWillSave(e => { e.waitUntil(this._proxy.$onSave(handle)); });
|
||||
model.onWillSaveAs(e => { e.waitUntil(this._proxy.$onSaveAs(handle, e.resource.toJSON(), e.targetResource.toJSON())); });
|
||||
|
||||
const model = await this.getModel(webviewInput);
|
||||
webviewInput.onDisposeWebview(() => {
|
||||
this._customEditorService.models.disposeModel(model);
|
||||
});
|
||||
@@ -315,6 +304,31 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
this._editorProviders.delete(viewType);
|
||||
}
|
||||
|
||||
public async $registerCapabilities(handle: extHostProtocol.WebviewPanelHandle, capabilities: readonly extHostProtocol.WebviewEditorCapabilities[]): Promise<void> {
|
||||
const webviewInput = this.getWebviewInput(handle);
|
||||
const model = await this.getModel(webviewInput);
|
||||
|
||||
const capabilitiesSet = new Set(capabilities);
|
||||
if (capabilitiesSet.has(extHostProtocol.WebviewEditorCapabilities.Editable)) {
|
||||
model.onUndo(edits => { this._proxy.$undoEdits(handle, edits.map(x => x.data)); });
|
||||
|
||||
model.onApplyEdit(edits => {
|
||||
const editsToApply = edits.filter(x => x.source !== webviewInput).map(x => x.data);
|
||||
if (editsToApply.length) {
|
||||
this._proxy.$applyEdits(handle, editsToApply);
|
||||
}
|
||||
});
|
||||
|
||||
model.onWillSave(e => { e.waitUntil(this._proxy.$onSave(handle)); });
|
||||
|
||||
model.onWillSaveAs(e => { e.waitUntil(this._proxy.$onSaveAs(handle, e.resource.toJSON(), e.targetResource.toJSON())); });
|
||||
}
|
||||
}
|
||||
|
||||
private getModel(webviewInput: WebviewInput) {
|
||||
return this._customEditorService.models.loadOrCreate(webviewInput.getResource(), webviewInput.viewType);
|
||||
}
|
||||
|
||||
public $onEdit(handle: extHostProtocol.WebviewPanelHandle, editData: any): void {
|
||||
const webview = this.getWebviewInput(handle);
|
||||
if (!(webview instanceof CustomFileEditorInput)) {
|
||||
|
||||
@@ -705,27 +705,21 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostLabelService.$registerResourceLabelFormatter(formatter);
|
||||
},
|
||||
onDidCreateFiles: (listener, thisArg, disposables) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.onDidCreateFile(listener, thisArg, disposables);
|
||||
},
|
||||
onDidDeleteFiles: (listener, thisArg, disposables) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.onDidDeleteFile(listener, thisArg, disposables);
|
||||
},
|
||||
onDidRenameFiles: (listener, thisArg, disposables) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.onDidRenameFile(listener, thisArg, disposables);
|
||||
},
|
||||
onWillCreateFiles: (listener: (e: vscode.FileWillCreateEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.getOnWillCreateFileEvent(extension)(listener, thisArg, disposables);
|
||||
},
|
||||
onWillDeleteFiles: (listener: (e: vscode.FileWillDeleteEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.getOnWillDeleteFileEvent(extension)(listener, thisArg, disposables);
|
||||
},
|
||||
onWillRenameFiles: (listener: (e: vscode.FileWillRenameEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.getOnWillRenameFileEvent(extension)(listener, thisArg, disposables);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -560,6 +560,10 @@ export interface WebviewExtensionDescription {
|
||||
readonly location: UriComponents;
|
||||
}
|
||||
|
||||
export enum WebviewEditorCapabilities {
|
||||
Editable,
|
||||
}
|
||||
|
||||
export interface MainThreadWebviewsShape extends IDisposable {
|
||||
$createWebviewPanel(extension: WebviewExtensionDescription, handle: WebviewPanelHandle, viewType: string, title: string, showOptions: WebviewPanelShowOptions, options: modes.IWebviewPanelOptions & modes.IWebviewOptions): void;
|
||||
$disposeWebview(handle: WebviewPanelHandle): void;
|
||||
@@ -577,6 +581,7 @@ export interface MainThreadWebviewsShape extends IDisposable {
|
||||
|
||||
$registerEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions): void;
|
||||
$unregisterEditorProvider(viewType: string): void;
|
||||
$registerCapabilities(handle: WebviewPanelHandle, capabilities: readonly WebviewEditorCapabilities[]): void;
|
||||
|
||||
$onEdit(handle: WebviewPanelHandle, editJson: any): void;
|
||||
}
|
||||
@@ -1287,6 +1292,7 @@ export interface IDataBreakpointDto extends IBreakpointDto {
|
||||
dataId: string;
|
||||
canPersist: boolean;
|
||||
label: string;
|
||||
accessTypes?: DebugProtocol.DataBreakpointAccessType[];
|
||||
}
|
||||
|
||||
export interface ISourceBreakpointDto extends IBreakpointDto {
|
||||
|
||||
@@ -1209,11 +1209,10 @@ class CallHierarchyAdapter {
|
||||
}
|
||||
|
||||
releaseSession(sessionId: string): void {
|
||||
this._cache.delete(sessionId.charAt(0));
|
||||
this._cache.delete(sessionId);
|
||||
}
|
||||
|
||||
private _cacheAndConvertItem(itemOrSessionId: string, item: vscode.CallHierarchyItem): extHostProtocol.ICallHierarchyItemDto {
|
||||
const sessionId = itemOrSessionId.charAt(0);
|
||||
private _cacheAndConvertItem(sessionId: string, item: vscode.CallHierarchyItem): extHostProtocol.ICallHierarchyItemDto {
|
||||
const map = this._cache.get(sessionId)!;
|
||||
const dto: extHostProtocol.ICallHierarchyItemDto = {
|
||||
_sessionId: sessionId,
|
||||
@@ -1231,7 +1230,7 @@ class CallHierarchyAdapter {
|
||||
|
||||
private _itemFromCache(sessionId: string, itemId: string): vscode.CallHierarchyItem | undefined {
|
||||
const map = this._cache.get(sessionId);
|
||||
return map && map.get(itemId);
|
||||
return map?.get(itemId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
|
||||
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelViewStateData } from './extHost.protocol';
|
||||
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelViewStateData, WebviewEditorCapabilities } from './extHost.protocol';
|
||||
import { Disposable as VSCodeDisposable } from './extHostTypes';
|
||||
|
||||
type IconPath = URI | { light: URI, dark: URI };
|
||||
@@ -257,12 +257,11 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa
|
||||
}
|
||||
|
||||
async _onSave(): Promise<void> {
|
||||
await assertIsDefined(this._capabilities).editingCapability?.save();
|
||||
await assertIsDefined(this._capabilities?.editingCapability)?.save();
|
||||
}
|
||||
|
||||
|
||||
async _onSaveAs(resource: vscode.Uri, targetResource: vscode.Uri): Promise<void> {
|
||||
await assertIsDefined(this._capabilities).editingCapability?.saveAs(resource, targetResource);
|
||||
await assertIsDefined(this._capabilities?.editingCapability)?.saveAs(resource, targetResource);
|
||||
}
|
||||
|
||||
private assertNotDisposed() {
|
||||
@@ -450,6 +449,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
this._webviewPanels.set(handle, revivedPanel);
|
||||
const capabilities = await provider.resolveWebviewEditor({ resource: URI.revive(input.resource) }, revivedPanel);
|
||||
revivedPanel._setCapabilities(capabilities);
|
||||
this.registerCapabilites(handle, capabilities);
|
||||
|
||||
// TODO: the first set of edits should likely be passed when resolving
|
||||
if (input.edits.length) {
|
||||
@@ -480,6 +480,14 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewEditor | undefined {
|
||||
return this._webviewPanels.get(handle);
|
||||
}
|
||||
|
||||
private registerCapabilites(handle: WebviewPanelHandle, capabilities: vscode.WebviewEditorCapabilities) {
|
||||
const declaredCapabilites: WebviewEditorCapabilities[] = [];
|
||||
if (capabilities.editingCapability) {
|
||||
declaredCapabilites.push(WebviewEditorCapabilities.Editable);
|
||||
}
|
||||
this._proxy.$registerCapabilities(handle, declaredCapabilites);
|
||||
}
|
||||
}
|
||||
|
||||
function convertWebviewOptions(
|
||||
|
||||
@@ -339,6 +339,11 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape, IExtHostWorkspac
|
||||
if (folders.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (folders.length > 1) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// #54483 @Joh Why are we still using fsPath?
|
||||
return folders[0].uri.fsPath;
|
||||
}
|
||||
|
||||
@@ -180,6 +180,8 @@ body.web {
|
||||
.monaco-workbench select {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
/* Hides inner border from FF */
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
.monaco-workbench .select-container {
|
||||
|
||||
@@ -7,21 +7,6 @@
|
||||
width: 48px;
|
||||
}
|
||||
|
||||
.monaco-workbench.windows.chromium .part.activitybar,
|
||||
.monaco-workbench.linux.chromium .part.activitybar {
|
||||
/*
|
||||
* Explicitly put the part onto its own layer to help Chrome to
|
||||
* render the content with LCD-anti-aliasing. By partioning the
|
||||
* workbench into multiple layers, we can ensure that a bad
|
||||
* behaving part is not making another part fallback to greyscale
|
||||
* rendering.
|
||||
*
|
||||
* macOS: does not render LCD-anti-aliased.
|
||||
*/
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
overflow: visible; /* when a new layer is created, we need to set overflow visible to avoid clipping the menubar */
|
||||
}
|
||||
|
||||
.monaco-workbench .activitybar > .content {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
||||
@@ -854,6 +854,7 @@ class ShowCurrentMarkerInStatusbarContribution extends Disposable {
|
||||
|
||||
update(editor: ICodeEditor | undefined): void {
|
||||
this.editor = editor;
|
||||
this.updateMarkers();
|
||||
this.updateStatus();
|
||||
}
|
||||
|
||||
|
||||
@@ -48,20 +48,6 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.monaco-workbench.windows.chromium .part.editor > .content .editor-group-container > .title,
|
||||
.monaco-workbench.linux.chromium .part.editor > .content .editor-group-container > .title {
|
||||
/*
|
||||
* Explicitly put the part onto its own layer to help Chrome to
|
||||
* render the content with LCD-anti-aliasing. By partioning the
|
||||
* workbench into multiple layers, we can ensure that a bad
|
||||
* behaving part is not making another part fallback to greyscale
|
||||
* rendering.
|
||||
*
|
||||
* macOS: does not render LCD-anti-aliased.
|
||||
*/
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title:not(.tabs) {
|
||||
display: flex; /* when tabs are not shown, use flex layout */
|
||||
flex-wrap: nowrap;
|
||||
|
||||
@@ -12,20 +12,6 @@
|
||||
z-index: initial;
|
||||
}
|
||||
|
||||
.monaco-workbench.windows.chromium .part.panel,
|
||||
.monaco-workbench.linux.chromium .part.panel {
|
||||
/*
|
||||
* Explicitly put the part onto its own layer to help Chrome to
|
||||
* render the content with LCD-anti-aliasing. By partioning the
|
||||
* workbench into multiple layers, we can ensure that a bad
|
||||
* behaving part is not making another part fallback to greyscale
|
||||
* rendering.
|
||||
*
|
||||
* macOS: does not render LCD-anti-aliased.
|
||||
*/
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.panel .title {
|
||||
height: 35px;
|
||||
display: flex;
|
||||
@@ -114,7 +100,7 @@
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
/** Actions */
|
||||
|
||||
|
||||
@@ -3,21 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench.windows.chromium .part.sidebar,
|
||||
.monaco-workbench.linux.chromium .part.sidebar {
|
||||
/*
|
||||
* Explicitly put the part onto its own layer to help Chrome to
|
||||
* render the content with LCD-anti-aliasing. By partioning the
|
||||
* workbench into multiple layers, we can ensure that a bad
|
||||
* behaving part is not making another part fallback to greyscale
|
||||
* rendering.
|
||||
*
|
||||
* macOS: does not render LCD-anti-aliased.
|
||||
*/
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.sidebar > .content {
|
||||
.monaco-workbench .sidebar > .content {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,20 +13,6 @@
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.monaco-workbench.windows.chromium .part.statusbar,
|
||||
.monaco-workbench.linux.chromium .part.statusbar {
|
||||
/*
|
||||
* Explicitly put the part onto its own layer to help Chrome to
|
||||
* render the content with LCD-anti-aliasing. By partioning the
|
||||
* workbench into multiple layers, we can ensure that a bad
|
||||
* behaving part is not making another part fallback to greyscale
|
||||
* rendering.
|
||||
*
|
||||
* macOS: does not render LCD-anti-aliased.
|
||||
*/
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.statusbar.status-border-top::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@@ -51,7 +37,6 @@
|
||||
|
||||
.monaco-workbench .part.statusbar > .left-items {
|
||||
flex-grow: 1; /* left items push right items to the far right end */
|
||||
overflow: hidden; /* Hide the overflowing entries */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.statusbar > .items-container > .statusbar-item {
|
||||
|
||||
@@ -19,22 +19,6 @@
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.monaco-workbench.windows .part.titlebar,
|
||||
.monaco-workbench.linux .part.titlebar {
|
||||
/*
|
||||
* Explicitly put the part onto its own layer to help Chrome to
|
||||
* render the content with LCD-anti-aliasing. By partioning the
|
||||
* workbench into multiple layers, we can ensure that a bad
|
||||
* behaving part is not making another part fallback to greyscale
|
||||
* rendering.
|
||||
*
|
||||
* macOS: does not render LCD-anti-aliased.
|
||||
*/
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
position: relative;
|
||||
z-index: 1000; /* move the entire titlebar above the workbench, except modals/dialogs */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.titlebar > .titlebar-drag-region {
|
||||
top: 0;
|
||||
left: 0;
|
||||
@@ -45,11 +29,6 @@
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.titlebar > .menubar {
|
||||
/* Move above drag region since negative z-index on that element causes AA issues */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.titlebar > .window-title {
|
||||
flex: 0 1 auto;
|
||||
font-size: 12px;
|
||||
@@ -78,6 +57,11 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.titlebar > .menubar {
|
||||
/* move menubar above drag region as negative z-index on drag region cause greyscale AA */
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.monaco-workbench.linux .part.titlebar > .window-title {
|
||||
font-size: inherit;
|
||||
}
|
||||
@@ -100,7 +84,7 @@
|
||||
width: 35px;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
z-index: 2; /* highest level of titlebar */
|
||||
z-index: 3000;
|
||||
background-image: url('code-icon.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
@@ -118,12 +102,11 @@
|
||||
flex-shrink: 0;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 2; /* highest level of titlebar */
|
||||
z-index: 3000;
|
||||
-webkit-app-region: no-drag;
|
||||
height: 100%;
|
||||
width: 138px;
|
||||
margin-left: auto;
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
|
||||
.monaco-workbench.fullscreen .part.titlebar > .window-controls-container {
|
||||
|
||||
@@ -101,8 +101,16 @@ export abstract class ViewContainerViewlet extends PaneViewlet implements IViews
|
||||
this.focus();
|
||||
}
|
||||
|
||||
getContextMenuActions(): IAction[] {
|
||||
getContextMenuActions(viewDescriptor?: IViewDescriptor): IAction[] {
|
||||
const result: IAction[] = [];
|
||||
if (viewDescriptor) {
|
||||
result.push(<IAction>{
|
||||
id: `${viewDescriptor.id}.removeView`,
|
||||
label: localize('hideView', "Hide"),
|
||||
enabled: viewDescriptor.canToggleVisibility,
|
||||
run: () => this.toggleViewVisibility(viewDescriptor.id)
|
||||
});
|
||||
}
|
||||
const viewToggleActions = this.viewsModel.viewDescriptors.map(viewDescriptor => (<IAction>{
|
||||
id: `${viewDescriptor.id}.toggleVisibility`,
|
||||
label: viewDescriptor.name,
|
||||
@@ -111,13 +119,17 @@ export abstract class ViewContainerViewlet extends PaneViewlet implements IViews
|
||||
run: () => this.toggleViewVisibility(viewDescriptor.id)
|
||||
}));
|
||||
|
||||
result.push(...viewToggleActions);
|
||||
const parentActions = this.getViewletContextMenuActions();
|
||||
if (viewToggleActions.length && parentActions.length) {
|
||||
if (result.length && viewToggleActions.length) {
|
||||
result.push(new Separator());
|
||||
}
|
||||
result.push(...viewToggleActions);
|
||||
|
||||
const parentActions = this.getViewletContextMenuActions();
|
||||
if (result.length && parentActions.length) {
|
||||
result.push(new Separator());
|
||||
}
|
||||
result.push(...parentActions);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -249,17 +261,7 @@ export abstract class ViewContainerViewlet extends PaneViewlet implements IViews
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
const actions: IAction[] = [];
|
||||
actions.push(<IAction>{
|
||||
id: `${viewDescriptor.id}.removeView`,
|
||||
label: localize('hideView', "Hide"),
|
||||
enabled: viewDescriptor.canToggleVisibility,
|
||||
run: () => this.toggleViewVisibility(viewDescriptor.id)
|
||||
});
|
||||
const otherActions = this.getContextMenuActions();
|
||||
if (otherActions.length) {
|
||||
actions.push(...[new Separator(), ...otherActions]);
|
||||
}
|
||||
const actions: IAction[] = this.getContextMenuActions(viewDescriptor);
|
||||
|
||||
let anchor: { x: number, y: number } = { x: event.posx, y: event.posy };
|
||||
this.contextMenuService.showContextMenu({
|
||||
@@ -377,6 +379,9 @@ export abstract class FilterViewContainerViewlet extends ViewContainerViewlet {
|
||||
protected abstract getFilterOn(viewDescriptor: IViewDescriptor): string | undefined;
|
||||
|
||||
private onFilterChanged(newFilterValue: string) {
|
||||
if (this.allViews.size === 0) {
|
||||
this.updateAllViews(this.viewsModel.viewDescriptors);
|
||||
}
|
||||
this.getViewsNotForTarget(newFilterValue).forEach(item => this.viewsModel.setVisible(item.id, false));
|
||||
this.getViewsForTarget(newFilterValue).forEach(item => this.viewsModel.setVisible(item.id, true));
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import { Range } from 'vs/editor/common/core/range';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { MenuId } from 'vs/platform/actions/common/actions';
|
||||
|
||||
const _ctxHasCompletionItemProvider = new RawContextKey<boolean>('editorHasCallHierarchyProvider', false);
|
||||
const _ctxHasCallHierarchyProvider = new RawContextKey<boolean>('editorHasCallHierarchyProvider', false);
|
||||
const _ctxCallHierarchyVisible = new RawContextKey<boolean>('callHierarchyVisible', false);
|
||||
|
||||
class CallHierarchyController implements IEditorContribution {
|
||||
@@ -52,7 +52,7 @@ class CallHierarchyController implements IEditorContribution {
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
) {
|
||||
this._ctxIsVisible = _ctxCallHierarchyVisible.bindTo(this._contextKeyService);
|
||||
this._ctxHasProvider = _ctxHasCompletionItemProvider.bindTo(this._contextKeyService);
|
||||
this._ctxHasProvider = _ctxHasCallHierarchyProvider.bindTo(this._contextKeyService);
|
||||
this._dispoables.add(Event.any<any>(_editor.onDidChangeModel, _editor.onDidChangeModelLanguage, CallHierarchyProviderRegistry.onDidChange)(() => {
|
||||
this._ctxHasProvider.set(_editor.hasModel() && CallHierarchyProviderRegistry.has(_editor.getModel()));
|
||||
}));
|
||||
@@ -172,8 +172,7 @@ registerEditorAction(class extends EditorAction {
|
||||
primary: KeyMod.Shift + KeyMod.Alt + KeyCode.KEY_H
|
||||
},
|
||||
precondition: ContextKeyExpr.and(
|
||||
_ctxCallHierarchyVisible.negate(),
|
||||
_ctxHasCompletionItemProvider,
|
||||
_ctxHasCallHierarchyProvider,
|
||||
PeekContext.notInPeekEditor
|
||||
)
|
||||
});
|
||||
|
||||
@@ -49,10 +49,10 @@ class ChangeHierarchyDirectionAction extends Action {
|
||||
});
|
||||
const update = () => {
|
||||
if (getDirection() === CallHierarchyDirection.CallsFrom) {
|
||||
this.label = localize('toggle.from', "Showing Calls");
|
||||
this.label = localize('toggle.from', "Show Incoming Calls");
|
||||
this.class = 'calls-from';
|
||||
} else {
|
||||
this.label = localize('toggle.to', "Showing Callers");
|
||||
this.label = localize('toggle.to', "Showing Outgoing Calls");
|
||||
this.class = 'calls-to';
|
||||
}
|
||||
};
|
||||
@@ -325,7 +325,11 @@ export class CallHierarchyTreePeekWidget extends peekView.PeekViewWidget {
|
||||
// set decorations for caller ranges (if in the same file)
|
||||
let decorations: IModelDeltaDecoration[] = [];
|
||||
let fullRange: IRange | undefined;
|
||||
for (const loc of element.locations) {
|
||||
let locations = element.locations;
|
||||
if (!locations) {
|
||||
locations = [{ uri: element.item.uri, range: element.item.selectionRange }];
|
||||
}
|
||||
for (const loc of locations) {
|
||||
if (loc.uri.toString() === previewUri.toString()) {
|
||||
decorations.push({ range: loc.range, options });
|
||||
fullRange = !fullRange ? loc.range : Range.plusRange(loc.range, fullRange);
|
||||
@@ -424,7 +428,7 @@ export class CallHierarchyTreePeekWidget extends peekView.PeekViewWidget {
|
||||
}
|
||||
|
||||
protected _doLayoutBody(height: number, width: number): void {
|
||||
if (this._dim.height !== height || this._dim.width === width) {
|
||||
if (this._dim.height !== height || this._dim.width !== width) {
|
||||
super._doLayoutBody(height, width);
|
||||
this._dim = { height, width };
|
||||
this._layoutInfo.height = this._viewZone ? this._viewZone.heightInLines : this._layoutInfo.height;
|
||||
|
||||
@@ -17,7 +17,7 @@ import { Range } from 'vs/editor/common/core/range';
|
||||
export class Call {
|
||||
constructor(
|
||||
readonly item: CallHierarchyItem,
|
||||
readonly locations: Location[],
|
||||
readonly locations: Location[] | undefined,
|
||||
readonly model: CallHierarchyModel,
|
||||
readonly parent: Call | undefined
|
||||
) { }
|
||||
@@ -43,7 +43,7 @@ export class DataSource implements IAsyncDataSource<CallHierarchyModel, Call> {
|
||||
|
||||
async getChildren(element: CallHierarchyModel | Call): Promise<Call[]> {
|
||||
if (element instanceof CallHierarchyModel) {
|
||||
return [new Call(element.root, [], element, undefined)];
|
||||
return [new Call(element.root, undefined, element, undefined)];
|
||||
}
|
||||
|
||||
const { model, item } = element;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5469 9.32812C12.3542 9.25 12.1562 9.21094 11.9531 9.21094C11.7344 9.20573 11.5495 9.23958 11.3984 9.3125C11.2474 9.38542 11.1042 9.47135 10.9688 9.57031C10.8333 9.66927 10.7135 9.77865 10.6094 9.89844C10.5052 10.0182 10.4036 10.1276 10.3047 10.2266C10.2057 10.3255 10.1094 10.4089 10.0156 10.4766C9.92188 10.5443 9.82031 10.5781 9.71094 10.5781C9.5599 10.5781 9.42969 10.5234 9.32031 10.4141C9.24219 10.3411 9.13281 10.237 8.99219 10.1016C8.85156 9.96615 8.67969 9.80208 8.47656 9.60938C8.27344 9.41667 8.0625 9.21354 7.84375 9C7.625 8.78646 7.39844 8.5651 7.16406 8.33594C6.92969 8.10677 6.71094 7.88542 6.50781 7.67188C6.30469 7.45833 6.11979 7.25781 5.95312 7.07031C5.78646 6.88281 5.65625 6.72135 5.5625 6.58594C5.46875 6.45052 5.42188 6.35156 5.42188 6.28906C5.41667 6.17448 5.45052 6.07031 5.52344 5.97656C5.59635 5.88281 5.68229 5.78646 5.78125 5.6875C5.88021 5.58854 5.98958 5.48438 6.10938 5.375C6.22917 5.26562 6.33854 5.14844 6.4375 5.02344C6.53646 4.89844 6.61979 4.75521 6.6875 4.59375C6.75521 4.43229 6.78906 4.25 6.78906 4.04688C6.78906 3.84375 6.75 3.64583 6.67188 3.45312C6.59375 3.26042 6.48177 3.09115 6.33594 2.94531C6.16927 2.78385 5.99219 2.59115 5.80469 2.36719C5.61719 2.14323 5.41146 1.92969 5.1875 1.72656C4.96354 1.52344 4.73177 1.35156 4.49219 1.21094C4.2526 1.07031 4.0026 1 3.74219 1C3.53906 1 3.34115 1.03906 3.14844 1.11719C2.95573 1.19531 2.78646 1.30729 2.64062 1.45313C2.36979 1.72396 2.13281 1.96615 1.92969 2.17969C1.72656 2.39323 1.55469 2.61458 1.41406 2.84375C1.27344 3.07292 1.16927 3.32812 1.10156 3.60938C1.03385 3.89062 1 4.22917 1 4.625C1 5.17708 1.08854 5.75 1.26562 6.34375C1.44271 6.9375 1.68229 7.52865 1.98438 8.11719C2.28646 8.70573 2.65365 9.28385 3.08594 9.85156C3.51823 10.4193 3.98698 10.9583 4.49219 11.4688C4.9974 11.9792 5.53385 12.4505 6.10156 12.8828C6.66927 13.3151 7.25 13.6875 7.84375 14C8.4375 14.3125 9.03385 14.5573 9.63281 14.7344C10.2318 14.9115 10.8151 15 11.3828 15C11.7682 14.9948 12.1042 14.9583 12.3906 14.8906C12.6771 14.8229 12.9349 14.7188 13.1641 14.5781C13.3932 14.4375 13.6146 14.2656 13.8281 14.0625C14.0417 13.8594 14.2812 13.625 14.5469 13.3594C14.6927 13.2135 14.8047 13.0443 14.8828 12.8516C14.9609 12.6589 15 12.4609 15 12.2578C14.9896 12.0859 14.9557 11.9141 14.8984 11.7422C14.8411 11.5703 14.7552 11.4089 14.6406 11.2578C14.526 11.1068 14.4036 10.9583 14.2734 10.8125C14.1432 10.6667 14.0026 10.526 13.8516 10.3906C13.7005 10.2552 13.5573 10.1276 13.4219 10.0078C13.2865 9.88802 13.1641 9.77344 13.0547 9.66406C12.9089 9.51823 12.7396 9.40625 12.5469 9.32812ZM12.1797 13.9141C11.9661 13.9714 11.7005 14 11.3828 14C10.8984 13.9948 10.3932 13.9141 9.86719 13.7578C9.34115 13.6016 8.8125 13.3802 8.28125 13.0938C7.75 12.8073 7.22396 12.4688 6.70312 12.0781C6.18229 11.6875 5.69271 11.2604 5.23438 10.7969C4.77604 10.3333 4.34635 9.84635 3.94531 9.33594C3.54427 8.82552 3.20052 8.29948 2.91406 7.75781C2.6276 7.21615 2.40365 6.67969 2.24219 6.14844C2.08073 5.61719 2 5.10156 2 4.60156C2.00521 4.29427 2.03646 4.03125 2.09375 3.8125C2.15104 3.59375 2.23698 3.39844 2.35156 3.22656C2.46615 3.05469 2.60677 2.88802 2.77344 2.72656C2.9401 2.5651 3.13021 2.3776 3.34375 2.16406C3.45312 2.05469 3.58594 2 3.74219 2C3.80469 1.99479 3.90104 2.03646 4.03125 2.125C4.16146 2.21354 4.30208 2.32031 4.45312 2.44531C4.60417 2.57031 4.76042 2.71354 4.92188 2.875C5.08333 3.03646 5.22656 3.19271 5.35156 3.34375C5.47656 3.49479 5.58073 3.63281 5.66406 3.75781C5.7474 3.88281 5.78906 3.97917 5.78906 4.04688C5.79427 4.17188 5.76042 4.27604 5.6875 4.35938C5.61458 4.44271 5.52865 4.53906 5.42969 4.64844C5.33073 4.75781 5.22135 4.86198 5.10156 4.96094C4.98177 5.0599 4.8724 5.17708 4.77344 5.3125C4.67448 5.44792 4.59115 5.59375 4.52344 5.75C4.45573 5.90625 4.42188 6.08594 4.42188 6.28906C4.42708 6.5026 4.46875 6.70312 4.54688 6.89062C4.625 7.07812 4.73698 7.24479 4.88281 7.39062L8.60938 11.1172C8.76042 11.2682 8.92969 11.3828 9.11719 11.4609C9.30469 11.5391 9.5026 11.5781 9.71094 11.5781C9.91927 11.5833 10.1016 11.5495 10.2578 11.4766C10.4141 11.4036 10.5573 11.3177 10.6875 11.2188C10.8177 11.1198 10.9375 11.0104 11.0469 10.8906C11.1562 10.7708 11.2578 10.6615 11.3516 10.5625C11.4453 10.4635 11.5417 10.3802 11.6406 10.3125C11.7396 10.2448 11.8438 10.2109 11.9531 10.2109C12.026 10.2109 12.125 10.2526 12.25 10.3359C12.375 10.4193 12.513 10.526 12.6641 10.6562C12.8151 10.7865 12.9714 10.9297 13.1328 11.0859C13.2943 11.2422 13.4375 11.3984 13.5625 11.5547C13.6875 11.7109 13.7917 11.8516 13.875 11.9766C13.9583 12.1016 14 12.1979 14 12.2656C14 12.4167 13.9453 12.5469 13.8359 12.6562C13.612 12.875 13.4219 13.0651 13.2656 13.2266C13.1094 13.388 12.9427 13.5286 12.7656 13.6484C12.5885 13.7682 12.3932 13.8568 12.1797 13.9141ZM15 1.70312L10.3594 6.35156L13.6484 6.35156V7.35156L8.64844 7.35156L8.64844 2.35156L9.64844 2.35156V5.64062L14.2969 1L15 1.70312Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5469 9.32812C12.3542 9.25 12.1562 9.21094 11.9531 9.21094C11.7344 9.20573 11.5495 9.23958 11.3984 9.3125C11.2474 9.38542 11.1042 9.47135 10.9688 9.57031C10.8333 9.66927 10.7135 9.77865 10.6094 9.89844C10.5052 10.0182 10.4036 10.1276 10.3047 10.2266C10.2057 10.3255 10.1094 10.4089 10.0156 10.4766C9.92188 10.5443 9.82031 10.5781 9.71094 10.5781C9.5599 10.5781 9.42969 10.5234 9.32031 10.4141C9.24219 10.3411 9.13281 10.237 8.99219 10.1016C8.85156 9.96615 8.67969 9.80208 8.47656 9.60938C8.27344 9.41667 8.0625 9.21354 7.84375 9C7.625 8.78646 7.39844 8.5651 7.16406 8.33594C6.92969 8.10677 6.71094 7.88542 6.50781 7.67188C6.30469 7.45833 6.11979 7.25781 5.95312 7.07031C5.78646 6.88281 5.65625 6.72135 5.5625 6.58594C5.46875 6.45052 5.42188 6.35156 5.42188 6.28906C5.41667 6.17448 5.45052 6.07031 5.52344 5.97656C5.59635 5.88281 5.68229 5.78646 5.78125 5.6875C5.88021 5.58854 5.98958 5.48438 6.10938 5.375C6.22917 5.26562 6.33854 5.14844 6.4375 5.02344C6.53646 4.89844 6.61979 4.75521 6.6875 4.59375C6.75521 4.43229 6.78906 4.25 6.78906 4.04688C6.78906 3.84375 6.75 3.64583 6.67188 3.45312C6.59375 3.26042 6.48177 3.09115 6.33594 2.94531C6.16927 2.78385 5.99219 2.59115 5.80469 2.36719C5.61719 2.14323 5.41146 1.92969 5.1875 1.72656C4.96354 1.52344 4.73177 1.35156 4.49219 1.21094C4.2526 1.07031 4.0026 1 3.74219 1C3.53906 1 3.34115 1.03906 3.14844 1.11719C2.95573 1.19531 2.78646 1.30729 2.64062 1.45313C2.36979 1.72396 2.13281 1.96615 1.92969 2.17969C1.72656 2.39323 1.55469 2.61458 1.41406 2.84375C1.27344 3.07292 1.16927 3.32812 1.10156 3.60938C1.03385 3.89062 1 4.22917 1 4.625C1 5.17708 1.08854 5.75 1.26562 6.34375C1.44271 6.9375 1.68229 7.52865 1.98438 8.11719C2.28646 8.70573 2.65365 9.28385 3.08594 9.85156C3.51823 10.4193 3.98698 10.9583 4.49219 11.4688C4.9974 11.9792 5.53385 12.4505 6.10156 12.8828C6.66927 13.3151 7.25 13.6875 7.84375 14C8.4375 14.3125 9.03385 14.5573 9.63281 14.7344C10.2318 14.9115 10.8151 15 11.3828 15C11.7682 14.9948 12.1042 14.9583 12.3906 14.8906C12.6771 14.8229 12.9349 14.7188 13.1641 14.5781C13.3932 14.4375 13.6146 14.2656 13.8281 14.0625C14.0417 13.8594 14.2812 13.625 14.5469 13.3594C14.6927 13.2135 14.8047 13.0443 14.8828 12.8516C14.9609 12.6589 15 12.4609 15 12.2578C14.9896 12.0859 14.9557 11.9141 14.8984 11.7422C14.8411 11.5703 14.7552 11.4089 14.6406 11.2578C14.526 11.1068 14.4036 10.9583 14.2734 10.8125C14.1432 10.6667 14.0026 10.526 13.8516 10.3906C13.7005 10.2552 13.5573 10.1276 13.4219 10.0078C13.2865 9.88802 13.1641 9.77344 13.0547 9.66406C12.9089 9.51823 12.7396 9.40625 12.5469 9.32812ZM12.1797 13.9141C11.9661 13.9714 11.7005 14 11.3828 14C10.8984 13.9948 10.3932 13.9141 9.86719 13.7578C9.34115 13.6016 8.8125 13.3802 8.28125 13.0938C7.75 12.8073 7.22396 12.4688 6.70312 12.0781C6.18229 11.6875 5.69271 11.2604 5.23438 10.7969C4.77604 10.3333 4.34635 9.84635 3.94531 9.33594C3.54427 8.82552 3.20052 8.29948 2.91406 7.75781C2.6276 7.21615 2.40365 6.67969 2.24219 6.14844C2.08073 5.61719 2 5.10156 2 4.60156C2.00521 4.29427 2.03646 4.03125 2.09375 3.8125C2.15104 3.59375 2.23698 3.39844 2.35156 3.22656C2.46615 3.05469 2.60677 2.88802 2.77344 2.72656C2.9401 2.5651 3.13021 2.3776 3.34375 2.16406C3.45312 2.05469 3.58594 2 3.74219 2C3.80469 1.99479 3.90104 2.03646 4.03125 2.125C4.16146 2.21354 4.30208 2.32031 4.45312 2.44531C4.60417 2.57031 4.76042 2.71354 4.92188 2.875C5.08333 3.03646 5.22656 3.19271 5.35156 3.34375C5.47656 3.49479 5.58073 3.63281 5.66406 3.75781C5.7474 3.88281 5.78906 3.97917 5.78906 4.04688C5.79427 4.17188 5.76042 4.27604 5.6875 4.35938C5.61458 4.44271 5.52865 4.53906 5.42969 4.64844C5.33073 4.75781 5.22135 4.86198 5.10156 4.96094C4.98177 5.0599 4.8724 5.17708 4.77344 5.3125C4.67448 5.44792 4.59115 5.59375 4.52344 5.75C4.45573 5.90625 4.42188 6.08594 4.42188 6.28906C4.42708 6.5026 4.46875 6.70312 4.54688 6.89062C4.625 7.07812 4.73698 7.24479 4.88281 7.39062L8.60938 11.1172C8.76042 11.2682 8.92969 11.3828 9.11719 11.4609C9.30469 11.5391 9.5026 11.5781 9.71094 11.5781C9.91927 11.5833 10.1016 11.5495 10.2578 11.4766C10.4141 11.4036 10.5573 11.3177 10.6875 11.2188C10.8177 11.1198 10.9375 11.0104 11.0469 10.8906C11.1562 10.7708 11.2578 10.6615 11.3516 10.5625C11.4453 10.4635 11.5417 10.3802 11.6406 10.3125C11.7396 10.2448 11.8438 10.2109 11.9531 10.2109C12.026 10.2109 12.125 10.2526 12.25 10.3359C12.375 10.4193 12.513 10.526 12.6641 10.6562C12.8151 10.7865 12.9714 10.9297 13.1328 11.0859C13.2943 11.2422 13.4375 11.3984 13.5625 11.5547C13.6875 11.7109 13.7917 11.8516 13.875 11.9766C13.9583 12.1016 14 12.1979 14 12.2656C14 12.4167 13.9453 12.5469 13.8359 12.6562C13.612 12.875 13.4219 13.0651 13.2656 13.2266C13.1094 13.388 12.9427 13.5286 12.7656 13.6484C12.5885 13.7682 12.3932 13.8568 12.1797 13.9141ZM15 1.70312L10.3594 6.35156L13.6484 6.35156V7.35156L8.64844 7.35156L8.64844 2.35156L9.64844 2.35156V5.64062L14.2969 1L15 1.70312Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.64844 6.64844L13.2891 2H10V1H15V6H14V2.71094L9.35156 7.35156L8.64844 6.64844ZM11.9531 9.21094C12.1562 9.21094 12.3542 9.25 12.5469 9.32812C12.7396 9.40625 12.9089 9.51823 13.0547 9.66406C13.1641 9.77344 13.2865 9.88802 13.4219 10.0078C13.5573 10.1276 13.7005 10.2552 13.8516 10.3906C14.0026 10.526 14.1432 10.6667 14.2734 10.8125C14.4036 10.9583 14.526 11.1068 14.6406 11.2578C14.7552 11.4089 14.8411 11.5703 14.8984 11.7422C14.9557 11.9141 14.9896 12.0859 15 12.2578C15 12.4609 14.9609 12.6589 14.8828 12.8516C14.8047 13.0443 14.6927 13.2135 14.5469 13.3594C14.2812 13.625 14.0417 13.8594 13.8281 14.0625C13.6146 14.2656 13.3932 14.4375 13.1641 14.5781C12.9349 14.7188 12.6771 14.8229 12.3906 14.8906C12.1042 14.9583 11.7682 14.9948 11.3828 15C10.8151 15 10.2318 14.9115 9.63281 14.7344C9.03385 14.5573 8.4375 14.3125 7.84375 14C7.25 13.6875 6.66927 13.3151 6.10156 12.8828C5.53385 12.4505 4.9974 11.9792 4.49219 11.4688C3.98698 10.9583 3.51823 10.4193 3.08594 9.85156C2.65365 9.28385 2.28646 8.70573 1.98438 8.11719C1.68229 7.52865 1.44271 6.9375 1.26562 6.34375C1.08854 5.75 1 5.17708 1 4.625C1 4.22917 1.03385 3.89062 1.10156 3.60938C1.16927 3.32812 1.27344 3.07292 1.41406 2.84375C1.55469 2.61458 1.72656 2.39323 1.92969 2.17969C2.13281 1.96615 2.36979 1.72396 2.64062 1.45312C2.78646 1.30729 2.95573 1.19531 3.14844 1.11719C3.34115 1.03906 3.53906 1 3.74219 1C4.0026 1 4.2526 1.07031 4.49219 1.21094C4.73177 1.35156 4.96354 1.52344 5.1875 1.72656C5.41146 1.92969 5.61719 2.14323 5.80469 2.36719C5.99219 2.59115 6.16927 2.78385 6.33594 2.94531C6.48177 3.09115 6.59375 3.26042 6.67188 3.45312C6.75 3.64583 6.78906 3.84375 6.78906 4.04688C6.78906 4.25 6.75521 4.43229 6.6875 4.59375C6.61979 4.75521 6.53646 4.89844 6.4375 5.02344C6.33854 5.14844 6.22917 5.26562 6.10938 5.375C5.98958 5.48438 5.88021 5.58854 5.78125 5.6875C5.68229 5.78646 5.59635 5.88281 5.52344 5.97656C5.45052 6.07031 5.41667 6.17448 5.42188 6.28906C5.42188 6.35156 5.46875 6.45052 5.5625 6.58594C5.65625 6.72135 5.78646 6.88281 5.95312 7.07031C6.11979 7.25781 6.30469 7.45833 6.50781 7.67188C6.71094 7.88542 6.92969 8.10677 7.16406 8.33594C7.39844 8.5651 7.625 8.78646 7.84375 9C8.0625 9.21354 8.27344 9.41667 8.47656 9.60938C8.67969 9.80208 8.85156 9.96615 8.99219 10.1016C9.13281 10.237 9.24219 10.3411 9.32031 10.4141C9.42969 10.5234 9.5599 10.5781 9.71094 10.5781C9.82031 10.5781 9.92188 10.5443 10.0156 10.4766C10.1094 10.4089 10.2057 10.3255 10.3047 10.2266C10.4036 10.1276 10.5052 10.0182 10.6094 9.89844C10.7135 9.77865 10.8333 9.66927 10.9688 9.57031C11.1042 9.47135 11.2474 9.38542 11.3984 9.3125C11.5495 9.23958 11.7344 9.20573 11.9531 9.21094ZM11.3828 14C11.7005 14 11.9661 13.9714 12.1797 13.9141C12.3932 13.8568 12.5885 13.7682 12.7656 13.6484C12.9427 13.5286 13.1094 13.388 13.2656 13.2266C13.4219 13.0651 13.612 12.875 13.8359 12.6562C13.9453 12.5469 14 12.4167 14 12.2656C14 12.1979 13.9583 12.1016 13.875 11.9766C13.7917 11.8516 13.6875 11.7109 13.5625 11.5547C13.4375 11.3984 13.2943 11.2422 13.1328 11.0859C12.9714 10.9297 12.8151 10.7865 12.6641 10.6562C12.513 10.526 12.375 10.4193 12.25 10.3359C12.125 10.2526 12.026 10.2109 11.9531 10.2109C11.8438 10.2109 11.7396 10.2448 11.6406 10.3125C11.5417 10.3802 11.4453 10.4635 11.3516 10.5625C11.2578 10.6615 11.1562 10.7708 11.0469 10.8906C10.9375 11.0104 10.8177 11.1198 10.6875 11.2188C10.5573 11.3177 10.4141 11.4036 10.2578 11.4766C10.1016 11.5495 9.91927 11.5833 9.71094 11.5781C9.5026 11.5781 9.30469 11.5391 9.11719 11.4609C8.92969 11.3828 8.76042 11.2682 8.60938 11.1172L4.88281 7.39062C4.73698 7.24479 4.625 7.07812 4.54688 6.89062C4.46875 6.70312 4.42708 6.5026 4.42188 6.28906C4.42188 6.08594 4.45573 5.90625 4.52344 5.75C4.59115 5.59375 4.67448 5.44792 4.77344 5.3125C4.8724 5.17708 4.98177 5.0599 5.10156 4.96094C5.22135 4.86198 5.33073 4.75781 5.42969 4.64844C5.52865 4.53906 5.61458 4.44271 5.6875 4.35938C5.76042 4.27604 5.79427 4.17188 5.78906 4.04688C5.78906 3.97917 5.7474 3.88281 5.66406 3.75781C5.58073 3.63281 5.47656 3.49479 5.35156 3.34375C5.22656 3.19271 5.08333 3.03646 4.92188 2.875C4.76042 2.71354 4.60417 2.57031 4.45312 2.44531C4.30208 2.32031 4.16146 2.21354 4.03125 2.125C3.90104 2.03646 3.80469 1.99479 3.74219 2C3.58594 2 3.45312 2.05469 3.34375 2.16406C3.13021 2.3776 2.9401 2.5651 2.77344 2.72656C2.60677 2.88802 2.46615 3.05469 2.35156 3.22656C2.23698 3.39844 2.15104 3.59375 2.09375 3.8125C2.03646 4.03125 2.00521 4.29427 2 4.60156C2 5.10156 2.08073 5.61719 2.24219 6.14844C2.40365 6.67969 2.6276 7.21615 2.91406 7.75781C3.20052 8.29948 3.54427 8.82552 3.94531 9.33594C4.34635 9.84635 4.77604 10.3333 5.23438 10.7969C5.69271 11.2604 6.18229 11.6875 6.70312 12.0781C7.22396 12.4688 7.75 12.8073 8.28125 13.0938C8.8125 13.3802 9.34115 13.6016 9.86719 13.7578C10.3932 13.9141 10.8984 13.9948 11.3828 14Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.64844 6.64844L13.2891 2H10V1H15V6H14V2.71094L9.35156 7.35156L8.64844 6.64844ZM11.9531 9.21094C12.1562 9.21094 12.3542 9.25 12.5469 9.32812C12.7396 9.40625 12.9089 9.51823 13.0547 9.66406C13.1641 9.77344 13.2865 9.88802 13.4219 10.0078C13.5573 10.1276 13.7005 10.2552 13.8516 10.3906C14.0026 10.526 14.1432 10.6667 14.2734 10.8125C14.4036 10.9583 14.526 11.1068 14.6406 11.2578C14.7552 11.4089 14.8411 11.5703 14.8984 11.7422C14.9557 11.9141 14.9896 12.0859 15 12.2578C15 12.4609 14.9609 12.6589 14.8828 12.8516C14.8047 13.0443 14.6927 13.2135 14.5469 13.3594C14.2812 13.625 14.0417 13.8594 13.8281 14.0625C13.6146 14.2656 13.3932 14.4375 13.1641 14.5781C12.9349 14.7188 12.6771 14.8229 12.3906 14.8906C12.1042 14.9583 11.7682 14.9948 11.3828 15C10.8151 15 10.2318 14.9115 9.63281 14.7344C9.03385 14.5573 8.4375 14.3125 7.84375 14C7.25 13.6875 6.66927 13.3151 6.10156 12.8828C5.53385 12.4505 4.9974 11.9792 4.49219 11.4688C3.98698 10.9583 3.51823 10.4193 3.08594 9.85156C2.65365 9.28385 2.28646 8.70573 1.98438 8.11719C1.68229 7.52865 1.44271 6.9375 1.26562 6.34375C1.08854 5.75 1 5.17708 1 4.625C1 4.22917 1.03385 3.89062 1.10156 3.60938C1.16927 3.32812 1.27344 3.07292 1.41406 2.84375C1.55469 2.61458 1.72656 2.39323 1.92969 2.17969C2.13281 1.96615 2.36979 1.72396 2.64062 1.45312C2.78646 1.30729 2.95573 1.19531 3.14844 1.11719C3.34115 1.03906 3.53906 1 3.74219 1C4.0026 1 4.2526 1.07031 4.49219 1.21094C4.73177 1.35156 4.96354 1.52344 5.1875 1.72656C5.41146 1.92969 5.61719 2.14323 5.80469 2.36719C5.99219 2.59115 6.16927 2.78385 6.33594 2.94531C6.48177 3.09115 6.59375 3.26042 6.67188 3.45312C6.75 3.64583 6.78906 3.84375 6.78906 4.04688C6.78906 4.25 6.75521 4.43229 6.6875 4.59375C6.61979 4.75521 6.53646 4.89844 6.4375 5.02344C6.33854 5.14844 6.22917 5.26562 6.10938 5.375C5.98958 5.48438 5.88021 5.58854 5.78125 5.6875C5.68229 5.78646 5.59635 5.88281 5.52344 5.97656C5.45052 6.07031 5.41667 6.17448 5.42188 6.28906C5.42188 6.35156 5.46875 6.45052 5.5625 6.58594C5.65625 6.72135 5.78646 6.88281 5.95312 7.07031C6.11979 7.25781 6.30469 7.45833 6.50781 7.67188C6.71094 7.88542 6.92969 8.10677 7.16406 8.33594C7.39844 8.5651 7.625 8.78646 7.84375 9C8.0625 9.21354 8.27344 9.41667 8.47656 9.60938C8.67969 9.80208 8.85156 9.96615 8.99219 10.1016C9.13281 10.237 9.24219 10.3411 9.32031 10.4141C9.42969 10.5234 9.5599 10.5781 9.71094 10.5781C9.82031 10.5781 9.92188 10.5443 10.0156 10.4766C10.1094 10.4089 10.2057 10.3255 10.3047 10.2266C10.4036 10.1276 10.5052 10.0182 10.6094 9.89844C10.7135 9.77865 10.8333 9.66927 10.9688 9.57031C11.1042 9.47135 11.2474 9.38542 11.3984 9.3125C11.5495 9.23958 11.7344 9.20573 11.9531 9.21094ZM11.3828 14C11.7005 14 11.9661 13.9714 12.1797 13.9141C12.3932 13.8568 12.5885 13.7682 12.7656 13.6484C12.9427 13.5286 13.1094 13.388 13.2656 13.2266C13.4219 13.0651 13.612 12.875 13.8359 12.6562C13.9453 12.5469 14 12.4167 14 12.2656C14 12.1979 13.9583 12.1016 13.875 11.9766C13.7917 11.8516 13.6875 11.7109 13.5625 11.5547C13.4375 11.3984 13.2943 11.2422 13.1328 11.0859C12.9714 10.9297 12.8151 10.7865 12.6641 10.6562C12.513 10.526 12.375 10.4193 12.25 10.3359C12.125 10.2526 12.026 10.2109 11.9531 10.2109C11.8438 10.2109 11.7396 10.2448 11.6406 10.3125C11.5417 10.3802 11.4453 10.4635 11.3516 10.5625C11.2578 10.6615 11.1562 10.7708 11.0469 10.8906C10.9375 11.0104 10.8177 11.1198 10.6875 11.2188C10.5573 11.3177 10.4141 11.4036 10.2578 11.4766C10.1016 11.5495 9.91927 11.5833 9.71094 11.5781C9.5026 11.5781 9.30469 11.5391 9.11719 11.4609C8.92969 11.3828 8.76042 11.2682 8.60938 11.1172L4.88281 7.39062C4.73698 7.24479 4.625 7.07812 4.54688 6.89062C4.46875 6.70312 4.42708 6.5026 4.42188 6.28906C4.42188 6.08594 4.45573 5.90625 4.52344 5.75C4.59115 5.59375 4.67448 5.44792 4.77344 5.3125C4.8724 5.17708 4.98177 5.0599 5.10156 4.96094C5.22135 4.86198 5.33073 4.75781 5.42969 4.64844C5.52865 4.53906 5.61458 4.44271 5.6875 4.35938C5.76042 4.27604 5.79427 4.17188 5.78906 4.04688C5.78906 3.97917 5.7474 3.88281 5.66406 3.75781C5.58073 3.63281 5.47656 3.49479 5.35156 3.34375C5.22656 3.19271 5.08333 3.03646 4.92188 2.875C4.76042 2.71354 4.60417 2.57031 4.45312 2.44531C4.30208 2.32031 4.16146 2.21354 4.03125 2.125C3.90104 2.03646 3.80469 1.99479 3.74219 2C3.58594 2 3.45312 2.05469 3.34375 2.16406C3.13021 2.3776 2.9401 2.5651 2.77344 2.72656C2.60677 2.88802 2.46615 3.05469 2.35156 3.22656C2.23698 3.39844 2.15104 3.59375 2.09375 3.8125C2.03646 4.03125 2.00521 4.29427 2 4.60156C2 5.10156 2.08073 5.61719 2.24219 6.14844C2.40365 6.67969 2.6276 7.21615 2.91406 7.75781C3.20052 8.29948 3.54427 8.82552 3.94531 9.33594C4.34635 9.84635 4.77604 10.3333 5.23438 10.7969C5.69271 11.2604 6.18229 11.6875 6.70312 12.0781C7.22396 12.4688 7.75 12.8073 8.28125 13.0938C8.8125 13.3802 9.34115 13.6016 9.86719 13.7578C10.3932 13.9141 10.8984 13.9948 11.3828 14Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
@@ -21,19 +21,27 @@
|
||||
}
|
||||
|
||||
.monaco-workbench .action-label.calls-to {
|
||||
background-image: url(files_CallTo_CallTo_16x.svg);
|
||||
background-image: url(action-call-to.svg);
|
||||
background-size: 14px 14px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left center;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .action-label.calls-to {
|
||||
background-image: url(action-call-to-dark.svg);
|
||||
}
|
||||
|
||||
.monaco-workbench .action-label.calls-from {
|
||||
background-image: url(files_CallFrom_CallFrom_16x.svg);
|
||||
background-image: url(action-call-from.svg);
|
||||
background-size: 14px 14px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left center;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .action-label.calls-from{
|
||||
background-image: url(action-call-from-dark.svg);
|
||||
}
|
||||
|
||||
.monaco-workbench .call-hierarchy .editor,
|
||||
.monaco-workbench .call-hierarchy .tree {
|
||||
height: 100%;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M12 6v4h2v4.987l-.398.3A3.46 3.46 0 0 1 11.5 16C9.57 16 8 14.43 8 12.5V9.006H6.344l1.318 1.322-2.119 2.119L1 7.92v-.798l4.55-4.55 2.12 2.12-1.309 1.313H8V3.5C8 1.57 9.57 0 11.5 0a3.46 3.46 0 0 1 2.102.713l.398.3V6h-2z" id="outline"/><path class="icon-vs-bg" d="M11 10.051V11h2v3.489a2.476 2.476 0 0 1-1.5.511A2.5 2.5 0 0 1 9 12.5v-9A2.5 2.5 0 0 1 11.5 1c.565 0 1.081.194 1.5.511V5h-2v5.051zM6.257 4.693l-.707-.707L2.016 7.52l3.526 3.514.707-.707-2.314-2.322h4.12v-1H3.953l2.304-2.312z" id="iconBg"/></svg>
|
||||
|
Before Width: | Height: | Size: 781 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M3.727 9.006H1.016v-3h2.693L2.4 4.692l2.12-2.12L8 6.052V3.5C8 1.57 9.57 0 11.5 0c.758 0 1.485.247 2.103.713l.362.273v14.028l-.362.273A3.465 3.465 0 0 1 11.5 16C9.57 16 8 14.43 8 12.5V8.986l-3.473 3.461-2.119-2.119 1.319-1.322z" id="outline"/><path class="icon-vs-bg" d="M11 10.051V11h2v3.489a2.476 2.476 0 0 1-1.5.511A2.5 2.5 0 0 1 9 12.5v-9A2.5 2.5 0 0 1 11.5 1c.565 0 1.081.194 1.5.511V5h-2v5.051zM3.813 4.693l2.305 2.312H2.016v1h4.12l-2.314 2.322.707.707L8.055 7.52 4.52 3.986l-.707.707z" id="iconBg"/></svg>
|
||||
|
Before Width: | Height: | Size: 787 B |
@@ -20,6 +20,7 @@ import { CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CONTEXT_HAS_CUSTOM_EDITORS,
|
||||
import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files';
|
||||
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IExplorerService } from 'vs/workbench/contrib/files/common/files';
|
||||
|
||||
const viewCategory = nls.localize('viewCategory', "View");
|
||||
|
||||
@@ -34,7 +35,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
when: EditorContextKeys.focus.toNegated(),
|
||||
handler: async (accessor: ServicesAccessor, resource: URI | object) => {
|
||||
const editorService = accessor.get(IEditorService);
|
||||
const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService);
|
||||
const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService, accessor.get(IExplorerService));
|
||||
const targetResource = firstOrDefault(resources);
|
||||
if (!targetResource) {
|
||||
return undefined; // {{SQL CARBON EDIT}} strict-null-check
|
||||
|
||||
@@ -17,6 +17,7 @@ import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { GroupIdentifier, IEditorInput, IRevertOptions, ISaveOptions, Verbosity } from 'vs/workbench/common/editor';
|
||||
import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
|
||||
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
|
||||
import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewWorkbenchService, LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
@@ -117,26 +118,19 @@ export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Preserve view state by opening the editor first. In addition
|
||||
// this allows the user to review the contents of the editor.
|
||||
// let viewState: IEditorViewState | undefined = undefined;
|
||||
// const editor = await this.editorService.openEditor(this, undefined, group);
|
||||
// if (isTextEditor(editor)) {
|
||||
// viewState = editor.getViewState();
|
||||
// }
|
||||
|
||||
let dialogPath = this._editorResource;
|
||||
// if (this._editorResource.scheme === Schemas.untitled) {
|
||||
// dialogPath = this.suggestFileName(resource);
|
||||
// }
|
||||
|
||||
const target = await this.promptForPath(this._editorResource, dialogPath, options?.availableFileSystems);
|
||||
if (!target) {
|
||||
return false; // save cancelled
|
||||
}
|
||||
|
||||
await this._model.saveAs(this._editorResource, target, options);
|
||||
if (!await this._model.saveAs(this._editorResource, target, options)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const replacement = this.handleMove(groupId, target) || this.instantiationService.createInstance(FileEditorInput, target, undefined, undefined);
|
||||
|
||||
await this.editorService.replaceEditors([{ editor: this, replacement, options: { pinned: true } }], groupId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -156,15 +150,24 @@ export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput {
|
||||
// Help user to find a name for the file by opening it first
|
||||
await this.editorService.openEditor({ resource, options: { revealIfOpened: true, preserveFocus: true } });
|
||||
|
||||
return this.fileDialogService.pickFileToSave({});//this.getSaveDialogOptions(defaultUri, availableFileSystems));
|
||||
return this.fileDialogService.pickFileToSave({
|
||||
availableFileSystems,
|
||||
defaultUri
|
||||
});
|
||||
}
|
||||
|
||||
public handleMove(groupId: GroupIdentifier, uri: URI, options?: ITextEditorOptions): IEditorInput | undefined {
|
||||
const webview = assertIsDefined(this.takeOwnershipOfWebview());
|
||||
return this.instantiationService.createInstance(CustomFileEditorInput,
|
||||
uri,
|
||||
this.viewType,
|
||||
generateUuid(),
|
||||
new Lazy(() => webview));
|
||||
const editorInfo = this.customEditorService.getCustomEditor(this.viewType);
|
||||
if (editorInfo?.matches(uri)) {
|
||||
const webview = assertIsDefined(this.takeOwnershipOfWebview());
|
||||
const newInput = this.instantiationService.createInstance(CustomFileEditorInput,
|
||||
uri,
|
||||
this.viewType,
|
||||
generateUuid(),
|
||||
new Lazy(() => webview));
|
||||
newInput.updateGroup(groupId);
|
||||
return newInput;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { coalesce, distinct, find, mergeSort } from 'vs/base/common/arrays';
|
||||
import * as glob from 'vs/base/common/glob';
|
||||
import { Lazy } from 'vs/base/common/lazy';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { basename, isEqual } from 'vs/base/common/resources';
|
||||
@@ -32,14 +31,14 @@ import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/wo
|
||||
import { CustomFileEditorInput } from './customEditorInput';
|
||||
const defaultEditorId = 'default';
|
||||
|
||||
const defaultEditorInfo: CustomEditorInfo = {
|
||||
const defaultEditorInfo = new CustomEditorInfo({
|
||||
id: defaultEditorId,
|
||||
displayName: nls.localize('promptOpenWith.defaultEditor', "VS Code's standard text editor"),
|
||||
selector: [
|
||||
{ filenamePattern: '*' }
|
||||
],
|
||||
priority: CustomEditorPriority.default,
|
||||
};
|
||||
});
|
||||
|
||||
export class CustomEditorInfoStore {
|
||||
private readonly contributedEditors = new Map<string, CustomEditorInfo>();
|
||||
@@ -64,7 +63,7 @@ export class CustomEditorInfoStore {
|
||||
|
||||
public getContributedEditors(resource: URI): readonly CustomEditorInfo[] {
|
||||
return Array.from(this.contributedEditors.values()).filter(customEditor =>
|
||||
customEditor.selector.some(selector => matches(selector, resource)));
|
||||
customEditor.matches(resource));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,12 +96,12 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
|
||||
|
||||
for (const extension of extensions) {
|
||||
for (const webviewEditorContribution of extension.value) {
|
||||
this._editorInfoStore.add({
|
||||
this._editorInfoStore.add(new CustomEditorInfo({
|
||||
id: webviewEditorContribution.viewType,
|
||||
displayName: webviewEditorContribution.displayName,
|
||||
selector: webviewEditorContribution.selector || [],
|
||||
priority: webviewEditorContribution.priority || CustomEditorPriority.default,
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
this.updateContexts();
|
||||
@@ -127,6 +126,10 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
|
||||
return { resource, viewType: activeInput.viewType };
|
||||
}
|
||||
|
||||
public getCustomEditor(viewType: string): CustomEditorInfo | undefined {
|
||||
return this._editorInfoStore.get(viewType);
|
||||
}
|
||||
|
||||
public getContributedCustomEditors(resource: URI): readonly CustomEditorInfo[] {
|
||||
return this._editorInfoStore.getContributedEditors(resource);
|
||||
}
|
||||
@@ -134,7 +137,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
|
||||
public getUserConfiguredCustomEditors(resource: URI): readonly CustomEditorInfo[] {
|
||||
const rawAssociations = this.configurationService.getValue<CustomEditorsAssociations>(customEditorsAssociationsKey) || [];
|
||||
return coalesce(rawAssociations
|
||||
.filter(association => matches(association, resource))
|
||||
.filter(association => CustomEditorInfo.selectorMatches(association, resource))
|
||||
.map(association => this._editorInfoStore.get(association.viewType)));
|
||||
}
|
||||
|
||||
@@ -332,6 +335,9 @@ export class CustomEditorContribution implements IWorkbenchContribution {
|
||||
return {
|
||||
override: (async () => {
|
||||
const standardEditor = await this.editorService.openEditor(editor, { ...options, ignoreOverrides: true }, group);
|
||||
// Give a moment to make sure the editor is showing.
|
||||
// Otherwise the focus shift can cause the prompt to be dismissed right away.
|
||||
await new Promise(resolve => setTimeout(resolve, 20));
|
||||
const selectedEditor = await this.customEditorService.promptOpenWith(resource, options, group);
|
||||
if (selectedEditor && selectedEditor.input) {
|
||||
await group.replaceEditors([{
|
||||
@@ -405,16 +411,6 @@ function priorityToRank(priority: CustomEditorPriority): number {
|
||||
}
|
||||
}
|
||||
|
||||
function matches(selector: CustomEditorSelector, resource: URI): boolean {
|
||||
if (selector.filenamePattern) {
|
||||
if (glob.match(selector.filenamePattern.toLowerCase(), basename(resource).toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
registerThemingParticipant((theme, collector) => {
|
||||
const shadow = theme.getColor(colorRegistry.scrollbarShadow);
|
||||
if (shadow) {
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import * as glob from 'vs/base/common/glob';
|
||||
import { basename } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { EditorInput, IEditor, ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor';
|
||||
import { EditorInput, IEditor, IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor';
|
||||
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
|
||||
@@ -29,6 +31,7 @@ export interface ICustomEditorService {
|
||||
|
||||
readonly activeCustomEditor: ICustomEditor | undefined;
|
||||
|
||||
getCustomEditor(viewType: string): CustomEditorInfo | undefined;
|
||||
getContributedCustomEditors(resource: URI): readonly CustomEditorInfo[];
|
||||
getUserConfiguredCustomEditors(resource: URI): readonly CustomEditorInfo[];
|
||||
|
||||
@@ -87,9 +90,35 @@ export interface CustomEditorSelector {
|
||||
readonly filenamePattern?: string;
|
||||
}
|
||||
|
||||
export interface CustomEditorInfo {
|
||||
readonly id: string;
|
||||
readonly displayName: string;
|
||||
readonly priority: CustomEditorPriority;
|
||||
readonly selector: readonly CustomEditorSelector[];
|
||||
export class CustomEditorInfo {
|
||||
|
||||
public readonly id: string;
|
||||
public readonly displayName: string;
|
||||
public readonly priority: CustomEditorPriority;
|
||||
public readonly selector: readonly CustomEditorSelector[];
|
||||
|
||||
constructor(descriptor: {
|
||||
readonly id: string;
|
||||
readonly displayName: string;
|
||||
readonly priority: CustomEditorPriority;
|
||||
readonly selector: readonly CustomEditorSelector[];
|
||||
}) {
|
||||
this.id = descriptor.id;
|
||||
this.displayName = descriptor.displayName;
|
||||
this.priority = descriptor.priority;
|
||||
this.selector = descriptor.selector;
|
||||
}
|
||||
|
||||
matches(resource: URI): boolean {
|
||||
return this.selector.some(selector => CustomEditorInfo.selectorMatches(selector, resource));
|
||||
}
|
||||
|
||||
static selectorMatches(selector: CustomEditorSelector, resource: URI): boolean {
|
||||
if (selector.filenamePattern) {
|
||||
if (glob.match(selector.filenamePattern.toLowerCase(), basename(resource).toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ class DataBreakpointsRenderer implements IListRenderer<DataBreakpoint, IBaseBrea
|
||||
|
||||
renderElement(dataBreakpoint: DataBreakpoint, index: number, data: IBaseBreakpointWithIconTemplateData): void {
|
||||
data.context = dataBreakpoint;
|
||||
data.name.textContent = dataBreakpoint.label;
|
||||
data.name.textContent = dataBreakpoint.description;
|
||||
const { className, message } = getBreakpointMessageAndClassName(this.debugService, dataBreakpoint);
|
||||
data.icon.className = `codicon ${className}`;
|
||||
data.icon.title = message ? message : '';
|
||||
@@ -713,25 +713,6 @@ export function getBreakpointMessageAndClassName(debugService: IDebugService, br
|
||||
};
|
||||
}
|
||||
|
||||
const focusedThread = debugService.getViewModel().focusedThread;
|
||||
if (focusedThread) {
|
||||
const callStack = focusedThread ? focusedThread.getCallStack() : undefined;
|
||||
const topStackFrame = callStack ? callStack[0] : undefined;
|
||||
if (topStackFrame && topStackFrame.source.uri.toString() === breakpoint.uri.toString() && topStackFrame.range.startLineNumber === breakpoint.lineNumber) {
|
||||
if (topStackFrame.range.startColumn === breakpoint.column) {
|
||||
return {
|
||||
className: 'codicon-debug-breakpoint-stackframe-dot',
|
||||
message: breakpoint.message || nls.localize('breakpoint', "Breakpoint")
|
||||
};
|
||||
} else if (breakpoint.column === undefined) {
|
||||
return {
|
||||
className: 'codicon-debug-breakpoint',
|
||||
message: breakpoint.message || nls.localize('breakpoint', "Breakpoint")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
className: 'codicon-debug-breakpoint',
|
||||
message: breakpoint.message || nls.localize('breakpoint', "Breakpoint")
|
||||
|
||||
@@ -505,7 +505,7 @@ class StackFramesRenderer implements ITreeRenderer<IStackFrame, FuzzyScore, ISta
|
||||
dom.toggleClass(data.stackFrame, 'disabled', !stackFrame.source || !stackFrame.source.available || isDeemphasized(stackFrame));
|
||||
dom.toggleClass(data.stackFrame, 'label', stackFrame.presentationHint === 'label');
|
||||
dom.toggleClass(data.stackFrame, 'subtle', stackFrame.presentationHint === 'subtle');
|
||||
const hasActions = stackFrame.thread.session.capabilities.supportsRestartFrame;
|
||||
const hasActions = stackFrame.thread.session.capabilities.supportsRestartFrame && stackFrame.presentationHint !== 'label' && stackFrame.presentationHint !== 'subtle';
|
||||
dom.toggleClass(data.stackFrame, 'has-actions', hasActions);
|
||||
|
||||
data.file.title = stackFrame.source.inMemory ? stackFrame.source.uri.path : this.labelService.getUriLabel(stackFrame.source.uri);
|
||||
|
||||
@@ -84,7 +84,7 @@ class OpenDebugPanelAction extends TogglePanelAction {
|
||||
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(ViewletDescriptor.create(
|
||||
DebugViewlet,
|
||||
VIEWLET_ID,
|
||||
nls.localize('debugAndRun', "Debug And Run"),
|
||||
nls.localize('debugAndRun', "Debug and Run"),
|
||||
'codicon-debug',
|
||||
13 // {{SQL CARBON EDIT}}
|
||||
));
|
||||
|
||||
@@ -186,9 +186,9 @@ registerThemingParticipant((theme, collector) => {
|
||||
.monaco-workbench .codicon-debug-breakpoint-function,
|
||||
.monaco-workbench .codicon-debug-breakpoint-data,
|
||||
.monaco-workbench .codicon-debug-breakpoint-unsupported,
|
||||
.monaco-workbench .codicon-debug-hint:not(*[class*='codicon-debug-breakpoint']) ,
|
||||
.monaco-workbench .codicon-debug-breakpoint-stackframe-dot,
|
||||
.monaco-workbench .codicon-debug-breakpoint.codicon-debug-breakpoint-stackframe-focused::after {
|
||||
.monaco-workbench .codicon-debug-hint:not([class*='codicon-debug-breakpoint']),
|
||||
.monaco-workbench .codicon-debug-breakpoint.codicon-debug-breakpoint-stackframe-focused::after,
|
||||
.monaco-workbench .codicon-debug-breakpoint.codicon-debug-breakpoint-stackframe::after {
|
||||
color: ${debugIconBreakpointColor} !important;
|
||||
}
|
||||
`);
|
||||
@@ -212,17 +212,16 @@ registerThemingParticipant((theme, collector) => {
|
||||
`);
|
||||
}
|
||||
|
||||
const debugIconBreakpointStackframeColor = theme.getColor(debugIconBreakpointStackframeForeground);
|
||||
if (debugIconBreakpointStackframeColor) {
|
||||
const debugIconBreakpointCurrentStackframeForegroundColor = theme.getColor(debugIconBreakpointCurrentStackframeForeground);
|
||||
if (debugIconBreakpointCurrentStackframeForegroundColor) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench .codicon-debug-breakpoint-stackframe,
|
||||
.monaco-workbench .codicon-debug-breakpoint-stackframe-dot::after {
|
||||
color: ${debugIconBreakpointStackframeColor} !important;
|
||||
.monaco-workbench .codicon-debug-breakpoint-stackframe {
|
||||
color: ${debugIconBreakpointCurrentStackframeForegroundColor} !important;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
const debugIconBreakpointStackframeFocusedColor = theme.getColor(debugIconBreakpointStackframeFocusedForeground);
|
||||
const debugIconBreakpointStackframeFocusedColor = theme.getColor(debugIconBreakpointStackframeForeground);
|
||||
if (debugIconBreakpointStackframeFocusedColor) {
|
||||
collector.addRule(`
|
||||
.monaco-workbench .codicon-debug-breakpoint-stackframe-focused {
|
||||
@@ -239,5 +238,5 @@ const focusedStackFrameColor = registerColor('editor.focusedStackFrameHighlightB
|
||||
const debugIconBreakpointForeground = registerColor('debugIcon.breakpointForeground', { dark: '#E51400', light: '#E51400', hc: '#E51400' }, localize('debugIcon.breakpointForeground', 'Icon color for breakpoints.'));
|
||||
const debugIconBreakpointDisabledForeground = registerColor('debugIcon.breakpointDisabledForeground', { dark: '#848484', light: '#848484', hc: '#848484' }, localize('debugIcon.breakpointDisabledForeground', 'Icon color for disabled breakpoints.'));
|
||||
const debugIconBreakpointUnverifiedForeground = registerColor('debugIcon.breakpointUnverifiedForeground', { dark: '#848484', light: '#848484', hc: '#848484' }, localize('debugIcon.breakpointUnverifiedForeground', 'Icon color for unverified breakpoints.'));
|
||||
const debugIconBreakpointStackframeForeground = registerColor('debugIcon.breakpointStackframeForeground', { dark: '#FFCC00', light: '#FFCC00', hc: '#FFCC00' }, localize('debugIcon.breakpointStackframeForeground', 'Icon color for breakpoints.'));
|
||||
const debugIconBreakpointStackframeFocusedForeground = registerColor('debugIcon.breakpointStackframeFocusedForeground', { dark: '#89D185', light: '#89D185', hc: '#89D185' }, localize('debugIcon.breakpointStackframeFocusedForeground', 'Icon color for breakpoints.'));
|
||||
const debugIconBreakpointCurrentStackframeForeground = registerColor('debugIcon.breakpointCurrentStackframeForeground', { dark: '#FFCC00', light: '#FFCC00', hc: '#FFCC00' }, localize('debugIcon.breakpointCurrentStackframeForeground', 'Icon color for the current breakpoint stack frame.'));
|
||||
const debugIconBreakpointStackframeForeground = registerColor('debugIcon.breakpointStackframeForeground', { dark: '#89D185', light: '#89D185', hc: '#89D185' }, localize('debugIcon.breakpointStackframeForeground', 'Icon color for all breakpoint stack frames.'));
|
||||
|
||||
@@ -18,7 +18,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterDescriptorFactory, IDebugAdapter, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory } from 'vs/workbench/contrib/debug/common/debug';
|
||||
@@ -80,7 +80,7 @@ export class ConfigurationManager implements IConfigurationManager {
|
||||
const previousSelectedRoot = this.storageService.get(DEBUG_SELECTED_ROOT, StorageScope.WORKSPACE);
|
||||
const previousSelectedLaunch = this.launches.filter(l => l.uri.toString() === previousSelectedRoot).pop();
|
||||
this.debugConfigurationTypeContext = CONTEXT_DEBUG_CONFIGURATION_TYPE.bindTo(contextKeyService);
|
||||
if (previousSelectedLaunch) {
|
||||
if (previousSelectedLaunch && previousSelectedLaunch.getConfigurationNames().length) {
|
||||
this.selectConfiguration(previousSelectedLaunch, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE));
|
||||
} else if (this.launches.length > 0) {
|
||||
const rootUri = historyService.getLastActiveWorkspaceRoot();
|
||||
@@ -284,7 +284,7 @@ export class ConfigurationManager implements IConfigurationManager {
|
||||
});
|
||||
});
|
||||
|
||||
this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => {
|
||||
this.toDispose.push(Event.any<IWorkspaceFoldersChangeEvent | WorkbenchState>(this.contextService.onDidChangeWorkspaceFolders, this.contextService.onDidChangeWorkbenchState)(() => {
|
||||
this.initLaunches();
|
||||
const toSelect = this.selectedLaunch || (this.launches.length > 0 ? this.launches[0] : undefined);
|
||||
this.selectConfiguration(toSelect);
|
||||
@@ -496,10 +496,13 @@ abstract class AbstractLaunch {
|
||||
|
||||
getConfigurationNames(includeCompounds = true): string[] {
|
||||
const config = this.getConfig();
|
||||
if (!config || !config.configurations || !Array.isArray(config.configurations)) {
|
||||
if (!config || (!Array.isArray(config.configurations) && !Array.isArray(config.compounds))) {
|
||||
return [];
|
||||
} else {
|
||||
const names = config.configurations.filter(cfg => cfg && typeof cfg.name === 'string').map(cfg => cfg.name);
|
||||
const names: string[] = [];
|
||||
if (config.configurations) {
|
||||
names.push(...config.configurations.filter(cfg => cfg && typeof cfg.name === 'string').map(cfg => cfg.name));
|
||||
}
|
||||
if (includeCompounds && config.compounds) {
|
||||
if (config.compounds) {
|
||||
names.push(...config.compounds.filter(compound => typeof compound.name === 'string' && compound.configurations && compound.configurations.length)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user