From 8476ff1a9ded4dcbb2ef06a42b5f45e4192eb26d Mon Sep 17 00:00:00 2001 From: kingwl Date: Tue, 22 Dec 2020 18:34:34 +0800 Subject: [PATCH] WIP --- build/azure-pipelines/common/symbols.js | 185 ++++++++++++++++++ .../editor/browser/widget/codeEditorWidget.ts | 4 + src/vs/editor/common/editorContextKeys.ts | 1 + src/vs/editor/common/modes.ts | 22 ++- src/vs/vscode.d.ts | 18 ++ .../api/browser/mainThreadLanguageFeatures.ts | 10 + .../workbench/api/common/extHost.protocol.ts | 13 ++ .../api/common/extHostLanguageFeatures.ts | 25 +++ .../api/common/extHostTypeConverters.ts | 10 + src/vs/workbench/api/common/extHostTypes.ts | 28 +++ 10 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 build/azure-pipelines/common/symbols.js diff --git a/build/azure-pipelines/common/symbols.js b/build/azure-pipelines/common/symbols.js new file mode 100644 index 00000000000..5a436897e66 --- /dev/null +++ b/build/azure-pipelines/common/symbols.js @@ -0,0 +1,185 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const request = require("request"); +const fs_1 = require("fs"); +const github = require("github-releases"); +const path_1 = require("path"); +const os_1 = require("os"); +const util_1 = require("util"); +const BASE_URL = 'https://rink.hockeyapp.net/api/2/'; +const HOCKEY_APP_TOKEN_HEADER = 'X-HockeyAppToken'; +var Platform; +(function (Platform) { + Platform["WIN_32"] = "win32-ia32"; + Platform["WIN_64"] = "win32-x64"; + Platform["LINUX_64"] = "linux-x64"; + Platform["MAC_OS"] = "darwin-x64"; +})(Platform || (Platform = {})); +function symbolsZipName(platform, electronVersion, insiders) { + return `${insiders ? 'insiders' : 'stable'}-symbols-v${electronVersion}-${platform}.zip`; +} +const SEED = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; +async function tmpFile(name) { + let res = ''; + for (let i = 0; i < 8; i++) { + res += SEED.charAt(Math.floor(Math.random() * SEED.length)); + } + const tmpParent = path_1.join(os_1.tmpdir(), res); + await util_1.promisify(fs_1.mkdir)(tmpParent); + return path_1.join(tmpParent, name); +} +function getVersions(accessor) { + return asyncRequest({ + url: `${BASE_URL}/apps/${accessor.appId}/app_versions`, + method: 'GET', + headers: { + [HOCKEY_APP_TOKEN_HEADER]: accessor.accessToken + } + }); +} +function createVersion(accessor, version) { + return asyncRequest({ + url: `${BASE_URL}/apps/${accessor.appId}/app_versions/new`, + method: 'POST', + headers: { + [HOCKEY_APP_TOKEN_HEADER]: accessor.accessToken + }, + formData: { + bundle_version: version + } + }); +} +function updateVersion(accessor, symbolsPath) { + return asyncRequest({ + url: `${BASE_URL}/apps/${accessor.appId}/app_versions/${accessor.id}`, + method: 'PUT', + headers: { + [HOCKEY_APP_TOKEN_HEADER]: accessor.accessToken + }, + formData: { + dsym: fs_1.createReadStream(symbolsPath) + } + }); +} +function asyncRequest(options) { + return new Promise((resolve, reject) => { + request(options, (error, _response, body) => { + if (error) { + reject(error); + } + else { + resolve(JSON.parse(body)); + } + }); + }); +} +function downloadAsset(repository, assetName, targetPath, electronVersion) { + return new Promise((resolve, reject) => { + repository.getReleases({ tag_name: `v${electronVersion}` }, (err, releases) => { + if (err) { + reject(err); + } + else { + const asset = releases[0].assets.filter((asset) => asset.name === assetName)[0]; + if (!asset) { + reject(new Error(`Asset with name ${assetName} not found`)); + } + else { + repository.downloadAsset(asset, (err, reader) => { + if (err) { + reject(err); + } + else { + const writer = fs_1.createWriteStream(targetPath); + writer.on('error', reject); + writer.on('close', resolve); + reader.on('error', reject); + reader.pipe(writer); + } + }); + } + } + }); + }); +} +async function ensureVersionAndSymbols(options) { + // Check version does not exist + console.log(`HockeyApp: checking for existing version ${options.versions.code} (${options.platform})`); + const versions = await getVersions({ accessToken: options.access.hockeyAppToken, appId: options.access.hockeyAppId }); + if (!Array.isArray(versions.app_versions)) { + throw new Error(`Unexpected response: ${JSON.stringify(versions)}`); + } + if (versions.app_versions.some(v => v.version === options.versions.code)) { + console.log(`HockeyApp: Returning without uploading symbols because version ${options.versions.code} (${options.platform}) was already found`); + return; + } + // Download symbols for platform and electron version + const symbolsName = symbolsZipName(options.platform, options.versions.electron, options.versions.insiders); + const symbolsPath = await tmpFile('symbols.zip'); + console.log(`HockeyApp: downloading symbols ${symbolsName} for electron ${options.versions.electron} (${options.platform}) into ${symbolsPath}`); + await downloadAsset(new github({ repo: options.repository, token: options.access.githubToken }), symbolsName, symbolsPath, options.versions.electron); + // Create version + console.log(`HockeyApp: creating new version ${options.versions.code} (${options.platform})`); + const version = await createVersion({ accessToken: options.access.hockeyAppToken, appId: options.access.hockeyAppId }, options.versions.code); + // Upload symbols + console.log(`HockeyApp: uploading symbols for version ${options.versions.code} (${options.platform})`); + await updateVersion({ id: String(version.id), accessToken: options.access.hockeyAppToken, appId: options.access.hockeyAppId }, symbolsPath); + // Cleanup + await util_1.promisify(fs_1.unlink)(symbolsPath); +} +// Environment +const pakage = require('../../../package.json'); +const product = require('../../../product.json'); +const repository = product.electronRepository; +const electronVersion = require('../../lib/electron').getElectronVersion(); +const insiders = product.quality !== 'stable'; +let codeVersion = pakage.version; +if (insiders) { + codeVersion = `${codeVersion}-insider`; +} +const githubToken = process.argv[2]; +const hockeyAppToken = process.argv[3]; +const is64 = process.argv[4] === 'x64'; +const hockeyAppId = process.argv[5]; +if (process.argv.length !== 6) { + throw new Error(`HockeyApp: Unexpected number of arguments. Got ${process.argv}`); +} +let platform; +if (process.platform === 'darwin') { + platform = Platform.MAC_OS; +} +else if (process.platform === 'win32') { + platform = is64 ? Platform.WIN_64 : Platform.WIN_32; +} +else { + platform = Platform.LINUX_64; +} +// Create version and upload symbols in HockeyApp +if (repository && codeVersion && electronVersion && (product.quality === 'stable' || product.quality === 'insider')) { + ensureVersionAndSymbols({ + repository, + platform, + versions: { + code: codeVersion, + insiders, + electron: electronVersion + }, + access: { + githubToken, + hockeyAppToken, + hockeyAppId + } + }).then(() => { + console.log('HockeyApp: done'); + }).catch(error => { + console.error(`HockeyApp: error ${error} (AppID: ${hockeyAppId})`); + return process.exit(1); + }); +} +else { + console.log(`HockeyApp: skipping due to unexpected context (repository: ${repository}, codeVersion: ${codeVersion}, electronVersion: ${electronVersion}, quality: ${product.quality})`); +} diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 4c87ce2bb2d..f18591d2a59 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -1834,6 +1834,7 @@ export class EditorModeContext extends Disposable { private readonly _hasMultipleDocumentFormattingProvider: IContextKey; private readonly _hasMultipleDocumentSelectionFormattingProvider: IContextKey; private readonly _hasSignatureHelpProvider: IContextKey; + private readonly _hasSignatureArgumentsLabelProvider: IContextKey; private readonly _isInWalkThrough: IContextKey; constructor( @@ -1856,6 +1857,7 @@ export class EditorModeContext extends Disposable { this._hasReferenceProvider = EditorContextKeys.hasReferenceProvider.bindTo(_contextKeyService); this._hasRenameProvider = EditorContextKeys.hasRenameProvider.bindTo(_contextKeyService); this._hasSignatureHelpProvider = EditorContextKeys.hasSignatureHelpProvider.bindTo(_contextKeyService); + this._hasSignatureArgumentsLabelProvider = EditorContextKeys.hasSignatureArgumentsLabelProvider.bindTo(_contextKeyService); this._hasDocumentFormattingProvider = EditorContextKeys.hasDocumentFormattingProvider.bindTo(_contextKeyService); this._hasDocumentSelectionFormattingProvider = EditorContextKeys.hasDocumentSelectionFormattingProvider.bindTo(_contextKeyService); this._hasMultipleDocumentFormattingProvider = EditorContextKeys.hasMultipleDocumentFormattingProvider.bindTo(_contextKeyService); @@ -1884,6 +1886,7 @@ export class EditorModeContext extends Disposable { this._register(modes.DocumentFormattingEditProviderRegistry.onDidChange(update)); this._register(modes.DocumentRangeFormattingEditProviderRegistry.onDidChange(update)); this._register(modes.SignatureHelpProviderRegistry.onDidChange(update)); + this._register(modes.SignatureArgumentsLabelProviderRegistry.onDidChange(update)); update(); } @@ -1935,6 +1938,7 @@ export class EditorModeContext extends Disposable { this._hasReferenceProvider.set(modes.ReferenceProviderRegistry.has(model)); this._hasRenameProvider.set(modes.RenameProviderRegistry.has(model)); this._hasSignatureHelpProvider.set(modes.SignatureHelpProviderRegistry.has(model)); + this._hasSignatureArgumentsLabelProvider.set(modes.SignatureArgumentsLabelProviderRegistry.has(model)); this._hasDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.has(model) || modes.DocumentRangeFormattingEditProviderRegistry.has(model)); this._hasDocumentSelectionFormattingProvider.set(modes.DocumentRangeFormattingEditProviderRegistry.has(model)); this._hasMultipleDocumentFormattingProvider.set(modes.DocumentFormattingEditProviderRegistry.all(model).length + modes.DocumentRangeFormattingEditProviderRegistry.all(model).length > 1); diff --git a/src/vs/editor/common/editorContextKeys.ts b/src/vs/editor/common/editorContextKeys.ts index a3a3b3de1dc..23e1d43150b 100644 --- a/src/vs/editor/common/editorContextKeys.ts +++ b/src/vs/editor/common/editorContextKeys.ts @@ -61,6 +61,7 @@ export namespace EditorContextKeys { export const hasReferenceProvider = new RawContextKey('editorHasReferenceProvider', false); export const hasRenameProvider = new RawContextKey('editorHasRenameProvider', false); export const hasSignatureHelpProvider = new RawContextKey('editorHasSignatureHelpProvider', false); + export const hasSignatureArgumentsLabelProvider = new RawContextKey('editorHasSignatureArgumentsLabelProvider', false); // -- mode context keys: formatting export const hasDocumentFormattingProvider = new RawContextKey('editorHasDocumentFormattingProvider', false); diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index fe0d7335d09..233ecd95eac 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -9,7 +9,7 @@ import { Event } from 'vs/base/common/event'; import { IMarkdownString } from 'vs/base/common/htmlContent'; import { IDisposable } from 'vs/base/common/lifecycle'; import { URI, UriComponents } from 'vs/base/common/uri'; -import { Position } from 'vs/editor/common/core/position'; +import { IPosition, Position } from 'vs/editor/common/core/position'; import { IRange, Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { TokenizationResult, TokenizationResult2 } from 'vs/editor/common/core/token'; @@ -1659,6 +1659,22 @@ export interface CodeLensProvider { resolveCodeLens?(model: model.ITextModel, codeLens: CodeLens, token: CancellationToken): ProviderResult; } +export interface SignautreArguments { + name: string + positions: IPosition[] +} +export interface SignatureArgumentsSignature { + arguments: SignautreArguments[] +} + +export interface SignatureArgumentsLabelList { + signatures: SignatureArgumentsSignature[] +} + +export interface SignatureArgumentsLabelProvider { + provideSignatureArgumentsLabels(model: model.ITextModel, token: CancellationToken): ProviderResult; +} + export interface SemanticTokensLegend { readonly tokenTypes: string[]; readonly tokenModifiers: string[]; @@ -1763,6 +1779,10 @@ export const TypeDefinitionProviderRegistry = new LanguageFeatureRegistry(); +/** + * @internal + */ +export const SignatureArgumentsLabelProviderRegistry = new LanguageFeatureRegistry(); /** * @internal diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 0def9b1af79..028a0430040 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -3755,6 +3755,24 @@ declare module 'vscode' { provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken, context: SignatureHelpContext): ProviderResult; } + export interface SignautreArguments { + name: string + positions: Position[] + } + export interface SignatureArgumentsSignature { + arguments: SignautreArguments[] + } + + export interface SignatureArgumentsLabelList { + signatures: SignatureArgumentsSignature[] + dispose(): void; + } + + + export interface SignatureArgumentsLabelProvider { + provideSignatureArgumentsLabels(model: TextDocument, token: CancellationToken): ProviderResult; + } + /** * Metadata about a registered [`SignatureHelpProvider`](#SignatureHelpProvider). */ diff --git a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts index ddea8e0e9d1..a0f4b2def79 100644 --- a/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts @@ -497,6 +497,16 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha })); } + // --- parameter labels + + $registerSignatureArgumentsLabelSupport(handle: number, selector: IDocumentFilterDto[]): void { + this._registrations.set(handle, modes.SignatureArgumentsLabelProviderRegistry.register(selector, { + provideSignatureArgumentsLabels: async (model: ITextModel, token: CancellationToken): Promise => { + return this._proxy.$provideSignatureArgumentsLabel(handle, model.uri, token); + } + })); + } + // --- links $registerDocumentLinkProvider(handle: number, selector: IDocumentFilterDto[], supportsResolve: boolean): void { diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 77016c491b0..e133a331a3c 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1269,6 +1269,18 @@ export interface ISignatureHelpContextDto { readonly activeSignatureHelp?: ISignatureHelpDto; } +export interface ISignautreArgumentsDto { + name: string + positions: IPosition[] +} +export interface ISignatureArgumentsSignatureDto { + arguments: ISignautreArgumentsDto[] +} + +export interface ISignatureArgumentsLabelDto { + signatures: ISignatureArgumentsSignatureDto[] +} + export interface ILocationDto { uri: UriComponents; range: IRange; @@ -1458,6 +1470,7 @@ export interface ExtHostLanguageFeaturesShape { $releaseCompletionItems(handle: number, id: number): void; $provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise; $releaseSignatureHelp(handle: number, id: number): void; + $provideSignatureArgumentsLabel(handle: number, resource: UriComponents, token: CancellationToken): Promise $provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise; $resolveDocumentLink(handle: number, id: ChainedCacheId, token: CancellationToken): Promise; $releaseDocumentLinks(handle: number, id: number): void; diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 49cde88e19c..086811373a6 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -1062,6 +1062,26 @@ class SignatureHelpAdapter { } } +class SignatureArgumentsLabelAdapter { + private readonly _cache = new Cache('SignatureArgumentsLabel'); + + constructor( + private readonly _documents: ExtHostDocuments, + private readonly _provider: vscode.SignatureArgumentsLabelProvider, + ) { } + + provideSignatureArgumentsLabels(resource: URI, token: CancellationToken): Promise { + const doc = this._documents.getDocument(resource); + return asPromise(() => this._provider.provideSignatureArgumentsLabels(doc, token)).then(value => { + if (value) { + const id = this._cache.add([value]); + return { ...typeConvert.SignatrueArgumentsLabelList.from(value), id }; + } + return undefined; + }); + } +} + class LinkProviderAdapter { private _cache = new Cache('DocumentLink'); @@ -1770,6 +1790,11 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.releaseSignatureHelp(id), undefined); } + // --- arguments labels + $provideSignatureArgumentsLabel(handle: number, resource: UriComponents, token: CancellationToken): Promise { + return this._withAdapter(handle, SignatureArgumentsLabelAdapter, adapter => adapter.provideSignatureArgumentsLabels(URI.revive(resource), token), undefined); + } + // --- links registerDocumentLinkProvider(extension: IExtensionDescription | undefined, selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable { diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index ee4a7197a3c..9ce93ea7dd5 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -1015,6 +1015,16 @@ export namespace SignatureHelp { } } +export namespace SignatrueArgumentsLabelList { + export function from(labels: vscode.SignatureArgumentsLabelList): modes.SignatureArgumentsLabelList { + + } + + export function to(labels: modes.SignatureArgumentsLabelList): vscode.SignatureArgumentsLabelList { + + } +} + export namespace DocumentLink { export function from(link: vscode.DocumentLink): modes.ILink { diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index e01c9270d39..815330cb618 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1373,6 +1373,34 @@ export enum SignatureHelpTriggerKind { ContentChange = 3, } +@es5ClassCompat +export class SignautreArguments { + name: string; + positions: Position[]; + + constructor(name: string, positions: Position[]) { + this.name = name; + this.positions = positions; + } +} + +@es5ClassCompat +export class SignatureArgumentsSignature { + arguments: SignautreArguments[]; + + constructor() { + this.arguments = []; + } +} + +@es5ClassCompat +export class SignatureArgumentsLabelList { + signatures: SignatureArgumentsSignature[]; + constructor() { + this.signatures = []; + } +} + export enum CompletionTriggerKind { Invoke = 0, TriggerCharacter = 1,