Merge from vscode 313ede61cbad8f9dc748907b3384e059ddddb79a (#7436)

* Merge from vscode 313ede61cbad8f9dc748907b3384e059ddddb79a

* fix strict null checks
This commit is contained in:
Anthony Dresser
2019-09-30 23:35:45 -07:00
committed by GitHub
parent 6ab03053a0
commit 084524cd2d
196 changed files with 2927 additions and 2547 deletions

View File

@@ -1,3 +1,3 @@
disturl "https://atom.io/download/electron" disturl "https://atom.io/download/electron"
target "6.0.9" target "4.2.10"
runtime "electron" runtime "electron"

View File

@@ -48,7 +48,7 @@ declare namespace monaco.editor {
#include(vs/editor/standalone/common/standaloneThemeService): BuiltinTheme, IStandaloneThemeData, IColors #include(vs/editor/standalone/common/standaloneThemeService): BuiltinTheme, IStandaloneThemeData, IColors
#include(vs/editor/common/modes/supports/tokenization): ITokenThemeRule #include(vs/editor/common/modes/supports/tokenization): ITokenThemeRule
#include(vs/editor/common/services/webWorker): MonacoWebWorker, IWebWorkerOptions #include(vs/editor/common/services/webWorker): MonacoWebWorker, IWebWorkerOptions
#include(vs/editor/standalone/browser/standaloneCodeEditor): IActionDescriptor, IEditorConstructionOptions, IDiffEditorConstructionOptions, IStandaloneCodeEditor, IStandaloneDiffEditor #include(vs/editor/standalone/browser/standaloneCodeEditor): IActionDescriptor, IStandaloneEditorConstructionOptions, IDiffEditorConstructionOptions, IStandaloneCodeEditor, IStandaloneDiffEditor
export interface ICommandHandler { export interface ICommandHandler {
(...args: any[]): void; (...args: any[]): void;
} }

View File

@@ -6,7 +6,7 @@
"git": { "git": {
"name": "chromium", "name": "chromium",
"repositoryUrl": "https://chromium.googlesource.com/chromium/src", "repositoryUrl": "https://chromium.googlesource.com/chromium/src",
"commitHash": "91f08db83c2ce8c722ddf0911ead8f7c473bedfa" "commitHash": "c6a08e5368de4352903e702cde750b33239a50ab"
} }
}, },
"licenseDetail": [ "licenseDetail": [
@@ -40,7 +40,7 @@
"SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
], ],
"isOnlyProductionDependency": true, "isOnlyProductionDependency": true,
"version": "76.0.3809.146" "version": "69.0.3497.128"
}, },
{ {
"component": { "component": {
@@ -48,11 +48,11 @@
"git": { "git": {
"name": "nodejs", "name": "nodejs",
"repositoryUrl": "https://github.com/nodejs/node", "repositoryUrl": "https://github.com/nodejs/node",
"commitHash": "64219741218aa87e259cf8257596073b8e747f0a" "commitHash": "8c70b2084ce5f76ea1e3b3c4ccdeee4483fe338b"
} }
}, },
"isOnlyProductionDependency": true, "isOnlyProductionDependency": true,
"version": "12.4.0" "version": "10.11.0"
}, },
{ {
"component": { "component": {
@@ -60,12 +60,12 @@
"git": { "git": {
"name": "electron", "name": "electron",
"repositoryUrl": "https://github.com/electron/electron", "repositoryUrl": "https://github.com/electron/electron",
"commitHash": "407747b48c47cdeed156a73dde1c47609470c95a" "commitHash": "4e4c7527c63fcf27dffaeb58bde996b8d859c0ed"
} }
}, },
"isOnlyProductionDependency": true, "isOnlyProductionDependency": true,
"license": "MIT", "license": "MIT",
"version": "6.0.9" "version": "4.2.10"
}, },
{ {
"component": { "component": {
@@ -98,11 +98,11 @@
"git": { "git": {
"name": "vscode-octicons-font", "name": "vscode-octicons-font",
"repositoryUrl": "https://github.com/Microsoft/vscode-octicons-font", "repositoryUrl": "https://github.com/Microsoft/vscode-octicons-font",
"commitHash": "415cd5b42ab699b6b46c0bf011ada0a2ae50bfb4" "commitHash": "4cbf2bd35cf0084eabd47d322cc58339fd7743cf"
} }
}, },
"license": "MIT", "license": "MIT",
"version": "1.3.1" "version": "1.3.2"
}, },
{ {
"component": { "component": {

View File

@@ -1268,7 +1268,7 @@ export class CommandCenter {
if (pick === saveAndCommit) { if (pick === saveAndCommit) {
await Promise.all(documents.map(d => d.save())); await Promise.all(documents.map(d => d.save()));
await repository.add(documents.map(d => d.uri)); await repository.add([]);
} else if (pick !== commit) { } else if (pick !== commit) {
return false; // do not commit on cancel return false; // do not commit on cancel
} }

View File

@@ -10,8 +10,8 @@ import { xhr, XHRResponse, getErrorStatusDescription } from 'request-light';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
import { workspace, window, languages, commands, ExtensionContext, extensions, Uri, LanguageConfiguration, Diagnostic, StatusBarAlignment, TextEditor } from 'vscode'; 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 } from 'vscode-languageclient'; import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification, HandleDiagnosticsSignature, ResponseError, DocumentRangeFormattingParams, DocumentRangeFormattingRequest } from 'vscode-languageclient';
import TelemetryReporter from 'vscode-extension-telemetry'; import TelemetryReporter from 'vscode-extension-telemetry';
import { hash } from './utils/hash'; import { hash } from './utils/hash';
@@ -65,6 +65,8 @@ export function activate(context: ExtensionContext) {
let toDispose = context.subscriptions; let toDispose = context.subscriptions;
let rangeFormatting: Disposable | undefined = undefined;
let packageInfo = getPackageInfo(context); let packageInfo = getPackageInfo(context);
telemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey); telemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
@@ -101,7 +103,8 @@ export function activate(context: ExtensionContext) {
// Register the server for json documents // Register the server for json documents
documentSelector, documentSelector,
initializationOptions: { initializationOptions: {
handledSchemaProtocols: ['file'] // language server only loads file-URI. Fetching schemas with other protocols ('http'...) are made on the client. handledSchemaProtocols: ['file'], // language server only loads file-URI. Fetching schemas with other protocols ('http'...) are made on the client.
provideFormatter: false // tell the server to not provide formatting capability and ignore the `json.format.enable` setting.
}, },
synchronize: { synchronize: {
// Synchronize the setting section 'json' to the server // Synchronize the setting section 'json' to the server
@@ -224,10 +227,13 @@ export function activate(context: ExtensionContext) {
extensions.onDidChange(_ => { extensions.onDidChange(_ => {
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context)); client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context));
}); });
// manually register / deregister format provider based on the `html.format.enable` setting avoiding issues with late registration. See #71652.
updateFormatterRegistration();
toDispose.push({ dispose: () => rangeFormatting && rangeFormatting.dispose() });
toDispose.push(workspace.onDidChangeConfiguration(e => e.affectsConfiguration('html.format.enable') && updateFormatterRegistration()));
}); });
let languageConfiguration: LanguageConfiguration = { let languageConfiguration: LanguageConfiguration = {
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/, wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
indentationRules: { indentationRules: {
@@ -237,8 +243,35 @@ export function activate(context: ExtensionContext) {
}; };
languages.setLanguageConfiguration('json', languageConfiguration); languages.setLanguageConfiguration('json', languageConfiguration);
languages.setLanguageConfiguration('jsonc', languageConfiguration); languages.setLanguageConfiguration('jsonc', languageConfiguration);
function updateFormatterRegistration() {
const formatEnabled = workspace.getConfiguration().get('json.format.enable');
if (!formatEnabled && rangeFormatting) {
rangeFormatting.dispose();
rangeFormatting = undefined;
} else if (formatEnabled && !rangeFormatting) {
rangeFormatting = languages.registerDocumentRangeFormattingEditProvider(documentSelector, {
provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
let params: DocumentRangeFormattingParams = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
range: client.code2ProtocolConverter.asRange(range),
options: client.code2ProtocolConverter.asFormattingOptions(options)
};
return client.sendRequest(DocumentRangeFormattingRequest.type, params, token).then(
client.protocol2CodeConverter.asTextEdits,
(error) => {
client.logFailedRequest(DocumentRangeFormattingRequest.type, error);
return Promise.resolve([]);
}
);
}
});
}
}
} }
export function deactivate(): Promise<any> { export function deactivate(): Promise<any> {
return telemetryReporter ? telemetryReporter.dispose() : Promise.resolve(null); return telemetryReporter ? telemetryReporter.dispose() : Promise.resolve(null);
} }
@@ -286,7 +319,6 @@ function getSettings(): Settings {
proxyStrictSSL: httpSettings.get('proxyStrictSSL') proxyStrictSSL: httpSettings.get('proxyStrictSSL')
}, },
json: { json: {
format: workspace.getConfiguration('json').get('format'),
schemas: [], schemas: [],
} }
}; };

View File

