Merge branch 'main' into joh/swc

This commit is contained in:
Johannes
2022-05-25 12:29:28 +02:00
159 changed files with 1894 additions and 930 deletions
+1
View File
@@ -6,6 +6,7 @@ on:
jobs:
main:
runs-on: ubuntu-latest
if: ${{ !github.event.pull_request.draft }}
steps:
- name: Checkout Actions
uses: actions/checkout@v2
+1 -1
View File
@@ -97,7 +97,7 @@ function writeControlFile(control) {
fs.writeFileSync(controlFilePath, JSON.stringify(control, null, 2));
}
function getBuiltInExtensions() {
log('Syncronizing built-in extensions...');
log('Synchronizing built-in extensions...');
log(`You can manage built-in extensions with the ${ansiColors.cyan('--builtin')} flag`);
const control = readControlFile();
const streams = [];
+1 -1
View File
@@ -136,7 +136,7 @@ function writeControlFile(control: IControlFile): void {
}
export function getBuiltInExtensions(): Promise<void> {
log('Syncronizing built-in extensions...');
log('Synchronizing built-in extensions...');
log(`You can manage built-in extensions with the ${ansiColors.cyan('--builtin')} flag`);
const control = readControlFile();
+1 -1
View File
@@ -119,7 +119,7 @@
"project": "vscode-workbench"
},
{
"name": "vs/workbench/contrib/localizations",
"name": "vs/workbench/contrib/localization",
"project": "vscode-workbench"
},
{
+6
View File
@@ -416,6 +416,7 @@ export class CommandCenter {
if (!url) {
/* __GDPR__
"clone" : {
"owner": "lszomoru",
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
@@ -441,6 +442,7 @@ export class CommandCenter {
if (!uris || uris.length === 0) {
/* __GDPR__
"clone" : {
"owner": "lszomoru",
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
@@ -499,6 +501,7 @@ export class CommandCenter {
/* __GDPR__
"clone" : {
"owner": "lszomoru",
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"openFolder": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }
}
@@ -518,6 +521,7 @@ export class CommandCenter {
if (/already exists and is not an empty directory/.test(err && err.stderr || '')) {
/* __GDPR__
"clone" : {
"owner": "lszomoru",
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
@@ -527,6 +531,7 @@ export class CommandCenter {
} else {
/* __GDPR__
"clone" : {
"owner": "lszomoru",
"outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
@@ -2920,6 +2925,7 @@ export class CommandCenter {
/* __GDPR__
"git.command" : {
"owner": "lszomoru",
"command" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
+3 -1
View File
@@ -192,7 +192,9 @@ export async function _activate(context: ExtensionContext): Promise<GitExtension
outputChannelLogger.logWarning(err.message);
/* __GDPR__
"git.missing" : {}
"git.missing" : {
"owner": "lszomoru"
}
*/
telemetryReporter.sendTelemetryEvent('git.missing');
+1
View File
@@ -1864,6 +1864,7 @@ export class Repository implements Disposable {
if (didHitLimit) {
/* __GDPR__
"statusLimit" : {
"owner": "lszomoru",
"ignoreSubmodules": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"limit": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"statusLength": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
@@ -496,6 +496,7 @@ export class GitHubServer implements IGitHubServer {
/* __GDPR__
"session" : {
"owner": "TylerLeonhardt",
"isEdu": { "classification": "NonIdentifiableDemographicInfo", "purpose": "FeatureInsight" }
}
*/
@@ -530,6 +531,7 @@ export class GitHubServer implements IGitHubServer {
/* __GDPR__
"ghe-session" : {
"owner": "TylerLeonhardt",
"version": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
@@ -601,6 +603,7 @@ export class GitHubEnterpriseServer implements IGitHubServer {
/* __GDPR__
"ghe-session" : {
"owner": "TylerLeonhardt",
"version": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
@@ -31,7 +31,7 @@ module.exports = function () {
queue.push(name);
};
enqueue('es6');
enqueue('es2020.full');
var result = [];
while (queue.length > 0) {
@@ -24,7 +24,7 @@ export function loadLibrary(name: string) {
try {
content = readFileSync(libPath).toString();
} catch (e) {
console.log(`Unable to load library ${name} at ${libPath}: ${e.message}`);
console.log(`Unable to load library ${name} at ${libPath}`);
content = '';
}
contents[name] = content;
@@ -19,7 +19,7 @@ import { getSemanticTokens, getSemanticTokenLegend } from './javascriptSemanticT
const JS_WORD_REGEX = /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g;
function getLanguageServiceHost(scriptKind: ts.ScriptKind) {
const compilerOptions: ts.CompilerOptions = { allowNonTsExtensions: true, allowJs: true, lib: ['lib.es6.d.ts'], target: ts.ScriptTarget.Latest, moduleResolution: ts.ModuleResolutionKind.Classic, experimentalDecorators: false };
const compilerOptions: ts.CompilerOptions = { allowNonTsExtensions: true, allowJs: true, lib: ['lib.es2020.full.d.ts'], target: ts.ScriptTarget.Latest, moduleResolution: ts.ModuleResolutionKind.Classic, experimentalDecorators: false };
let currentTextDocument = TextDocument.create('init', 'javascript', 1, '');
const jsLanguageService = import(/* webpackChunkName: "javascriptLibs" */ './javascriptLibs').then(libs => {
@@ -52,7 +52,7 @@ function getLanguageServiceHost(scriptKind: ts.ScriptKind) {
};
},
getCurrentDirectory: () => '',
getDefaultLibFileName: (_options: ts.CompilerOptions) => 'es6',
getDefaultLibFileName: (_options: ts.CompilerOptions) => 'es2020.full',
readFile: (path: string, _encoding?: string | undefined): string | undefined => {
if (path === currentTextDocument.uri) {
return currentTextDocument.getText();
@@ -66,6 +66,15 @@ function getLanguageServiceHost(scriptKind: ts.ScriptKind) {
} else {
return !!libs.loadLibrary(path);
}
},
directoryExists: (path: string): boolean => {
// typescript tries to first find libraries in node_modules/@types and node_modules/@typescript
// there's no node_modules in our setup
if (path.startsWith('node_modules')) {
return false;
}
return true;
}
};
return ts.createLanguageService(host);
@@ -16,7 +16,8 @@
"Programming Languages"
],
"enabledApiProposals": [
"textEditorDrop"
"textEditorDrop",
"documentPaste"
],
"activationEvents": [
"onLanguage:markdown",
@@ -414,6 +415,12 @@
"markdownDescription": "%configuration.markdown.editor.drop.enabled%",
"scope": "resource"
},
"markdown.experimental.editor.pasteLinks.enabled": {
"type": "boolean",
"default": false,
"markdownDescription": "%configuration.markdown.editor.pasteLinks.enabled%",
"scope": "resource"
},
"markdown.experimental.validate.enabled": {
"type": "boolean",
"scope": "resource",
@@ -28,7 +28,8 @@
"configuration.markdown.links.openLocation.currentGroup": "Open links in the active editor group.",
"configuration.markdown.links.openLocation.beside": "Open links beside the active editor.",
"configuration.markdown.suggest.paths.enabled.description": "Enable/disable path suggestions for markdown links",
"configuration.markdown.editor.drop.enabled": "Enable/disable dropping into the markdown editor to insert shift. Requires enabling `#workbench.experimental.editor.dropIntoEditor.enabled#`.",
"configuration.markdown.editor.drop.enabled": "Enable/disable dropping into the markdown editor to insert shift. Requires enabling `#workbenck.experimental.editor.dropIntoEditor.enabled#`.",
"configuration.markdown.editor.pasteLinks.enabled": "Enable/disable pasting files into a Markdown editor inserts Markdown links.",
"configuration.markdown.experimental.validate.enabled.description": "Enable/disable all error reporting in Markdown files.",
"configuration.markdown.experimental.validate.referenceLinks.enabled.description": "Validate reference links in Markdown files, e.g. `[link][ref]`. Requires enabling `#markdown.experimental.validate.enabled#`.",
"configuration.markdown.experimental.validate.headerLinks.enabled.description": "Validate links to headers in Markdown files, e.g. `[link](#header)`. Requires enabling `#markdown.experimental.validate.enabled#`.",
@@ -6,8 +6,9 @@
import * as vscode from 'vscode';
import { CommandManager } from './commandManager';
import * as commands from './commands/index';
import { register as registerDiagnostics } from './languageFeatures/diagnostics';
import { registerPasteProvider } from './languageFeatures/copyPaste';
import { MdDefinitionProvider } from './languageFeatures/definitionProvider';
import { register as registerDiagnostics } from './languageFeatures/diagnostics';
import { MdLinkProvider } from './languageFeatures/documentLinkProvider';
import { MdDocumentSymbolProvider } from './languageFeatures/documentSymbolProvider';
import { registerDropIntoEditor } from './languageFeatures/dropIntoEditor';
@@ -78,6 +79,7 @@ function registerMarkdownLanguageFeatures(
MdPathCompletionProvider.register(selector, engine, linkProvider),
registerDiagnostics(selector, engine, workspaceContents, linkProvider, commandManager),
registerDropIntoEditor(selector),
registerPasteProvider(selector),
registerFindFileReferences(commandManager, referencesProvider),
);
}
@@ -0,0 +1,26 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { tryInsertUriList } from './dropIntoEditor';
export function registerPasteProvider(selector: vscode.DocumentSelector) {
return vscode.languages.registerDocumentPasteEditProvider(selector, new class implements vscode.DocumentPasteEditProvider {
async provideDocumentPasteEdits(
document: vscode.TextDocument,
range: vscode.Range,
dataTransfer: vscode.DataTransfer,
token: vscode.CancellationToken,
): Promise<vscode.SnippetTextEdit | undefined> {
const enabled = vscode.workspace.getConfiguration('markdown', document).get('experimental.editor.pasteLinks.enabled', false);
if (!enabled) {
return;
}
return tryInsertUriList(document, range, dataTransfer, token);
}
});
}
@@ -32,45 +32,45 @@ export function registerDropIntoEditor(selector: vscode.DocumentSelector) {
}
const replacementRange = new vscode.Range(position, position);
return this.tryInsertUriList(document, replacementRange, dataTransfer, token);
}
private async tryInsertUriList(document: vscode.TextDocument, replacementRange: vscode.Range, dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise<vscode.SnippetTextEdit | undefined> {
const urlList = await dataTransfer.get('text/uri-list')?.asString();
if (!urlList || token.isCancellationRequested) {
return undefined;
}
const uris: vscode.Uri[] = [];
for (const resource of urlList.split('\n')) {
try {
uris.push(vscode.Uri.parse(resource));
} catch {
// noop
}
}
if (!uris.length) {
return;
}
const snippet = new vscode.SnippetString();
uris.forEach((uri, i) => {
const mdPath = document.uri.scheme === uri.scheme
? encodeURI(path.relative(URI.Utils.dirname(document.uri).fsPath, uri.fsPath).replace(/\\/g, '/'))
: uri.toString(false);
const ext = URI.Utils.extname(uri).toLowerCase();
snippet.appendText(imageFileExtensions.has(ext) ? '![' : '[');
snippet.appendTabstop();
snippet.appendText(`](${mdPath})`);
if (i <= uris.length - 1 && uris.length > 1) {
snippet.appendText(' ');
}
});
return new vscode.SnippetTextEdit(replacementRange, snippet);
return tryInsertUriList(document, replacementRange, dataTransfer, token);
}
});
}
export async function tryInsertUriList(document: vscode.TextDocument, replacementRange: vscode.Range, dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise<vscode.SnippetTextEdit | undefined> {
const urlList = await dataTransfer.get('text/uri-list')?.asString();
if (!urlList || token.isCancellationRequested) {
return undefined;
}
const uris: vscode.Uri[] = [];
for (const resource of urlList.split('\n')) {
try {
uris.push(vscode.Uri.parse(resource));
} catch {
// noop
}
}
if (!uris.length) {
return;
}
const snippet = new vscode.SnippetString();
uris.forEach((uri, i) => {
const mdPath = document.uri.scheme === uri.scheme
? encodeURI(path.relative(URI.Utils.dirname(document.uri).fsPath, uri.fsPath).replace(/\\/g, '/'))
: uri.toString(false);
const ext = URI.Utils.extname(uri).toLowerCase();
snippet.appendText(imageFileExtensions.has(ext) ? '![' : '[');
snippet.appendTabstop();
snippet.appendText(`](${mdPath})`);
if (i <= uris.length - 1 && uris.length > 1) {
snippet.appendText(' ');
}
});
return new vscode.SnippetTextEdit(replacementRange, snippet);
}
@@ -7,6 +7,7 @@
"src/**/*",
"../../src/vscode-dts/vscode.d.ts",
"../../src/vscode-dts/vscode.proposed.textEditorDrop.d.ts",
"../../src/vscode-dts/vscode.proposed.dataTransferFiles.d.ts"
"../../src/vscode-dts/vscode.proposed.dataTransferFiles.d.ts",
"../../src/vscode-dts/vscode.proposed.documentPaste.d.ts"
]
}
+1 -1
View File
@@ -4,7 +4,7 @@
"license": "MIT",
"description": "Dependencies shared by all extensions",
"dependencies": {
"typescript": "4.7.1-rc"
"typescript": "4.7"
},
"scripts": {
"postinstall": "node ./postinstall.mjs"
@@ -554,6 +554,7 @@ class CompletionAcceptedCommand implements Command {
if (item instanceof MyCompletionItem) {
/* __GDPR__
"completions.accept" : {
"owner": "mjbvz",
"isPackageJsonImport" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"isImportStatementCompletion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"${include}": [
@@ -820,6 +821,7 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider<
) {
/* __GDPR__
"completions.execute" : {
"owner": "mjbvz",
"duration" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
@@ -32,6 +32,7 @@ class OrganizeImportsCommand implements Command {
public async execute(file: string, sortOnly = false): Promise<any> {
/* __GDPR__
"organizeImports.execute" : {
"owner": "mjbvz",
"${include}": [
"${TypeScriptCommonProperties}"
]
@@ -37,6 +37,7 @@ class ApplyCodeActionCommand implements Command {
): Promise<boolean> {
/* __GDPR__
"quickFix.execute" : {
"owner": "mjbvz",
"fixName" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"${include}": [
"${TypeScriptCommonProperties}"
@@ -67,6 +68,7 @@ class ApplyFixAllCodeAction implements Command {
public async execute(args: ApplyFixAllCodeAction_args): Promise<void> {
/* __GDPR__
"quickFixAll.execute" : {
"owner": "mjbvz",
"fixName" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"${include}": [
"${TypeScriptCommonProperties}"
@@ -36,6 +36,7 @@ class DidApplyRefactoringCommand implements Command {
public async execute(args: DidApplyRefactoringCommand_Args): Promise<void> {
/* __GDPR__
"refactor.execute" : {
"owner": "mjbvz",
"action" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"${include}": [
"${TypeScriptCommonProperties}"
@@ -230,6 +230,7 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
if (!executeInfo.token || !executeInfo.token.isCancellationRequested) {
/* __GDPR__
"languageServiceErrorResponse" : {
"owner": "mjbvz",
"${include}": [
"${TypeScriptCommonProperties}",
"${TypeScriptRequestErrorProperties}"
@@ -388,6 +388,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
/* __GDPR__
"tsserver.spawned" : {
"owner": "mjbvz",
"${include}": [
"${TypeScriptCommonProperties}"
],
@@ -418,6 +419,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
/* __GDPR__
"tsserver.error" : {
"owner": "mjbvz",
"${include}": [
"${TypeScriptCommonProperties}"
]
@@ -443,6 +445,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
this.error(`TSServer exited with code: ${code}. Signal: ${signal}`);
/* __GDPR__
"tsserver.exitWithCode" : {
"owner": "mjbvz",
"code" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
"signal" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
"${include}": [
@@ -601,6 +604,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
/* __GDPR__
"serviceExited" : {
"owner": "mjbvz",
"${include}": [
"${TypeScriptCommonProperties}"
]
@@ -846,6 +850,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
private fatalError(command: string, error: unknown): void {
/* __GDPR__
"fatalError" : {
"owner": "mjbvz",
"${include}": [
"${TypeScriptCommonProperties}",
"${TypeScriptRequestErrorProperties}"
@@ -977,6 +982,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
/* __GDPR__
"typingsInstalled" : {
"owner": "mjbvz",
"installedPackages" : { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"installSuccess": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
"typingsInstallerVersion": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
@@ -49,6 +49,7 @@ class ExcludeHintItem {
this._item.show();
/* __GDPR__
"js.hintProjectExcludes" : {
"owner": "mjbvz",
"${include}": [
"${TypeScriptCommonProperties}"
]
+4 -4
View File
@@ -42,10 +42,10 @@ node-gyp-build@^4.3.0:
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==
typescript@4.7.1-rc:
version "4.7.1-rc"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.1-rc.tgz#23a0517d36c56de887b4457f29e2d265647bbd7c"
integrity sha512-EQd2NVelDe6ZVc2sO1CSpuSs+RHzY8c2n/kTNQAHw4um/eAXY+ZY4IKoUpNK0wO6C5hN+XcUXR7yqT8VbwwNIQ==
typescript@4.7:
version "4.7.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4"
integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==
vscode-grammar-updater@^1.1.0:
version "1.1.0"
+18
View File
@@ -37,6 +37,11 @@ if (process.env['VSCODE_PARENT_PID']) {
terminateWhenParentTerminates();
}
// Listen for message ports
if (process.env['VSCODE_WILL_SEND_MESSAGE_PORT']) {
listenForMessagePort();
}
// Load AMD entry point
require('./bootstrap-amd').load(process.env['VSCODE_AMD_ENTRYPOINT']);
@@ -264,4 +269,17 @@ function terminateWhenParentTerminates() {
}
}
function listenForMessagePort() {
// We need to listen for the 'port' event as soon as possible,
// otherwise we might miss the event. But we should also be
// prepared in case the event arrives late.
process.on('port', (e) => {
if (global.vscodePortsCallback) {
global.vscodePortsCallback(e.ports);
} else {
global.vscodePorts = e.ports;
}
});
}
//#endregion
+1
View File
@@ -14,6 +14,7 @@ export interface ITelemetryData {
}
export type WorkbenchActionExecutedClassification = {
owner: 'bpasero';
id: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
from: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
+4
View File
@@ -37,6 +37,10 @@ export class VSDataTransfer {
this._data.set(mimeType, value);
}
public delete(mimeType: string) {
this._data.delete(mimeType);
}
public setString(mimeType: string, stringOrPromise: string | Promise<string>) {
this.set(mimeType, {
asString: async () => stringOrPromise,
@@ -4,13 +4,13 @@
*--------------------------------------------------------------------------------------------*/
import { Disposable } from 'vs/base/common/lifecycle';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
import { LanguagePackService } from 'vs/platform/languagePacks/node/languagePacks';
export class LocalizationsUpdater extends Disposable {
constructor(
@ILocalizationsService private readonly localizationsService: LocalizationsService
@ILanguagePackService private readonly localizationsService: LanguagePackService
) {
super();
@@ -46,8 +46,8 @@ import { InstantiationService } from 'vs/platform/instantiation/common/instantia
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { MessagePortMainProcessService } from 'vs/platform/ipc/electron-browser/mainProcessService';
import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/services';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
import { LanguagePackService } from 'vs/platform/languagePacks/node/languagePacks';
import { ConsoleLogger, ILoggerService, ILogService, MultiplexLogService } from 'vs/platform/log/common/log';
import { FollowerLogService, LoggerChannelClient, LogLevelChannelClient } from 'vs/platform/log/common/logIpc';
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
@@ -311,7 +311,7 @@ class SharedProcessMain extends Disposable {
services.set(IExtensionTipsService, new SyncDescriptor(ExtensionTipsService));
// Localizations
services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService));
services.set(ILanguagePackService, new SyncDescriptor(LanguagePackService));
// Diagnostics
services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService));
@@ -360,9 +360,9 @@ class SharedProcessMain extends Disposable {
const channel = new ExtensionManagementChannel(accessor.get(IExtensionManagementService), () => null);
this.server.registerChannel('extensions', channel);
// Localizations
const localizationsChannel = ProxyChannel.fromService(accessor.get(ILocalizationsService));
this.server.registerChannel('localizations', localizationsChannel);
// Language Packs
const languagePacksChannel = ProxyChannel.fromService(accessor.get(ILanguagePackService));
this.server.registerChannel('languagePacks', languagePacksChannel);
// Diagnostics
const diagnosticsChannel = ProxyChannel.fromService(accessor.get(IDiagnosticsService));
+1 -1
View File
@@ -1105,7 +1105,7 @@ export class CodeApplication extends Disposable {
code: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The type of shared process crash to understand the nature of the crash better.' };
visible: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Whether shared process window was visible or not.' };
shuttingdown: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Whether the application is shutting down when the crash happens.' };
owner: 'bpaser';
owner: 'bpasero';
comment: 'Event which fires whenever an error occurs in the shared process';
};
+3 -3
View File
@@ -36,8 +36,8 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
import { LanguagePackService } from 'vs/platform/languagePacks/node/languagePacks';
import { ConsoleLogger, getLogLevel, ILogger, ILogService, LogLevel, MultiplexLogService } from 'vs/platform/log/common/log';
import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog';
import { FilePolicyService } from 'vs/platform/policy/common/filePolicyService';
@@ -161,7 +161,7 @@ class CliMain extends Disposable {
services.set(IExtensionManagementCLIService, new SyncDescriptor(ExtensionManagementCLIService));
// Localizations
services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService));
services.set(ILanguagePackService, new SyncDescriptor(LanguagePackService));
// Telemetry
const appenders: AppInsightsAppender[] = [];
+28
View File
@@ -0,0 +1,28 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { VSDataTransfer } from 'vs/base/common/dataTransfer';
import { URI } from 'vs/base/common/uri';
export function toVSDataTransfer(dataTransfer: DataTransfer) {
const vsDataTransfer = new VSDataTransfer();
for (const item of dataTransfer.items) {
const type = item.type;
if (item.kind === 'string') {
const asStringValue = new Promise<string>(resolve => item.getAsString(resolve));
vsDataTransfer.setString(type, asStringValue);
} else if (item.kind === 'file') {
const file = item.getAsFile() as null | (File & { path?: string });
if (file) {
const uri = file.path ? URI.parse(file.path) : undefined;
vsDataTransfer.setFile(type, file.name, uri, async () => {
return new Uint8Array(await file.arrayBuffer());
});
}
}
}
return vsDataTransfer;
}
@@ -338,6 +338,7 @@ export abstract class EditorAction extends EditorCommand {
protected reportTelemetry(accessor: ServicesAccessor, editor: ICodeEditor) {
type EditorActionInvokedClassification = {
owner: 'alexdima';
name: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
id: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
+9
View File
@@ -721,6 +721,15 @@ export interface CodeActionProvider {
_getAdditionalMenuItems?(context: CodeActionContext, actions: readonly CodeAction[]): Command[];
}
/**
* @internal
*/
export interface DocumentPasteEditProvider {
prepareDocumentPaste?(model: model.ITextModel, selection: Selection, dataTransfer: VSDataTransfer, token: CancellationToken): Promise<undefined | VSDataTransfer>;
provideDocumentPasteEdits(model: model.ITextModel, selection: Selection, dataTransfer: VSDataTransfer, token: CancellationToken): Promise<WorkspaceEdit | SnippetTextEdit | undefined>;
}
/**
* Represents a parameter of a callable-signature. A parameter can
* have a label and a doc-comment.
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { LanguageFeatureRegistry, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry';
import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages';
import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentPasteEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const ILanguageFeaturesService = createDecorator<ILanguageFeaturesService>('ILanguageFeaturesService');
@@ -25,6 +25,8 @@ export interface ILanguageFeaturesService {
readonly codeActionProvider: LanguageFeatureRegistry<CodeActionProvider>;
readonly documentPasteEditProvider: LanguageFeatureRegistry<DocumentPasteEditProvider>;
readonly renameProvider: LanguageFeatureRegistry<RenameProvider>;
readonly documentFormattingEditProvider: LanguageFeatureRegistry<DocumentFormattingEditProvider>;
@@ -5,7 +5,7 @@
import { URI } from 'vs/base/common/uri';
import { LanguageFeatureRegistry, NotebookInfo, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry';
import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages';
import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DocumentPasteEditProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
@@ -41,6 +41,7 @@ export class LanguageFeaturesService implements ILanguageFeaturesService {
readonly documentRangeSemanticTokensProvider = new LanguageFeatureRegistry<DocumentRangeSemanticTokensProvider>(this._score.bind(this));
readonly documentSemanticTokensProvider = new LanguageFeatureRegistry<DocumentSemanticTokensProvider>(this._score.bind(this));
readonly documentOnDropEditProvider = new LanguageFeatureRegistry<DocumentOnDropEditProvider>(this._score.bind(this));
readonly documentPasteEditProvider = new LanguageFeatureRegistry<DocumentPasteEditProvider>(this._score.bind(this));
private _notebookTypeResolver?: NotebookInfoResolver;
@@ -0,0 +1,25 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { editorConfigurationBaseNode } from 'vs/editor/common/config/editorConfigurationSchema';
import { CopyPasteController } from 'vs/editor/contrib/copyPaste/browser/copyPasteController';
import * as nls from 'vs/nls';
import { ConfigurationScope, Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
registerEditorContribution(CopyPasteController.ID, CopyPasteController);
Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration({
...editorConfigurationBaseNode,
properties: {
'editor.experimental.pasteActions.enabled': {
type: 'boolean',
scope: ConfigurationScope.LANGUAGE_OVERRIDABLE,
description: nls.localize('pasteActions', "Enable/disable running edits from extensions on paste."),
default: false,
},
}
});
@@ -0,0 +1,195 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { addDisposableListener } from 'vs/base/browser/dom';
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { VSDataTransfer } from 'vs/base/common/dataTransfer';
import { Disposable } from 'vs/base/common/lifecycle';
import { Mimes } from 'vs/base/common/mime';
import { generateUuid } from 'vs/base/common/uuid';
import { toVSDataTransfer } from 'vs/editor/browser/dnd';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IBulkEditService, ResourceEdit, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService';
import { Selection } from 'vs/editor/common/core/selection';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { DocumentPasteEditProvider, SnippetTextEdit, WorkspaceEdit } from 'vs/editor/common/languages';
import { ITextModel } from 'vs/editor/common/model';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { CodeEditorStateFlag, EditorStateCancellationTokenSource } from 'vs/editor/contrib/editorState/browser/editorState';
import { performSnippetEdit } from 'vs/editor/contrib/snippet/browser/snippetController2';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
const vscodeClipboardMime = 'application/vnd.code.copyId';
class DefaultPasteEditProvider implements DocumentPasteEditProvider {
async provideDocumentPasteEdits(model: ITextModel, selection: Selection, dataTransfer: VSDataTransfer, _token: CancellationToken): Promise<WorkspaceEdit | undefined> {
const textDataTransfer = dataTransfer.get(Mimes.text) ?? dataTransfer.get('text');
if (textDataTransfer) {
const text = await textDataTransfer.asString();
return {
edits: [new ResourceTextEdit(model.uri, { range: selection, text })]
};
}
return undefined;
}
}
export class CopyPasteController extends Disposable implements IEditorContribution {
public static readonly ID = 'editor.contrib.copyPasteActionController';
public static get(editor: ICodeEditor): CopyPasteController {
return editor.getContribution<CopyPasteController>(CopyPasteController.ID)!;
}
private readonly _editor: ICodeEditor;
private _currentClipboardItem: undefined | {
readonly handle: string;
readonly dataTransferPromise: CancelablePromise<VSDataTransfer>;
};
constructor(
editor: ICodeEditor,
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
@IClipboardService private readonly _clipboardService: IClipboardService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
) {
super();
this._editor = editor;
this._languageFeaturesService.documentPasteEditProvider.register('*', new DefaultPasteEditProvider());
const container = editor.getContainerDomNode();
this._register(addDisposableListener(container, 'copy', (e: ClipboardEvent) => {
if (!e.clipboardData) {
return;
}
const model = editor.getModel();
const selection = this._editor.getSelection();
if (!model || !selection) {
return;
}
if (!this.arePasteActionsEnabled(model)) {
return;
}
const providers = this._languageFeaturesService.documentPasteEditProvider.ordered(model).filter(x => !!x.prepareDocumentPaste);
if (!providers.length) {
return;
}
const dataTransfer = toVSDataTransfer(e.clipboardData);
// Save off a handle pointing to data that VS Code maintains.
const handle = generateUuid();
e.clipboardData.setData(vscodeClipboardMime, handle);
const promise = createCancelablePromise(async token => {
const results = await Promise.all(providers.map(provider => {
return provider.prepareDocumentPaste!(model, selection, dataTransfer, token);
}));
for (const result of results) {
result?.forEach((value, key) => {
dataTransfer.set(key, value);
});
}
return dataTransfer;
});
this._currentClipboardItem?.dataTransferPromise.cancel();
this._currentClipboardItem = { handle: handle, dataTransferPromise: promise };
}));
this._register(addDisposableListener(container, 'paste', async (e: ClipboardEvent) => {
const selection = this._editor.getSelection();
if (!e.clipboardData || !selection || !editor.hasModel()) {
return;
}
const model = editor.getModel();
if (!this.arePasteActionsEnabled(model)) {
return;
}
const originalDocVersion = model.getVersionId();
const providers = this._languageFeaturesService.documentPasteEditProvider.ordered(model);
if (!providers.length) {
return;
}
const handle = e.clipboardData?.getData(vscodeClipboardMime);
if (typeof handle !== 'string') {
return;
}
e.preventDefault();
e.stopImmediatePropagation();
const tokenSource = new EditorStateCancellationTokenSource(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Selection);
try {
const dataTransfer = toVSDataTransfer(e.clipboardData);
if (handle && this._currentClipboardItem?.handle === handle) {
const toMergeDataTransfer = await this._currentClipboardItem.dataTransferPromise;
toMergeDataTransfer.forEach((value, key) => {
dataTransfer.set(key, value);
});
}
if (!dataTransfer.has(Mimes.uriList)) {
const resources = await this._clipboardService.readResources();
if (resources.length) {
const value = resources.join('\n');
dataTransfer.set(Mimes.uriList, {
value,
asString: async () => value,
asFile: () => undefined,
});
}
}
dataTransfer.delete(vscodeClipboardMime);
for (const provider of providers) {
const edit = await provider.provideDocumentPasteEdits(model, selection, dataTransfer, tokenSource.token);
if (originalDocVersion !== model.getVersionId()) {
return;
}
if (edit) {
if ((edit as WorkspaceEdit).edits) {
await this._bulkEditService.apply(ResourceEdit.convert(edit as WorkspaceEdit), { editor });
} else {
performSnippetEdit(editor, edit as SnippetTextEdit);
}
return;
}
}
} finally {
tokenSource.dispose();
}
}, true));
}
public arePasteActionsEnabled(model: ITextModel): boolean {
return this._configurationService.getValue('editor.experimental.pasteActions.enabled', {
resource: model.uri
});
}
}
@@ -121,10 +121,8 @@ export class DropIntoEditorController extends Disposable implements IEditorContr
.map(input => input.resource!.toString());
if (editorData.length) {
const added = new VSDataTransfer();
const str = distinct(editorData).join('\n');
added.setString(Mimes.uriList.toLowerCase(), str);
return added;
textEditorDataTransfer.setString(Mimes.uriList.toLowerCase(), str);
}
}
@@ -188,3 +186,4 @@ class DefaultOnDropProvider implements DocumentOnDropEditProvider {
registerEditorContribution(DropIntoEditorController.ID, DropIntoEditorController);
@@ -451,11 +451,11 @@ export class SuggestController implements IEditorContribution {
type AcceptedSuggestionClassification = {
owner: 'jrieken';
comment: 'Information accepting completion items';
providerId: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comments: 'Provider of the completions item' };
basenameHash: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comments: 'Hash of the basename of the file into which the completion was inserted' };
fileExtension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comments: 'File extension of the file into which the completion was inserted' };
languageId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comments: 'Language type of the file into which the completion was inserted' };
kind: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comments: 'The completion item kind' };
providerId: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comment: 'Provider of the completions item' };
basenameHash: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight'; comment: 'Hash of the basename of the file into which the completion was inserted' };
fileExtension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'File extension of the file into which the completion was inserted' };
languageId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Language type of the file into which the completion was inserted' };
kind: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The completion item kind' };
};
// _debugDisplayName looks like `vscode.css-language-features(/-:)`, where the last bit is the trigger chars
// normalize it to just the extension ID and lowercase
+1
View File
@@ -15,6 +15,7 @@ import 'vs/editor/contrib/clipboard/browser/clipboard';
import 'vs/editor/contrib/codeAction/browser/codeActionContributions';
import 'vs/editor/contrib/codelens/browser/codelensController';
import 'vs/editor/contrib/colorPicker/browser/colorContributions';
import 'vs/editor/contrib/copyPaste/browser/copyPasteContribution';
import 'vs/editor/contrib/comment/browser/comment';
import 'vs/editor/contrib/contextmenu/browser/contextmenu';
import 'vs/editor/contrib/cursorUndo/browser/cursorUndo';
@@ -536,8 +536,10 @@ export class DiagnosticsService implements IDiagnosticsService {
try {
const stats = await collectWorkspaceStats(folder, ['node_modules', '.git']);
type WorkspaceStatsClassification = {
'workspace.id': { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
rendererSessionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
owner: 'lramos15';
comment: 'Metadata related to the workspace';
'workspace.id': { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'A UUID given to a workspace to identify it.' };
rendererSessionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the session' };
};
type WorkspaceStatsEvent = {
'workspace.id': string | undefined;
@@ -548,9 +550,11 @@ export class DiagnosticsService implements IDiagnosticsService {
rendererSessionId: workspace.rendererSessionId
});
type WorkspaceStatsFileClassification = {
rendererSessionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
type: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
count: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
owner: 'lramos15';
comment: 'Helps us gain insights into what type of files are being used in a workspace';
rendererSessionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the session.' };
type: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'The type of file' };
count: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true; comment: 'How many types of that file are present' };
};
type WorkspaceStatsFileEvent = {
rendererSessionId: string;
+1 -1
View File
@@ -7,7 +7,7 @@ import { getClientArea, getTopLeftOffset } from 'vs/base/browser/dom';
import { coalesce } from 'vs/base/common/arrays';
import { language, locale } from 'vs/base/common/platform';
import { IElement, ILocaleInfo, ILocalizedStrings, IWindowDriver } from 'vs/platform/driver/common/driver';
import localizedStrings from 'vs/platform/localizations/common/localizedStrings';
import localizedStrings from 'vs/platform/languagePacks/common/localizedStrings';
export class BrowserWindowDriver implements IWindowDriver {
@@ -616,6 +616,7 @@ export function reportTelemetry(telemetryService: ITelemetryService, eventName:
const errorcode = error ? error instanceof ExtensionManagementError ? error.code : ExtensionManagementErrorCode.Internal : undefined;
/* __GDPR__
"extensionGallery:install" : {
"owner": "sandy081",
"success": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"durationSinceUpdate" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
@@ -628,6 +629,7 @@ export function reportTelemetry(telemetryService: ITelemetryService, eventName:
*/
/* __GDPR__
"extensionGallery:uninstall" : {
"owner": "sandy081",
"success": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"errorcode": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
@@ -638,6 +640,7 @@ export function reportTelemetry(telemetryService: ITelemetryService, eventName:
*/
/* __GDPR__
"extensionGallery:update" : {
"owner": "sandy081",
"success": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"duration" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"errorcode": { "classification": "CallstackOrException", "purpose": "PerformanceAndHealth" },
@@ -235,6 +235,7 @@ const DefaultQueryState: IQueryState = {
};
type GalleryServiceQueryClassification = {
owner: 'sandy081';
readonly filterTypes: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
readonly flags: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
readonly sortBy: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
@@ -272,6 +273,7 @@ type GalleryServiceQueryEvent = QueryTelemetryData & {
};
type GalleryServiceAdditionalQueryClassification = {
owner: 'sandy081';
readonly duration: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; 'isMeasurement': true };
readonly count: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
@@ -992,6 +994,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi
const startTime = new Date().getTime();
/* __GDPR__
"galleryService:downloadVSIX" : {
"owner": "sandy081",
"duration": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true },
"${include}": [
"${GalleryExtensionTelemetryData}"
@@ -1124,6 +1127,7 @@ abstract class AbstractExtensionGalleryService implements IExtensionGalleryServi
const message = getErrorMessage(err);
type GalleryServiceCDNFallbackClassification = {
owner: 'sandy081';
url: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
message: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
@@ -27,6 +27,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
type ExeExtensionRecommendationsClassification = {
owner: 'sandy081';
extensionId: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight' };
exeName: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight' };
};
@@ -12,6 +12,9 @@ export const IExtensionHostStarter = createDecorator<IExtensionHostStarter>('ext
export const ipcExtensionHostStarterChannelName = 'extensionHostStarter';
export interface IExtensionHostProcessOptions {
responseWindowId: number;
responseChannel: string;
responseNonce: string;
env: { [key: string]: string | undefined };
detached: boolean;
execArgv: string[] | undefined;
@@ -27,8 +30,9 @@ export interface IExtensionHostStarter {
onDynamicError(id: string): Event<{ error: SerializedError }>;
onDynamicExit(id: string): Event<{ code: number; signal: string }>;
createExtensionHost(): Promise<{ id: string }>;
start(id: string, opts: IExtensionHostProcessOptions): Promise<{ pid: number }>;
canUseUtilityProcess(): Promise<boolean>;
createExtensionHost(useUtilityProcess: boolean): Promise<{ id: string }>;
start(id: string, opts: IExtensionHostProcessOptions): Promise<void>;
enableInspectPort(id: string): Promise<boolean>;
kill(id: string): Promise<void>;
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { canceled, SerializedError, transformErrorForSerialization } from 'vs/base/common/errors';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { IExtensionHostProcessOptions, IExtensionHostStarter } from 'vs/platform/extensions/common/extensionHostStarter';
import { Emitter, Event } from 'vs/base/common/event';
import { ILogService } from 'vs/platform/log/common/log';
@@ -17,20 +17,40 @@ import { FileAccess } from 'vs/base/common/network';
import { mixin } from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import { cwd } from 'vs/base/common/process';
import type { EventEmitter } from 'events';
import * as electron from 'electron';
declare namespace UtilityProcessProposedApi {
interface UtilityProcessOptions {
serviceName?: string | undefined;
execArgv?: string[] | undefined;
env?: NodeJS.ProcessEnv | undefined;
}
export class UtilityProcess extends EventEmitter {
readonly pid?: number | undefined;
constructor(modulePath: string, args?: string[] | undefined, options?: UtilityProcessOptions);
postMessage(channel: string, message: any, transfer?: Electron.MessagePortMain[]): void;
kill(signal?: number | string): boolean;
on(event: 'exit', listener: (code: number) => void): this;
on(event: 'spawn', listener: () => void): this;
}
}
const UtilityProcess = <typeof UtilityProcessProposedApi.UtilityProcess>((electron as any).UtilityProcess);
const canUseUtilityProcess = (typeof UtilityProcess !== 'undefined');
export class ExtensionHostStarter implements IDisposable, IExtensionHostStarter {
_serviceBrand: undefined;
private static _lastId: number = 0;
protected readonly _extHosts: Map<string, ExtensionHostProcess>;
protected readonly _extHosts: Map<string, ExtensionHostProcess | UtilityExtensionHostProcess>;
private _shutdown = false;
constructor(
@ILogService private readonly _logService: ILogService,
@ILifecycleMainService lifecycleMainService: ILifecycleMainService
) {
this._extHosts = new Map<string, ExtensionHostProcess>();
this._extHosts = new Map<string, ExtensionHostProcess | UtilityExtensionHostProcess>();
// On shutdown: gracefully await extension host shutdowns
lifecycleMainService.onWillShutdown((e) => {
@@ -43,7 +63,7 @@ export class ExtensionHostStarter implements IDisposable, IExtensionHostStarter
// Intentionally not killing the extension host processes
}
private _getExtHost(id: string): ExtensionHostProcess {
private _getExtHost(id: string): ExtensionHostProcess | UtilityExtensionHostProcess {
const extHostProcess = this._extHosts.get(id);
if (!extHostProcess) {
throw new Error(`Unknown extension host!`);
@@ -71,12 +91,24 @@ export class ExtensionHostStarter implements IDisposable, IExtensionHostStarter
return this._getExtHost(id).onExit;
}
async createExtensionHost(): Promise<{ id: string }> {
async canUseUtilityProcess(): Promise<boolean> {
return canUseUtilityProcess;
}
async createExtensionHost(useUtilityProcess: boolean): Promise<{ id: string }> {
if (this._shutdown) {
throw canceled();
}
const id = String(++ExtensionHostStarter._lastId);
const extHost = new ExtensionHostProcess(id, this._logService);
let extHost: UtilityExtensionHostProcess | ExtensionHostProcess;
if (useUtilityProcess) {
if (!canUseUtilityProcess) {
throw new Error(`Cannot use UtilityProcess!`);
}
extHost = new UtilityExtensionHostProcess(id, this._logService);
} else {
extHost = new ExtensionHostProcess(id, this._logService);
}
this._extHosts.set(id, extHost);
extHost.onExit(({ pid, code, signal }) => {
this._logService.info(`Extension host with pid ${pid} exited with code: ${code}, signal: ${signal}.`);
@@ -88,7 +120,7 @@ export class ExtensionHostStarter implements IDisposable, IExtensionHostStarter
return { id };
}
async start(id: string, opts: IExtensionHostProcessOptions): Promise<{ pid: number }> {
async start(id: string, opts: IExtensionHostProcessOptions): Promise<void> {
if (this._shutdown) {
throw canceled();
}
@@ -160,7 +192,7 @@ class ExtensionHostProcess extends Disposable {
super();
}
start(opts: IExtensionHostProcessOptions): { pid: number } {
start(opts: IExtensionHostProcessOptions): void {
if (platform.isCI) {
this._logService.info(`Calling fork to start extension host...`);
}
@@ -199,8 +231,130 @@ class ExtensionHostProcess extends Disposable {
this._hasExited = true;
this._onExit.fire({ pid, code, signal });
});
return { pid };
}
enableInspectPort(): boolean {
if (!this._process) {
return false;
}
this._logService.info(`Enabling inspect port on extension host with pid ${this._process.pid}.`);
interface ProcessExt {
_debugProcess?(n: number): any;
}
if (typeof (<ProcessExt>process)._debugProcess === 'function') {
// use (undocumented) _debugProcess feature of node
(<ProcessExt>process)._debugProcess!(this._process.pid!);
return true;
} else if (!platform.isWindows) {
// use KILL USR1 on non-windows platforms (fallback)
this._process.kill('SIGUSR1');
return true;
} else {
// not supported...
return false;
}
}
kill(): void {
if (!this._process) {
return;
}
this._logService.info(`Killing extension host with pid ${this._process.pid}.`);
this._process.kill();
}
async waitForExit(maxWaitTimeMs: number): Promise<void> {
if (!this._process) {
return;
}
const pid = this._process.pid;
this._logService.info(`Waiting for extension host with pid ${pid} to exit.`);
await Promise.race([Event.toPromise(this.onExit), timeout(maxWaitTimeMs)]);
if (!this._hasExited) {
// looks like we timed out
this._logService.info(`Extension host with pid ${pid} did not exit within ${maxWaitTimeMs}ms.`);
this._process.kill();
}
}
}
class UtilityExtensionHostProcess extends Disposable {
readonly onStdout = Event.None;
readonly onStderr = Event.None;
readonly onError = Event.None;
readonly _onMessage = this._register(new Emitter<any>());
readonly onMessage = this._onMessage.event;
readonly _onExit = this._register(new Emitter<{ pid: number; code: number; signal: string }>());
readonly onExit = this._onExit.event;
private _process: UtilityProcessProposedApi.UtilityProcess | null = null;
private _hasExited: boolean = false;
constructor(
public readonly id: string,
@ILogService private readonly _logService: ILogService,
) {
super();
}
start(opts: IExtensionHostProcessOptions): void {
const responseWindow = electron.BrowserWindow.fromId(opts.responseWindowId);
if (!responseWindow || responseWindow.isDestroyed() || responseWindow.webContents.isDestroyed()) {
this._logService.info(`Refusing to create new Extension Host UtilityProcess because requesting window cannot be found...`);
return;
}
const serviceName = `extensionHost${this.id}`;
const modulePath = FileAccess.asFileUri('bootstrap-fork.js', require).fsPath;
const args: string[] = ['--type=extensionHost', '--skipWorkspaceStorageLock'];
const execArgv: string[] = opts.execArgv || [];
const env: { [key: string]: any } = { ...opts.env };
// Make sure all values are strings, otherwise the process will not start
for (const key of Object.keys(env)) {
env[key] = String(env[key]);
}
this._logService.info(`Creating new UtilityProcess to start extension host...`);
this._process = new UtilityProcess(modulePath, args, { serviceName, env, execArgv });
this._process.on('spawn', () => {
this._logService.info(`Utility process emits spawn!`);
});
this._process.on('exit', (code: number) => {
this._logService.info(`Utility process emits exit!`);
this._hasExited = true;
this._onExit.fire({ pid: this._process!.pid!, code, signal: '' });
});
const listener = (event: electron.Event, details: electron.Details) => {
if (details.type !== 'Utility') {
return;
}
// Despite the fact that we pass the argument `seviceName`,
// the details have a field called `name` where this value appears
if (details.name === serviceName) {
this._logService.info(`Utility process emits exit!`);
this._hasExited = true;
this._onExit.fire({ pid: this._process!.pid!, code: details.exitCode, signal: '' });
}
};
electron.app.on('child-process-gone', listener);
this._register(toDisposable(() => {
electron.app.off('child-process-gone', listener);
}));
const { port1, port2 } = new electron.MessageChannelMain();
this._process.postMessage('port', null, [port2]);
responseWindow.webContents.postMessage(opts.responseChannel, opts.responseNonce, [port1]);
}
enableInspectPort(): boolean {
@@ -16,6 +16,7 @@ import { createFileSystemProviderError, FileChangeType, IFileDeleteOptions, IFil
import { DBClosedError, IndexedDB } from 'vs/base/browser/indexedDB';
export type IndexedDBFileSystemProviderErrorDataClassification = {
owner: 'sandy081';
readonly scheme: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
readonly operation: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
readonly code: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth' };
@@ -0,0 +1,12 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const ILanguagePackService = createDecorator<ILanguagePackService>('languagePackService');
export interface ILanguagePackService {
readonly _serviceBrand: undefined;
getInstalledLanguages(): Promise<string[]>;
}
@@ -13,7 +13,8 @@ import { Promises } from 'vs/base/node/pfs';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { IExtensionIdentifier, IExtensionManagementService, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ILocalizationsService, isValidLocalization } from 'vs/platform/localizations/common/localizations';
import { ILocalizationContribution } from 'vs/platform/extensions/common/extensions';
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
import { ILogService } from 'vs/platform/log/common/log';
interface ILanguagePack {
@@ -25,7 +26,7 @@ interface ILanguagePack {
translations: { [id: string]: string };
}
export class LocalizationsService extends Disposable implements ILocalizationsService {
export class LanguagePackService extends Disposable implements ILanguagePackService {
declare readonly _serviceBrand: undefined;
@@ -48,7 +49,7 @@ export class LocalizationsService extends Disposable implements ILocalizationsSe
});
}
async getLanguageIds(): Promise<string[]> {
async getInstalledLanguages(): Promise<string[]> {
const languagePacks = await this.cache.getLanguagePacks();
// Contributed languages are those installed via extension packs, so does not include English
const languages = ['en', ...Object.keys(languagePacks)];
@@ -174,3 +175,27 @@ class LanguagePacksCache extends Disposable {
});
}
}
function isValidLocalization(localization: ILocalizationContribution): boolean {
if (typeof localization.languageId !== 'string') {
return false;
}
if (!Array.isArray(localization.translations) || localization.translations.length === 0) {
return false;
}
for (const translation of localization.translations) {
if (typeof translation.id !== 'string') {
return false;
}
if (typeof translation.path !== 'string') {
return false;
}
}
if (localization.languageName && typeof localization.languageName !== 'string') {
return false;
}
if (localization.localizedLanguageName && typeof localization.localizedLanguageName !== 'string') {
return false;
}
return true;
}
@@ -1,37 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ILocalizationContribution } from 'vs/platform/extensions/common/extensions';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const ILocalizationsService = createDecorator<ILocalizationsService>('localizationsService');
export interface ILocalizationsService {
readonly _serviceBrand: undefined;
getLanguageIds(): Promise<string[]>;
}
export function isValidLocalization(localization: ILocalizationContribution): boolean {
if (typeof localization.languageId !== 'string') {
return false;
}
if (!Array.isArray(localization.translations) || localization.translations.length === 0) {
return false;
}
for (const translation of localization.translations) {
if (typeof translation.id !== 'string') {
return false;
}
if (typeof translation.path !== 'string') {
return false;
}
}
if (localization.languageName && typeof localization.languageName !== 'string') {
return false;
}
if (localization.localizedLanguageName && typeof localization.localizedLanguageName !== 'string') {
return false;
}
return true;
}
@@ -84,8 +84,10 @@ export function configurationTelemetry(telemetryService: ITelemetryService, conf
return configurationService.onDidChangeConfiguration(event => {
if (event.source !== ConfigurationTarget.DEFAULT) {
type UpdateConfigurationClassification = {
configurationSource: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
configurationKeys: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
owner: 'lramos15, sbatten';
comment: 'Event which fires when user updates telemetry configuration';
configurationSource: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'What configuration file was updated i.e user or workspace' };
configurationKeys: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'What configuration keys were updated' };
};
type UpdateConfigurationEvent = {
configurationSource: string;
@@ -144,7 +144,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
private _handleVSCodeSequence(data: string): boolean {
const didHandle = this._doHandleVSCodeSequence(data);
if (!this._hasUpdatedTelemetry && didHandle) {
this._telemetryService?.publicLog2<{ classification: 'SystemMetaData'; purpose: 'FeatureInsight' }>('terminal/shellIntegrationActivationSucceeded');
this._telemetryService?.publicLog2<{}, { owner: 'meganrogge'; comment: 'Indicates shell integration was activated' }>('terminal/shellIntegrationActivationSucceeded');
this._hasUpdatedTelemetry = true;
if (this._activationTimeout !== undefined) {
clearTimeout(this._activationTimeout);
@@ -232,7 +232,7 @@ export class ShellIntegrationAddon extends Disposable implements IShellIntegrati
private async _ensureCapabilitiesOrAddFailureTelemetry(): Promise<void> {
this._activationTimeout = setTimeout(() => {
if (!this.capabilities.get(TerminalCapability.CommandDetection) && !this.capabilities.get(TerminalCapability.CwdDetection)) {
this._telemetryService?.publicLog2<{ classification: 'SystemMetaData'; purpose: 'FeatureInsight' }>('terminal/shellIntegrationActivationTimeout');
this._telemetryService?.publicLog2<{}, { owner: 'meganrogge'; comment: 'Indicates shell integration activation did not occur within 10 seconds' }>('terminal/shellIntegrationActivationTimeout');
this._logService.warn('Shell integration failed to add capabilities within 10 seconds');
}
this._hasUpdatedTelemetry = true;
@@ -19,6 +19,7 @@ export function createUpdateURL(platform: string, quality: string, productServic
}
export type UpdateNotAvailableClassification = {
owner: 'joaomoreno';
explicit: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
};
@@ -92,6 +92,7 @@ export class DarwinUpdateService extends AbstractUpdateService {
}
type UpdateDownloadedClassification = {
owner: 'joaomoreno';
version: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
this.telemetryService.publicLog2<{ version: String }, UpdateDownloadedClassification>('update:downloaded', { version: update.version });
@@ -29,6 +29,7 @@ import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'
import { Change, getLastSyncResourceUri, IRemoteUserData, IResourcePreview as IBaseResourcePreview, ISyncData, ISyncResourceHandle, ISyncResourcePreview as IBaseSyncResourcePreview, IUserData, IUserDataInitializer, IUserDataManifest, IUserDataSyncBackupStoreService, IUserDataSyncConfiguration, IUserDataSynchroniser, IUserDataSyncLogService, IUserDataSyncEnablementService, IUserDataSyncStoreService, IUserDataSyncUtilService, MergeState, PREVIEW_DIR_NAME, SyncResource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, USER_DATA_SYNC_CONFIGURATION_SCOPE, USER_DATA_SYNC_SCHEME } from 'vs/platform/userDataSync/common/userDataSync';
type SyncSourceClassification = {
owner: 'sandy081';
source?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
};
@@ -22,10 +22,12 @@ import { IUserDataSyncAccountService } from 'vs/platform/userDataSync/common/use
import { IUserDataSyncMachinesService } from 'vs/platform/userDataSync/common/userDataSyncMachines';
type AutoSyncClassification = {
owner: 'sandy081';
sources: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
};
type AutoSyncErrorClassification = {
owner: 'sandy081';
code: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
service: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
};
@@ -194,7 +196,7 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto
// Reset
if (everywhere) {
this.telemetryService.publicLog2('sync/turnOffEveryWhere');
this.telemetryService.publicLog2<{}, { owner: 'sandy081' }>('sync/turnOffEveryWhere');
await this.userDataSyncService.reset();
} else {
await this.userDataSyncService.resetLocal();
@@ -12,6 +12,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { ALL_SYNC_RESOURCES, getEnablementKey, IUserDataSyncEnablementService, IUserDataSyncStoreManagementService, SyncResource } from 'vs/platform/userDataSync/common/userDataSync';
type SyncEnablementClassification = {
owner: 'sandy081';
enabled?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
};
@@ -28,6 +28,7 @@ import { TasksSynchroniser } from 'vs/platform/userDataSync/common/tasksSync';
import { ALL_SYNC_RESOURCES, Change, createSyncHeaders, IManualSyncTask, IResourcePreview, ISyncResourceHandle, ISyncResourcePreview, ISyncTask, IUserDataManifest, IUserDataSyncConfiguration, IUserDataSyncEnablementService, IUserDataSynchroniser, IUserDataSyncLogService, IUserDataSyncService, IUserDataSyncStoreManagementService, IUserDataSyncStoreService, MergeState, SyncResource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, UserDataSyncStoreError, USER_DATA_SYNC_CONFIGURATION_SCOPE } from 'vs/platform/userDataSync/common/userDataSync';
type SyncErrorClassification = {
owner: 'sandy081';
code: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
service: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
serverCode?: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
@@ -28,8 +28,8 @@ import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog';
import { RemoteExtensionLogFileName } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IServerEnvironmentService, ServerEnvironmentService, ServerParsedArgs } from 'vs/server/node/serverEnvironmentService';
import { ExtensionManagementCLIService } from 'vs/platform/extensionManagement/common/extensionManagementCLIService';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
import { LanguagePackService } from 'vs/platform/languagePacks/node/languagePacks';
import { getErrorMessage } from 'vs/base/common/errors';
import { URI } from 'vs/base/common/uri';
import { isAbsolute, join } from 'vs/base/common/path';
@@ -104,7 +104,7 @@ class CliMain extends Disposable {
services.set(IExtensionsScannerService, new SyncDescriptor(ExtensionsScannerService));
services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService));
services.set(IExtensionManagementCLIService, new SyncDescriptor(ExtensionManagementCLIService));
services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService));
services.set(ILanguagePackService, new SyncDescriptor(LanguagePackService));
return new InstantiationService(services);
}
@@ -757,10 +757,10 @@ export async function createServer(address: string | net.AddressInfo | null, arg
type ServerStartClassification = {
owner: 'alexdima';
comment: 'The server has started up';
startTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth' };
startedTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth' };
codeLoadedTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth' };
readyTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth' };
startTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The time the server started at.' };
startedTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The time the server began listening for connections.' };
codeLoadedTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The time which the code loaded on the server' };
readyTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The time when the server was completely ready' };
};
type ServerStartEvent = {
startTime: number;
+3 -3
View File
@@ -35,8 +35,8 @@ import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
import { LanguagePackService } from 'vs/platform/languagePacks/node/languagePacks';
import { AbstractLogger, DEFAULT_LOG_LEVEL, getLogLevel, ILogService, LogLevel, LogService, MultiplexLogService } from 'vs/platform/log/common/log';
import { LogLevelChannel } from 'vs/platform/log/common/logIpc';
import { SpdLogLogger } from 'vs/platform/log/node/spdlogLog';
@@ -159,7 +159,7 @@ export async function setupServerServices(connectionToken: ServerConnectionToken
services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService));
const instantiationService: IInstantiationService = new InstantiationService(services);
services.set(ILocalizationsService, instantiationService.createInstance(LocalizationsService));
services.set(ILanguagePackService, instantiationService.createInstance(LanguagePackService));
const extensionManagementCLIService = instantiationService.createInstance(ExtensionManagementCLIService);
services.set(IExtensionManagementCLIService, extensionManagementCLIService);
@@ -5,6 +5,7 @@
import { VSBuffer } from 'vs/base/common/buffer';
import { CancellationToken } from 'vs/base/common/cancellation';
import { VSDataTransfer } from 'vs/base/common/dataTransfer';
import { CancellationError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
import { combinedDisposable, Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
@@ -23,14 +24,13 @@ import { ITextModel } from 'vs/editor/common/model';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { decodeSemanticTokensDto } from 'vs/editor/common/services/semanticTokensDto';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
import { DataTransferCache } from 'vs/workbench/api/common/shared/dataTransferCache';
import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import * as search from 'vs/workbench/contrib/search/common/search';
import * as typeh from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
import { ExtHostContext, ExtHostLanguageFeaturesShape, ICallHierarchyItemDto, ICodeActionDto, ICodeActionProviderMetadataDto, IdentifiableInlineCompletion, IdentifiableInlineCompletions, IDocumentFilterDto, IIndentationRuleDto, IInlayHintDto, ILanguageConfigurationDto, ILanguageWordDefinitionDto, ILinkDto, ILocationDto, ILocationLinkDto, IOnEnterRuleDto, IRegExpDto, ISignatureHelpProviderMetadataDto, ISuggestDataDto, ISuggestDataDtoField, ISuggestResultDtoField, ITypeHierarchyItemDto, IWorkspaceSymbolDto, MainContext, MainThreadLanguageFeaturesShape, reviveWorkspaceEditDto } from '../common/extHost.protocol';
import { VSDataTransfer } from 'vs/base/common/dataTransfer';
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
import { ExtHostContext, ExtHostLanguageFeaturesShape, ICallHierarchyItemDto, ICodeActionDto, ICodeActionProviderMetadataDto, IdentifiableInlineCompletion, IdentifiableInlineCompletions, IDocumentFilterDto, IIndentationRuleDto, IInlayHintDto, ILanguageConfigurationDto, ILanguageWordDefinitionDto, ILinkDto, ILocationDto, ILocationLinkDto, IOnEnterRuleDto, IRegExpDto, ISignatureHelpProviderMetadataDto, ISuggestDataDto, ISuggestDataDtoField, ISuggestResultDtoField, ITypeHierarchyItemDto, IWorkspaceEditDto, IWorkspaceSymbolDto, MainContext, MainThreadLanguageFeaturesShape, reviveWorkspaceEditDto } from '../common/extHost.protocol';
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
export class MainThreadLanguageFeatures extends Disposable implements MainThreadLanguageFeaturesShape {
@@ -366,6 +366,47 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
this._registrations.set(handle, this._languageFeaturesService.codeActionProvider.register(selector, provider));
}
// --- copy paste action provider
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], supportsCopy: boolean): void {
const provider: languages.DocumentPasteEditProvider = {
prepareDocumentPaste: supportsCopy
? async (model: ITextModel, selection: Selection, dataTransfer: VSDataTransfer, token: CancellationToken): Promise<VSDataTransfer | undefined> => {
const dataTransferDto = await typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
if (token.isCancellationRequested) {
return undefined;
}
const result = await this._proxy.$prepareDocumentPaste(handle, model.uri, selection, dataTransferDto, token);
if (!result) {
return undefined;
}
const dataTransferOut = new VSDataTransfer();
result.items.forEach(([type, item]) => {
dataTransferOut.setString(type, item.asString);
});
return dataTransferOut;
}
: undefined,
provideDocumentPasteEdits: async (model: ITextModel, selection: Selection, dataTransfer: VSDataTransfer, token: CancellationToken) => {
const d = await typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
const result = await this._proxy.$providePasteEdits(handle, model.uri, selection, d, token);
if (!result) {
return;
} else if ((result as IWorkspaceEditDto).edits) {
return reviveWorkspaceEditDto(result as IWorkspaceEditDto);
} else {
return result as languages.SnippetTextEdit;
}
}
};
this._registrations.set(handle, this._languageFeaturesService.documentPasteEditProvider.register(selector, provider));
}
// --- formatting
$registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void {
@@ -421,6 +421,16 @@ export class MainThreadSCM implements MainThreadSCMShape {
repository.input.placeholder = placeholder;
}
$setInputBoxEnablement(sourceControlHandle: number, enabled: boolean): void {
const repository = this._repositories.get(sourceControlHandle);
if (!repository) {
return;
}
repository.input.enabled = enabled;
}
$setInputBoxVisibility(sourceControlHandle: number, visible: boolean): void {
const repository = this._repositories.get(sourceControlHandle);
@@ -37,14 +37,14 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTreeViews);
}
async $registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean; canSelectMany: boolean; dropMimeTypes: string[]; dragMimeTypes: string[]; hasHandleDrag: boolean; hasHandleDrop: boolean }): Promise<void> {
async $registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean; canSelectMany: boolean; dropMimeTypes: string[]; dragMimeTypes: string[]; hasHandleDrag: boolean; hasHandleDrop: boolean; supportsFileDataTransfers: boolean }): Promise<void> {
this.logService.trace('MainThreadTreeViews#$registerTreeViewDataProvider', treeViewId, options);
this.extensionService.whenInstalledExtensionsRegistered().then(() => {
const dataProvider = new TreeViewDataProvider(treeViewId, this._proxy, this.notificationService);
this._dataProviders.set(treeViewId, dataProvider);
const dndController = (options.hasHandleDrag || options.hasHandleDrop)
? new TreeViewDragAndDropController(treeViewId, options.dropMimeTypes, options.dragMimeTypes, options.hasHandleDrag, this._proxy) : undefined;
? new TreeViewDragAndDropController(treeViewId, options.dropMimeTypes, options.dragMimeTypes, options.hasHandleDrag, options.supportsFileDataTransfers, this._proxy) : undefined;
const viewer = this.getTreeView(treeViewId);
if (viewer) {
// Order is important here. The internal tree isn't created until the dataProvider is set.
@@ -201,6 +201,7 @@ class TreeViewDragAndDropController implements ITreeViewDragAndDropController {
readonly dropMimeTypes: string[],
readonly dragMimeTypes: string[],
readonly hasWillDrop: boolean,
readonly supportsFileDataTransfers: boolean,
private readonly _proxy: ExtHostTreeViewsShape) { }
async handleDrop(dataTransfer: VSDataTransfer, targetTreeItem: ITreeItem | undefined, token: CancellationToken,
@@ -457,6 +457,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable {
return extHostLanguageFeatures.registerCodeActionProvider(extension, checkSelector(selector), provider, metadata);
},
registerDocumentPasteEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentPasteEditProvider): vscode.Disposable {
checkProposedApiEnabled(extension, 'documentPaste');
return extHostLanguageFeatures.registerDocumentPasteEditProvider(extension, checkSelector(selector), provider);
},
registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
return extHostLanguageFeatures.registerCodeLensProvider(extension, checkSelector(selector), provider);
},
@@ -524,7 +528,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
return extHostLanguageFeatures.registerCompletionItemProvider(extension, checkSelector(selector), provider, triggerCharacters);
},
registerInlineCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.InlineCompletionItemProvider): vscode.Disposable {
checkProposedApiEnabled(extension, 'inlineCompletions');
if (provider.handleDidShowCompletionItem) {
checkProposedApiEnabled(extension, 'inlineCompletionsAdditions');
}
@@ -258,7 +258,7 @@ export interface MainThreadTextEditorsShape extends IDisposable {
}
export interface MainThreadTreeViewsShape extends IDisposable {
$registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean; canSelectMany: boolean; dropMimeTypes: readonly string[]; dragMimeTypes: readonly string[]; hasHandleDrag: boolean; hasHandleDrop: boolean }): Promise<void>;
$registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean; canSelectMany: boolean; dropMimeTypes: readonly string[]; dragMimeTypes: readonly string[]; hasHandleDrag: boolean; hasHandleDrop: boolean; supportsFileDataTransfers: boolean }): Promise<void>;
$refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem }): Promise<void>;
$reveal(treeViewId: string, itemInfo: { item: ITreeItem; parentChain: ITreeItem[] } | undefined, options: IRevealOptions): Promise<void>;
$setMessage(treeViewId: string, message: string): void;
@@ -372,6 +372,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
$registerLinkedEditingRangeProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerReferenceSupport(handle: number, selector: IDocumentFilterDto[]): void;
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], metadata: ICodeActionProviderMetadataDto, displayName: string, supportsResolve: boolean): void;
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], supportsCopy: boolean): void;
$registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
$registerOnTypeFormattingSupport(handle: number, selector: IDocumentFilterDto[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void;
@@ -1187,6 +1188,7 @@ export interface MainThreadSCMShape extends IDisposable {
$setInputBoxValue(sourceControlHandle: number, value: string): void;
$setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void;
$setInputBoxEnablement(sourceControlHandle: number, enabled: boolean): void;
$setInputBoxVisibility(sourceControlHandle: number, visible: boolean): void;
$showValidationMessage(sourceControlHandle: number, message: string | IMarkdownString, type: InputValidationType): void;
$setValidationProviderIsEnabled(sourceControlHandle: number, enabled: boolean): void;
@@ -1729,6 +1731,8 @@ export interface ExtHostLanguageFeaturesShape {
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: languages.CodeActionContext, token: CancellationToken): Promise<ICodeActionListDto | undefined>;
$resolveCodeAction(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<IWorkspaceEditDto | undefined>;
$releaseCodeActions(handle: number, cacheId: number): void;
$prepareDocumentPaste(handle: number, uri: UriComponents, range: IRange, dataTransfer: DataTransferDTO, token: CancellationToken): Promise<DataTransferDTO | undefined>;
$providePasteEdits(handle: number, uri: UriComponents, range: IRange, dataTransfer: DataTransferDTO, token: CancellationToken): Promise<IWorkspaceEditDto | Dto<languages.SnippetTextEdit> | undefined>;
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: languages.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: languages.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: languages.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
@@ -424,6 +424,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
private _logExtensionActivationTimes(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason, outcome: string, activationTimes?: ExtensionActivationTimes) {
const event = getTelemetryActivationEvent(extensionDescription, reason);
type ExtensionActivationTimesClassification = {
owner: 'jrieken';
outcome: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
} & TelemetryActivationEventFragment & ExtensionActivationTimesFragment;
@@ -447,7 +448,9 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
private _doActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {
const event = getTelemetryActivationEvent(extensionDescription, reason);
type ActivatePluginClassification = {} & TelemetryActivationEventFragment;
type ActivatePluginClassification = {
owner: 'jrieken';
} & TelemetryActivationEventFragment;
this._mainThreadTelemetryProxy.$publicLog2<TelemetryActivationEvent, ActivatePluginClassification>('activatePlugin', event);
const entryPoint = this._getEntryPoint(extensionDescription);
if (!entryPoint) {
@@ -7,7 +7,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import { mixin } from 'vs/base/common/objects';
import type * as vscode from 'vscode';
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit, Location, InlineCompletionTriggerKindNew, InlineCompletionTriggerKind } from 'vs/workbench/api/common/extHostTypes';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit, Location, InlineCompletionTriggerKindNew, InlineCompletionTriggerKind, WorkspaceEdit } from 'vs/workbench/api/common/extHostTypes';
import { ISingleEditOperation } from 'vs/editor/common/core/editOperation';
import * as languages from 'vs/editor/common/languages';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
@@ -31,7 +31,7 @@ import { IdGenerator } from 'vs/base/common/idGenerator';
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
import { Cache } from './cache';
import { StopWatch } from 'vs/base/common/stopwatch';
import { isCancellationError } from 'vs/base/common/errors';
import { isCancellationError, NotImplementedError } from 'vs/base/common/errors';
import { raceCancellationError } from 'vs/base/common/async';
import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { Dto } from 'vs/workbench/services/extensions/common/proxyIdentifier';
@@ -485,6 +485,52 @@ class CodeActionAdapter {
}
}
class DocumentPasteEditProvider {
constructor(
private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape,
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.DocumentPasteEditProvider,
private readonly _handle: number,
) { }
async prepareDocumentPaste(resource: URI, range: IRange, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.DataTransferDTO | undefined> {
if (!this._provider.prepareDocumentPaste) {
return undefined;
}
const doc = this._documents.getDocument(resource);
const vscodeRange = typeConvert.Range.to(range);
const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, () => {
throw new NotImplementedError();
});
await this._provider.prepareDocumentPaste(doc, vscodeRange, dataTransfer, token);
return typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
}
async providePasteEdits(requestId: number, resource: URI, range: IRange, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<undefined | extHostProtocol.IWorkspaceEditDto | Dto<languages.SnippetTextEdit>> {
const doc = this._documents.getDocument(resource);
const vscodeRange = typeConvert.Range.to(range);
const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, async (index) => {
return (await this._proxy.$resolveDocumentOnDropFileData(this._handle, requestId, index)).buffer;
});
const edit = await this._provider.provideDocumentPasteEdits(doc, vscodeRange, dataTransfer, token);
if (!edit) {
return;
}
if (edit instanceof WorkspaceEdit) {
return typeConvert.WorkspaceEdit.from(edit);
} else {
return typeConvert.SnippetTextEdit.from(edit as vscode.SnippetTextEdit);
}
}
}
class DocumentFormattingAdapter {
constructor(
@@ -1769,7 +1815,7 @@ class DocumentOnDropEditAdapter {
}
type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentFormattingAdapter
| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentPasteEditProvider | DocumentFormattingAdapter
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
| CompletionsAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter
| TypeDefinitionAdapter | ColorProviderAdapter | FoldingProviderAdapter | DeclarationAdapter
@@ -2413,6 +2459,23 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
Promise.resolve(adapter.provideDocumentOnDropEdits(requestId, URI.revive(resource), position, dataTransferDto, token)), undefined, undefined);
}
// --- copy/paste actions
registerDocumentPasteEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentPasteEditProvider): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new AdapterData(new DocumentPasteEditProvider(this._proxy, this._documents, provider, handle), extension));
this._proxy.$registerPasteEditProvider(handle, this._transformDocumentSelector(selector), !!provider.prepareDocumentPaste);
return this._createDisposable(handle);
}
$prepareDocumentPaste(handle: number, resource: UriComponents, range: IRange, dataTransfer: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.DataTransferDTO | undefined> {
return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.prepareDocumentPaste(URI.revive(resource), range, dataTransfer, token), undefined, token);
}
$providePasteEdits(handle: number, resource: UriComponents, range: IRange, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.IWorkspaceEditDto | Dto<languages.SnippetTextEdit> | undefined> {
return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.providePasteEdits(0, URI.revive(resource), range, dataTransferDto, token), undefined, token);
}
// --- configuration
private static _serializeRegExp(regExp: RegExp): extHostProtocol.IRegExpDto {
@@ -249,6 +249,7 @@ class KeytarNodeModuleFactory implements INodeModuleFactory {
public load(_request: string, parent: URI): any {
const ext = this._extensionPaths.findSubstr(parent);
type ShimmingKeytarClassification = {
owner: 'jrieken';
extension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
this._mainThreadTelemetry.$publicLog2<{ extension: string }, ShimmingKeytarClassification>('shimming.keytar', { extension: ext?.identifier.value ?? 'unknown_extension' });
@@ -346,6 +347,7 @@ class OpenNodeModuleFactory implements INodeModuleFactory {
return;
}
type ShimmingOpenClassification = {
owner: 'jrieken';
extension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
this._mainThreadTelemetry.$publicLog2<{ extension: string }, ShimmingOpenClassification>('shimming.open', { extension: this._extensionId });
@@ -356,6 +358,7 @@ class OpenNodeModuleFactory implements INodeModuleFactory {
return;
}
type ShimmingOpenCallNoForwardClassification = {
owner: 'jrieken';
extension: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
this._mainThreadTelemetry.$publicLog2<{ extension: string }, ShimmingOpenCallNoForwardClassification>('shimming.open.call.noForward', { extension: this._extensionId });
+23 -1
View File
@@ -249,6 +249,25 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
this.#proxy.$setValidationProviderIsEnabled(this._sourceControlHandle, !!fn);
}
private _enabled: boolean = true;
get enabled(): boolean {
checkProposedApiEnabled(this._extension, 'scmInput');
return this._enabled;
}
set enabled(enabled: boolean) {
checkProposedApiEnabled(this._extension, 'scmInput');
enabled = !!enabled;
if (this._enabled === enabled) {
return;
}
this._enabled = enabled;
this.#proxy.$setInputBoxEnablement(this._sourceControlHandle, enabled);
}
private _visible: boolean = true;
get visible(): boolean {
@@ -722,7 +741,10 @@ export class ExtHostSCM implements ExtHostSCMShape {
this.logService.trace('ExtHostSCM#createSourceControl', extension.identifier.value, id, label, rootUri);
type TEvent = { extensionId: string };
type TMeta = { extensionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' } };
type TMeta = {
owner: 'joaomoreno';
extensionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
this._telemetry.$publicLog2<TEvent, TMeta>('api/scm/createSourceControl', {
extensionId: extension.identifier.value,
});
+1 -1
View File
@@ -24,7 +24,7 @@ import { Schemas } from 'vs/base/common/network';
import * as Platform from 'vs/base/common/platform';
import { ILogService } from 'vs/platform/log/common/log';
import { IExtHostApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
import { USER_TASKS_GROUP_KEY } from 'vs/workbench/contrib/tasks/common/taskService';
import { USER_TASKS_GROUP_KEY } from 'vs/workbench/contrib/tasks/common/tasks';
import { NotSupportedError } from 'vs/base/common/errors';
export interface IExtHostTask extends ExtHostTaskShape {
@@ -24,7 +24,7 @@ import { IMarkdownString } from 'vs/base/common/htmlContent';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { Command } from 'vs/editor/common/languages';
import { ITreeViewsService, TreeviewsService } from 'vs/workbench/services/views/common/treeViewsService';
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { checkProposedApiEnabled, isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
type TreeItemHandle = string;
@@ -92,7 +92,8 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
const dragMimeTypes = options.dragAndDropController?.dragMimeTypes ?? [];
const hasHandleDrag = !!options.dragAndDropController?.handleDrag;
const hasHandleDrop = !!options.dragAndDropController?.handleDrop;
const registerPromise = this._proxy.$registerTreeViewDataProvider(viewId, { showCollapseAll: !!options.showCollapseAll, canSelectMany: !!options.canSelectMany, dropMimeTypes, dragMimeTypes, hasHandleDrag, hasHandleDrop });
const supportsFileDataTransfers = isProposedApiEnabled(extension, 'dataTransferFiles');
const registerPromise = this._proxy.$registerTreeViewDataProvider(viewId, { showCollapseAll: !!options.showCollapseAll, canSelectMany: !!options.canSelectMany, dropMimeTypes, dragMimeTypes, hasHandleDrag, hasHandleDrop, supportsFileDataTransfers });
const treeView = this.createExtHostTreeView(viewId, options, extension);
return {
get onDidCollapseElement() { return treeView.onDidCollapseElement; },
@@ -23,6 +23,7 @@ import { IHostUtils } from 'vs/workbench/api/common/extHostExtensionService';
import { ProcessTimeRunOnceScheduler } from 'vs/base/common/async';
import { boolean } from 'vs/editor/common/config/editorOptions';
import { createURITransformer } from 'vs/workbench/api/node/uriTransformer';
import { MessagePortMain } from 'electron';
import 'vs/workbench/api/common/extHost.common.services';
import 'vs/workbench/api/node/extHost.node.services';
@@ -102,8 +103,37 @@ let onTerminate = function (reason: string) {
nativeExit();
};
function _createExtHostProtocol(): Promise<PersistentProtocol> {
if (process.env.VSCODE_EXTHOST_WILL_SEND_SOCKET) {
function _createExtHostProtocol(): Promise<IMessagePassingProtocol> {
if (process.env.VSCODE_WILL_SEND_MESSAGE_PORT) {
return new Promise<IMessagePassingProtocol>((resolve, reject) => {
const withPorts = (ports: MessagePortMain[]) => {
const port = ports[0];
const onMessage = new BufferedEmitter<VSBuffer>();
port.on('message', (e) => onMessage.fire(VSBuffer.wrap(e.data)));
port.on('close', () => {
onTerminate('renderer closed the MessagePort');
});
port.start();
resolve({
onMessage: onMessage.event,
send: message => port.postMessage(message.buffer)
});
};
if ((<any>global).vscodePorts) {
const ports = (<any>global).vscodePorts;
delete (<any>global).vscodePorts;
withPorts(ports);
} else {
(<any>global).vscodePortsCallback = withPorts;
}
});
} else if (process.env.VSCODE_EXTHOST_WILL_SEND_SOCKET) {
return new Promise<PersistentProtocol>((resolve, reject) => {
@@ -220,8 +250,10 @@ async function createExtHostProtocol(): Promise<IMessagePassingProtocol> {
}
}
drain(): Promise<void> {
return protocol.drain();
async drain(): Promise<void> {
if (protocol.drain) {
return protocol.drain();
}
}
};
}
@@ -75,7 +75,7 @@ suite('MainThreadHostTreeView', function () {
}
drain(): any { return null; }
}, new TestViewsService(), new TestNotificationService(), testExtensionService, new NullLogService());
mainThreadTreeViews.$registerTreeViewDataProvider(testTreeViewId, { showCollapseAll: false, canSelectMany: false, dropMimeTypes: [], dragMimeTypes: [], hasHandleDrag: false, hasHandleDrop: false });
mainThreadTreeViews.$registerTreeViewDataProvider(testTreeViewId, { showCollapseAll: false, canSelectMany: false, dropMimeTypes: [], dragMimeTypes: [], hasHandleDrag: false, hasHandleDrop: false, supportsFileDataTransfers: false });
await testExtensionService.whenInstalledExtensionsRegistered();
});
@@ -102,6 +102,7 @@ export class ViewContainerActivityAction extends ActivityAction {
private logAction(action: string) {
type ActivityBarActionClassification = {
owner: 'sbatten';
viewletId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
action: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
@@ -968,6 +968,7 @@ function registerCloseEditorCommands() {
]);
type WorkbenchEditorReopenClassification = {
owner: 'rebornix';
scheme: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
ext: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
from: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
@@ -575,6 +575,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
/* __GDPR__
"editorOpened" : {
"owner": "bpasero",
"${include}": [
"${EditorTelemetryDescriptor}"
]
@@ -611,6 +612,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
/* __GDPR__
"editorClosed" : {
"owner": "bpasero",
"${include}": [
"${EditorTelemetryDescriptor}"
]
@@ -66,7 +66,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
import { IHoverService } from 'vs/workbench/services/hover/browser/hover';
import { ThemeSettings } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { ITreeViewsService } from 'vs/workbench/services/views/browser/treeViewsService';
import { CodeDataTransfers } from 'vs/platform/dnd/browser/dnd';
import { CodeDataTransfers, FileAdditionalNativeProperties } from 'vs/platform/dnd/browser/dnd';
export class TreeViewPane extends ViewPane {
@@ -1503,40 +1503,21 @@ export class CustomTreeViewDragAndDrop implements ITreeDragAndDrop<ITreeItem> {
}
const treeDataTransfer = new VSDataTransfer();
const uris: URI[] = [];
let itemsCount = Array.from(originalEvent.dataTransfer.items).reduce((previous, current) => {
if ((current.kind === 'string') || (current.kind === 'file')) {
return previous + 1;
}
return previous;
}, 0);
let treeSourceInfo: TreeDragSourceInfo | undefined;
let willDropUuid: string | undefined;
if (this.treeItemsTransfer.hasData(DraggedTreeItemsIdentifier.prototype)) {
willDropUuid = this.treeItemsTransfer.getData(DraggedTreeItemsIdentifier.prototype)![0].identifier;
}
await new Promise<void>(resolve => {
function decrementStringCount() {
itemsCount--;
if (itemsCount === 0) {
// Check if there are uris to add and add them
if (uris.length) {
treeDataTransfer.setString(Mimes.uriList, uris.map(uri => uri.toString()).join('\n'));
}
resolve();
}
}
if (!originalEvent.dataTransfer) {
return;
}
for (const dataItem of originalEvent.dataTransfer.items) {
const type = dataItem.type;
const kind = dataItem.kind;
const convertedType = this.convertKnownMimes(type, kind).type;
if ((INTERNAL_MIME_TYPES.indexOf(convertedType) < 0)
&& (convertedType === this.treeMimeType) || (dndController.dropMimeTypes.indexOf(convertedType) >= 0)) {
if (dataItem.kind === 'string') {
await Promise.all([...originalEvent.dataTransfer.items].map(async dataItem => {
const type = dataItem.type;
const kind = dataItem.kind;
const convertedType = this.convertKnownMimes(type, kind).type;
if ((INTERNAL_MIME_TYPES.indexOf(convertedType) < 0)
&& (convertedType === this.treeMimeType) || (dndController.dropMimeTypes.indexOf(convertedType) >= 0)) {
if (dataItem.kind === 'string') {
await new Promise<void>(resolve =>
dataItem.getAsString(dataValue => {
if (convertedType === this.treeMimeType) {
treeSourceInfo = JSON.parse(dataValue);
@@ -1545,20 +1526,27 @@ export class CustomTreeViewDragAndDrop implements ITreeDragAndDrop<ITreeItem> {
const converted = this.convertKnownMimes(type, kind, dataValue);
treeDataTransfer.setString(converted.type, converted.value + '');
}
decrementStringCount();
});
} else if (dataItem.kind === 'file') {
const dataValue = dataItem.getAsFile();
if (dataValue) {
uris.push(URI.file(dataValue.path));
resolve();
}));
} else if (dataItem.kind === 'file') {
const file = dataItem.getAsFile();
if (file) {
uris.push(URI.file(file.path));
const uri = (file as FileAdditionalNativeProperties).path ? URI.parse((file as FileAdditionalNativeProperties).path!) : undefined;
if (dndController.supportsFileDataTransfers) {
treeDataTransfer.setFile(type, file.name, uri, async () => {
return new Uint8Array(await file.arrayBuffer());
});
}
decrementStringCount();
}
} else if (dataItem.kind === 'string' || dataItem.kind === 'file') {
decrementStringCount();
}
}
});
}));
// Check if there are uris to add and add them
if (uris.length) {
treeDataTransfer.setString(Mimes.uriList, uris.map(uri => uri.toString()).join('\n'));
}
const additionalWillDropPromise = this.treeViewsDragAndDropService.removeDragOperationTransfer(willDropUuid);
if (!additionalWillDropPromise) {
@@ -51,6 +51,7 @@ export interface IViewPaneOptions extends IPaneOptions {
}
type WelcomeActionClassification = {
owner: 'sandy081';
viewId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
uri: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
@@ -821,6 +821,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
if (this.viewContainerModel.activeViewDescriptors.some(viewDescriptor => viewDescriptor.id === viewId)) {
const visible = !this.viewContainerModel.isVisible(viewId);
type ViewsToggleVisibilityClassification = {
owner: 'sandy081';
viewId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
visible: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
+1
View File
@@ -831,6 +831,7 @@ export interface ITreeViewDataProvider {
export interface ITreeViewDragAndDropController {
readonly dropMimeTypes: string[];
readonly dragMimeTypes: string[];
readonly supportsFileDataTransfers: boolean;
handleDrag(sourceTreeItemHandles: string[], operationUuid: string, token: CancellationToken): Promise<VSDataTransfer | undefined>;
handleDrop(elements: VSDataTransfer, target: ITreeItem | undefined, token: CancellationToken, operationUuid?: string, sourceTreeId?: string, sourceTreeItemHandles?: string[]): Promise<void>;
}
@@ -6,7 +6,7 @@
import * as nls from 'vs/nls';
import severity from 'vs/base/common/severity';
import { Event } from 'vs/base/common/event';
import Constants from 'vs/workbench/contrib/markers/browser/constants';
import { Markers } from 'vs/workbench/contrib/markers/common/markers';
import { ITaskService, ITaskSummary } from 'vs/workbench/contrib/tasks/common/taskService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkspaceFolder, IWorkspace } from 'vs/platform/workspace/common/workspace';
@@ -76,7 +76,7 @@ export class DebugTaskRunner {
return TaskRunResult.Success;
}
if (onTaskErrors === 'showErrors') {
await this.viewsService.openView(Constants.MARKERS_VIEW_ID, true);
await this.viewsService.openView(Markers.MARKERS_VIEW_ID, true);
return Promise.resolve(TaskRunResult.Failure);
}
if (onTaskErrors === 'abort') {
@@ -113,7 +113,7 @@ export class DebugTaskRunner {
return TaskRunResult.Success;
}
await this.viewsService.openView(Constants.MARKERS_VIEW_ID, true);
await this.viewsService.openView(Markers.MARKERS_VIEW_ID, true);
return Promise.resolve(TaskRunResult.Failure);
} catch (err) {
const taskConfigureAction = this.taskService.configureAction();
@@ -541,6 +541,7 @@ CommandsRegistry.registerCommand({
if (ext || await tryInstallHexEditor(notifications, progressService, extensionService, commandService)) {
/* __GDPR__
"debug/didViewMemory" : {
"owner": "connor4312",
"debugType" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
@@ -18,6 +18,7 @@ export class DebugTelemetry {
const extension = dbgr.getMainExtensionDescriptor();
/* __GDPR__
"debugSessionStart" : {
"owner": "connor4312",
"type": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"breakpointCount": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"exceptionBreakpoints": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
@@ -44,6 +45,7 @@ export class DebugTelemetry {
/* __GDPR__
"debugSessionStop" : {
"owner": "connor4312",
"type" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"success": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"sessionLengthInSeconds": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
@@ -306,6 +306,7 @@ export class ExperimentService extends Disposable implements IExperimentService
const promises = rawExperiments.map(experiment => this.evaluateExperiment(experiment));
return Promise.all(promises).then(() => {
type ExperimentsClassification = {
owner: 'sbatten';
experiments: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
this.telemetryService.publicLog2<{ experiments: string[] }, ExperimentsClassification>('experiments', { experiments: this._experiments.map(e => e.id) });
@@ -16,6 +16,7 @@ import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionRe
import { localize } from 'vs/nls';
type DynamicWorkspaceRecommendationsClassification = {
owner: 'sandy081';
count: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
cache: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
};
@@ -562,6 +562,7 @@ export class ExtensionEditor extends EditorPane {
}
/* __GDPR__
"extensionGallery:openExtension" : {
"owner": "sandy081",
"recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"${include}": [
"${GalleryExtensionTelemetryData}"
@@ -644,6 +645,7 @@ export class ExtensionEditor extends EditorPane {
private setRecommendationText(extension: IExtension, template: IExtensionEditorTemplate): void {
const updateRecommendationText = (layout: boolean) => {
reset(template.recommendation);
const extRecommendations = this.extensionRecommendationsService.getAllRecommendationsWithReason();
if (extRecommendations[extension.identifier.id.toLowerCase()]) {
const reasonText = extRecommendations[extension.identifier.id.toLowerCase()].reasonText;
@@ -658,8 +660,8 @@ export class ExtensionEditor extends EditorPane {
this.layout(this.dimension);
}
};
reset(template.recommendation);
if (extension.deprecationInfo || extension.state === ExtensionState.Installed) {
reset(template.recommendation);
return;
}
updateRecommendationText(false);
@@ -27,12 +27,14 @@ import { EnablementState, IWorkbenchExtensionManagementService, IWorkbenchExtens
import { IExtensionIgnoredRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
type ExtensionRecommendationsNotificationClassification = {
owner: 'sandy081';
userReaction: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
extensionId?: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight' };
source: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
type ExtensionWorkspaceRecommendationsNotificationClassification = {
owner: 'sandy081';
userReaction: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
};
@@ -29,6 +29,7 @@ import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/com
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
type IgnoreRecommendationClassification = {
owner: 'sandy081';
recommendationReason: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; isMeasurement: true };
extensionId: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight' };
};
@@ -233,6 +234,7 @@ export class ExtensionRecommendationsService extends Disposable implements IExte
if (recommendationReason) {
/* __GDPR__
"extensionGallery:install:recommendations" : {
"owner": "sandy081",
"recommendationReason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"${include}": [
"${GalleryExtensionTelemetryData}"
@@ -13,7 +13,7 @@ import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging';
import { Event } from 'vs/base/common/event';
import { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
import { UpdateAction, ManageExtensionAction, ReloadAction, ExtensionStatusLabelAction, RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction, WebInstallAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { UpdateAction, ManageExtensionAction, ReloadAction, ExtensionStatusLabelAction, RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction, WebInstallAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, MigrateDeprecatedExtension } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, ExtensionPackCountWidget as ExtensionPackBadgeWidget, SyncIgnoredWidget, ExtensionHoverWidget, ExtensionActivationStatusWidget, PreReleaseBookmarkWidget, extensionVerifiedPublisherIconColor } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
import { IExtensionService, toExtension } from 'vs/workbench/services/extensions/common/extensions';
@@ -118,6 +118,7 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
const reloadAction = this.instantiationService.createInstance(ReloadAction);
const actions = [
this.instantiationService.createInstance(ExtensionStatusLabelAction),
this.instantiationService.createInstance(MigrateDeprecatedExtension, true),
this.instantiationService.createInstance(UpdateAction),
reloadAction,
this.instantiationService.createInstance(InstallDropdownAction),
@@ -61,6 +61,7 @@ import { isOfflineError } from 'vs/base/parts/request/common/request';
const FORCE_FEATURE_EXTENSIONS = ['vscode.git', 'vscode.git-base', 'vscode.search-result'];
type WorkspaceRecommendationsClassification = {
owner: 'sandy081';
count: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; 'isMeasurement': true };
};
@@ -57,6 +57,7 @@ interface InstalledExtensionsEvent {
readonly count: number;
}
interface ExtensionsLoadClassification extends GDPRClassification<InstalledExtensionsEvent> {
owner: 'digitarald';
readonly extensionIds: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight' };
readonly count: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight' };
}
@@ -1454,6 +1455,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
if (changed[i]) {
/* __GDPR__
"extension:enable" : {
"owner": "sandy081",
"${include}": [
"${GalleryExtensionTelemetryData}"
]
@@ -1461,6 +1463,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
*/
/* __GDPR__
"extension:disable" : {
"owner": "sandy081",
"${include}": [
"${GalleryExtensionTelemetryData}"
]
@@ -37,6 +37,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
type FileExtensionSuggestionClassification = {
owner: 'sandy081';
userReaction: { classification: 'SystemMetaData'; purpose: 'FeatureInsight' };
fileExtension: { classification: 'PublicNonPersonalData'; purpose: 'FeatureInsight' };
};
@@ -4,9 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
import { IHostService } from 'vs/workbench/services/host/browser/host';
@@ -17,27 +16,22 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IProductService } from 'vs/platform/product/common/productService';
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
import { ViewContainerLocation } from 'vs/workbench/common/views';
import { Action2, MenuId } from 'vs/platform/actions/common/actions';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
export class ConfigureLocaleAction extends Action {
public static readonly ID = 'workbench.action.configureLocale';
public static readonly LABEL = localize('configureLocale', "Configure Display Language");
constructor(id: string, label: string,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@ILocalizationsService private readonly localizationService: ILocalizationsService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IJSONEditingService private readonly jsonEditingService: IJSONEditingService,
@IHostService private readonly hostService: IHostService,
@INotificationService private readonly notificationService: INotificationService,
@IPaneCompositePartService private readonly paneCompositeService: IPaneCompositePartService,
@IDialogService private readonly dialogService: IDialogService,
@IProductService private readonly productService: IProductService
) {
super(id, label);
export class ConfigureLocaleAction extends Action2 {
constructor() {
super({
id: 'workbench.action.configureLocale',
title: { original: 'Configure Display Language', value: localize('configureLocale', "Configure Display Language") },
menu: {
id: MenuId.CommandPalette
}
});
}
private async getLanguageOptions(): Promise<IQuickPickItem[]> {
const availableLanguages = await this.localizationService.getLanguageIds();
private async getLanguageOptions(localizationService: ILanguagePackService): Promise<IQuickPickItem[]> {
const availableLanguages = await localizationService.getInstalledLanguages();
availableLanguages.sort();
return availableLanguages
@@ -45,12 +39,22 @@ export class ConfigureLocaleAction extends Action {
.concat({ label: localize('installAdditionalLanguages', "Install Additional Languages...") });
}
public override async run(): Promise<void> {
const languageOptions = await this.getLanguageOptions();
public override async run(accessor: ServicesAccessor): Promise<void> {
const environmentService: IEnvironmentService = accessor.get(IEnvironmentService);
const languagePackService: ILanguagePackService = accessor.get(ILanguagePackService);
const quickInputService: IQuickInputService = accessor.get(IQuickInputService);
const jsonEditingService: IJSONEditingService = accessor.get(IJSONEditingService);
const hostService: IHostService = accessor.get(IHostService);
const notificationService: INotificationService = accessor.get(INotificationService);
const paneCompositeService: IPaneCompositePartService = accessor.get(IPaneCompositePartService);
const dialogService: IDialogService = accessor.get(IDialogService);
const productService: IProductService = accessor.get(IProductService);
const languageOptions = await this.getLanguageOptions(languagePackService);
const currentLanguageIndex = languageOptions.findIndex(l => l.label === language);
try {
const selectedLanguage = await this.quickInputService.pick(languageOptions,
const selectedLanguage = await quickInputService.pick(languageOptions,
{
canPickMany: false,
placeHolder: localize('chooseDisplayLanguage', "Select Display Language"),
@@ -58,7 +62,7 @@ export class ConfigureLocaleAction extends Action {
});
if (selectedLanguage === languageOptions[languageOptions.length - 1]) {
return this.paneCompositeService.openPaneComposite(EXTENSIONS_VIEWLET_ID, ViewContainerLocation.Sidebar, true)
return paneCompositeService.openPaneComposite(EXTENSIONS_VIEWLET_ID, ViewContainerLocation.Sidebar, true)
.then(viewlet => viewlet?.getViewPaneContainer())
.then(viewlet => {
const extensionsViewlet = viewlet as IExtensionsViewPaneContainer;
@@ -68,20 +72,20 @@ export class ConfigureLocaleAction extends Action {
}
if (selectedLanguage) {
await this.jsonEditingService.write(this.environmentService.argvResource, [{ path: ['locale'], value: selectedLanguage.label }], true);
const restart = await this.dialogService.confirm({
await jsonEditingService.write(environmentService.argvResource, [{ path: ['locale'], value: selectedLanguage.label }], true);
const restart = await dialogService.confirm({
type: 'info',
message: localize('relaunchDisplayLanguageMessage', "A restart is required for the change in display language to take effect."),
detail: localize('relaunchDisplayLanguageDetail', "Press the restart button to restart {0} and change the display language.", this.productService.nameLong),
detail: localize('relaunchDisplayLanguageDetail', "Press the restart button to restart {0} and change the display language.", productService.nameLong),
primaryButton: localize('restart', "&&Restart")
});
if (restart.confirmed) {
this.hostService.restart();
hostService.restart();
}
}
} catch (e) {
this.notificationService.error(e);
notificationService.error(e);
}
}
}
@@ -6,10 +6,7 @@
import { localize } from 'vs/nls';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContribution, Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { Disposable } from 'vs/base/common/lifecycle';
import { ConfigureLocaleAction } from 'vs/workbench/contrib/localizations/browser/localizationsActions';
import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import * as platform from 'vs/base/common/platform';
@@ -21,15 +18,16 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { VIEWLET_ID as EXTENSIONS_VIEWLET_ID, IExtensionsViewPaneContainer } from 'vs/workbench/contrib/extensions/common/extensions';
import { minimumTranslatedStrings } from 'vs/workbench/contrib/localizations/browser/minimalTranslations';
import { minimumTranslatedStrings } from 'vs/workbench/contrib/localization/electron-sandbox/minimalTranslations';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
import { ViewContainerLocation } from 'vs/workbench/common/views';
import { registerAction2 } from 'vs/platform/actions/common/actions';
import { ConfigureLocaleAction } from 'vs/workbench/contrib/localization/browser/localizationsActions';
// Register action to configure locale and related settings
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ConfigureLocaleAction), 'Configure Display Language');
registerAction2(ConfigureLocaleAction);
const LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY = 'extensionsAssistant/languagePackSuggestionIgnore';
@@ -119,7 +117,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
const loc = manifest && manifest.contributes && manifest.contributes.localizations && manifest.contributes.localizations.filter(x => x.languageId.toLowerCase() === locale)[0];
const languageName = loc ? (loc.languageName || locale) : locale;
const languageDisplayName = loc ? (loc.localizedLanguageName || loc.languageName || locale) : locale;
const translationsFromPack: any = translation && translation.contents ? translation.contents['vs/workbench/contrib/localizations/browser/minimalTranslations'] : {};
const translationsFromPack: any = translation && translation.contents ? translation.contents['vs/workbench/contrib/localization/electron-sandbox/minimalTranslations'] : {};
const promptMessageKey = extensionToInstall ? 'installAndRestartMessage' : 'showLanguagePackExtensions';
const useEnglish = !translationsFromPack[promptMessageKey];
@@ -135,6 +133,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
const logUserReaction = (userReaction: string) => {
/* __GDPR__
"languagePackSuggestion:popup" : {
"owner": "TylerLeonhardt",
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"language": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}

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