@@ -104,7 +104,7 @@
"dependencies": { "dependencies": {
"request-light": "^0.2.4", "request-light": "^0.2.4",
"vscode-extension-telemetry": "0.1.1", "vscode-extension-telemetry": "0.1.1",
"vscode-languageclient": "^5.3.0-next.6", "vscode-languageclient": "^6.0.0-next.1",
"vscode-nls": "^4.1.1" "vscode-nls": "^4.1.1"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -12,7 +12,7 @@ The JSON Language server provides language-specific smarts for editing, validati
The JSON language server supports requests on documents of language id `json` and `jsonc`. The JSON language server supports requests on documents of language id `json` and `jsonc`.
- `json` documents are parsed and validated following the [JSON specification](https://tools.ietf.org/html/rfc7159). - `json` documents are parsed and validated following the [JSON specification](https://tools.ietf.org/html/rfc7159).
- `jsonc` documents additionally accept single line (`//`) and multi-line comments (`/* ... */`) and accepts trailing commas. JSONC is a VSCode specific file format, intended for VSCode configuration files, without any aspirations to define a new common file format. - `jsonc` documents additionally accept single line (`//`) and multi-line comments (`/* ... */`). JSONC is a VSCode specific file format, intended for VSCode configuration files, without any aspirations to define a new common file format.
The server implements the following capabilities of the language server protocol: The server implements the following capabilities of the language server protocol:
@@ -40,6 +40,13 @@ The JSON language server has the following dependencies on the client's capabili
## Configuration ## Configuration
### Initialization options
The client can send the following initialization options to the server:
- `provideFormatter: boolean | undefined`. If defined, the value defines wheter the server provides the `documentRangeFormattingProvider` capability on initialization. If undefined, the setting `json.format.enable` is used to determined wheter formatting is provided. The formatter will then be registered through dynamic registration. If the client does not support dynamic registration, no formatter will be available.
- `handledSchemaProtocols`: The URI schemas handles by the server. See section `Schema configuration` below.
### Settings ### Settings
Clients may send a `workspace/didChangeConfiguration` notification to notify the server of settings changes. Clients may send a `workspace/didChangeConfiguration` notification to notify the server of settings changes.
@@ -51,7 +58,7 @@ The server supports the following settings:
- json - json
- `format` - `format`
- `enable`: Whether the server should register the formatting support. This option is only applicable if the client supports *dynamicRegistration* for *rangeFormatting* - `enable`: Whether the server should register the formatting support. This option is only applicable if the client supports *dynamicRegistration* for *rangeFormatting* and `initializationOptions.provideFormatter` is not defined.
- `schema`: Configures association of file names to schema URL or schemas and/or associations of schema URL to schema content. - `schema`: Configures association of file names to schema URL or schemas and/or associations of schema URL to schema content.
- `fileMatch`: an array or file names or paths (separated by `/`). `*` can be used as a wildcard. - `fileMatch`: an array or 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. - `url`: The URL of the schema, optional when also a schema is provided.

View File

@@ -14,8 +14,8 @@
"dependencies": { "dependencies": {
"jsonc-parser": "^2.1.1", "jsonc-parser": "^2.1.1",
"request-light": "^0.2.4", "request-light": "^0.2.4",
"vscode-json-languageservice": "^3.3.4", "vscode-json-languageservice": "^3.3.5",
"vscode-languageserver": "^5.3.0-next.8", "vscode-languageserver": "^6.0.0-next.1",
"vscode-nls": "^4.1.1", "vscode-nls": "^4.1.1",
"vscode-uri": "^2.0.3" "vscode-uri": "^2.0.3"
}, },

View File

@@ -114,7 +114,7 @@ const documents: TextDocuments = new TextDocuments();
documents.listen(connection); documents.listen(connection);
let clientSnippetSupport = false; let clientSnippetSupport = false;
let clientDynamicRegisterSupport = false; let dynamicFormatterRegistration = false;
let foldingRangeLimit = Number.MAX_VALUE; let foldingRangeLimit = Number.MAX_VALUE;
let hierarchicalDocumentSymbolSupport = false; let hierarchicalDocumentSymbolSupport = false;
@@ -144,7 +144,7 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
} }
clientSnippetSupport = getClientCapability('textDocument.completion.completionItem.snippetSupport', false); clientSnippetSupport = getClientCapability('textDocument.completion.completionItem.snippetSupport', false);
clientDynamicRegisterSupport = getClientCapability('workspace.symbol.dynamicRegistration', false); dynamicFormatterRegistration = getClientCapability('textDocument.rangeFormatting.dynamicRegistration', false) && (params.initializationOptions.provideFormatter === undefined);
foldingRangeLimit = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE); foldingRangeLimit = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE);
hierarchicalDocumentSymbolSupport = getClientCapability('textDocument.documentSymbol.hierarchicalDocumentSymbolSupport', false); hierarchicalDocumentSymbolSupport = getClientCapability('textDocument.documentSymbol.hierarchicalDocumentSymbolSupport', false);
const capabilities: ServerCapabilities = { const capabilities: ServerCapabilities = {
@@ -156,7 +156,8 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
documentRangeFormattingProvider: false, documentRangeFormattingProvider: false,
colorProvider: {}, colorProvider: {},
foldingRangeProvider: true, foldingRangeProvider: true,
selectionRangeProvider: true selectionRangeProvider: true,
documentFormattingProvider: params.initializationOptions.provideFormatter === true
}; };
return { capabilities }; return { capabilities };
@@ -195,7 +196,7 @@ connection.onDidChangeConfiguration((change) => {
updateConfiguration(); updateConfiguration();
// dynamically enable & disable the formatter // dynamically enable & disable the formatter
if (clientDynamicRegisterSupport) { if (dynamicFormatterRegistration) {
const enableFormatter = settings && settings.json && settings.json.format && settings.json.format.enable; const enableFormatter = settings && settings.json && settings.json.format && settings.json.format.enable;
if (enableFormatter) { if (enableFormatter) {
if (!formatterRegistration) { if (!formatterRegistration) {

View File

@@ -73,42 +73,41 @@ request-light@^0.2.4:
https-proxy-agent "^2.2.1" https-proxy-agent "^2.2.1"
vscode-nls "^4.0.0" vscode-nls "^4.0.0"
vscode-json-languageservice@^3.3.4: vscode-json-languageservice@^3.3.5:
version "3.3.4" version "3.3.5"
resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.3.4.tgz#4ff67580491d3a5dc469f4a78643f20adff0278d" resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.3.5.tgz#e222e8391beeb23cfa40cf17fd57d1594d295fc7"
integrity sha512-/nuI4uDBfxyVyeGtBdYwP/tIaXYKOoymUOSozYKLzsmrDmu555gZpzc11LrARa96z92wSaa5hfjTtNMAoM2mxw== integrity sha512-Le6SG5aRdrRc5jVeVMRkYbGH9rrVaZHCW0Oa8zCFQ0T8viUud9qdZ29lSv5NPNLwTB8mn4pYucFyyEPM2YWvLA==
dependencies: dependencies:
jsonc-parser "^2.1.1" jsonc-parser "^2.1.1"
vscode-languageserver-types "^3.15.0-next.2" vscode-languageserver-types "^3.15.0-next.5"
vscode-nls "^4.1.1" vscode-nls "^4.1.1"
vscode-uri "^2.0.3" vscode-uri "^2.0.3"
vscode-jsonrpc@^4.1.0-next.2: vscode-jsonrpc@^5.0.0-next.2:
version "4.1.0-next.2" version "5.0.0-next.2"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca"
integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg==
vscode-languageserver-protocol@^3.15.0-next.6: vscode-languageserver-protocol@^3.15.0-next.9:
version "3.15.0-next.6" version "3.15.0-next.9"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz#e768256bd5b580b25bfbc8099bc03bc4c42ebf30"
integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== integrity sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g==
dependencies: dependencies:
vscode-jsonrpc "^4.1.0-next.2" vscode-jsonrpc "^5.0.0-next.2"
vscode-languageserver-types "^3.15.0-next.2" vscode-languageserver-types "^3.15.0-next.5"
vscode-languageserver-types@^3.15.0-next.2: vscode-languageserver-types@^3.15.0-next.5:
version "3.15.0-next.2" version "3.15.0-next.5"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz#863d711bf47b338ff5e63ae19fb20d4fcd4d713b"
integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== integrity sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw==
vscode-languageserver@^5.3.0-next.8: vscode-languageserver@^6.0.0-next.1:
version "5.3.0-next.8" version "6.0.0-next.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-5.3.0-next.8.tgz#12a4adf60374dbb93e153e08bdca5525f9b2029f" resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-6.0.0-next.1.tgz#4d71886d4a17d22eafc61b3a5fbf84e8e27c191f"
integrity sha512-6vUb96wsRfrFqndril3gct/FBCSc24OxFZ2iz7kuEuXvLaIcEVOcSZIqQK8oFN7PdbAIaa9nnIpKSy4Yd15cIw== integrity sha512-LSF6bXoFeXfMPRNyqzI3yFX/kD2DzXBemqvyj1kDWNVraiWttm4xKF4YXsvJ7Z3s9sVt/Dpu3CFU3w61PGNZMg==
dependencies: dependencies:
vscode-languageserver-protocol "^3.15.0-next.6" vscode-languageserver-protocol "^3.15.0-next.9"
vscode-textbuffer "^1.0.0" vscode-textbuffer "^1.0.0"
vscode-uri "^1.0.6"
vscode-nls@^4.0.0: vscode-nls@^4.0.0:
version "4.0.0" version "4.0.0"
@@ -125,11 +124,6 @@ vscode-textbuffer@^1.0.0:
resolved "https://registry.yarnpkg.com/vscode-textbuffer/-/vscode-textbuffer-1.0.0.tgz#1faee638c8e0e4131c8d5c353993a1874acda086" resolved "https://registry.yarnpkg.com/vscode-textbuffer/-/vscode-textbuffer-1.0.0.tgz#1faee638c8e0e4131c8d5c353993a1874acda086"
integrity sha512-zPaHo4urgpwsm+PrJWfNakolRpryNja18SUip/qIIsfhuEqEIPEXMxHOlFPjvDC4JgTaimkncNW7UMXRJTY6ow== integrity sha512-zPaHo4urgpwsm+PrJWfNakolRpryNja18SUip/qIIsfhuEqEIPEXMxHOlFPjvDC4JgTaimkncNW7UMXRJTY6ow==
vscode-uri@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.6.tgz#6b8f141b0bbc44ad7b07e94f82f168ac7608ad4d"
integrity sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww==
vscode-uri@^2.0.3: vscode-uri@^2.0.3:
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.3.tgz#25e5f37f552fbee3cec7e5f80cef8469cefc6543"

View File

@@ -101,10 +101,10 @@ semver@^5.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==
semver@^5.5.0: semver@^6.3.0:
version "5.5.1" version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
vscode-extension-telemetry@0.1.1: vscode-extension-telemetry@0.1.1:
version "0.1.1" version "0.1.1"
@@ -113,31 +113,31 @@ vscode-extension-telemetry@0.1.1:
dependencies: dependencies:
applicationinsights "1.0.8" applicationinsights "1.0.8"
vscode-jsonrpc@^4.1.0-next.2: vscode-jsonrpc@^5.0.0-next.2:
version "4.1.0-next.2" version "5.0.0-next.2"
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.2.tgz#3bd318910a48e631742b290975386e3dae685be3" resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz#a44bc03f67069e53f8d8beb88b96c0cacbfefbca"
integrity sha512-GsBLjP9DxQ42yl1mW9GEIlnSc0+R8mfzhaebwmmTPEJjezD5SPoAo3DFrIAFZha9yvQ1nzZfZlhtVpGQmgxtXg== integrity sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg==
vscode-languageclient@^5.3.0-next.6: vscode-languageclient@^6.0.0-next.1:
version "5.3.0-next.6" version "6.0.0-next.1"
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-5.3.0-next.6.tgz#35e74882781158e8b111911c0953869d3df08777" resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.0.0-next.1.tgz#deca1743afd20da092e04e40ef73cedbbd978455"
integrity sha512-DxT8+gkenjCjJV6ArcP75/AQfx6HP6m6kHIbacPCpffMeoE1YMLKj6ZixA9J87yr0fMtBmqumLmDeGe7MIF2bw== integrity sha512-eJ9VjLFNINArgRzLbQ11YlWry7dM93GEODkQBXTRfrSypksiO9qSGr4SHhWgxxP26p4FRSpzc/17+N+Egnnchg==
dependencies: dependencies:
semver "^5.5.0" semver "^6.3.0"
vscode-languageserver-protocol "^3.15.0-next.6" vscode-languageserver-protocol "^3.15.0-next.9"
vscode-languageserver-protocol@^3.15.0-next.6: vscode-languageserver-protocol@^3.15.0-next.9:
version "3.15.0-next.6" version "3.15.0-next.9"
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.6.tgz#a8aeb7e7dd65da8216b386db59494cdfd3215d92" resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz#e768256bd5b580b25bfbc8099bc03bc4c42ebf30"
integrity sha512-/yDpYlWyNs26mM23mT73xmOFsh1iRfgZfBdHmfAxwDKwpQKLoOSqVidtYfxlK/pD3IEKGcAVnT4WXTsguxxAMQ== integrity sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g==
dependencies: dependencies:
vscode-jsonrpc "^4.1.0-next.2" vscode-jsonrpc "^5.0.0-next.2"
vscode-languageserver-types "^3.15.0-next.2" vscode-languageserver-types "^3.15.0-next.5"
vscode-languageserver-types@^3.15.0-next.2: vscode-languageserver-types@^3.15.0-next.5:
version "3.15.0-next.2" version "3.15.0-next.5"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz#a0601332cdaafac21931f497bb080cfb8d73f254" resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz#863d711bf47b338ff5e63ae19fb20d4fcd4d713b"
integrity sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ== integrity sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw==
vscode-nls@^4.0.0: vscode-nls@^4.0.0:
version "4.0.0" version "4.0.0"

View File

@@ -171,8 +171,7 @@
}, },
{ {
"scope": [ "scope": [
"meta.preprocessor", "meta.preprocessor"
"keyword.control.directive"
], ],
"settings": { "settings": {
"foreground": "#569cd6" "foreground": "#569cd6"

View File

@@ -169,8 +169,7 @@
}, },
{ {
"scope": [ "scope": [
"meta.preprocessor", "meta.preprocessor"
"keyword.control.directive"
], ],
"settings": { "settings": {
"foreground": "#0000ff" "foreground": "#0000ff"

View File

@@ -1,3 +1,3 @@
disturl "http://nodejs.org/dist" disturl "http://nodejs.org/dist"
target "12.4.0" target "10.11.0"
runtime "node" runtime "node"

View File

@@ -2,7 +2,7 @@
Name=@@NAME_LONG@@ - URL Handler Name=@@NAME_LONG@@ - URL Handler
Comment=Azure Data Studio Comment=Azure Data Studio
GenericName=Text Editor GenericName=Text Editor
Exec=@@EXEC@@ --no-sandbox --open-url %U Exec=@@EXEC@@ --open-url %U
Icon=@@ICON@@ Icon=@@ICON@@
Type=Application Type=Application
NoDisplay=true NoDisplay=true

View File

@@ -2,7 +2,7 @@
Name=@@NAME_LONG@@ Name=@@NAME_LONG@@
Comment=Data Management Tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux. Comment=Data Management Tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux.
GenericName=Text Editor GenericName=Text Editor
Exec=@@EXEC@@ --no-sandbox --unity-launch %F Exec=@@EXEC@@ --unity-launch %F
Icon=@@ICON@@ Icon=@@ICON@@
Type=Application Type=Application
StartupNotify=false StartupNotify=false
@@ -14,5 +14,5 @@ Keywords=azuredatastudio;
[Desktop Action new-empty-window] [Desktop Action new-empty-window]
Name=New Empty Window Name=New Empty Window
Exec=@@EXEC@@ --no-sandbox --new-window %F Exec=@@EXEC@@ --new-window %F
Icon=@@ICON@@ Icon=@@ICON@@

View File

@@ -8,7 +8,7 @@ if [[ "$OSTYPE" == "darwin"* ]]; then
else else
ROOT=$(dirname $(dirname $(readlink -f $0))) ROOT=$(dirname $(dirname $(readlink -f $0)))
VSCODEUSERDATADIR=`mktemp -d 2>/dev/null` VSCODEUSERDATADIR=`mktemp -d 2>/dev/null`
LINUX_NO_SANDBOX="--no-sandbox" # Electron 6 introduces a chrome-sandbox that requires root to run. This can fail. Disable sandbox via --no-sandbox. LINUX_NO_SANDBOX=""
fi fi
cd $ROOT cd $ROOT

View File

@@ -34,5 +34,5 @@ else
cd $ROOT ; \ cd $ROOT ; \
ELECTRON_ENABLE_LOGGING=1 \ ELECTRON_ENABLE_LOGGING=1 \
"$CODE" \ "$CODE" \
test/electron/index.js --no-sandbox "$@" # Electron 6 introduces a chrome-sandbox that requires root to run. This can fail. Disable sandbox via --no-sandbox. test/electron/index.js "$@"
fi fi

18
src/bootstrap.js vendored
View File

@@ -21,7 +21,6 @@ process.on('SIGPIPE', () => {
//#endregion //#endregion
//#region Add support for redirecting the loading of node modules //#region Add support for redirecting the loading of node modules
exports.injectNodeModuleLookupPath = function (injectPath) { exports.injectNodeModuleLookupPath = function (injectPath) {
if (!injectPath) { if (!injectPath) {
throw new Error('Missing injectPath'); throw new Error('Missing injectPath');
@@ -37,8 +36,10 @@ exports.injectNodeModuleLookupPath = function (injectPath) {
const originalResolveLookupPaths = Module._resolveLookupPaths; const originalResolveLookupPaths = Module._resolveLookupPaths;
// @ts-ignore // @ts-ignore
Module._resolveLookupPaths = function (moduleName, parent) { Module._resolveLookupPaths = function (moduleName, parent, newReturn) {
const paths = originalResolveLookupPaths(moduleName, parent); const result = originalResolveLookupPaths(moduleName, parent, newReturn);
const paths = newReturn ? result : result[1];
for (let i = 0, len = paths.length; i < len; i++) { for (let i = 0, len = paths.length; i < len; i++) {
if (paths[i] === nodeModulesPath) { if (paths[i] === nodeModulesPath) {
paths.splice(i, 0, injectPath); paths.splice(i, 0, injectPath);
@@ -46,7 +47,7 @@ exports.injectNodeModuleLookupPath = function (injectPath) {
} }
} }
return paths; return result;
}; };
}; };
//#endregion //#endregion
@@ -70,10 +71,11 @@ exports.enableASARSupport = function (nodeModulesPath) {
// @ts-ignore // @ts-ignore
const originalResolveLookupPaths = Module._resolveLookupPaths; const originalResolveLookupPaths = Module._resolveLookupPaths;
// @ts-ignore // @ts-ignore
Module._resolveLookupPaths = function (request, parent) { Module._resolveLookupPaths = function (request, parent, newReturn) {
const paths = originalResolveLookupPaths(request, parent); const result = originalResolveLookupPaths(request, parent, newReturn);
const paths = newReturn ? result : result[1];
for (let i = 0, len = paths.length; i < len; i++) { for (let i = 0, len = paths.length; i < len; i++) {
if (paths[i] === NODE_MODULES_PATH) { if (paths[i] === NODE_MODULES_PATH) {
paths.splice(i, 0, NODE_MODULES_ASAR_PATH); paths.splice(i, 0, NODE_MODULES_ASAR_PATH);
@@ -81,7 +83,7 @@ exports.enableASARSupport = function (nodeModulesPath) {
} }
} }
return paths; return result;
}; };
}; };
//#endregion //#endregion

View File

@@ -17,7 +17,7 @@ const paths = require('./paths');
// @ts-ignore // @ts-ignore
const product = require('../product.json'); const product = require('../product.json');
// @ts-ignore // @ts-ignore
const { app, protocol } = require('electron'); const app = require('electron').app;
// Enable portable support // Enable portable support
const portable = bootstrap.configurePortable(); const portable = bootstrap.configurePortable();
@@ -33,11 +33,6 @@ app.setPath('userData', userDataPath);
// Update cwd based on environment and platform // Update cwd based on environment and platform
setCurrentWorkingDirectory(); setCurrentWorkingDirectory();
// Register custom schemes with privileges
protocol.registerSchemesAsPrivileged([
{ scheme: 'vscode-resource', privileges: { secure: true, supportFetchAPI: true, corsEnabled: true } }
]);
// Global app listeners // Global app listeners
registerListeners(); registerListeners();

View File

@@ -0,0 +1,12 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AbstractEnablePreviewFeatures } from 'sql/workbench/common/enablePreviewFeatures';
export class BrowserEnablePreviewFeatures extends AbstractEnablePreviewFeatures {
protected async getWindowCount(): Promise<number> {
return 1;
}
}

View File

@@ -11,7 +11,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IHostService } from 'vs/workbench/services/host/browser/host';
export class EnablePreviewFeatures implements IWorkbenchContribution { export abstract class AbstractEnablePreviewFeatures implements IWorkbenchContribution {
private static ENABLE_PREVIEW_FEATURES_SHOWN = 'workbench.enablePreviewFeaturesShown'; private static ENABLE_PREVIEW_FEATURES_SHOWN = 'workbench.enablePreviewFeaturesShown';
@@ -22,12 +22,12 @@ export class EnablePreviewFeatures implements IWorkbenchContribution {
@IConfigurationService configurationService: IConfigurationService @IConfigurationService configurationService: IConfigurationService
) { ) {
let previewFeaturesEnabled = configurationService.getValue('workbench')['enablePreviewFeatures']; let previewFeaturesEnabled = configurationService.getValue('workbench')['enablePreviewFeatures'];
if (previewFeaturesEnabled || storageService.get(EnablePreviewFeatures.ENABLE_PREVIEW_FEATURES_SHOWN, StorageScope.GLOBAL)) { if (previewFeaturesEnabled || storageService.get(AbstractEnablePreviewFeatures.ENABLE_PREVIEW_FEATURES_SHOWN, StorageScope.GLOBAL)) {
return; return;
} }
Promise.all([ Promise.all([
hostService.hasFocus, hostService.hasFocus,
hostService.windowCount this.getWindowCount()
]).then(([focused, count]) => { ]).then(([focused, count]) => {
if (!focused && count > 1) { if (!focused && count > 1) {
return null; return null;
@@ -42,7 +42,7 @@ export class EnablePreviewFeatures implements IWorkbenchContribution {
label: localize('enablePreviewFeatures.yes', "Yes"), label: localize('enablePreviewFeatures.yes', "Yes"),
run: () => { run: () => {
configurationService.updateValue('workbench.enablePreviewFeatures', true); configurationService.updateValue('workbench.enablePreviewFeatures', true);
storageService.store(EnablePreviewFeatures.ENABLE_PREVIEW_FEATURES_SHOWN, true, StorageScope.GLOBAL); storageService.store(AbstractEnablePreviewFeatures.ENABLE_PREVIEW_FEATURES_SHOWN, true, StorageScope.GLOBAL);
} }
}, { }, {
label: localize('enablePreviewFeatures.no', "No"), label: localize('enablePreviewFeatures.no', "No"),
@@ -53,7 +53,7 @@ export class EnablePreviewFeatures implements IWorkbenchContribution {
label: localize('enablePreviewFeatures.never', "No, don't show again"), label: localize('enablePreviewFeatures.never', "No, don't show again"),
run: () => { run: () => {
configurationService.updateValue('workbench.enablePreviewFeatures', false); configurationService.updateValue('workbench.enablePreviewFeatures', false);
storageService.store(EnablePreviewFeatures.ENABLE_PREVIEW_FEATURES_SHOWN, true, StorageScope.GLOBAL); storageService.store(AbstractEnablePreviewFeatures.ENABLE_PREVIEW_FEATURES_SHOWN, true, StorageScope.GLOBAL);
}, },
isSecondary: true isSecondary: true
}] }]
@@ -61,4 +61,6 @@ export class EnablePreviewFeatures implements IWorkbenchContribution {
}) })
.then(null, onUnexpectedError); .then(null, onUnexpectedError);
} }
protected abstract getWindowCount(): Promise<number>;
} }

View File

@@ -0,0 +1,27 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AbstractEnablePreviewFeatures } from 'sql/workbench/common/enablePreviewFeatures';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IElectronService } from 'vs/platform/electron/node/electron';
export class NativeEnablePreviewFeatures extends AbstractEnablePreviewFeatures {
constructor(
@IStorageService storageService: IStorageService,
@INotificationService notificationService: INotificationService,
@IHostService hostService: IHostService,
@IConfigurationService configurationService: IConfigurationService,
@IElectronService private readonly electronService: IElectronService
) {
super(storageService, notificationService, hostService, configurationService);
}
protected getWindowCount(): Promise<number> {
return this.electronService.getWindowCount();
}
}

View File

@@ -138,7 +138,7 @@ registerAction({
await workspaceEditingService.addFolders(folders.map(folder => ({ uri: folder }))); await workspaceEditingService.addFolders(folders.map(folder => ({ uri: folder })));
await viewletService.openViewlet(viewletService.getDefaultViewletId(), true); await viewletService.openViewlet(viewletService.getDefaultViewletId(), true);
if (options.forceNewWindow) { if (options.forceNewWindow) {
return hostService.openInWindow([{ folderUri: folders[0] }], { forceNewWindow: options.forceNewWindow }); return hostService.openWindow([{ folderUri: folders[0] }], { forceNewWindow: options.forceNewWindow });
} }
else { else {
return hostService.reload(); return hostService.reload();

View File

@@ -4,10 +4,10 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { Registry } from 'vs/platform/registry/common/platform'; import { Registry } from 'vs/platform/registry/common/platform';
import { OpenWelcomePageInBrowser } from './openWebsite';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { BrowserEnablePreviewFeatures } from 'sql/workbench/browser/enablePreviewFeatures';
Registry Registry
.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench) .as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(OpenWelcomePageInBrowser, LifecyclePhase.Restored); .registerWorkbenchContribution(BrowserEnablePreviewFeatures, LifecyclePhase.Eventually);

View File

@@ -0,0 +1,13 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { NativeEnablePreviewFeatures } from 'sql/workbench/electron-browser/enablePreviewFeatures';
Registry
.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(NativeEnablePreviewFeatures, LifecyclePhase.Eventually);

View File

@@ -14,7 +14,7 @@
"./sql/azdata.d.ts", "./sql/azdata.d.ts",
"./sql/azdata.proposed.d.ts", "./sql/azdata.proposed.d.ts",
"./vs/base/**/*.ts", "./vs/base/**/*.ts",
"./vs/platform/**/*.ts", // "./vs/platform/**/*.ts",
"./sql/base/**/*.ts", "./sql/base/**/*.ts",
"./sql/editor/**/*.ts", "./sql/editor/**/*.ts",
"./sql/platform/angularEventing/**/*.ts", "./sql/platform/angularEventing/**/*.ts",

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
import { IMarkdownString, parseHrefAndDimensions, removeMarkdownEscapes } from 'vs/base/common/htmlContent'; import { IMarkdownString, parseHrefAndDimensions, removeMarkdownEscapes } from 'vs/base/common/htmlContent';
import { defaultGenerator } from 'vs/base/common/idGenerator'; import { defaultGenerator } from 'vs/base/common/idGenerator';
import * as marked from 'vs/base/common/marked/marked'; import * as marked from 'vs/base/common/marked/marked';
import * as insane from 'vs/base/common/insane/insane'; import { insane } from 'vs/base/common/insane/insane';
import { parse } from 'vs/base/common/marshalling'; import { parse } from 'vs/base/common/marshalling';
import { cloneAndChange } from 'vs/base/common/objects'; import { cloneAndChange } from 'vs/base/common/objects';
import { escape } from 'vs/base/common/strings'; import { escape } from 'vs/base/common/strings';

View File

@@ -152,34 +152,48 @@ export class StandardWheelEvent {
this.deltaX = deltaX; this.deltaX = deltaX;
if (e) { if (e) {
let e1 = <IWebKitMouseWheelEvent><any>e; if (e.type === 'wheel') {
let e2 = <IGeckoMouseWheelEvent><any>e;
// vertical delta scroll // Modern wheel event
if (typeof e1.wheelDeltaY !== 'undefined') { // https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent
this.deltaY = e1.wheelDeltaY / 120; const ev = <WheelEvent><unknown>e;
} else if (typeof e2.VERTICAL_AXIS !== 'undefined' && e2.axis === e2.VERTICAL_AXIS) {
this.deltaY = -e2.detail / 3;
} else {
this.deltaY = -e.deltaY / 40;
}
// horizontal delta scroll if (ev.deltaMode === ev.DOM_DELTA_LINE) {
if (typeof e1.wheelDeltaX !== 'undefined') { // the deltas are expressed in lines
if (browser.isSafari && platform.isWindows) { this.deltaY = -e.deltaY;
this.deltaX = - (e1.wheelDeltaX / 120); this.deltaX = -e.deltaX;
} else { } else {
this.deltaX = e1.wheelDeltaX / 120; this.deltaY = -e.deltaY / 40;
this.deltaX = -e.deltaX / 40;
} }
} else if (typeof e2.HORIZONTAL_AXIS !== 'undefined' && e2.axis === e2.HORIZONTAL_AXIS) {
this.deltaX = -e.detail / 3;
} else {
this.deltaX = -e.deltaX / 40;
}
// Assume a vertical scroll if nothing else worked } else {
if (this.deltaY === 0 && this.deltaX === 0 && e.wheelDelta) { // Old (deprecated) wheel events
this.deltaY = e.wheelDelta / 120; let e1 = <IWebKitMouseWheelEvent><any>e;
let e2 = <IGeckoMouseWheelEvent><any>e;
// vertical delta scroll
if (typeof e1.wheelDeltaY !== 'undefined') {
this.deltaY = e1.wheelDeltaY / 120;
} else if (typeof e2.VERTICAL_AXIS !== 'undefined' && e2.axis === e2.VERTICAL_AXIS) {
this.deltaY = -e2.detail / 3;
}
// horizontal delta scroll
if (typeof e1.wheelDeltaX !== 'undefined') {
if (browser.isSafari && platform.isWindows) {
this.deltaX = - (e1.wheelDeltaX / 120);
} else {
this.deltaX = e1.wheelDeltaX / 120;
}
} else if (typeof e2.HORIZONTAL_AXIS !== 'undefined' && e2.axis === e2.HORIZONTAL_AXIS) {
this.deltaX = -e.detail / 3;
}
// Assume a vertical scroll if nothing else worked
if (this.deltaY === 0 && this.deltaX === 0 && e.wheelDelta) {
this.deltaY = e.wheelDelta / 120;
}
} }
} }
} }

View File

@@ -86,15 +86,21 @@ export class Gesture extends Disposable {
this._register(DomUtils.addDisposableListener(document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e))); this._register(DomUtils.addDisposableListener(document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e)));
} }
public static addTarget(element: HTMLElement): void { public static addTarget(element: HTMLElement): IDisposable {
if (!Gesture.isTouchDevice()) { if (!Gesture.isTouchDevice()) {
return; return Disposable.None;
} }
if (!Gesture.INSTANCE) { if (!Gesture.INSTANCE) {
Gesture.INSTANCE = new Gesture(); Gesture.INSTANCE = new Gesture();
} }
Gesture.INSTANCE.targets.push(element); Gesture.INSTANCE.targets.push(element);
return {
dispose: () => {
Gesture.INSTANCE.targets = Gesture.INSTANCE.targets.filter(t => t !== element);
}
};
} }
@memoize @memoize

View File

@@ -103,7 +103,7 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
render(container: HTMLElement): void { render(container: HTMLElement): void {
this.element = container; this.element = container;
Gesture.addTarget(container); this._register(Gesture.addTarget(container));
const enableDragging = this.options && this.options.draggable; const enableDragging = this.options && this.options.draggable;
if (enableDragging) { if (enableDragging) {

View File

@@ -63,7 +63,7 @@ export class Button extends Disposable {
container.appendChild(this._element); container.appendChild(this._element);
Gesture.addTarget(this._element); this._register(Gesture.addTarget(this._element));
[DOM.EventType.CLICK, EventType.Tap].forEach(eventType => { [DOM.EventType.CLICK, EventType.Tap].forEach(eventType => {
this._register(DOM.addDisposableListener(this._element, eventType, e => { this._register(DOM.addDisposableListener(this._element, eventType, e => {

View File

@@ -83,7 +83,7 @@ export class BaseDropdown extends ActionRunner {
this._register(cleanupFn); this._register(cleanupFn);
} }
Gesture.addTarget(this._label); this._register(Gesture.addTarget(this._label));
} }
get element(): HTMLElement { get element(): HTMLElement {

View File

@@ -236,7 +236,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.rowsContainer = document.createElement('div'); this.rowsContainer = document.createElement('div');
this.rowsContainer.className = 'monaco-list-rows'; this.rowsContainer.className = 'monaco-list-rows';
Gesture.addTarget(this.rowsContainer); this.disposables.add(Gesture.addTarget(this.rowsContainer));
this.scrollableElement = this.disposables.add(new ScrollableElement(this.rowsContainer, { this.scrollableElement = this.disposables.add(new ScrollableElement(this.rowsContainer, {
alwaysConsumeMouseWheel: true, alwaysConsumeMouseWheel: true,

View File

@@ -542,7 +542,7 @@ export class MouseController<T> implements IDisposable {
list.onContextMenu(this.onContextMenu, this, this.disposables); list.onContextMenu(this.onContextMenu, this, this.disposables);
list.onMouseDblClick(this.onDoubleClick, this, this.disposables); list.onMouseDblClick(this.onDoubleClick, this, this.disposables);
list.onTouchStart(this.onMouseDown, this, this.disposables); list.onTouchStart(this.onMouseDown, this, this.disposables);
Gesture.addTarget(list.getHTMLElement()); this.disposables.add(Gesture.addTarget(list.getHTMLElement()));
} }
list.onMouseClick(this.onPointer, this, this.disposables); list.onMouseClick(this.onPointer, this, this.disposables);

View File

@@ -398,7 +398,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
EventHelper.stop(e, true); EventHelper.stop(e, true);
this.onClick(e); this.onClick(e);
})); }));
}, 50); }, 100);
this._register(this.runOnceToEnableMouseUp); this._register(this.runOnceToEnableMouseUp);
} }

View File

@@ -238,7 +238,7 @@ export class MenuBar extends Disposable {
} }
})); }));
Gesture.addTarget(buttonElement); this._register(Gesture.addTarget(buttonElement));
this._register(DOM.addDisposableListener(buttonElement, EventType.Tap, (e: GestureEvent) => { this._register(DOM.addDisposableListener(buttonElement, EventType.Tap, (e: GestureEvent) => {
// Ignore this touch if the menu is touched // Ignore this touch if the menu is touched
if (this.isOpen && this.focusedMenu && this.focusedMenu.holder && DOM.isAncestor(e.initialTarget as HTMLElement, this.focusedMenu.holder)) { if (this.isOpen && this.focusedMenu && this.focusedMenu.holder && DOM.isAncestor(e.initialTarget as HTMLElement, this.focusedMenu.holder)) {
@@ -322,7 +322,7 @@ export class MenuBar extends Disposable {
} }
})); }));
Gesture.addTarget(buttonElement); this._register(Gesture.addTarget(buttonElement));
this._register(DOM.addDisposableListener(buttonElement, EventType.Tap, (e: GestureEvent) => { this._register(DOM.addDisposableListener(buttonElement, EventType.Tap, (e: GestureEvent) => {
// Ignore this touch if the menu is touched // Ignore this touch if the menu is touched
if (this.isOpen && this.focusedMenu && this.focusedMenu.holder && DOM.isAncestor(e.initialTarget as HTMLElement, this.focusedMenu.holder)) { if (this.isOpen && this.focusedMenu && this.focusedMenu.holder && DOM.isAncestor(e.initialTarget as HTMLElement, this.focusedMenu.holder)) {

View File

@@ -1,6 +1,6 @@
@font-face { @font-face {
font-family: "octicons"; font-family: "octicons";
src: url("./octicons.ttf?628f71ee09945d25ba5fceb0c17f7b0f") format("truetype"); src: url("./octicons.ttf?1829db8570ee0fa5a4bef3bb41d5f62e") format("truetype");
} }
.octicon, .mega-octicon { .octicon, .mega-octicon {

View File

@@ -139,7 +139,7 @@ export class Sash extends Disposable {
this._register(domEvent(this.el, 'mousedown')(this.onMouseDown, this)); this._register(domEvent(this.el, 'mousedown')(this.onMouseDown, this));
this._register(domEvent(this.el, 'dblclick')(this.onMouseDoubleClick, this)); this._register(domEvent(this.el, 'dblclick')(this.onMouseDoubleClick, this));
Gesture.addTarget(this.el); this._register(Gesture.addTarget(this.el));
this._register(domEvent(this.el, EventType.Start)(this.onTouchStart, this)); this._register(domEvent(this.el, EventType.Start)(this.onTouchStart, this));
if (isIPad) { if (isIPad) {

View File

@@ -23,7 +23,10 @@ export class MarkdownString implements IMarkdownString {
appendText(value: string): MarkdownString { appendText(value: string): MarkdownString {
// escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
this.value += value.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&'); this.value += value
.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&')
.replace('\n', '\n\n');
return this; return this;
} }

View File

@@ -3,11 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
export as namespace insane; export function insane(
export = insane;
declare function insane(
html: string, html: string,
options?: { options?: {
readonly allowedSchemes?: readonly string[], readonly allowedSchemes?: readonly string[],
@@ -16,5 +12,3 @@ declare function insane(
}, },
strict?: boolean, strict?: boolean,
): string; ): string;
declare namespace insane { }

View File

@@ -21,11 +21,7 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
// ESM-comment-begin let __insane_func;
let __insane_exports;
// ESM-comment-end
(function () { function r(e, n, t) { function o(i, f) { if (!n[i]) { if (!e[i]) { var c = "function" == typeof require && require; if (!f && c) return c(i, !0); if (u) return u(i, !0); var a = new Error("Cannot find module '" + i + "'"); throw a.code = "MODULE_NOT_FOUND", a } var p = n[i] = { exports: {} }; e[i][0].call(p.exports, function (r) { var n = e[i][1][r]; return o(n || r) }, p, p.exports, r, e, n, t) } return n[i].exports } for (var u = "function" == typeof require && require, i = 0; i < t.length; i++)o(t[i]); return o } return r })()({ (function () { function r(e, n, t) { function o(i, f) { if (!n[i]) { if (!e[i]) { var c = "function" == typeof require && require; if (!f && c) return c(i, !0); if (u) return u(i, !0); var a = new Error("Cannot find module '" + i + "'"); throw a.code = "MODULE_NOT_FOUND", a } var p = n[i] = { exports: {} }; e[i][0].call(p.exports, function (r) { var n = e[i][1][r]; return o(n || r) }, p, p.exports, r, e, n, t) } return n[i].exports } for (var u = "function" == typeof require && require, i = 0; i < t.length; i++)o(t[i]); return o } return r })()({
1: [function (require, module, exports) { 1: [function (require, module, exports) {
@@ -92,7 +88,7 @@ let __insane_exports;
insane.defaults = defaults; insane.defaults = defaults;
module.exports = insane; module.exports = insane;
__insane_exports = insane; __insane_func = insane;
}, { "./defaults": 2, "./parser": 7, "./sanitizer": 8, "assignment": 6, "he": 9 }], 5: [function (require, module, exports) { }, { "./defaults": 2, "./parser": 7, "./sanitizer": 8, "assignment": 6, "he": 9 }], 5: [function (require, module, exports) {
'use strict'; 'use strict';
@@ -469,10 +465,10 @@ let __insane_exports;
}, {}] }, {}]
}, {}, [4]); }, {}, [4]);
// BEGIN MONACOCHANGE
// __marked_exports = marked;
// }).call(this);
// ESM-comment-begin // ESM-comment-begin
define(function() { return __insane_exports; }); define(function() { return { insane: __insane_func }; });
// ESM-comment-end // ESM-comment-end
// ESM-uncomment-begin
// export var insane = __insane_func;
// ESM-uncomment-end

View File

@@ -92,7 +92,10 @@ class RemoteAuthoritiesImpl {
return this._delegate(uri); return this._delegate(uri);
} }
const authority = uri.authority; const authority = uri.authority;
const host = this._hosts[authority]; let host = this._hosts[authority];
if (host.indexOf(':') !== -1) {
host = `[${host}]`;
}
const port = this._ports[authority]; const port = this._ports[authority];
const connectionToken = this._connectionTokens[authority]; const connectionToken = this._connectionTokens[authority];
return URI.from({ return URI.from({

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { Menu, MenuItem, BrowserWindow, ipcMain, IpcMainEvent } from 'electron'; import { Menu, MenuItem, BrowserWindow, ipcMain, Event as IpcMainEvent } from 'electron';
import { ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_CHANNEL, IPopupOptions } from 'vs/base/parts/contextmenu/common/contextmenu'; import { ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_CHANNEL, IPopupOptions } from 'vs/base/parts/contextmenu/common/contextmenu';
export function registerContextMenuListener(): void { export function registerContextMenuListener(): void {

View File

@@ -437,6 +437,7 @@ export class TreeView extends HeightMap {
private shouldInvalidateDropReaction: boolean; private shouldInvalidateDropReaction: boolean;
private currentDropTargets: ViewItem[] | null = null; private currentDropTargets: ViewItem[] | null = null;
private currentDropDisposable: Lifecycle.IDisposable = Lifecycle.Disposable.None; private currentDropDisposable: Lifecycle.IDisposable = Lifecycle.Disposable.None;
private gestureDisposable: Lifecycle.IDisposable = Lifecycle.Disposable.None;
private dragAndDropScrollInterval: number | null = null; private dragAndDropScrollInterval: number | null = null;
private dragAndDropScrollTimeout: number | null = null; private dragAndDropScrollTimeout: number | null = null;
private dragAndDropMouseY: number | null = null; private dragAndDropMouseY: number | null = null;
@@ -523,7 +524,7 @@ export class TreeView extends HeightMap {
this.wrapper.style.msTouchAction = 'none'; this.wrapper.style.msTouchAction = 'none';
this.wrapper.style.msContentZooming = 'none'; this.wrapper.style.msContentZooming = 'none';
} else { } else {
Touch.Gesture.addTarget(this.wrapper); this.gestureDisposable = Touch.Gesture.addTarget(this.wrapper);
} }
this.rowsContainer = document.createElement('div'); this.rowsContainer = document.createElement('div');
@@ -1681,6 +1682,7 @@ export class TreeView extends HeightMap {
if (this.context.cache) { if (this.context.cache) {
this.context.cache.dispose(); this.context.cache.dispose();
} }
this.gestureDisposable.dispose();
super.dispose(); super.dispose();
} }

View File

@@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------------------------
* 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 { MarkdownString } from 'vs/base/common/htmlContent';
suite('markdownString', () => {
test('escape', () => {
const mds = new MarkdownString();
mds.appendText('# foo\n*bar*');
assert.equal(mds.value, '\\# foo\n\n\\*bar\\*');
});
});

View File

@@ -27,6 +27,7 @@ function getWorker(workerId: string, label: string): Worker | Promise<Worker> {
throw new Error(`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`); throw new Error(`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`);
} }
// ESM-comment-begin
export function getWorkerBootstrapUrl(scriptPath: string, label: string): string { export function getWorkerBootstrapUrl(scriptPath: string, label: string): string {
if (/^(http:)|(https:)|(file:)/.test(scriptPath)) { if (/^(http:)|(https:)|(file:)/.test(scriptPath)) {
const currentUrl = String(window.location); const currentUrl = String(window.location);
@@ -43,6 +44,7 @@ export function getWorkerBootstrapUrl(scriptPath: string, label: string): string
} }
return scriptPath + '#' + label; return scriptPath + '#' + label;
} }
// ESM-comment-end
function isPromiseLike<T>(obj: any): obj is PromiseLike<T> { function isPromiseLike<T>(obj: any): obj is PromiseLike<T> {
if (typeof obj.then === 'function') { if (typeof obj.then === 'function') {

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, IpcMainEvent } from 'electron'; import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, Event as IpcMainEvent, BrowserWindow } from 'electron';
import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform'; import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform';
import { WindowsManager } from 'vs/code/electron-main/windows'; import { WindowsManager } from 'vs/code/electron-main/windows';
import { OpenContext, IWindowOpenable } from 'vs/platform/windows/common/windows'; import { OpenContext, IWindowOpenable } from 'vs/platform/windows/common/windows';
@@ -78,6 +78,8 @@ import { IElectronService } from 'vs/platform/electron/node/electron';
import { ElectronMainService } from 'vs/platform/electron/electron-main/electronMainService'; import { ElectronMainService } from 'vs/platform/electron/electron-main/electronMainService';
import { ISharedProcessMainService, SharedProcessMainService } from 'vs/platform/ipc/electron-main/sharedProcessMainService'; import { ISharedProcessMainService, SharedProcessMainService } from 'vs/platform/ipc/electron-main/sharedProcessMainService';
import { assign } from 'vs/base/common/objects'; import { assign } from 'vs/base/common/objects';
import { IDialogMainService, DialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
import { withNullAsUndefined } from 'vs/base/common/types';
export class CodeApplication extends Disposable { export class CodeApplication extends Disposable {
@@ -85,6 +87,7 @@ export class CodeApplication extends Disposable {
private static readonly TRUE_MACHINE_ID_KEY = 'telemetry.trueMachineId'; private static readonly TRUE_MACHINE_ID_KEY = 'telemetry.trueMachineId';
private windowsMainService: IWindowsMainService | undefined; private windowsMainService: IWindowsMainService | undefined;
private dialogMainService: IDialogMainService | undefined;
constructor( constructor(
private readonly mainIpcServer: Server, private readonly mainIpcServer: Server,
@@ -381,8 +384,7 @@ export class CodeApplication extends Disposable {
} }
// Setup Auth Handler // Setup Auth Handler
const authHandler = appInstantiationService.createInstance(ProxyAuthHandler); this._register(new ProxyAuthHandler());
this._register(authHandler);
// Open Windows // Open Windows
const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor, electronIpcServer, sharedProcessClient)); const windows = appInstantiationService.invokeFunction(accessor => this.openFirstWindow(accessor, electronIpcServer, sharedProcessClient));
@@ -449,6 +451,7 @@ export class CodeApplication extends Disposable {
} }
services.set(IWindowsMainService, new SyncDescriptor(WindowsManager, [machineId, this.userEnv])); services.set(IWindowsMainService, new SyncDescriptor(WindowsManager, [machineId, this.userEnv]));
services.set(IDialogMainService, new SyncDescriptor(DialogMainService));
services.set(ISharedProcessMainService, new SyncDescriptor(SharedProcessMainService, [sharedProcess])); services.set(ISharedProcessMainService, new SyncDescriptor(SharedProcessMainService, [sharedProcess]));
services.set(ILaunchMainService, new SyncDescriptor(LaunchMainService)); services.set(ILaunchMainService, new SyncDescriptor(LaunchMainService));
@@ -503,13 +506,13 @@ export class CodeApplication extends Disposable {
contentTracing.stopRecording(join(homedir(), `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`), path => { contentTracing.stopRecording(join(homedir(), `${product.applicationName}-${Math.random().toString(16).slice(-4)}.trace.txt`), path => {
if (!timeout) { if (!timeout) {
if (this.windowsMainService) { if (this.dialogMainService) {
this.windowsMainService.showMessageBox({ this.dialogMainService.showMessageBox({
type: 'info', type: 'info',
message: localize('trace.message', "Successfully created trace."), message: localize('trace.message', "Successfully created trace."),
detail: localize('trace.detail', "Please create an issue and manually attach the following file:\n{0}", path), detail: localize('trace.detail', "Please create an issue and manually attach the following file:\n{0}", path),
buttons: [localize('trace.ok', "Ok")] buttons: [localize('trace.ok', "Ok")]
}, this.windowsMainService.getLastActiveWindow()); }, withNullAsUndefined(BrowserWindow.getFocusedWindow()));
} }
} else { } else {
this.logService.info(`Tracing: data recorded (after 30s timeout) to ${path}`); this.logService.info(`Tracing: data recorded (after 30s timeout) to ${path}`);
@@ -580,6 +583,7 @@ export class CodeApplication extends Disposable {
// Propagate to clients // Propagate to clients
const windowsMainService = this.windowsMainService = accessor.get(IWindowsMainService); const windowsMainService = this.windowsMainService = accessor.get(IWindowsMainService);
this.dialogMainService = accessor.get(IDialogMainService);
// Create a URL handler to open file URIs in the active window // Create a URL handler to open file URIs in the active window
const environmentService = accessor.get(IEnvironmentService); const environmentService = accessor.get(IEnvironmentService);

View File

@@ -4,8 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
import { Event } from 'vs/base/common/event'; import { Event } from 'vs/base/common/event';
import { BrowserWindow, app, AuthInfo, WebContents, Event as ElectronEvent } from 'electron'; import { BrowserWindow, app, AuthInfo, WebContents, Event as ElectronEvent } from 'electron';
@@ -22,18 +21,21 @@ type Credentials = {
password: string; password: string;
}; };
export class ProxyAuthHandler { export class ProxyAuthHandler extends Disposable {
_serviceBrand: undefined; _serviceBrand: undefined;
private retryCount = 0; private retryCount = 0;
private disposables: IDisposable[] = [];
constructor( constructor() {
@IWindowsMainService private readonly windowsMainService: IWindowsMainService super();
) {
this.registerListeners();
}
private registerListeners(): void {
const onLogin = Event.fromNodeEventEmitter<LoginEvent>(app, 'login', (event, webContents, req, authInfo, cb) => ({ event, webContents, req, authInfo, cb })); const onLogin = Event.fromNodeEventEmitter<LoginEvent>(app, 'login', (event, webContents, req, authInfo, cb) => ({ event, webContents, req, authInfo, cb }));
onLogin(this.onLogin, this, this.disposables); this._register(onLogin(this.onLogin, this));
} }
private onLogin({ event, authInfo, cb }: LoginEvent): void { private onLogin({ event, authInfo, cb }: LoginEvent): void {
@@ -61,10 +63,9 @@ export class ProxyAuthHandler {
} }
}; };
const focusedWindow = this.windowsMainService.getFocusedWindow(); const focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow) { if (focusedWindow) {
opts.parent = focusedWindow.win; opts.parent = focusedWindow;
opts.modal = true; opts.modal = true;
} }
@@ -89,8 +90,4 @@ export class ProxyAuthHandler {
win.close(); win.close();
}); });
} }
dispose(): void {
this.disposables = dispose(this.disposables);
}
} }

View File

@@ -7,7 +7,7 @@ import { assign } from 'vs/base/common/objects';
import { memoize } from 'vs/base/common/decorators'; import { memoize } from 'vs/base/common/decorators';
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { BrowserWindow, ipcMain } from 'electron'; import { BrowserWindow, ipcMain } from 'electron';
import { ISharedProcess } from 'vs/platform/windows/electron-main/windows'; import { ISharedProcess } from 'vs/platform/ipc/electron-main/sharedProcessMainService';
import { Barrier } from 'vs/base/common/async'; import { Barrier } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';

View File

@@ -561,7 +561,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
autoDetectHighContrast = false; autoDetectHighContrast = false;
} }
windowConfiguration.highContrast = isWindows && autoDetectHighContrast && systemPreferences.isInvertedColorScheme(); windowConfiguration.highContrast = isWindows && autoDetectHighContrast && systemPreferences.isInvertedColorScheme();
windowConfiguration.accessibilitySupport = app.accessibilitySupportEnabled; windowConfiguration.accessibilitySupport = app.isAccessibilitySupportEnabled();
// Title style related // Title style related
windowConfiguration.maximized = this._win.isMaximized(); windowConfiguration.maximized = this._win.isMaximized();

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as fs from 'fs'; import * as fs from 'fs';
import { basename, normalize, join, dirname } from 'vs/base/common/path'; import { basename, normalize, join, } from 'vs/base/common/path';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import * as arrays from 'vs/base/common/arrays'; import * as arrays from 'vs/base/common/arrays';
import { assign, mixin } from 'vs/base/common/objects'; import { assign, mixin } from 'vs/base/common/objects';
@@ -13,34 +13,36 @@ import { IEmptyWindowBackupInfo } from 'vs/platform/backup/node/backup';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { IStateService } from 'vs/platform/state/node/state'; import { IStateService } from 'vs/platform/state/node/state';
import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window'; import { CodeWindow, defaultWindowState } from 'vs/code/electron-main/window';
import { ipcMain as ipc, screen, BrowserWindow, dialog, systemPreferences, FileFilter, shell, MessageBoxReturnValue, MessageBoxOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, Display } from 'electron'; import { ipcMain as ipc, screen, BrowserWindow, systemPreferences, MessageBoxOptions, Display } from 'electron';
import { parseLineAndColumnAware } from 'vs/code/node/paths'; import { parseLineAndColumnAware } from 'vs/code/node/paths';
import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILifecycleMainService, UnloadReason, LifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, IPathsToWaitFor, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { IWindowSettings, OpenContext, IPath, IWindowConfiguration, IPathsToWaitFor, isFileToOpen, isWorkspaceToOpen, isFolderToOpen, IWindowOpenable, IOpenEmptyWindowOptions, IAddFoldersRequest } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs';
import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri } from 'vs/code/node/windowsFinder'; import { getLastActiveWindow, findBestWindowOrFolderForFile, findWindowOnWorkspace, findWindowOnExtensionDevelopmentPath, findWindowOnWorkspaceOrFolderUri } from 'vs/platform/windows/node/window';
import { Event as CommonEvent, Emitter } from 'vs/base/common/event'; import { Event as CommonEvent, Emitter } from 'vs/base/common/event';
import product from 'vs/platform/product/common/product'; import product from 'vs/platform/product/common/product';
import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService, ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows'; import { IWindowsMainService, IOpenConfiguration, IWindowsCountChangedEvent, ICodeWindow, IWindowState as ISingleWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows';
import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService'; import { IWorkspacesHistoryMainService } from 'vs/platform/workspaces/electron-main/workspacesHistoryMainService';
import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform'; import { IProcessEnvironment, isMacintosh, isWindows } from 'vs/base/common/platform';
import { IWorkspaceIdentifier, WORKSPACE_FILTER, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension, IEnterWorkspaceResult, IRecent } from 'vs/platform/workspaces/common/workspaces'; import { IWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, hasWorkspaceFileExtension, IRecent } from 'vs/platform/workspaces/common/workspaces';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { mnemonicButtonLabel } from 'vs/base/common/labels'; import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { Schemas } from 'vs/base/common/network'; import { Schemas } from 'vs/base/common/network';
import { normalizeNFC } from 'vs/base/common/normalization';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { Queue } from 'vs/base/common/async'; import { dirExists } from 'vs/base/node/pfs';
import { exists, dirExists } from 'vs/base/node/pfs'; import { getComparisonKey, isEqual, normalizePath, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources';
import { getComparisonKey, isEqual, normalizePath, basename as resourcesBasename, originalFSPath, hasTrailingPathSeparator, removeTrailingPathSeparator } from 'vs/base/common/resources';
import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts';
import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage'; import { restoreWindowsState, WindowsStateStorageData, getWindowsStateStoreData } from 'vs/code/electron-main/windowsStateStorage';
import { getWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService'; import { getWorkspaceIdentifier, IWorkspacesMainService } from 'vs/platform/workspaces/electron-main/workspacesMainService';
import { once } from 'vs/base/common/functional'; import { once } from 'vs/base/common/functional';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
import { withNullAsUndefined } from 'vs/base/common/types';
import { isWindowsDriveLetter, toSlashes } from 'vs/base/common/extpath';
import { CharCode } from 'vs/base/common/charCode';
const enum WindowError { const enum WindowError {
UNRESPONSIVE = 1, UNRESPONSIVE = 1,
@@ -167,9 +169,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
private readonly windowsState: IWindowsState; private readonly windowsState: IWindowsState;
private lastClosedWindowState?: IWindowState; private lastClosedWindowState?: IWindowState;
private readonly dialogs: Dialogs;
private readonly workspacesManager: WorkspacesManager;
private readonly _onWindowReady = this._register(new Emitter<ICodeWindow>()); private readonly _onWindowReady = this._register(new Emitter<ICodeWindow>());
readonly onWindowReady: CommonEvent<ICodeWindow> = this._onWindowReady.event; readonly onWindowReady: CommonEvent<ICodeWindow> = this._onWindowReady.event;
@@ -194,7 +193,8 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
@IConfigurationService private readonly configurationService: IConfigurationService, @IConfigurationService private readonly configurationService: IConfigurationService,
@IWorkspacesHistoryMainService private readonly workspacesHistoryMainService: IWorkspacesHistoryMainService, @IWorkspacesHistoryMainService private readonly workspacesHistoryMainService: IWorkspacesHistoryMainService,
@IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService, @IWorkspacesMainService private readonly workspacesMainService: IWorkspacesMainService,
@IInstantiationService private readonly instantiationService: IInstantiationService @IInstantiationService private readonly instantiationService: IInstantiationService,
@IDialogMainService private readonly dialogMainService: IDialogMainService
) { ) {
super(); super();
@@ -203,9 +203,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
this.windowsState.openedWindows = []; this.windowsState.openedWindows = [];
} }
this.dialogs = new Dialogs(stateService, this);
this.workspacesManager = new WorkspacesManager(workspacesMainService, backupMainService, this);
this.lifecycleMainService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners()); this.lifecycleMainService.when(LifecycleMainPhase.Ready).then(() => this.registerListeners());
this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen).then(() => this.installWindowsMutex()); this.lifecycleMainService.when(LifecycleMainPhase.AfterWindowOpen).then(() => this.installWindowsMutex());
} }
@@ -260,6 +257,11 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
this.lastClosedWindowState = undefined; this.lastClosedWindowState = undefined;
} }
}); });
// Signal a window is ready after having entered a workspace
this._register(this.workspacesMainService.onWorkspaceEntered(event => {
this._onWindowReady.fire(event.window);
}));
} }
// Note that onBeforeShutdown() and onBeforeWindowClose() are fired in different order depending on the OS: // Note that onBeforeShutdown() and onBeforeWindowClose() are fired in different order depending on the OS:
@@ -380,12 +382,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
}; };
} }
async openExternal(url: string): Promise<boolean> {
shell.openExternal(url);
return true;
}
open(openConfig: IOpenConfiguration): ICodeWindow[] { open(openConfig: IOpenConfiguration): ICodeWindow[] {
this.logService.trace('windowsManager#open'); this.logService.trace('windowsManager#open');
openConfig = this.validateOpenConfig(openConfig); openConfig = this.validateOpenConfig(openConfig);
@@ -776,7 +772,9 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
private doAddFoldersToExistingWindow(window: ICodeWindow, foldersToAdd: URI[]): ICodeWindow { private doAddFoldersToExistingWindow(window: ICodeWindow, foldersToAdd: URI[]): ICodeWindow {
window.focus(); // make sure window has focus window.focus(); // make sure window has focus
window.sendWhenReady('vscode:addFolders', { foldersToAdd }); const request: IAddFoldersRequest = { foldersToAdd };
window.sendWhenReady('vscode:addFolders', request);
return window; return window;
} }
@@ -862,7 +860,8 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
path.label = pathToOpen.label; path.label = pathToOpen.label;
pathsToOpen.push(path); pathsToOpen.push(path);
} else { } else {
const uri = resourceFromURIToOpen(pathToOpen); const uri = this.resourceFromURIToOpen(pathToOpen);
// Warn about the invalid URI or path // Warn about the invalid URI or path
let message, detail; let message, detail;
if (uri.scheme === Schemas.file) { if (uri.scheme === Schemas.file) {
@@ -881,7 +880,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
noLink: true noLink: true
}; };
this.dialogs.showMessageBox(options, this.getFocusedWindow()); this.dialogMainService.showMessageBox(options, withNullAsUndefined(BrowserWindow.getFocusedWindow()));
} }
} }
return pathsToOpen; return pathsToOpen;
@@ -1011,10 +1010,12 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
this.logService.error(`Invalid URI input string, scheme missing: ${arg}`); this.logService.error(`Invalid URI input string, scheme missing: ${arg}`);
return undefined; return undefined;
} }
return uri; return uri;
} catch (e) { } catch (e) {
this.logService.error(`Invalid URI input string: ${arg}, ${e.message}`); this.logService.error(`Invalid URI input string: ${arg}, ${e.message}`);
} }
return undefined; return undefined;
} }
@@ -1023,7 +1024,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
return undefined; return undefined;
} }
let uri = resourceFromURIToOpen(toOpen); let uri = this.resourceFromURIToOpen(toOpen);
if (uri.scheme === Schemas.file) { if (uri.scheme === Schemas.file) {
return this.parsePath(uri.fsPath, options, isFileToOpen(toOpen)); return this.parsePath(uri.fsPath, options, isFileToOpen(toOpen));
} }
@@ -1050,6 +1051,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
remoteAuthority remoteAuthority
}; };
} }
return { return {
fileUri: uri, fileUri: uri,
remoteAuthority remoteAuthority
@@ -1071,6 +1073,18 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
}; };
} }
private resourceFromURIToOpen(openable: IWindowOpenable): URI {
if (isWorkspaceToOpen(openable)) {
return openable.workspaceUri;
}
if (isFolderToOpen(openable)) {
return openable.folderUri;
}
return openable.fileUri;
}
private parsePath(anyPath: string, options: IPathParseOptions, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined { private parsePath(anyPath: string, options: IPathParseOptions, forceOpenWorkspaceAsFile?: boolean): IPathToOpen | undefined {
if (!anyPath) { if (!anyPath) {
return undefined; return undefined;
@@ -1086,11 +1100,36 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
anyPath = parsedPath.path; anyPath = parsedPath.path;
} }
// open remote if either specified in the cli even if it is a local file. TODO@aeschli: Future idea: resolve in remote host context. // open remote if either specified in the cli even if it is a local file.
const remoteAuthority = options.remoteAuthority; const remoteAuthority = options.remoteAuthority;
const candidate = normalize(anyPath); if (remoteAuthority) {
// assume it's a folder or workspace file
const first = anyPath.charCodeAt(0);
// make absolute
if (first !== CharCode.Slash) {
if (isWindowsDriveLetter(first) && anyPath.charCodeAt(anyPath.charCodeAt(1)) === CharCode.Colon) {
anyPath = toSlashes(anyPath);
}
anyPath = '/' + anyPath;
}
const uri = URI.from({ scheme: Schemas.vscodeRemote, authority: remoteAuthority, path: anyPath });
if (hasWorkspaceFileExtension(anyPath)) {
if (forceOpenWorkspaceAsFile) {
return { fileUri: uri, remoteAuthority };
}
return { workspace: getWorkspaceIdentifier(uri), remoteAuthority };
}
return { folderUri: uri, remoteAuthority };
}
let candidate = normalize(anyPath);
try { try {
const candidateStat = fs.statSync(candidate); const candidateStat = fs.statSync(candidate);
if (candidateStat.isFile()) { if (candidateStat.isFile()) {
@@ -1185,7 +1224,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
return { openFolderInNewWindow: !!openFolderInNewWindow, openFilesInNewWindow }; return { openFolderInNewWindow: !!openFolderInNewWindow, openFilesInNewWindow };
} }
openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): void { openExtensionDevelopmentHostWindow(extensionDevelopmentPath: string[], openConfig: IOpenConfiguration): ICodeWindow[] {
// Reload an existing extension development host window on the same path // Reload an existing extension development host window on the same path
// We currently do not allow more than one extension development window // We currently do not allow more than one extension development window
@@ -1195,7 +1234,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
this.reload(existingWindow, openConfig.cli); this.reload(existingWindow, openConfig.cli);
existingWindow.focus(); // make sure it gets focus and is restored existingWindow.focus(); // make sure it gets focus and is restored
return; return [existingWindow];
} }
let folderUris = openConfig.cli['folder-uri'] || []; let folderUris = openConfig.cli['folder-uri'] || [];
let fileUris = openConfig.cli['file-uri'] || []; let fileUris = openConfig.cli['file-uri'] || [];
@@ -1286,7 +1325,8 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
noRecentEntry: true, noRecentEntry: true,
waitMarkerFileURI: openConfig.waitMarkerFileURI waitMarkerFileURI: openConfig.waitMarkerFileURI
}; };
this.open(openArgs);
return this.open(openArgs);
} }
private openInBrowserWindow(options: IOpenBrowserWindowOptions): ICodeWindow { private openInBrowserWindow(options: IOpenBrowserWindowOptions): ICodeWindow {
@@ -1580,23 +1620,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
}); });
} }
async enterWorkspace(win: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | undefined> {
const result = await this.workspacesManager.enterWorkspace(win, path);
return result ? this.doEnterWorkspace(win, result) : undefined;
}
private doEnterWorkspace(win: ICodeWindow, result: IEnterWorkspaceResult): IEnterWorkspaceResult {
// Mark as recently opened
this.workspacesHistoryMainService.addRecentlyOpened([{ workspace: result.workspace }]);
// Trigger Eevent to indicate load of workspace into window
this._onWindowReady.fire(win);
return result;
}
focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow { focusLastActive(cli: ParsedArgs, context: OpenContext): ICodeWindow {
const lastActive = this.getLastActiveWindow(); const lastActive = this.getLastActiveWindow();
if (lastActive) { if (lastActive) {
@@ -1613,7 +1636,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
return getLastActiveWindow(WindowsManager.WINDOWS); return getLastActiveWindow(WindowsManager.WINDOWS);
} }
getLastActiveWindowForAuthority(remoteAuthority: string | undefined): ICodeWindow | undefined { private getLastActiveWindowForAuthority(remoteAuthority: string | undefined): ICodeWindow | undefined {
return getLastActiveWindow(WindowsManager.WINDOWS.filter(window => window.remoteAuthority === remoteAuthority)); return getLastActiveWindow(WindowsManager.WINDOWS.filter(window => window.remoteAuthority === remoteAuthority));
} }
@@ -1623,13 +1646,11 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
if (cli && (cli.remote !== remote)) { if (cli && (cli.remote !== remote)) {
cli = { ...cli, remote }; cli = { ...cli, remote };
} }
const forceReuseWindow = options && options.reuse;
const forceNewWindow = !forceReuseWindow;
return this.open({ context, cli, forceEmpty: true, forceNewWindow, forceReuseWindow });
}
openNewTabbedWindow(context: OpenContext): ICodeWindow[] { const forceReuseWindow = options && options.forceReuseWindow;
return this.open({ context, cli: this.environmentService.args, forceNewTabbedWindow: true, forceEmpty: true }); const forceNewWindow = !forceReuseWindow;
return this.open({ context, cli, forceEmpty: true, forceNewWindow, forceReuseWindow });
} }
waitForWindowCloseOrLoad(windowId: number): Promise<void> { waitForWindowCloseOrLoad(windowId: number): Promise<void> {
@@ -1666,7 +1687,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
} }
} }
getFocusedWindow(): ICodeWindow | undefined { private getFocusedWindow(): ICodeWindow | undefined {
const win = BrowserWindow.getFocusedWindow(); const win = BrowserWindow.getFocusedWindow();
if (win) { if (win) {
return this.getWindowById(win.id); return this.getWindowById(win.id);
@@ -1710,14 +1731,14 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
} }
// Show Dialog // Show Dialog
this.dialogs.showMessageBox({ this.dialogMainService.showMessageBox({
title: product.nameLong, title: product.nameLong,
type: 'warning', type: 'warning',
buttons: [mnemonicButtonLabel(localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(localize({ key: 'wait', comment: ['&& denotes a mnemonic'] }, "&&Keep Waiting")), mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))], buttons: [mnemonicButtonLabel(localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(localize({ key: 'wait', comment: ['&& denotes a mnemonic'] }, "&&Keep Waiting")), mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
message: localize('appStalled', "The window is no longer responding"), message: localize('appStalled', "The window is no longer responding"),
detail: localize('appStalledDetail', "You can reopen or close the window or keep waiting."), detail: localize('appStalledDetail', "You can reopen or close the window or keep waiting."),
noLink: true noLink: true
}, window).then(result => { }, window.win).then(result => {
if (!window.win) { if (!window.win) {
return; // Return early if the window has been going down already return; // Return early if the window has been going down already
} }
@@ -1733,14 +1754,14 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
// Crashed // Crashed
else { else {
this.dialogs.showMessageBox({ this.dialogMainService.showMessageBox({
title: product.nameLong, title: product.nameLong,
type: 'warning', type: 'warning',
buttons: [mnemonicButtonLabel(localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))], buttons: [mnemonicButtonLabel(localize({ key: 'reopen', comment: ['&& denotes a mnemonic'] }, "&&Reopen")), mnemonicButtonLabel(localize({ key: 'close', comment: ['&& denotes a mnemonic'] }, "&&Close"))],
message: localize('appCrashed', "The window has crashed"), message: localize('appCrashed', "The window has crashed"),
detail: localize('appCrashedDetail', "We are sorry for the inconvenience! You can reopen the window to continue where you left off."), detail: localize('appCrashedDetail', "We are sorry for the inconvenience! You can reopen the window to continue where you left off."),
noLink: true noLink: true
}, window).then(result => { }, window.win).then(result => {
if (!window.win) { if (!window.win) {
return; // Return early if the window has been going down already return; // Return early if the window has been going down already
} }
@@ -1770,8 +1791,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
} }
async pickFileFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> { async pickFileFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> {
const title = localize('open', "Open"); const paths = await this.dialogMainService.pickFileFolder(options);
const paths = await this.dialogs.pick({ ...options, pickFolders: true, pickFiles: true, title });
if (paths) { if (paths) {
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFileFolder', options.telemetryExtraData); this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFileFolder', options.telemetryExtraData);
const urisToOpen = await Promise.all(paths.map(async path => { const urisToOpen = await Promise.all(paths.map(async path => {
@@ -1790,8 +1810,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
} }
async pickFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> { async pickFolderAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> {
const title = localize('openFolder', "Open Folder"); const paths = await this.dialogMainService.pickFolder(options);
const paths = await this.dialogs.pick({ ...options, pickFolders: true, title });
if (paths) { if (paths) {
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFolder', options.telemetryExtraData); this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFolder', options.telemetryExtraData);
this.open({ this.open({
@@ -1805,8 +1824,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
} }
async pickFileAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> { async pickFileAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> {
const title = localize('openFile', "Open File"); const paths = await this.dialogMainService.pickFile(options);
const paths = await this.dialogs.pick({ ...options, pickFiles: true, title });
if (paths) { if (paths) {
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFile', options.telemetryExtraData); this.sendPickerTelemetry(paths, options.telemetryEventName || 'openFile', options.telemetryExtraData);
this.open({ this.open({
@@ -1820,10 +1838,7 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
} }
async pickWorkspaceAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> { async pickWorkspaceAndOpen(options: INativeOpenDialogOptions, win?: ICodeWindow): Promise<void> {
const title = localize('openWorkspaceTitle', "Open Workspace"); const paths = await this.dialogMainService.pickWorkspace(options);
const buttonLabel = mnemonicButtonLabel(localize({ key: 'openWorkspace', comment: ['&& denotes a mnemonic'] }, "&&Open"));
const filters = WORKSPACE_FILTER;
const paths = await this.dialogs.pick({ ...options, pickFiles: true, title, filters, buttonLabel });
if (paths) { if (paths) {
this.sendPickerTelemetry(paths, options.telemetryEventName || 'openWorkspace', options.telemetryExtraData); this.sendPickerTelemetry(paths, options.telemetryEventName || 'openWorkspace', options.telemetryExtraData);
this.open({ this.open({
@@ -1838,7 +1853,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
} }
private sendPickerTelemetry(paths: string[], telemetryEventName: string, telemetryExtraData?: ITelemetryData) { private sendPickerTelemetry(paths: string[], telemetryEventName: string, telemetryExtraData?: ITelemetryData) {
const numberOfPaths = paths ? paths.length : 0; const numberOfPaths = paths ? paths.length : 0;
// Telemetry // Telemetry
@@ -1850,18 +1864,6 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
}); });
} }
showMessageBox(options: MessageBoxOptions, win?: ICodeWindow): Promise<MessageBoxReturnValue> {
return this.dialogs.showMessageBox(options, win);
}
showSaveDialog(options: SaveDialogOptions, win?: ICodeWindow): Promise<SaveDialogReturnValue> {
return this.dialogs.showSaveDialog(options, win);
}
showOpenDialog(options: OpenDialogOptions, win?: ICodeWindow): Promise<OpenDialogReturnValue> {
return this.dialogs.showOpenDialog(options, win);
}
quit(): void { quit(): void {
// If the user selected to exit from an extension development host window, do not quit, but just // If the user selected to exit from an extension development host window, do not quit, but just
@@ -1879,240 +1881,3 @@ export class WindowsManager extends Disposable implements IWindowsMainService {
} }
} }
} }
interface IInternalNativeOpenDialogOptions extends INativeOpenDialogOptions {
pickFolders?: boolean;
pickFiles?: boolean;
title: string;
buttonLabel?: string;
filters?: FileFilter[];
}
class Dialogs {
private static readonly workingDirPickerStorageKey = 'pickerWorkingDir';
private readonly mapWindowToDialogQueue: Map<number, Queue<void>>;
private readonly noWindowDialogQueue: Queue<void>;
constructor(
private readonly stateService: IStateService,
private readonly windowsMainService: IWindowsMainService
) {
this.mapWindowToDialogQueue = new Map<number, Queue<void>>();
this.noWindowDialogQueue = new Queue<void>();
}
async pick(options: IInternalNativeOpenDialogOptions, win?: ICodeWindow): Promise<string[] | undefined> {
// Ensure dialog options
const dialogOptions: OpenDialogOptions = {
title: options.title,
buttonLabel: options.buttonLabel,
filters: options.filters
};
// Ensure defaultPath
dialogOptions.defaultPath = options.defaultPath || this.stateService.getItem<string>(Dialogs.workingDirPickerStorageKey);
// Ensure properties
if (typeof options.pickFiles === 'boolean' || typeof options.pickFolders === 'boolean') {
dialogOptions.properties = undefined; // let it override based on the booleans
if (options.pickFiles && options.pickFolders) {
dialogOptions.properties = ['multiSelections', 'openDirectory', 'openFile', 'createDirectory'];
}
}
if (!dialogOptions.properties) {
dialogOptions.properties = ['multiSelections', options.pickFolders ? 'openDirectory' : 'openFile', 'createDirectory'];
}
if (isMacintosh) {
dialogOptions.properties.push('treatPackageAsDirectory'); // always drill into .app files
}
// Show Dialog
const windowToUse = win || this.windowsMainService.getFocusedWindow();
const result = await this.showOpenDialog(dialogOptions, windowToUse);
if (result && result.filePaths && result.filePaths.length > 0) {
// Remember path in storage for next time
this.stateService.setItem(Dialogs.workingDirPickerStorageKey, dirname(result.filePaths[0]));
return result.filePaths;
}
return undefined; // {{SQL CARBON EDIT}} @anthonydresser strict-null-check
}
private getDialogQueue(window?: ICodeWindow): Queue<any> {
if (!window) {
return this.noWindowDialogQueue;
}
let windowDialogQueue = this.mapWindowToDialogQueue.get(window.id);
if (!windowDialogQueue) {
windowDialogQueue = new Queue<any>();
this.mapWindowToDialogQueue.set(window.id, windowDialogQueue);
}
return windowDialogQueue;
}
showMessageBox(options: MessageBoxOptions, window?: ICodeWindow): Promise<MessageBoxReturnValue> {
return this.getDialogQueue(window).queue(async () => {
if (window) {
return dialog.showMessageBox(window.win, options);
}
return dialog.showMessageBox(options);
});
}
showSaveDialog(options: SaveDialogOptions, window?: ICodeWindow): Promise<SaveDialogReturnValue> {
function normalizePath(path: string | undefined): string | undefined {
if (path && isMacintosh) {
path = normalizeNFC(path); // normalize paths returned from the OS
}
return path;
}
return this.getDialogQueue(window).queue(async () => {
let result: SaveDialogReturnValue;
if (window) {
result = await dialog.showSaveDialog(window.win, options);
} else {
result = await dialog.showSaveDialog(options);
}
result.filePath = normalizePath(result.filePath);
return result;
});
}
showOpenDialog(options: OpenDialogOptions, window?: ICodeWindow): Promise<OpenDialogReturnValue> {
function normalizePaths(paths: string[] | undefined): string[] | undefined {
if (paths && paths.length > 0 && isMacintosh) {
paths = paths.map(path => normalizeNFC(path)); // normalize paths returned from the OS
}
return paths;
}
return this.getDialogQueue(window).queue(async () => {
// Ensure the path exists (if provided)
if (options.defaultPath) {
const pathExists = await exists(options.defaultPath);
if (!pathExists) {
options.defaultPath = undefined;
}
}
// Show dialog
let result: OpenDialogReturnValue;
if (window) {
result = await dialog.showOpenDialog(window.win, options);
} else {
result = await dialog.showOpenDialog(options);
}
result.filePaths = normalizePaths(result.filePaths);
return result;
});
}
}
class WorkspacesManager {
constructor(
private readonly workspacesMainService: IWorkspacesMainService,
private readonly backupMainService: IBackupMainService,
private readonly windowsMainService: IWindowsMainService,
) { }
async enterWorkspace(window: ICodeWindow, path: URI): Promise<IEnterWorkspaceResult | null> {
if (!window || !window.win || !window.isReady) {
return null; // return early if the window is not ready or disposed
}
const isValid = await this.isValidTargetWorkspacePath(window, path);
if (!isValid) {
return null; // return early if the workspace is not valid
}
return this.doOpenWorkspace(window, getWorkspaceIdentifier(path));
}
private async isValidTargetWorkspacePath(window: ICodeWindow, path?: URI): Promise<boolean> {
if (!path) {
return true;
}
if (window.openedWorkspace && isEqual(window.openedWorkspace.configPath, path)) {
return false; // window is already opened on a workspace with that path
}
// Prevent overwriting a workspace that is currently opened in another window
if (findWindowOnWorkspace(this.windowsMainService.getWindows(), getWorkspaceIdentifier(path))) {
const options: MessageBoxOptions = {
title: product.nameLong,
type: 'info',
buttons: [localize('ok', "OK")],
message: localize('workspaceOpenedMessage', "Unable to save workspace '{0}'", resourcesBasename(path)),
detail: localize('workspaceOpenedDetail', "The workspace is already opened in another window. Please close that window first and then try again."),
noLink: true
};
await this.windowsMainService.showMessageBox(options, this.windowsMainService.getFocusedWindow());
return false;
}
return true; // OK
}
private doOpenWorkspace(window: ICodeWindow, workspace: IWorkspaceIdentifier): IEnterWorkspaceResult {
window.focus();
// Register window for backups and migrate current backups over
let backupPath: string | undefined;
if (!window.config.extensionDevelopmentPath) {
backupPath = this.backupMainService.registerWorkspaceBackupSync({ workspace, remoteAuthority: window.remoteAuthority }, window.config.backupPath);
}
// if the window was opened on an untitled workspace, delete it.
if (window.openedWorkspace && this.workspacesMainService.isUntitledWorkspace(window.openedWorkspace)) {
this.workspacesMainService.deleteUntitledWorkspaceSync(window.openedWorkspace);
}
// Update window configuration properly based on transition to workspace
window.config.folderUri = undefined;
window.config.workspace = workspace;
window.config.backupPath = backupPath;
return { workspace, backupPath };
}
}
function resourceFromURIToOpen(openable: IWindowOpenable): URI {
if (isWorkspaceToOpen(openable)) {
return openable.workspaceUri;
}
if (isFolderToOpen(openable)) {
return openable.folderUri;
}
return openable.fileUri;
}

View File

@@ -35,12 +35,15 @@ export function restoreWindowsState(data: WindowsStateStorageData | undefined):
if (windowsState.lastActiveWindow) { if (windowsState.lastActiveWindow) {
result.lastActiveWindow = restoreWindowState(windowsState.lastActiveWindow); result.lastActiveWindow = restoreWindowState(windowsState.lastActiveWindow);
} }
if (windowsState.lastPluginDevelopmentHostWindow) { if (windowsState.lastPluginDevelopmentHostWindow) {
result.lastPluginDevelopmentHostWindow = restoreWindowState(windowsState.lastPluginDevelopmentHostWindow); result.lastPluginDevelopmentHostWindow = restoreWindowState(windowsState.lastPluginDevelopmentHostWindow);
} }
if (Array.isArray(windowsState.openedWindows)) { if (Array.isArray(windowsState.openedWindows)) {
result.openedWindows = windowsState.openedWindows.map(windowState => restoreWindowState(windowState)); result.openedWindows = windowsState.openedWindows.map(windowState => restoreWindowState(windowState));
} }
return result; return result;
} }
@@ -49,9 +52,11 @@ function restoreWindowState(windowState: ISerializedWindowState): IWindowState {
if (windowState.backupPath) { if (windowState.backupPath) {
result.backupPath = windowState.backupPath; result.backupPath = windowState.backupPath;
} }
if (windowState.remoteAuthority) { if (windowState.remoteAuthority) {
result.remoteAuthority = windowState.remoteAuthority; result.remoteAuthority = windowState.remoteAuthority;
} }
if (windowState.folder) { if (windowState.folder) {
result.folderUri = URI.parse(windowState.folder); result.folderUri = URI.parse(windowState.folder);
} else if (windowState.folderUri) { } else if (windowState.folderUri) {
@@ -59,11 +64,13 @@ function restoreWindowState(windowState: ISerializedWindowState): IWindowState {
} else if (windowState.folderPath) { } else if (windowState.folderPath) {
result.folderUri = URI.file(windowState.folderPath); result.folderUri = URI.file(windowState.folderPath);
} }
if (windowState.workspaceIdentifier) { if (windowState.workspaceIdentifier) {
result.workspace = { id: windowState.workspaceIdentifier.id, configPath: URI.parse(windowState.workspaceIdentifier.configURIPath) }; result.workspace = { id: windowState.workspaceIdentifier.id, configPath: URI.parse(windowState.workspaceIdentifier.configURIPath) };
} else if (windowState.workspace) { } else if (windowState.workspace) {
result.workspace = { id: windowState.workspace.id, configPath: URI.file(windowState.workspace.configPath) }; result.workspace = { id: windowState.workspace.id, configPath: URI.file(windowState.workspace.configPath) };
} }
return result; return result;
} }

View File

@@ -3,19 +3,18 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as os from 'os';
import * as fs from 'fs';
import { spawn, ChildProcess, SpawnOptions } from 'child_process'; import { spawn, ChildProcess, SpawnOptions } from 'child_process';
import { buildHelpMessage, buildVersionMessage, addArg, createWaitMarkerFile, OPTIONS } from 'vs/platform/environment/node/argv'; import { buildHelpMessage, buildVersionMessage, addArg, createWaitMarkerFile, OPTIONS } from 'vs/platform/environment/node/argv';
import { parseCLIProcessArgv } from 'vs/platform/environment/node/argvHelper'; import { parseCLIProcessArgv } from 'vs/platform/environment/node/argvHelper';
import { ParsedArgs } from 'vs/platform/environment/common/environment'; import { ParsedArgs } from 'vs/platform/environment/common/environment';
import product from 'vs/platform/product/common/product'; import product from 'vs/platform/product/common/product';
import * as paths from 'vs/base/common/path'; import * as paths from 'vs/base/common/path';
import * as os from 'os';
import * as fs from 'fs';
import { whenDeleted, writeFileSync } from 'vs/base/node/pfs'; import { whenDeleted, writeFileSync } from 'vs/base/node/pfs';
import { findFreePort, randomPort } from 'vs/base/node/ports'; import { findFreePort, randomPort } from 'vs/base/node/ports';
import { resolveTerminalEncoding } from 'vs/base/node/encoding'; import { resolveTerminalEncoding } from 'vs/base/node/encoding';
import * as iconv from 'iconv-lite'; import { isWindows } from 'vs/base/common/platform';
import { isWindows, isLinux } from 'vs/base/common/platform';
import { ProfilingSession, Target } from 'v8-inspect-profiler'; import { ProfilingSession, Target } from 'v8-inspect-profiler';
import { isString } from 'vs/base/common/types'; import { isString } from 'vs/base/common/types';
@@ -179,7 +178,8 @@ export async function main(argv: string[]): Promise<any> {
if (!stdinFileError) { if (!stdinFileError) {
// Pipe into tmp file using terminals encoding // Pipe into tmp file using terminals encoding
resolveTerminalEncoding(verbose).then(encoding => { resolveTerminalEncoding(verbose).then(async encoding => {
const iconv = await import('iconv-lite');
const converterStream = iconv.decodeStream(encoding); const converterStream = iconv.decodeStream(encoding);
process.stdin.pipe(converterStream).pipe(stdinFileStream); process.stdin.pipe(converterStream).pipe(stdinFileStream);
}); });
@@ -360,10 +360,6 @@ export async function main(argv: string[]): Promise<any> {
options['stdio'] = 'ignore'; options['stdio'] = 'ignore';
} }
if (isLinux) {
addArg(argv, '--no-sandbox'); // Electron 6 introduces a chrome-sandbox that requires root to run. This can fail. Disable sandbox via --no-sandbox
}
const child = spawn(process.execPath, argv.slice(2), options); const child = spawn(process.execPath, argv.slice(2), options);
if (args.wait && waitMarkerFilePath) { if (args.wait && waitMarkerFilePath) {

View File

@@ -1,131 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as platform from 'vs/base/common/platform';
import * as extpath from 'vs/base/common/extpath';
import { OpenContext } from 'vs/platform/windows/common/windows';
import { IWorkspaceIdentifier, IResolvedWorkspace, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { isEqual, isEqualOrParent } from 'vs/base/common/resources';
export interface ISimpleWindow {
openedWorkspace?: IWorkspaceIdentifier;
openedFolderUri?: URI;
extensionDevelopmentPath?: string[];
lastFocusTime: number;
}
export interface IBestWindowOrFolderOptions<W extends ISimpleWindow> {
windows: W[];
newWindow: boolean;
context: OpenContext;
fileUri?: URI;
userHome?: string;
codeSettingsFolder?: string;
localWorkspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace | null;
}
export function findBestWindowOrFolderForFile<W extends ISimpleWindow>({ windows, newWindow, context, fileUri, localWorkspaceResolver: workspaceResolver }: IBestWindowOrFolderOptions<W>): W | undefined {
if (!newWindow && fileUri && (context === OpenContext.DESKTOP || context === OpenContext.CLI || context === OpenContext.DOCK)) {
const windowOnFilePath = findWindowOnFilePath(windows, fileUri, workspaceResolver);
if (windowOnFilePath) {
return windowOnFilePath;
}
}
return !newWindow ? getLastActiveWindow(windows) : undefined;
}
function findWindowOnFilePath<W extends ISimpleWindow>(windows: W[], fileUri: URI, localWorkspaceResolver: (workspace: IWorkspaceIdentifier) => IResolvedWorkspace | null): W | null {
// First check for windows with workspaces that have a parent folder of the provided path opened
for (const window of windows) {
const workspace = window.openedWorkspace;
if (workspace) {
const resolvedWorkspace = localWorkspaceResolver(workspace);
if (resolvedWorkspace) {
// workspace could be resolved: It's in the local file system
if (resolvedWorkspace.folders.some(folder => isEqualOrParent(fileUri, folder.uri))) {
return window;
}
} else {
// use the config path instead
if (isEqualOrParent(fileUri, workspace.configPath)) {
return window;
}
}
}
}
// Then go with single folder windows that are parent of the provided file path
const singleFolderWindowsOnFilePath = windows.filter(window => window.openedFolderUri && isEqualOrParent(fileUri, window.openedFolderUri));
if (singleFolderWindowsOnFilePath.length) {
return singleFolderWindowsOnFilePath.sort((a, b) => -(a.openedFolderUri!.path.length - b.openedFolderUri!.path.length))[0];
}
return null;
}
export function getLastActiveWindow<W extends ISimpleWindow>(windows: W[]): W | undefined {
const lastFocusedDate = Math.max.apply(Math, windows.map(window => window.lastFocusTime));
return windows.filter(window => window.lastFocusTime === lastFocusedDate)[0];
}
export function findWindowOnWorkspace<W extends ISimpleWindow>(windows: W[], workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier)): W | null {
if (isSingleFolderWorkspaceIdentifier(workspace)) {
for (const window of windows) {
// match on folder
if (isSingleFolderWorkspaceIdentifier(workspace)) {
if (window.openedFolderUri && isEqual(window.openedFolderUri, workspace)) {
return window;
}
}
}
} else if (isWorkspaceIdentifier(workspace)) {
for (const window of windows) {
// match on workspace
if (window.openedWorkspace && window.openedWorkspace.id === workspace.id) {
return window;
}
}
}
return null;
}
export function findWindowOnExtensionDevelopmentPath<W extends ISimpleWindow>(windows: W[], extensionDevelopmentPaths: string[]): W | null {
const matches = (uriString: string): boolean => {
return extensionDevelopmentPaths.some(p => extpath.isEqual(p, uriString, !platform.isLinux /* ignorecase */));
};
for (const window of windows) {
// match on extension development path. The path can be one or more paths or uri strings, using paths.isEqual is not 100% correct but good enough
const currPaths = window.extensionDevelopmentPath;
if (currPaths && currPaths.some(p => matches(p))) {
return window;
}
}
return null;
}
export function findWindowOnWorkspaceOrFolderUri<W extends ISimpleWindow>(windows: W[], uri: URI | undefined): W | null {
if (!uri) {
return null;
}
for (const window of windows) {
// check for workspace config path
if (window.openedWorkspace && isEqual(window.openedWorkspace.configPath, uri)) {
return window;
}
// check for folder path
if (window.openedFolderUri && isEqual(window.openedFolderUri, uri)) {
return window;
}
}
return null;
}

View File

@@ -11,7 +11,7 @@ import * as platform from 'vs/base/common/platform';
import { CharWidthRequest, CharWidthRequestType, readCharWidths } from 'vs/editor/browser/config/charWidthReader'; import { CharWidthRequest, CharWidthRequestType, readCharWidths } from 'vs/editor/browser/config/charWidthReader';
import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver'; import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver';
import { CommonEditorConfiguration, IEnvConfiguration } from 'vs/editor/common/config/commonEditorConfig'; import { CommonEditorConfiguration, IEnvConfiguration } from 'vs/editor/common/config/commonEditorConfig';
import { IEditorOptions, EditorOption } from 'vs/editor/common/config/editorOptions'; import { EditorOption, IEditorConstructionOptions } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo'; import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo';
import { IDimension } from 'vs/editor/common/editorCommon'; import { IDimension } from 'vs/editor/common/editorCommon';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
@@ -310,13 +310,13 @@ export class Configuration extends CommonEditorConfiguration {
constructor( constructor(
isSimpleWidget: boolean, isSimpleWidget: boolean,
options: IEditorOptions, options: IEditorConstructionOptions,
referenceDomElement: HTMLElement | null = null, referenceDomElement: HTMLElement | null = null,
private readonly accessibilityService: IAccessibilityService private readonly accessibilityService: IAccessibilityService
) { ) {
super(isSimpleWidget, options); super(isSimpleWidget, options);
this._elementSizeObserver = this._register(new ElementSizeObserver(referenceDomElement, () => this._onReferenceDomElementSizeChanged())); this._elementSizeObserver = this._register(new ElementSizeObserver(referenceDomElement, options.dimension, () => this._onReferenceDomElementSizeChanged()));
this._register(CSSBasedConfiguration.INSTANCE.onDidChange(() => this._onCSSBasedConfigurationChanged())); this._register(CSSBasedConfiguration.INSTANCE.onDidChange(() => this._onCSSBasedConfigurationChanged()));

View File

@@ -14,14 +14,14 @@ export class ElementSizeObserver extends Disposable {
private width: number; private width: number;
private height: number; private height: number;
constructor(referenceDomElement: HTMLElement | null, changeCallback: () => void) { constructor(referenceDomElement: HTMLElement | null, dimension: IDimension | undefined, changeCallback: () => void) {
super(); super();
this.referenceDomElement = referenceDomElement; this.referenceDomElement = referenceDomElement;
this.changeCallback = changeCallback; this.changeCallback = changeCallback;
this.measureReferenceDomElementToken = -1; this.measureReferenceDomElementToken = -1;
this.width = -1; this.width = -1;
this.height = -1; this.height = -1;
this.measureReferenceDomElement(false); this.measureReferenceDomElement(false, dimension);
} }
public dispose(): void { public dispose(): void {
@@ -75,4 +75,4 @@ export class ElementSizeObserver extends Disposable {
} }
} }
} }

View File

@@ -190,7 +190,7 @@ class TouchHandler extends MouseHandler {
constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) { constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {
super(context, viewController, viewHelper); super(context, viewController, viewHelper);
Gesture.addTarget(this.viewHelper.linesContentDomNode); this._register(Gesture.addTarget(this.viewHelper.linesContentDomNode));
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Tap, (e) => this.onTap(e))); this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Tap, (e) => this.onTap(e)));
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Change, (e) => this.onChange(e))); this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Change, (e) => this.onChange(e)));

View File

@@ -152,6 +152,10 @@ export class TextAreaHandler extends ViewPart {
this.textArea.setAttribute('aria-haspopup', 'false'); this.textArea.setAttribute('aria-haspopup', 'false');
this.textArea.setAttribute('aria-autocomplete', 'both'); this.textArea.setAttribute('aria-autocomplete', 'both');
if (platform.isWeb && options.get(EditorOption.readOnly)) {
this.textArea.setAttribute('readonly', 'true');
}
this.textAreaCover = createFastDomNode(document.createElement('div')); this.textAreaCover = createFastDomNode(document.createElement('div'));
this.textAreaCover.setPosition('absolute'); this.textAreaCover.setPosition('absolute');
@@ -395,6 +399,14 @@ export class TextAreaHandler extends ViewPart {
this._copyWithSyntaxHighlighting = options.get(EditorOption.copyWithSyntaxHighlighting); this._copyWithSyntaxHighlighting = options.get(EditorOption.copyWithSyntaxHighlighting);
this.textArea.setAttribute('aria-label', this._getAriaLabel(options)); this.textArea.setAttribute('aria-label', this._getAriaLabel(options));
if (platform.isWeb && e.hasChanged(EditorOption.readOnly)) {
if (options.get(EditorOption.readOnly)) {
this.textArea.setAttribute('readonly', 'true');
} else {
this.textArea.removeAttribute('readonly');
}
}
if (e.hasChanged(EditorOption.accessibilitySupport)) { if (e.hasChanged(EditorOption.accessibilitySupport)) {
this._textAreaInput.writeScreenReaderContent('strategy changed'); this._textAreaInput.writeScreenReaderContent('strategy changed');
} }

View File

@@ -29,6 +29,7 @@ import { registerThemingParticipant } from 'vs/platform/theme/common/themeServic
import { ModelDecorationMinimapOptions } from 'vs/editor/common/model/textModel'; import { ModelDecorationMinimapOptions } from 'vs/editor/common/model/textModel';
import { Selection } from 'vs/editor/common/core/selection'; import { Selection } from 'vs/editor/common/core/selection';
import { Color } from 'vs/base/common/color'; import { Color } from 'vs/base/common/color';
import { GestureEvent, EventType, Gesture } from 'vs/base/browser/touch';
function getMinimapLineHeight(renderMinimap: RenderMinimap): number { function getMinimapLineHeight(renderMinimap: RenderMinimap): number {
if (renderMinimap === RenderMinimap.Large) { if (renderMinimap === RenderMinimap.Large) {
@@ -208,6 +209,10 @@ class MinimapLayout {
return Math.round(desiredSliderPosition / this._computedSliderRatio); return Math.round(desiredSliderPosition / this._computedSliderRatio);
} }
public getDesiredScrollTopFromTouchLocation(pageY: number): number {
return Math.round((pageY - this.sliderHeight / 2) / this._computedSliderRatio);
}
public static create( public static create(
options: MinimapOptions, options: MinimapOptions,
viewportStartLineNumber: number, viewportStartLineNumber: number,
@@ -451,12 +456,17 @@ export class Minimap extends ViewPart {
private readonly _mouseDownListener: IDisposable; private readonly _mouseDownListener: IDisposable;
private readonly _sliderMouseMoveMonitor: GlobalMouseMoveMonitor<IStandardMouseMoveEventData>; private readonly _sliderMouseMoveMonitor: GlobalMouseMoveMonitor<IStandardMouseMoveEventData>;
private readonly _sliderMouseDownListener: IDisposable; private readonly _sliderMouseDownListener: IDisposable;
private readonly _gestureDisposable: IDisposable;
private readonly _sliderTouchStartListener: IDisposable;
private readonly _sliderTouchMoveListener: IDisposable;
private readonly _sliderTouchEndListener: IDisposable;
private _options: MinimapOptions; private _options: MinimapOptions;
private _lastRenderData: RenderData | null; private _lastRenderData: RenderData | null;
private _selections: Selection[] = []; private _selections: Selection[] = [];
private _selectionColor: Color | undefined; private _selectionColor: Color | undefined;
private _renderDecorations: boolean = false; private _renderDecorations: boolean = false;
private _gestureInProgress: boolean = false;
private _buffers: MinimapBuffers | null; private _buffers: MinimapBuffers | null;
constructor(context: ViewContext) { constructor(context: ViewContext) {
@@ -566,12 +576,50 @@ export class Minimap extends ViewPart {
); );
} }
}); });
this._gestureDisposable = Gesture.addTarget(this._domNode.domNode);
this._sliderTouchStartListener = dom.addDisposableListener(this._domNode.domNode, EventType.Start, (e: GestureEvent) => {
e.preventDefault();
e.stopPropagation();
if (this._lastRenderData) {
this._slider.toggleClassName('active', true);
this._gestureInProgress = true;
this.scrollDueToTouchEvent(e);
}
});
this._sliderTouchMoveListener = dom.addStandardDisposableListener(this._domNode.domNode, EventType.Change, (e: GestureEvent) => {
e.preventDefault();
e.stopPropagation();
if (this._lastRenderData && this._gestureInProgress) {
this.scrollDueToTouchEvent(e);
}
});
this._sliderTouchEndListener = dom.addStandardDisposableListener(this._domNode.domNode, EventType.End, (e: GestureEvent) => {
e.preventDefault();
e.stopPropagation();
this._gestureInProgress = false;
this._slider.toggleClassName('active', false);
});
}
private scrollDueToTouchEvent(touch: GestureEvent) {
const startY = this._domNode.domNode.getBoundingClientRect().top;
const scrollTop = this._lastRenderData!.renderedLayout.getDesiredScrollTopFromTouchLocation(touch.pageY - startY);
this._context.viewLayout.setScrollPositionNow({
scrollTop: scrollTop
});
} }
public dispose(): void { public dispose(): void {
this._mouseDownListener.dispose(); this._mouseDownListener.dispose();
this._sliderMouseMoveMonitor.dispose(); this._sliderMouseMoveMonitor.dispose();
this._sliderMouseDownListener.dispose(); this._sliderMouseDownListener.dispose();
this._gestureDisposable.dispose();
this._sliderTouchStartListener.dispose();
this._sliderTouchMoveListener.dispose();
this._sliderTouchEndListener.dispose();
super.dispose(); super.dispose();
} }

View File

@@ -23,7 +23,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
import { ICommandDelegate } from 'vs/editor/browser/view/viewController'; import { ICommandDelegate } from 'vs/editor/browser/view/viewController';
import { IContentWidgetData, IOverlayWidgetData, View } from 'vs/editor/browser/view/viewImpl'; import { IContentWidgetData, IOverlayWidgetData, View } from 'vs/editor/browser/view/viewImpl';
import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents'; import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents';
import { ConfigurationChangedEvent, EditorLayoutInfo, IEditorOptions, EditorOption, IComputedEditorOptions, FindComputedEditorOptionValueById } from 'vs/editor/common/config/editorOptions'; import { ConfigurationChangedEvent, EditorLayoutInfo, IEditorOptions, EditorOption, IComputedEditorOptions, FindComputedEditorOptionValueById, IEditorConstructionOptions } from 'vs/editor/common/config/editorOptions';
import { Cursor, CursorStateChangedEvent } from 'vs/editor/common/controller/cursor'; import { Cursor, CursorStateChangedEvent } from 'vs/editor/common/controller/cursor';
import { CursorColumns, ICursors } from 'vs/editor/common/controller/cursorCommon'; import { CursorColumns, ICursors } from 'vs/editor/common/controller/cursorCommon';
import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents'; import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
@@ -236,7 +236,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
constructor( constructor(
domElement: HTMLElement, domElement: HTMLElement,
options: IEditorOptions, options: IEditorConstructionOptions,
codeEditorWidgetOptions: ICodeEditorWidgetOptions, codeEditorWidgetOptions: ICodeEditorWidgetOptions,
@IInstantiationService instantiationService: IInstantiationService, @IInstantiationService instantiationService: IInstantiationService,
@ICodeEditorService codeEditorService: ICodeEditorService, @ICodeEditorService codeEditorService: ICodeEditorService,
@@ -329,7 +329,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
this._codeEditorService.addCodeEditor(this); this._codeEditorService.addCodeEditor(this);
} }
protected _createConfiguration(options: IEditorOptions, accessibilityService: IAccessibilityService): editorCommon.IConfiguration { protected _createConfiguration(options: IEditorConstructionOptions, accessibilityService: IAccessibilityService): editorCommon.IConfiguration {
return new Configuration(this.isSimpleWidget, options, this._domElement, accessibilityService); return new Configuration(this.isSimpleWidget, options, this._domElement, accessibilityService);
} }

View File

@@ -12,6 +12,7 @@ import { USUAL_WORD_SEPARATORS } from 'vs/editor/common/model/wordHelper';
import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
import { isObject } from 'vs/base/common/types'; import { isObject } from 'vs/base/common/types';
import { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry'; import { IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
import { IDimension } from 'vs/editor/common/editorCommon';
//#region typed options //#region typed options
@@ -516,6 +517,13 @@ export interface IEditorOptions {
showUnused?: boolean; showUnused?: boolean;
} }
export interface IEditorConstructionOptions extends IEditorOptions {
/**
* The initial editor dimension (to avoid measuring the container).
*/
dimension?: IDimension;
}
/** /**
* Configuration options for the diff editor. * Configuration options for the diff editor.
*/ */

View File

@@ -280,6 +280,8 @@ export interface IEditor {
/** /**
* Instructs the editor to remeasure its container. This method should * Instructs the editor to remeasure its container. This method should
* be called when the container of the editor gets resized. * be called when the container of the editor gets resized.
*
* If a dimension is passed in, the passed in value will be used.
*/ */
layout(dimension?: IDimension): void; layout(dimension?: IDimension): void;

View File

@@ -922,7 +922,7 @@ export interface DocumentSymbol {
/** /**
* The document symbol provider interface defines the contract between extensions and * The document symbol provider interface defines the contract between extensions and
* the [go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_goto-symbol)-feature. * the [go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-symbol)-feature.
*/ */
export interface DocumentSymbolProvider { export interface DocumentSymbolProvider {

View File

@@ -14,7 +14,7 @@ import { ScrollType, IEditorContribution } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model'; import { ITextModel } from 'vs/editor/common/model';
import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction, registerInstantiatedEditorAction } from 'vs/editor/browser/editorExtensions'; import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction, registerInstantiatedEditorAction } from 'vs/editor/browser/editorExtensions';
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { FoldingModel, setCollapseStateAtLevel, CollapseMemento, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines, setCollapseStateForType } from 'vs/editor/contrib/folding/foldingModel'; import { FoldingModel, setCollapseStateAtLevel, CollapseMemento, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines, setCollapseStateForType, toggleCollapseState } from 'vs/editor/contrib/folding/foldingModel';
import { FoldingDecorationProvider } from './foldingDecorations'; import { FoldingDecorationProvider } from './foldingDecorations';
import { FoldingRegions, FoldingRegion } from './foldingRanges'; import { FoldingRegions, FoldingRegion } from './foldingRanges';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
@@ -656,6 +656,30 @@ class FoldAction extends FoldingAction<FoldingArguments> {
} }
} }
class ToggleFoldAction extends FoldingAction<void> {
constructor() {
super({
id: 'editor.toggleFold',
label: nls.localize('toggleFoldAction.label', "Toggle Fold"),
alias: 'Toggle Fold',
precondition: CONTEXT_FOLDING_ENABLED,
kbOpts: {
kbExpr: EditorContextKeys.editorTextFocus,
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_K),
weight: KeybindingWeight.EditorContrib
}
});
}
invoke(_foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void {
let selectedLines = this.getSelectedLines(editor);
toggleCollapseState(foldingModel, 1, selectedLines);
}
}
class FoldRecursivelyAction extends FoldingAction<void> { class FoldRecursivelyAction extends FoldingAction<void> {
constructor() { constructor() {
@@ -842,6 +866,7 @@ registerEditorAction(UnfoldAllAction);
registerEditorAction(FoldAllBlockCommentsAction); registerEditorAction(FoldAllBlockCommentsAction);
registerEditorAction(FoldAllRegionsAction); registerEditorAction(FoldAllRegionsAction);
registerEditorAction(UnfoldAllRegionsAction); registerEditorAction(UnfoldAllRegionsAction);
registerEditorAction(ToggleFoldAction);
for (let i = 1; i <= 7; i++) { for (let i = 1; i <= 7; i++) {
registerInstantiatedEditorAction( registerInstantiatedEditorAction(

View File

@@ -242,6 +242,26 @@ export class FoldingModel {
} }
/**
* Collapse or expand the regions at the given locations
* @param levels The number of levels. Use 1 to only impact the regions at the location, use Number.MAX_VALUE for all levels.
* @param lineNumbers the location of the regions to collapse or expand, or if not set, all regions in the model.
*/
export function toggleCollapseState(foldingModel: FoldingModel, levels: number, lineNumbers: number[]) {
let toToggle: FoldingRegion[] = [];
for (let lineNumber of lineNumbers) {
let region = foldingModel.getRegionAtLine(lineNumber);
if (region) {
const doCollapse = !region.isCollapsed;
toToggle.push(region);
if (levels > 1) {
let regionsInside = foldingModel.getRegionsInside(region, (r, level: number) => r.isCollapsed !== doCollapse && level < levels);
toToggle.push(...regionsInside);
}
}
}
foldingModel.toggleCollapseState(toToggle);
}
/** /**

View File

@@ -37,7 +37,7 @@
margin: 8px 0; margin: 8px 0;
} }
.monaco-editor-hover p > code { .monaco-editor-hover code {
font-family: var(--monaco-monospace-font); font-family: var(--monaco-monospace-font);
} }

View File

@@ -53,7 +53,7 @@
padding-left: 20px; padding-left: 20px;
} }
.monaco-editor .suggest-widget > .details p > code { .monaco-editor .suggest-widget > .details p code {
font-family: var(--monaco-monospace-font); font-family: var(--monaco-monospace-font);
} }

View File

@@ -21,7 +21,7 @@ import { Selection } from 'vs/editor/common/core/selection';
import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ToggleTabFocusModeAction } from 'vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode'; import { ToggleTabFocusModeAction } from 'vs/editor/contrib/toggleTabFocusMode/toggleTabFocusMode';
import { IEditorConstructionOptions } from 'vs/editor/standalone/browser/standaloneCodeEditor'; import { IStandaloneEditorConstructionOptions } from 'vs/editor/standalone/browser/standaloneCodeEditor';
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
@@ -164,7 +164,7 @@ class AccessibilityHelpWidget extends Widget implements IOverlayWidget {
if (e.equals(KeyMod.CtrlCmd | KeyCode.KEY_H)) { if (e.equals(KeyMod.CtrlCmd | KeyCode.KEY_H)) {
alert(AccessibilityHelpNLS.openingDocs); alert(AccessibilityHelpNLS.openingDocs);
let url = (<IEditorConstructionOptions>this._editor.getRawOptions()).accessibilityHelpUrl; let url = (<IStandaloneEditorConstructionOptions>this._editor.getRawOptions()).accessibilityHelpUrl;
if (typeof url === 'undefined') { if (typeof url === 'undefined') {
url = 'https://go.microsoft.com/fwlink/?linkid=852450'; url = 'https://go.microsoft.com/fwlink/?linkid=852450';
} }

View File

@@ -10,7 +10,7 @@ import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget'; import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget'; import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IDiffEditorOptions, IEditorOptions, IEditorConstructionOptions } from 'vs/editor/common/config/editorOptions';
import { InternalEditorAction } from 'vs/editor/common/editorAction'; import { InternalEditorAction } from 'vs/editor/common/editorAction';
import { IModelChangedEvent } from 'vs/editor/common/editorCommon'; import { IModelChangedEvent } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model'; import { ITextModel } from 'vs/editor/common/model';
@@ -79,7 +79,7 @@ export interface IActionDescriptor {
/** /**
* The options to create an editor. * The options to create an editor.
*/ */
export interface IEditorConstructionOptions extends IEditorOptions { export interface IStandaloneEditorConstructionOptions extends IEditorConstructionOptions {
/** /**
* The initial model associated with this code editor. * The initial model associated with this code editor.
*/ */
@@ -158,7 +158,7 @@ export class StandaloneCodeEditor extends CodeEditorWidget implements IStandalon
constructor( constructor(
domElement: HTMLElement, domElement: HTMLElement,
options: IEditorConstructionOptions, options: IStandaloneEditorConstructionOptions,
@IInstantiationService instantiationService: IInstantiationService, @IInstantiationService instantiationService: IInstantiationService,
@ICodeEditorService codeEditorService: ICodeEditorService, @ICodeEditorService codeEditorService: ICodeEditorService,
@ICommandService commandService: ICommandService, @ICommandService commandService: ICommandService,
@@ -287,7 +287,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
constructor( constructor(
domElement: HTMLElement, domElement: HTMLElement,
options: IEditorConstructionOptions | undefined, options: IStandaloneEditorConstructionOptions | undefined,
toDispose: IDisposable, toDispose: IDisposable,
@IInstantiationService instantiationService: IInstantiationService, @IInstantiationService instantiationService: IInstantiationService,
@ICodeEditorService codeEditorService: ICodeEditorService, @ICodeEditorService codeEditorService: ICodeEditorService,

View File

@@ -24,7 +24,7 @@ import { IWebWorkerOptions, MonacoWebWorker, createWebWorker as actualCreateWebW
import * as standaloneEnums from 'vs/editor/common/standalone/standaloneEnums'; import * as standaloneEnums from 'vs/editor/common/standalone/standaloneEnums';
import { Colorizer, IColorizerElementOptions, IColorizerOptions } from 'vs/editor/standalone/browser/colorizer'; import { Colorizer, IColorizerElementOptions, IColorizerOptions } from 'vs/editor/standalone/browser/colorizer';
import { SimpleEditorModelResolverService } from 'vs/editor/standalone/browser/simpleServices'; import { SimpleEditorModelResolverService } from 'vs/editor/standalone/browser/simpleServices';
import { IDiffEditorConstructionOptions, IEditorConstructionOptions, IStandaloneCodeEditor, IStandaloneDiffEditor, StandaloneDiffEditor, StandaloneEditor } from 'vs/editor/standalone/browser/standaloneCodeEditor'; import { IDiffEditorConstructionOptions, IStandaloneEditorConstructionOptions, IStandaloneCodeEditor, IStandaloneDiffEditor, StandaloneDiffEditor, StandaloneEditor } from 'vs/editor/standalone/browser/standaloneCodeEditor';
import { DynamicStandaloneServices, IEditorOverrideServices, StaticServices } from 'vs/editor/standalone/browser/standaloneServices'; import { DynamicStandaloneServices, IEditorOverrideServices, StaticServices } from 'vs/editor/standalone/browser/standaloneServices';
import { IStandaloneThemeData, IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService'; import { IStandaloneThemeData, IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneThemeService';
import { ICommandService } from 'vs/platform/commands/common/commands'; import { ICommandService } from 'vs/platform/commands/common/commands';
@@ -68,7 +68,7 @@ function withAllStandaloneServices<T extends editorCommon.IEditor>(domElement: H
* `domElement` should be empty (not contain other dom nodes). * `domElement` should be empty (not contain other dom nodes).
* The editor will read the size of `domElement`. * The editor will read the size of `domElement`.
*/ */
export function create(domElement: HTMLElement, options?: IEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneCodeEditor { export function create(domElement: HTMLElement, options?: IStandaloneEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneCodeEditor {
return withAllStandaloneServices(domElement, override || {}, (services) => { return withAllStandaloneServices(domElement, override || {}, (services) => {
return new StandaloneEditor( return new StandaloneEditor(
domElement, domElement,

View File

@@ -29,7 +29,7 @@ import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService
export class TestCodeEditor extends CodeEditorWidget implements editorBrowser.ICodeEditor { export class TestCodeEditor extends CodeEditorWidget implements editorBrowser.ICodeEditor {
//#region testing overrides //#region testing overrides
protected _createConfiguration(options: editorOptions.IEditorOptions): editorCommon.IConfiguration { protected _createConfiguration(options: editorOptions.IEditorConstructionOptions): editorCommon.IConfiguration {
return new TestConfiguration(options); return new TestConfiguration(options);
} }
protected _createView(viewModel: ViewModel, cursor: Cursor): [View, boolean] { protected _createView(viewModel: ViewModel, cursor: Cursor): [View, boolean] {

15
src/vs/monaco.d.ts vendored
View File

@@ -813,7 +813,7 @@ declare namespace monaco.editor {
* `domElement` should be empty (not contain other dom nodes). * `domElement` should be empty (not contain other dom nodes).
* The editor will read the size of `domElement`. * The editor will read the size of `domElement`.
*/ */
export function create(domElement: HTMLElement, options?: IEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneCodeEditor; export function create(domElement: HTMLElement, options?: IStandaloneEditorConstructionOptions, override?: IEditorOverrideServices): IStandaloneCodeEditor;
/** /**
* Emitted when an editor is created. * Emitted when an editor is created.
@@ -1051,7 +1051,7 @@ declare namespace monaco.editor {
/** /**
* The options to create an editor. * The options to create an editor.
*/ */
export interface IEditorConstructionOptions extends IEditorOptions { export interface IStandaloneEditorConstructionOptions extends IEditorConstructionOptions {
/** /**
* The initial model associated with this code editor. * The initial model associated with this code editor.
*/ */
@@ -2061,6 +2061,8 @@ declare namespace monaco.editor {
/** /**
* Instructs the editor to remeasure its container. This method should * Instructs the editor to remeasure its container. This method should
* be called when the container of the editor gets resized. * be called when the container of the editor gets resized.
*
* If a dimension is passed in, the passed in value will be used.
*/ */
layout(dimension?: IDimension): void; layout(dimension?: IDimension): void;
/** /**
@@ -2918,6 +2920,13 @@ declare namespace monaco.editor {
showUnused?: boolean; showUnused?: boolean;
} }
export interface IEditorConstructionOptions extends IEditorOptions {
/**
* The initial editor dimension (to avoid measuring the container).
*/
dimension?: IDimension;
}
/** /**
* Configuration options for the diff editor. * Configuration options for the diff editor.
*/ */
@@ -5131,7 +5140,7 @@ declare namespace monaco.languages {
/** /**
* The document symbol provider interface defines the contract between extensions and * The document symbol provider interface defines the contract between extensions and
* the [go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_goto-symbol)-feature. * the [go to symbol](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-symbol)-feature.
*/ */
export interface DocumentSymbolProvider { export interface DocumentSymbolProvider {
displayName?: string; displayName?: string;

View File

@@ -8,6 +8,7 @@ import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth
import { ICredentialsService } from 'vs/platform/credentials/common/credentials'; import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IProductService } from 'vs/platform/product/common/productService'; import { IProductService } from 'vs/platform/product/common/productService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
const SERVICE_NAME = 'VS Code'; const SERVICE_NAME = 'VS Code';
const ACCOUNT = 'MyAccount'; const ACCOUNT = 'MyAccount';
@@ -23,9 +24,10 @@ export class AuthTokenService extends Disposable implements IAuthTokenService {
constructor( constructor(
@ICredentialsService private readonly credentialsService: ICredentialsService, @ICredentialsService private readonly credentialsService: ICredentialsService,
@IProductService productService: IProductService, @IProductService productService: IProductService,
@IConfigurationService configurationService: IConfigurationService,
) { ) {
super(); super();
if (productService.settingsSyncStoreUrl) { if (productService.settingsSyncStoreUrl && configurationService.getValue('configurationSync.enableAuth')) {
this._status = AuthTokenStatus.Inactive; this._status = AuthTokenStatus.Inactive;
this.getToken().then(token => { this.getToken().then(token => {
if (token) { if (token) {

View File

@@ -0,0 +1,211 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { MessageBoxOptions, SaveDialogOptions, OpenDialogOptions, dialog, FileFilter, BrowserWindow } from 'electron';
import { Queue } from 'vs/base/common/async';
import { IStateService } from 'vs/platform/state/node/state';
import { isMacintosh } from 'vs/base/common/platform';
import { dirname } from 'vs/base/common/path';
import { normalizeNFC } from 'vs/base/common/normalization';
import { exists } from 'vs/base/node/pfs';
import { INativeOpenDialogOptions, MessageBoxReturnValue, SaveDialogReturnValue, OpenDialogReturnValue } from 'vs/platform/dialogs/node/dialogs';
import { withNullAsUndefined } from 'vs/base/common/types';
import { localize } from 'vs/nls';
import { WORKSPACE_FILTER } from 'vs/platform/workspaces/common/workspaces';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
export const IDialogMainService = createDecorator<IDialogMainService>('dialogMainService');
export interface IDialogMainService {
_serviceBrand: undefined;
pickFileFolder(options: INativeOpenDialogOptions, window?: BrowserWindow): Promise<string[] | undefined>;
pickFolder(options: INativeOpenDialogOptions, window?: BrowserWindow): Promise<string[] | undefined>;
pickFile(options: INativeOpenDialogOptions, window?: BrowserWindow): Promise<string[] | undefined>;
pickWorkspace(options: INativeOpenDialogOptions, window?: BrowserWindow): Promise<string[] | undefined>;
showMessageBox(options: MessageBoxOptions, window?: BrowserWindow): Promise<MessageBoxReturnValue>;
showSaveDialog(options: SaveDialogOptions, window?: BrowserWindow): Promise<SaveDialogReturnValue>;
showOpenDialog(options: OpenDialogOptions, window?: BrowserWindow): Promise<OpenDialogReturnValue>;
}
interface IInternalNativeOpenDialogOptions extends INativeOpenDialogOptions {
pickFolders?: boolean;
pickFiles?: boolean;
title: string;
buttonLabel?: string;
filters?: FileFilter[];
}
export class DialogMainService implements IDialogMainService {
_serviceBrand: undefined;
private static readonly workingDirPickerStorageKey = 'pickerWorkingDir';
private readonly mapWindowToDialogQueue: Map<number, Queue<void>>;
private readonly noWindowDialogQueue: Queue<void>;
constructor(
@IStateService private readonly stateService: IStateService
) {
this.mapWindowToDialogQueue = new Map<number, Queue<void>>();
this.noWindowDialogQueue = new Queue<void>();
}
pickFileFolder(options: INativeOpenDialogOptions, window?: BrowserWindow): Promise<string[] | undefined> {
return this.doPick({ ...options, pickFolders: true, pickFiles: true, title: localize('open', "Open") }, window);
}
pickFolder(options: INativeOpenDialogOptions, window?: BrowserWindow): Promise<string[] | undefined> {
return this.doPick({ ...options, pickFolders: true, title: localize('openFolder', "Open Folder") }, window);
}
pickFile(options: INativeOpenDialogOptions, window?: BrowserWindow): Promise<string[] | undefined> {
return this.doPick({ ...options, pickFiles: true, title: localize('openFile', "Open File") }, window);
}
pickWorkspace(options: INativeOpenDialogOptions, window?: BrowserWindow): Promise<string[] | undefined> {
const title = localize('openWorkspaceTitle', "Open Workspace");
const buttonLabel = mnemonicButtonLabel(localize({ key: 'openWorkspace', comment: ['&& denotes a mnemonic'] }, "&&Open"));
const filters = WORKSPACE_FILTER;
return this.doPick({ ...options, pickFiles: true, title, filters, buttonLabel }, window);
}
private async doPick(options: IInternalNativeOpenDialogOptions, window?: BrowserWindow): Promise<string[] | undefined> {
// Ensure dialog options
const dialogOptions: OpenDialogOptions = {
title: options.title,
buttonLabel: options.buttonLabel,
filters: options.filters
};
// Ensure defaultPath
dialogOptions.defaultPath = options.defaultPath || this.stateService.getItem<string>(DialogMainService.workingDirPickerStorageKey);
// Ensure properties
if (typeof options.pickFiles === 'boolean' || typeof options.pickFolders === 'boolean') {
dialogOptions.properties = undefined; // let it override based on the booleans
if (options.pickFiles && options.pickFolders) {
dialogOptions.properties = ['multiSelections', 'openDirectory', 'openFile', 'createDirectory'];
}
}
if (!dialogOptions.properties) {
dialogOptions.properties = ['multiSelections', options.pickFolders ? 'openDirectory' : 'openFile', 'createDirectory'];
}
if (isMacintosh) {
dialogOptions.properties.push('treatPackageAsDirectory'); // always drill into .app files
}
// Show Dialog
const windowToUse = window || BrowserWindow.getFocusedWindow();
const result = await this.showOpenDialog(dialogOptions, withNullAsUndefined(windowToUse));
if (result && result.filePaths && result.filePaths.length > 0) {
// Remember path in storage for next time
this.stateService.setItem(DialogMainService.workingDirPickerStorageKey, dirname(result.filePaths[0]));
return result.filePaths;
}
return undefined; // {{SQL CARBON EDIT}} strict-null-check
}
private getDialogQueue(window?: BrowserWindow): Queue<any> {
if (!window) {
return this.noWindowDialogQueue;
}
let windowDialogQueue = this.mapWindowToDialogQueue.get(window.id);
if (!windowDialogQueue) {
windowDialogQueue = new Queue<any>();
this.mapWindowToDialogQueue.set(window.id, windowDialogQueue);
}
return windowDialogQueue;
}
showMessageBox(options: MessageBoxOptions, window?: BrowserWindow): Promise<MessageBoxReturnValue> {
return this.getDialogQueue(window).queue(async () => {
return new Promise(resolve => {
if (window) {
return dialog.showMessageBox(window, options, (response, checkboxChecked) => resolve({ response, checkboxChecked }));
}
return dialog.showMessageBox(options);
});
});
}
showSaveDialog(options: SaveDialogOptions, window?: BrowserWindow): Promise<SaveDialogReturnValue> {
function normalizePath(path: string | undefined): string | undefined {
if (path && isMacintosh) {
path = normalizeNFC(path); // normalize paths returned from the OS
}
return path;
}
return this.getDialogQueue(window).queue(async () => {
return new Promise<SaveDialogReturnValue>(resolve => {
if (window) {
dialog.showSaveDialog(window, options, filePath => resolve({ filePath }));
} else {
dialog.showSaveDialog(options, filePath => resolve({ filePath }));
}
}).then(result => {
result.filePath = normalizePath(result.filePath);
return result;
});
});
}
showOpenDialog(options: OpenDialogOptions, window?: BrowserWindow): Promise<OpenDialogReturnValue> {
function normalizePaths(paths: string[] | undefined): string[] | undefined {
if (paths && paths.length > 0 && isMacintosh) {
paths = paths.map(path => normalizeNFC(path)); // normalize paths returned from the OS
}
return paths;
}
return this.getDialogQueue(window).queue(async () => {
// Ensure the path exists (if provided)
if (options.defaultPath) {
const pathExists = await exists(options.defaultPath);
if (!pathExists) {
options.defaultPath = undefined;
}
}
// Show dialog
return new Promise<OpenDialogReturnValue>(resolve => {
if (window) {
dialog.showOpenDialog(window, options, filePaths => resolve({ filePaths }));
} else {
dialog.showOpenDialog(options, filePaths => resolve({ filePaths }));
}
}).then(result => {
result.filePaths = normalizePaths(result.filePaths);
return result;
});
});
}
}

View File

@@ -13,3 +13,16 @@ export interface INativeOpenDialogOptions {
telemetryEventName?: string; telemetryEventName?: string;
telemetryExtraData?: ITelemetryData; telemetryExtraData?: ITelemetryData;
} }
export interface MessageBoxReturnValue {
response: number;
checkboxChecked: boolean;
}
export interface SaveDialogReturnValue {
filePath?: string;
}
export interface OpenDialogReturnValue {
filePaths?: string[];
}

View File

@@ -5,16 +5,17 @@
import { Event } from 'vs/base/common/event'; import { Event } from 'vs/base/common/event';
import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; import { IWindowsMainService } from 'vs/platform/windows/electron-main/windows';
import { MessageBoxOptions, MessageBoxReturnValue, shell, OpenDevToolsOptions, SaveDialogOptions, SaveDialogReturnValue, OpenDialogOptions, OpenDialogReturnValue, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app } from 'electron'; import { MessageBoxOptions, shell, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, CrashReporterStartOptions, crashReporter, Menu, BrowserWindow, app } from 'electron';
import { INativeOpenInWindowOptions } from 'vs/platform/windows/node/window'; import { INativeOpenWindowOptions } from 'vs/platform/windows/node/window';
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService'; import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
import { IOpenedWindow, OpenContext, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows'; import { IOpenedWindow, OpenContext, IWindowOpenable, IOpenEmptyWindowOptions } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { INativeOpenDialogOptions, MessageBoxReturnValue, SaveDialogReturnValue, OpenDialogReturnValue } from 'vs/platform/dialogs/node/dialogs';
import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform'; import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform';
import { IElectronService } from 'vs/platform/electron/node/electron'; import { IElectronService } from 'vs/platform/electron/node/electron';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment'; import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
import { AddFirstParameterToFunctions } from 'vs/base/common/types'; import { AddFirstParameterToFunctions } from 'vs/base/common/types';
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
export class ElectronMainService implements AddFirstParameterToFunctions<IElectronService, Promise<any> /* only methods, not events */, number /* window ID */> { export class ElectronMainService implements AddFirstParameterToFunctions<IElectronService, Promise<any> /* only methods, not events */, number /* window ID */> {
@@ -22,6 +23,7 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
constructor( constructor(
@IWindowsMainService private readonly windowsMainService: IWindowsMainService, @IWindowsMainService private readonly windowsMainService: IWindowsMainService,
@IDialogMainService private readonly dialogMainService: IDialogMainService,
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService, @ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
@IEnvironmentService private readonly environmentService: IEnvironmentService @IEnvironmentService private readonly environmentService: IEnvironmentService
) { ) {
@@ -61,7 +63,7 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
} }
async getActiveWindowId(windowId: number): Promise<number | undefined> { async getActiveWindowId(windowId: number): Promise<number | undefined> {
const activeWindow = this.windowsMainService.getFocusedWindow() || this.windowsMainService.getLastActiveWindow(); const activeWindow = BrowserWindow.getFocusedWindow() || this.windowsMainService.getLastActiveWindow();
if (activeWindow) { if (activeWindow) {
return activeWindow.id; return activeWindow.id;
} }
@@ -69,11 +71,17 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
return undefined; return undefined;
} }
async openEmptyWindow(windowId: number, options?: IOpenEmptyWindowOptions): Promise<void> { openWindow(windowId: number, options?: IOpenEmptyWindowOptions): Promise<void>;
this.windowsMainService.openEmptyWindow(OpenContext.API, options); openWindow(windowId: number, toOpen: IWindowOpenable[], options?: INativeOpenWindowOptions): Promise<void>;
openWindow(windowId: number, arg1?: IOpenEmptyWindowOptions | IWindowOpenable[], arg2?: INativeOpenWindowOptions): Promise<void> {
if (Array.isArray(arg1)) {
return this.doOpenWindow(windowId, arg1, arg2);
}
return this.doOpenEmptyWindow(windowId, arg1);
} }
async openInWindow(windowId: number, toOpen: IWindowOpenable[], options: INativeOpenInWindowOptions = Object.create(null)): Promise<void> { private async doOpenWindow(windowId: number, toOpen: IWindowOpenable[], options: INativeOpenWindowOptions = Object.create(null)): Promise<void> {
if (toOpen.length > 0) { if (toOpen.length > 0) {
this.windowsMainService.open({ this.windowsMainService.open({
context: OpenContext.API, context: OpenContext.API,
@@ -91,6 +99,10 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
} }
} }
private async doOpenEmptyWindow(windowId: number, options?: IOpenEmptyWindowOptions): Promise<void> {
this.windowsMainService.openEmptyWindow(OpenContext.API, options);
}
async toggleFullScreen(windowId: number): Promise<void> { async toggleFullScreen(windowId: number): Promise<void> {
const window = this.windowsMainService.getWindowById(windowId); const window = this.windowsMainService.getWindowById(windowId);
if (window) { if (window) {
@@ -164,15 +176,24 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
//#region Dialog //#region Dialog
async showMessageBox(windowId: number, options: MessageBoxOptions): Promise<MessageBoxReturnValue> { async showMessageBox(windowId: number, options: MessageBoxOptions): Promise<MessageBoxReturnValue> {
return this.windowsMainService.showMessageBox(options, this.windowsMainService.getWindowById(windowId)); return this.dialogMainService.showMessageBox(options, this.toBrowserWindow(windowId));
} }
async showSaveDialog(windowId: number, options: SaveDialogOptions): Promise<SaveDialogReturnValue> { async showSaveDialog(windowId: number, options: SaveDialogOptions): Promise<SaveDialogReturnValue> {
return this.windowsMainService.showSaveDialog(options, this.windowsMainService.getWindowById(windowId)); return this.dialogMainService.showSaveDialog(options, this.toBrowserWindow(windowId));
} }
async showOpenDialog(windowId: number, options: OpenDialogOptions): Promise<OpenDialogReturnValue> { async showOpenDialog(windowId: number, options: OpenDialogOptions): Promise<OpenDialogReturnValue> {
return this.windowsMainService.showOpenDialog(options, this.windowsMainService.getWindowById(windowId)); return this.dialogMainService.showOpenDialog(options, this.toBrowserWindow(windowId));
}
private toBrowserWindow(windowId: number): BrowserWindow | undefined {
const window = this.windowsMainService.getWindowById(windowId);
if (window) {
return window.win;
}
return undefined;
} }
async pickFileFolderAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise<void> { async pickFileFolderAndOpen(windowId: number, options: INativeOpenDialogOptions): Promise<void> {
@@ -214,7 +235,9 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
} }
async openExternal(windowId: number, url: string): Promise<boolean> { async openExternal(windowId: number, url: string): Promise<boolean> {
return this.windowsMainService.openExternal(url); shell.openExternal(url);
return true;
} }
async updateTouchBar(windowId: number, items: ISerializableCommandAction[][]): Promise<void> { async updateTouchBar(windowId: number, items: ISerializableCommandAction[][]): Promise<void> {
@@ -229,7 +252,7 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
//#region macOS Touchbar //#region macOS Touchbar
async newWindowTab(): Promise<void> { async newWindowTab(): Promise<void> {
this.windowsMainService.openNewTabbedWindow(OpenContext.API); this.windowsMainService.open({ context: OpenContext.API, cli: this.environmentService.args, forceNewTabbedWindow: true, forceEmpty: true });
} }
async showPreviousWindowTab(): Promise<void> { async showPreviousWindowTab(): Promise<void> {
@@ -267,7 +290,7 @@ export class ElectronMainService implements AddFirstParameterToFunctions<IElectr
} }
} }
async closeWorkpsace(windowId: number): Promise<void> { async closeWorkspace(windowId: number): Promise<void> {
const window = this.windowsMainService.getWindowById(windowId); const window = this.windowsMainService.getWindowById(windowId);
if (window) { if (window) {
return this.windowsMainService.closeWorkspace(window); return this.windowsMainService.closeWorkspace(window);

View File

@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event'; import { Event } from 'vs/base/common/event';
import { MessageBoxOptions, MessageBoxReturnValue, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, OpenDialogReturnValue, SaveDialogReturnValue, CrashReporterStartOptions } from 'electron'; import { MessageBoxOptions, OpenDevToolsOptions, SaveDialogOptions, OpenDialogOptions, CrashReporterStartOptions } from 'electron';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IWindowOpenable, IOpenEmptyWindowOptions, IOpenedWindow } from 'vs/platform/windows/common/windows'; import { IWindowOpenable, IOpenEmptyWindowOptions, IOpenedWindow } from 'vs/platform/windows/common/windows';
import { INativeOpenDialogOptions } from 'vs/platform/dialogs/node/dialogs'; import { INativeOpenDialogOptions, MessageBoxReturnValue, SaveDialogReturnValue, OpenDialogReturnValue } from 'vs/platform/dialogs/node/dialogs';
import { ISerializableCommandAction } from 'vs/platform/actions/common/actions'; import { ISerializableCommandAction } from 'vs/platform/actions/common/actions';
import { ParsedArgs } from 'vscode-minimist'; import { ParsedArgs } from 'vscode-minimist';
import { IProcessEnvironment } from 'vs/base/common/platform'; import { IProcessEnvironment } from 'vs/base/common/platform';
import { INativeOpenInWindowOptions } from 'vs/platform/windows/node/window'; import { INativeOpenWindowOptions } from 'vs/platform/windows/node/window';
export const IElectronService = createDecorator<IElectronService>('electronService'); export const IElectronService = createDecorator<IElectronService>('electronService');
@@ -33,8 +33,8 @@ export interface IElectronService {
getWindowCount(): Promise<number>; getWindowCount(): Promise<number>;
getActiveWindowId(): Promise<number | undefined>; getActiveWindowId(): Promise<number | undefined>;
openEmptyWindow(options?: IOpenEmptyWindowOptions): Promise<void>; openWindow(options?: IOpenEmptyWindowOptions): Promise<void>;
openInWindow(toOpen: IWindowOpenable[], options?: INativeOpenInWindowOptions): Promise<void>; openWindow(toOpen: IWindowOpenable[], options?: INativeOpenWindowOptions): Promise<void>;
toggleFullScreen(): Promise<void>; toggleFullScreen(): Promise<void>;
@@ -76,7 +76,7 @@ export interface IElectronService {
// Lifecycle // Lifecycle
relaunch(options?: { addArgs?: string[], removeArgs?: string[] }): Promise<void>; relaunch(options?: { addArgs?: string[], removeArgs?: string[] }): Promise<void>;
reload(): Promise<void>; reload(): Promise<void>;
closeWorkpsace(): Promise<void>; closeWorkspace(): Promise<void>;
closeWindow(): Promise<void>; closeWindow(): Promise<void>;
quit(): Promise<void>; quit(): Promise<void>;

View File

@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ISharedProcess } from 'vs/platform/windows/electron-main/windows';
export const ISharedProcessMainService = createDecorator<ISharedProcessMainService>('sharedProcessMainService'); export const ISharedProcessMainService = createDecorator<ISharedProcessMainService>('sharedProcessMainService');
@@ -15,6 +14,12 @@ export interface ISharedProcessMainService {
whenSharedProcessReady(): Promise<void>; whenSharedProcessReady(): Promise<void>;
toggleSharedProcessWindow(): Promise<void>; toggleSharedProcessWindow(): Promise<void>;
} }
export interface ISharedProcess {
whenReady(): Promise<void>;
toggle(): void;
}
export class SharedProcessMainService implements ISharedProcessMainService { export class SharedProcessMainService implements ISharedProcessMainService {
_serviceBrand: undefined; _serviceBrand: undefined;

View File

@@ -7,15 +7,16 @@ import { localize } from 'vs/nls';
import * as objects from 'vs/base/common/objects'; import * as objects from 'vs/base/common/objects';
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
import { IIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/node/issue'; import { IIssueService, IssueReporterData, IssueReporterFeatures, ProcessExplorerData } from 'vs/platform/issue/node/issue';
import { BrowserWindow, ipcMain, screen, dialog, IpcMainEvent, Display } from 'electron'; import { BrowserWindow, ipcMain, screen, Event as IpcMainEvent, Display, shell } from 'electron';
import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService'; import { ILaunchMainService } from 'vs/platform/launch/electron-main/launchMainService';
import { PerformanceInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; import { PerformanceInfo, isRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
import { IDiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsService'; import { IDiagnosticsService } from 'vs/platform/diagnostics/node/diagnosticsService';
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform'; import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform';
import { ILogService } from 'vs/platform/log/common/log'; import { ILogService } from 'vs/platform/log/common/log';
import { IWindowState, IWindowsMainService } from 'vs/platform/windows/electron-main/windows'; import { IWindowState } from 'vs/platform/windows/electron-main/windows';
import { listProcesses } from 'vs/base/node/ps'; import { listProcesses } from 'vs/base/node/ps';
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogs';
const DEFAULT_BACKGROUND_COLOR = '#1E1E1E'; const DEFAULT_BACKGROUND_COLOR = '#1E1E1E';
@@ -33,7 +34,7 @@ export class IssueMainService implements IIssueService {
@ILaunchMainService private readonly launchMainService: ILaunchMainService, @ILaunchMainService private readonly launchMainService: ILaunchMainService,
@ILogService private readonly logService: ILogService, @ILogService private readonly logService: ILogService,
@IDiagnosticsService private readonly diagnosticsService: IDiagnosticsService, @IDiagnosticsService private readonly diagnosticsService: IDiagnosticsService,
@IWindowsMainService private readonly windowsMainService: IWindowsMainService @IDialogMainService private readonly dialogMainService: IDialogMainService
) { ) {
this.registerListeners(); this.registerListeners();
} }
@@ -89,7 +90,7 @@ export class IssueMainService implements IIssueService {
}; };
if (this._issueWindow) { if (this._issueWindow) {
dialog.showMessageBox(this._issueWindow, messageOptions) this.dialogMainService.showMessageBox(messageOptions, this._issueWindow)
.then(result => { .then(result => {
event.sender.send('vscode:issueReporterClipboardResponse', result.response === 0); event.sender.send('vscode:issueReporterClipboardResponse', result.response === 0);
}); });
@@ -113,7 +114,7 @@ export class IssueMainService implements IIssueService {
}; };
if (this._issueWindow) { if (this._issueWindow) {
dialog.showMessageBox(this._issueWindow, messageOptions) this.dialogMainService.showMessageBox(messageOptions, this._issueWindow)
.then(result => { .then(result => {
if (result.response === 0) { if (result.response === 0) {
if (this._issueWindow) { if (this._issueWindow) {
@@ -146,7 +147,7 @@ export class IssueMainService implements IIssueService {
}); });
ipcMain.on('vscode:openExternal', (_: unknown, arg: string) => { ipcMain.on('vscode:openExternal', (_: unknown, arg: string) => {
this.windowsMainService.openExternal(arg); shell.openExternal(arg);
}); });
ipcMain.on('vscode:closeIssueReporter', (event: IpcMainEvent) => { ipcMain.on('vscode:closeIssueReporter', (event: IpcMainEvent) => {

View File

@@ -141,6 +141,7 @@ export class LaunchMainService implements ILaunchMainService {
} }
} }
// Open new Window
if (openNewWindow) { if (openNewWindow) {
usedWindows = this.windowsMainService.open({ usedWindows = this.windowsMainService.open({
context, context,
@@ -150,8 +151,18 @@ export class LaunchMainService implements ILaunchMainService {
forceEmpty: true, forceEmpty: true,
waitMarkerFileURI waitMarkerFileURI
}); });
} else { }
usedWindows = [this.windowsMainService.focusLastActive(args, context)];
// Focus existing window or open if none opened
else {
const lastActive = this.windowsMainService.getLastActiveWindow();
if (lastActive) {
lastActive.focus();
usedWindows = [lastActive];
} else {
usedWindows = this.windowsMainService.open({ context, cli: args, forceEmpty: true });
}
} }
} }
@@ -216,7 +227,7 @@ export class LaunchMainService implements ILaunchMainService {
mainPID: process.pid, mainPID: process.pid,
mainArguments: process.argv.slice(1), mainArguments: process.argv.slice(1),
windows, windows,
screenReader: !!app.accessibilitySupportEnabled, screenReader: !!app.isAccessibilitySupportEnabled(),
gpuFeatureStatus: app.getGPUFeatureStatus() gpuFeatureStatus: app.getGPUFeatureStatus()
}); });
} }

View File

@@ -87,4 +87,10 @@ export class BufferLogService extends AbstractLogService implements ILogService
this._logger.dispose(); this._logger.dispose();
} }
} }
flush(): void {
if (this._logger) {
this._logger.flush();
}
}
} }

View File

@@ -78,8 +78,7 @@ export class FileLogService extends AbstractLogService implements ILogService {
} }
} }
flush(): Promise<void> { flush(): void {
return this.queue.queue(() => Promise.resolve());
} }
log(level: LogLevel, args: any[]): void { log(level: LogLevel, args: any[]): void {

View File

@@ -41,6 +41,11 @@ export interface ILogger extends IDisposable {
warn(message: string, ...args: any[]): void; warn(message: string, ...args: any[]): void;
error(message: string | Error, ...args: any[]): void; error(message: string | Error, ...args: any[]): void;
critical(message: string | Error, ...args: any[]): void; critical(message: string | Error, ...args: any[]): void;
/**
* An operation to flush the contents. Can be synchronous.
*/
flush(): void;
} }
export interface ILogService extends ILogger { export interface ILogService extends ILogger {
@@ -69,6 +74,7 @@ export abstract class AbstractLogService extends Disposable {
getLevel(): LogLevel { getLevel(): LogLevel {
return this.level; return this.level;
} }
} }
export class ConsoleLogMainService extends AbstractLogService implements ILogService { export class ConsoleLogMainService extends AbstractLogService implements ILogService {
@@ -145,6 +151,11 @@ export class ConsoleLogMainService extends AbstractLogService implements ILogSer
dispose(): void { dispose(): void {
// noop // noop
} }
flush(): void {
// noop
}
} }
export class ConsoleLogService extends AbstractLogService implements ILogService { export class ConsoleLogService extends AbstractLogService implements ILogService {
@@ -192,7 +203,13 @@ export class ConsoleLogService extends AbstractLogService implements ILogService
} }
} }
dispose(): void { } dispose(): void {
// noop
}
flush(): void {
// noop
}
} }
export class ConsoleLogInMainService extends AbstractLogService implements ILogService { export class ConsoleLogInMainService extends AbstractLogService implements ILogService {
@@ -240,7 +257,13 @@ export class ConsoleLogInMainService extends AbstractLogService implements ILogS
} }
} }
dispose(): void { } dispose(): void {
// noop
}
flush(): void {
// noop
}
} }
export class MultiplexLogService extends AbstractLogService implements ILogService { export class MultiplexLogService extends AbstractLogService implements ILogService {
@@ -296,6 +319,12 @@ export class MultiplexLogService extends AbstractLogService implements ILogServi
} }
} }
flush(): void {
for (const logService of this.logServices) {
logService.flush();
}
}
dispose(): void { dispose(): void {
for (const logService of this.logServices) { for (const logService of this.logServices) {
logService.dispose(); logService.dispose();
@@ -346,6 +375,10 @@ export class DelegatedLogService extends Disposable implements ILogService {
critical(message: string | Error, ...args: any[]): void { critical(message: string | Error, ...args: any[]): void {
this.logService.critical(message, ...args); this.logService.critical(message, ...args);
} }
flush(): void {
this.logService.flush();
}
} }
export class NullLogService implements ILogService { export class NullLogService implements ILogService {
@@ -360,6 +393,7 @@ export class NullLogService implements ILogService {
error(message: string | Error, ...args: any[]): void { } error(message: string | Error, ...args: any[]): void { }
critical(message: string | Error, ...args: any[]): void { } critical(message: string | Error, ...args: any[]): void { }
dispose(): void { } dispose(): void { }
flush(): void { }
} }
export function getLogLevel(environmentService: IEnvironmentService): LogLevel { export function getLogLevel(environmentService: IEnvironmentService): LogLevel {

View File

@@ -32,7 +32,7 @@ export class LoggerService extends Disposable implements ILoggerService {
if (resource.scheme === Schemas.file) { if (resource.scheme === Schemas.file) {
const baseName = basename(resource); const baseName = basename(resource);
const ext = extname(resource); const ext = extname(resource);
logger = new SpdLogService(baseName.substring(0, baseName.length - ext.length), dirname(resource).path, this.logService.getLevel()); logger = new SpdLogService(baseName.substring(0, baseName.length - ext.length), dirname(resource).fsPath, this.logService.getLevel());
} else { } else {
logger = this.instantiationService.createInstance(FileLogService, basename(resource), resource, this.logService.getLevel()); logger = this.instantiationService.createInstance(FileLogService, basename(resource), resource, this.logService.getLevel());
} }

View File

@@ -30,7 +30,7 @@ interface ILog {
message: string; message: string;
} }
function log(logger: spdlog.RotatingLogger, level: LogLevel, message: string, sync: boolean): void { function log(logger: spdlog.RotatingLogger, level: LogLevel, message: string): void {
switch (level) { switch (level) {
case LogLevel.Trace: logger.trace(message); break; case LogLevel.Trace: logger.trace(message); break;
case LogLevel.Debug: logger.debug(message); break; case LogLevel.Debug: logger.debug(message); break;
@@ -40,9 +40,6 @@ function log(logger: spdlog.RotatingLogger, level: LogLevel, message: string, sy
case LogLevel.Critical: logger.critical(message); break; case LogLevel.Critical: logger.critical(message); break;
default: throw new Error('Invalid log level'); default: throw new Error('Invalid log level');
} }
if (sync) {
logger.flush();
}
} }
export class SpdLogService extends AbstractLogService implements ILogService { export class SpdLogService extends AbstractLogService implements ILogService {
@@ -53,7 +50,7 @@ export class SpdLogService extends AbstractLogService implements ILogService {
private _loggerCreationPromise: Promise<void> | undefined = undefined; private _loggerCreationPromise: Promise<void> | undefined = undefined;
private _logger: spdlog.RotatingLogger | undefined; private _logger: spdlog.RotatingLogger | undefined;
constructor(private readonly name: string, private readonly logsFolder: string, level: LogLevel, private readonly sync: boolean = false) { constructor(private readonly name: string, private readonly logsFolder: string, level: LogLevel) {
super(); super();
this.setLevel(level); this.setLevel(level);
this._createSpdLogLogger(); this._createSpdLogLogger();
@@ -72,7 +69,7 @@ export class SpdLogService extends AbstractLogService implements ILogService {
this._logger = logger; this._logger = logger;
this._logger.setLevel(this.getLevel()); this._logger.setLevel(this.getLevel());
for (const { level, message } of this.buffer) { for (const { level, message } of this.buffer) {
log(this._logger, level, message, this.sync); log(this._logger, level, message);
} }
this.buffer = []; this.buffer = [];
} }
@@ -83,7 +80,7 @@ export class SpdLogService extends AbstractLogService implements ILogService {
private _log(level: LogLevel, message: string): void { private _log(level: LogLevel, message: string): void {
if (this._logger) { if (this._logger) {
log(this._logger, level, message, this.sync); log(this._logger, level, message);
} else if (this.getLevel() <= level) { } else if (this.getLevel() <= level) {
this.buffer.push({ level, message }); this.buffer.push({ level, message });
} }
@@ -132,6 +129,14 @@ export class SpdLogService extends AbstractLogService implements ILogService {
} }
} }
flush(): void {
if (this._logger) {
this._logger.flush();
} else if (this._loggerCreationPromise) {
this._loggerCreationPromise.then(() => this.flush());
}
}
dispose(): void { dispose(): void {
if (this._logger) { if (this._logger) {
this.disposeLogger(); this.disposeLogger();

View File

@@ -6,7 +6,7 @@
import * as nls from 'vs/nls'; import * as nls from 'vs/nls';
import { isMacintosh, language } from 'vs/base/common/platform'; import { isMacintosh, language } from 'vs/base/common/platform';
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { app, shell, Menu, MenuItem, BrowserWindow, MenuItemConstructorOptions, WebContents, Event, KeyboardEvent } from 'electron'; import { app, shell, Menu, MenuItem, BrowserWindow, MenuItemConstructorOptions, WebContents, Event, Event as KeyboardEvent } from 'electron';
import { OpenContext, IRunActionInWindowRequest, getTitleBarStyle, IRunKeybindingInWindowRequest, IWindowOpenable } from 'vs/platform/windows/common/windows'; import { OpenContext, IRunActionInWindowRequest, getTitleBarStyle, IRunKeybindingInWindowRequest, IWindowOpenable } from 'vs/platform/windows/common/windows';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -368,13 +368,13 @@ export class Menubar {
const servicesMenu = new Menu(); const servicesMenu = new Menu();
const services = new MenuItem({ label: nls.localize('mServices', "Services"), role: 'services', submenu: servicesMenu }); const services = new MenuItem({ label: nls.localize('mServices', "Services"), role: 'services', submenu: servicesMenu });
const hide = new MenuItem({ label: nls.localize('mHide', "Hide {0}", product.nameLong), role: 'hide', accelerator: 'Command+H' }); const hide = new MenuItem({ label: nls.localize('mHide', "Hide {0}", product.nameLong), role: 'hide', accelerator: 'Command+H' });
const hideOthers = new MenuItem({ label: nls.localize('mHideOthers', "Hide Others"), role: 'hideOthers', accelerator: 'Command+Alt+H' }); const hideOthers = new MenuItem({ label: nls.localize('mHideOthers', "Hide Others"), role: 'hideothers', accelerator: 'Command+Alt+H' });
const showAll = new MenuItem({ label: nls.localize('mShowAll', "Show All"), role: 'unhide' }); const showAll = new MenuItem({ label: nls.localize('mShowAll', "Show All"), role: 'unhide' });
const quit = new MenuItem(this.likeAction('workbench.action.quit', { const quit = new MenuItem(this.likeAction('workbench.action.quit', {
label: nls.localize('miQuit', "Quit {0}", product.nameLong), click: () => { label: nls.localize('miQuit', "Quit {0}", product.nameLong), click: () => {
if ( if (
this.windowsMainService.getWindowCount() === 0 || // allow to quit when no more windows are open this.windowsMainService.getWindowCount() === 0 || // allow to quit when no more windows are open
!!this.windowsMainService.getFocusedWindow() || // allow to quit when window has focus (fix for https://github.com/Microsoft/vscode/issues/39191) !!BrowserWindow.getFocusedWindow() || // allow to quit when window has focus (fix for https://github.com/Microsoft/vscode/issues/39191)
this.windowsMainService.getLastActiveWindow()!.isMinimized() // allow to quit when window has no focus but is minimized (https://github.com/Microsoft/vscode/issues/63000) this.windowsMainService.getLastActiveWindow()!.isMinimized() // allow to quit when window has no focus but is minimized (https://github.com/Microsoft/vscode/issues/63000)
) { ) {
this.windowsMainService.quit(); this.windowsMainService.quit();
@@ -557,7 +557,7 @@ export class Menubar {
label: this.mnemonicLabel(nls.localize('miCheckForUpdates', "Check for &&Updates...")), click: () => setTimeout(() => { label: this.mnemonicLabel(nls.localize('miCheckForUpdates', "Check for &&Updates...")), click: () => setTimeout(() => {
this.reportMenuActionTelemetry('CheckForUpdate'); this.reportMenuActionTelemetry('CheckForUpdate');
const focusedWindow = this.windowsMainService.getFocusedWindow(); const focusedWindow = BrowserWindow.getFocusedWindow();
const context = focusedWindow ? { windowId: focusedWindow.id } : null; const context = focusedWindow ? { windowId: focusedWindow.id } : null;
this.updateService.checkForUpdates(context); this.updateService.checkForUpdates(context);
}, 0) }, 0)
@@ -697,15 +697,16 @@ export class Menubar {
private makeContextAwareClickHandler(click: () => void, contextSpecificHandlers: IMenuItemClickHandler): () => void { private makeContextAwareClickHandler(click: () => void, contextSpecificHandlers: IMenuItemClickHandler): () => void {
return () => { return () => {
// No Active Window // No Active Window
const activeWindow = this.windowsMainService.getFocusedWindow(); const activeWindow = BrowserWindow.getFocusedWindow();
if (!activeWindow) { if (!activeWindow) {
return contextSpecificHandlers.inNoWindow(); return contextSpecificHandlers.inNoWindow();
} }
// DevTools focused // DevTools focused
if (activeWindow.win.webContents.isDevToolsFocused()) { if (activeWindow.webContents.isDevToolsFocused()) {
return contextSpecificHandlers.inDevTools(activeWindow.win.webContents.devToolsWebContents); return contextSpecificHandlers.inDevTools(activeWindow.webContents.devToolsWebContents);
} }
// Finally execute command in Window // Finally execute command in Window
@@ -719,14 +720,15 @@ export class Menubar {
// https://github.com/Microsoft/vscode/issues/11928 // https://github.com/Microsoft/vscode/issues/11928
// Still allow to run when the last active window is minimized though for // Still allow to run when the last active window is minimized though for
// https://github.com/Microsoft/vscode/issues/63000 // https://github.com/Microsoft/vscode/issues/63000
let activeWindow = this.windowsMainService.getFocusedWindow(); let activeBrowserWindow = BrowserWindow.getFocusedWindow();
if (!activeWindow) { if (!activeBrowserWindow) {
const lastActiveWindow = this.windowsMainService.getLastActiveWindow(); const lastActiveWindow = this.windowsMainService.getLastActiveWindow();
if (lastActiveWindow && lastActiveWindow.isMinimized()) { if (lastActiveWindow && lastActiveWindow.isMinimized()) {
activeWindow = lastActiveWindow; activeBrowserWindow = lastActiveWindow.win;
} }
} }
const activeWindow = activeBrowserWindow ? this.windowsMainService.getWindowById(activeBrowserWindow.id) : undefined;
if (activeWindow) { if (activeWindow) {
this.logService.trace('menubar#runActionInRenderer', invocation); this.logService.trace('menubar#runActionInRenderer', invocation);

View File

@@ -27,7 +27,7 @@ export function extractLocalHostUriMetaDataForPortMapping(uri: URI): { address:
if (uri.scheme !== 'http' && uri.scheme !== 'https') { if (uri.scheme !== 'http' && uri.scheme !== 'https') {
return undefined; return undefined;
} }
const localhostMatch = /^(localhost|127\.0\.0\.1):(\d+)$/.exec(uri.authority); const localhostMatch = /^(localhost|127\.0\.0\.1|0\.0\.0\.0):(\d+)$/.exec(uri.authority);
if (!localhostMatch) { if (!localhostMatch) {
return undefined; return undefined;
} }

View File

@@ -70,6 +70,7 @@ class TestableLogService extends AbstractLogService implements ILogService {
} }
dispose(): void { } dispose(): void { }
flush(): void { }
} }
suite('AIAdapter', () => { suite('AIAdapter', () => {
@@ -198,4 +199,4 @@ suite('AIAdapter', () => {
} }
}])); }]));
}); });
}); });

View File

@@ -63,6 +63,12 @@ export function registerConfiguration(): IDisposable {
$ref: ignoredSettingsSchemaId, $ref: ignoredSettingsSchemaId,
additionalProperties: true, additionalProperties: true,
uniqueItems: true uniqueItems: true
},
'configurationSync.enableAuth': {
'type': 'boolean',
description: localize('configurationSync.enableAuth', "Enables authentication and requires VS Code restart when changed"),
'default': false,
'scope': ConfigurationScope.APPLICATION
} }
} }
}); });

View File

@@ -44,4 +44,8 @@ export class UserDataSyncLogService extends AbstractLogService implements IUserD
this.logger.critical(message, ...args); this.logger.critical(message, ...args);
} }
flush(): void {
this.logger.flush();
}
} }

View File

@@ -131,27 +131,32 @@ export class UserDataAutoSync extends Disposable {
@IAuthTokenService private readonly authTokenService: IAuthTokenService, @IAuthTokenService private readonly authTokenService: IAuthTokenService,
) { ) {
super(); super();
this.updateEnablement(); this.updateEnablement(false);
this.sync(true); this._register(Event.any<any>(authTokenService.onDidChangeStatus, userDataSyncService.onDidChangeStatus)(() => this.updateEnablement(true)));
this._register(Event.any<any>(authTokenService.onDidChangeStatus, userDataSyncService.onDidChangeStatus)(() => this.updateEnablement())); this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('configurationSync.enable'))(() => this.updateEnablement(true)));
this._register(Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration('configurationSync.enable'))(() => this.updateEnablement()));
// Sync immediately if there is a local change. // Sync immediately if there is a local change.
this._register(Event.debounce(this.userDataSyncService.onDidChangeLocal, () => undefined, 500)(() => this.sync(false))); this._register(Event.debounce(this.userDataSyncService.onDidChangeLocal, () => undefined, 500)(() => this.sync(false)));
} }
private updateEnablement(): void { private updateEnablement(stopIfDisabled: boolean): void {
const enabled = this.isSyncEnabled(); const enabled = this.isSyncEnabled();
if (this.enabled !== enabled) { if (this.enabled === enabled) {
this.enabled = enabled; return;
if (this.enabled) { }
this.userDataSyncLogService.info('Syncing configuration started');
this.sync(true); this.enabled = enabled;
} else { if (this.enabled) {
this.userDataSyncLogService.info('Syncing configuration started');
this.sync(true);
return;
} else {
if (stopIfDisabled) {
this.userDataSyncService.stop(); this.userDataSyncService.stop();
this.userDataSyncLogService.info('Syncing configuration stopped.'); this.userDataSyncLogService.info('Syncing configuration stopped.');
} }
} }
} }
private async sync(loop: boolean): Promise<void> { private async sync(loop: boolean): Promise<void> {

Some files were not shown because too many files have changed in this diff Show More