Merge from vscode ff915844119ce9485abfe8aa9076ec76b5300ddd (#10030)

This commit is contained in:
Anthony Dresser
2020-04-16 15:12:30 -07:00
committed by GitHub
parent 4fc9057025
commit f3d4a55bb1
14 changed files with 103 additions and 32 deletions

View File

@@ -186,6 +186,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
const checksums = computeChecksums(out, [
'vs/workbench/workbench.desktop.main.js',
'vs/workbench/workbench.desktop.main.css',
'vs/workbench/services/extensions/node/extensionHostProcess.js',
'vs/code/electron-browser/workbench/workbench.html',
'vs/code/electron-browser/workbench/workbench.js'
]);

View File

@@ -1262,7 +1262,7 @@
"timeline/item/context": [
{
"command": "git.timeline.openDiff",
"group": "1_actions",
"group": "1_timeline",
"when": "config.git.enabled && !git.missing && timelineItem =~ /git:file\\b/"
},
{

View File

@@ -443,7 +443,10 @@ export class Git {
);
if (networkPath !== undefined) {
return path.normalize(
repoUri.fsPath.replace(networkPath, `${letter.toLowerCase()}:`),
repoUri.fsPath.replace(
networkPath,
`${letter.toLowerCase()}:${networkPath.endsWith('\\') ? '\\' : ''}`
),
);
}
} catch { }

View File

@@ -268,10 +268,10 @@ export type FuzzyScore2 = [number /* score*/, IMatch[]];
const NO_SCORE2: FuzzyScore2 = [NO_MATCH, []];
export function scoreFuzzy2(target: string, query: IPreparedQuery, patternStart = 0, matchOffset = 0): FuzzyScore2 {
export function scoreFuzzy2(target: string, query: IPreparedQuery, patternStart = 0, matchOffset = 0, skipMultiMatching = false): FuzzyScore2 {
// Score: multiple inputs
if (query.values && query.values.length > 1) {
// Score: multiple inputs (unless disabled)
if (!skipMultiMatching && query.values && query.values.length > 1) {
return doScoreFuzzy2Multiple(target, query.values, patternStart, matchOffset);
}

View File

@@ -662,7 +662,7 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
this.ui.list.clearFocus();
}
}));
this.visibleDisposables.add(this.ui.inputBox.onKeyDown(event => {
this.visibleDisposables.add((this._hideInput ? this.ui.list : this.ui.inputBox).onKeyDown((event: KeyboardEvent | StandardKeyboardEvent) => {
switch (event.keyCode) {
case KeyCode.DownArrow:
this.ui.list.focus(QuickInputListFocus.Next);

View File

@@ -259,6 +259,8 @@ export class QuickInputList {
onChangedCheckedElements: Event<IQuickPickItem[]> = this._onChangedCheckedElements.event;
private readonly _onButtonTriggered = new Emitter<IQuickPickItemButtonEvent<IQuickPickItem>>();
onButtonTriggered = this._onButtonTriggered.event;
private readonly _onKeyDown = new Emitter<StandardKeyboardEvent>();
onKeyDown: Event<StandardKeyboardEvent> = this._onKeyDown.event;
private readonly _onLeave = new Emitter<void>();
onLeave: Event<void> = this._onLeave.event;
private _fireCheckedEvents = true;
@@ -314,6 +316,8 @@ export class QuickInputList {
}
break;
}
this._onKeyDown.fire(event);
}));
this.disposables.push(this.list.onMouseDown(e => {
if (e.browserEvent.button !== 2) {

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, IpcMainEvent, BrowserWindow } from 'electron';
import { app, ipcMain as ipc, systemPreferences, shell, Event, contentTracing, protocol, powerMonitor, IpcMainEvent, BrowserWindow, dialog } from 'electron';
import { IProcessEnvironment, isWindows, isMacintosh } from 'vs/base/common/platform';
import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService';
import { IWindowOpenable } from 'vs/platform/windows/common/windows';
@@ -80,6 +80,7 @@ import { coalesce } from 'vs/base/common/arrays';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { StorageKeysSyncRegistryChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
import { INativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
import { mnemonicButtonLabel, getPathLabel } from 'vs/base/common/labels';
export class CodeApplication extends Disposable {
private windowsMainService: IWindowsMainService | undefined;
@@ -605,6 +606,11 @@ export class CodeApplication extends Disposable {
return undefined;
}
})).filter(pendingUriToHandle => {
// if URI should be blocked, filter it out
if (this.shouldBlockURI(pendingUriToHandle)) {
return false;
}
// filter out any protocol link that wants to open as window so that
// we open the right set of windows on startup and not restore the
// previous workspace too.
@@ -623,6 +629,10 @@ export class CodeApplication extends Disposable {
const environmentService = this.environmentService;
urlService.registerHandler({
async handleURL(uri: URI): Promise<boolean> {
// if URI should be blocked, behave as if it's handled
if (app.shouldBlockURI(uri)) {
return true;
}
// Check for URIs to open in window
const windowOpenableFromProtocolLink = app.getWindowOpenableFromProtocolLink(uri);
@@ -727,6 +737,29 @@ export class CodeApplication extends Disposable {
});
}
private shouldBlockURI(uri: URI): boolean {
if (uri.authority === Schemas.file && isWindows) {
const res = dialog.showMessageBoxSync({
title: product.nameLong,
type: 'question',
buttons: [
mnemonicButtonLabel(localize({ key: 'open', comment: ['&& denotes a mnemonic'] }, "&&Yes")),
mnemonicButtonLabel(localize({ key: 'cancel', comment: ['&& denotes a mnemonic'] }, "&&No")),
],
cancelId: 1,
message: localize('confirmOpenMessage', "An external application wants to open '{0}' in {1}. Do you want to open this file or folder?", getPathLabel(uri.fsPath), product.nameShort),
detail: localize('confirmOpenDetail', "If you did not initiate this request, it may represent an attempted attack on your system. Unless you took an explicit action to initiate this request, you should press 'No'"),
noLink: true
});
if (res === 1) {
return true;
}
}
return false;
}
private getWindowOpenableFromProtocolLink(uri: URI): IWindowOpenable | undefined {
if (!uri.path) {
return undefined;

View File

@@ -220,6 +220,7 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
const symbolLabel = trim(symbol.name);
const symbolLabelWithIcon = `$(symbol-${SymbolKinds.toString(symbol.kind) || 'property'}) ${symbolLabel}`;
const symbolLabelIconOffset = symbolLabelWithIcon.length - symbolLabel.length;
let containerLabel = symbol.containerName;
if (options?.extraContainerLabel) {
@@ -238,14 +239,28 @@ export abstract class AbstractGotoSymbolQuickAccessProvider extends AbstractEdit
if (query.original.length > filterPos) {
// Score by symbol
[symbolScore, symbolMatches] = scoreFuzzy2(symbolLabel, symbolQuery, filterPos, symbolLabelWithIcon.length - symbolLabel.length /* Readjust matches to account for codicons in label */);
// First: try to score on the entire query, it is possible that
// the symbol matches perfectly (e.g. searching for "change log"
// can be a match on a markdown symbol "change log"). In that
// case we want to skip the container query altogether.
let skipContainerQuery = false;
if (symbolQuery !== query) {
[symbolScore, symbolMatches] = scoreFuzzy2(symbolLabel, query, filterPos, symbolLabelIconOffset, true /* skip multi matching */);
if (symbolScore) {
skipContainerQuery = true; // since we consumed the query, skip any container matching
}
}
// Otherwise: score on the symbol query and match on the container later
if (!symbolScore) {
continue;
[symbolScore, symbolMatches] = scoreFuzzy2(symbolLabel, symbolQuery, filterPos, symbolLabelIconOffset);
if (!symbolScore) {
continue;
}
}
// Score by container if specified
if (containerQuery) {
if (!skipContainerQuery && containerQuery) {
if (containerLabel && containerQuery.original.length > 0) {
[containerScore, containerMatches] = scoreFuzzy2(containerLabel, containerQuery);
}

View File

@@ -18,7 +18,7 @@ import { DelayedDragHandler } from 'vs/base/browser/dnd';
import { IActivity } from 'vs/workbench/common/activity';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { Emitter } from 'vs/base/common/event';
import { LocalSelectionTransfer, DraggedCompositeIdentifier, DraggedViewIdentifier, CompositeDragAndDropObserver, ICompositeDragAndDrop, Before2D } from 'vs/workbench/browser/dnd';
import { CompositeDragAndDropObserver, ICompositeDragAndDrop, Before2D } from 'vs/workbench/browser/dnd';
import { Color } from 'vs/base/common/color';
export interface ICompositeActivity {
@@ -452,7 +452,6 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
private static manageExtensionAction: ManageExtensionAction;
private compositeActivity: IActivity | undefined;
private compositeTransfer: LocalSelectionTransfer<DraggedCompositeIdentifier | DraggedViewIdentifier>;
constructor(
private compositeActivityAction: ActivityAction,
@@ -470,8 +469,6 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
) {
super(compositeActivityAction, { draggable: true, colors, icon }, themeService);
this.compositeTransfer = LocalSelectionTransfer.getInstance<DraggedCompositeIdentifier | DraggedViewIdentifier>();
if (!CompositeActionViewItem.manageExtensionAction) {
CompositeActionViewItem.manageExtensionAction = instantiationService.createInstance(ManageExtensionAction);
}
@@ -670,9 +667,6 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
dispose(): void {
super.dispose();
this.compositeTransfer.clearData(DraggedCompositeIdentifier.prototype);
this.label.remove();
}
}

View File

@@ -816,7 +816,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
return TriggerAction.CLOSE_PICKER;
},
accept: (keyMods, event) => this.openAnything(activeGlobalResource, { keyMods, range: editorSymbolPick.range?.selection, preserveFocus: event.inBackground })
accept: (keyMods, event) => this.openAnything(activeGlobalResource, { keyMods, range: editorSymbolPick.range?.selection, preserveFocus: event.inBackground, forcePinned: event.inBackground })
};
});
}
@@ -901,14 +901,14 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
return TriggerAction.NO_ACTION;
},
accept: (keyMods, event) => this.openAnything(resourceOrEditor, { keyMods, range: this.pickState.lastRange, preserveFocus: event.inBackground })
accept: (keyMods, event) => this.openAnything(resourceOrEditor, { keyMods, range: this.pickState.lastRange, preserveFocus: event.inBackground, forcePinned: event.inBackground })
};
}
private async openAnything(resourceOrEditor: URI | IEditorInput | IResourceEditorInput, options: { keyMods?: IKeyMods, preserveFocus?: boolean, range?: IRange, forceOpenSideBySide?: boolean }): Promise<void> {
private async openAnything(resourceOrEditor: URI | IEditorInput | IResourceEditorInput, options: { keyMods?: IKeyMods, preserveFocus?: boolean, range?: IRange, forceOpenSideBySide?: boolean, forcePinned?: boolean }): Promise<void> {
const editorOptions: ITextEditorOptions = {
preserveFocus: options.preserveFocus,
pinned: options.keyMods?.alt || this.configuration.openEditorPinned,
pinned: options.keyMods?.alt || options.forcePinned || this.configuration.openEditorPinned,
selection: options.range ? Range.collapseToStart(options.range) : undefined
};

View File

@@ -130,15 +130,31 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider<ISymbo
const symbolLabel = symbol.name;
const symbolLabelWithIcon = `$(symbol-${SymbolKinds.toString(symbol.kind) || 'property'}) ${symbolLabel}`;
const symbolLabelIconOffset = symbolLabelWithIcon.length - symbolLabel.length;
// Score by symbol label if searching
let symbolScore: number | undefined = undefined;
let symbolMatches: IMatch[] | undefined = undefined;
let skipContainerQuery = false;
if (symbolQuery.original.length > 0) {
[symbolScore, symbolMatches] = scoreFuzzy2(symbolLabel, symbolQuery, 0, symbolLabelWithIcon.length - symbolLabel.length /* Readjust matches to account for codicons in label */);
// First: try to score on the entire query, it is possible that
// the symbol matches perfectly (e.g. searching for "change log"
// can be a match on a markdown symbol "change log"). In that
// case we want to skip the container query altogether.
if (symbolQuery !== query) {
[symbolScore, symbolMatches] = scoreFuzzy2(symbolLabel, query, 0, symbolLabelIconOffset, true /* skip multi matching */);
if (symbolScore) {
skipContainerQuery = true; // since we consumed the query, skip any container matching
}
}
// Otherwise: score on the symbol query and match on the container later
if (!symbolScore) {
continue;
[symbolScore, symbolMatches] = scoreFuzzy2(symbolLabel, symbolQuery, 0, symbolLabelIconOffset);
if (!symbolScore) {
continue;
}
}
}
@@ -156,7 +172,7 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider<ISymbo
// Score by container if specified and searching
let containerScore: number | undefined = undefined;
let containerMatches: IMatch[] | undefined = undefined;
if (containerQuery && containerQuery.original.length > 0) {
if (!skipContainerQuery && containerQuery && containerQuery.original.length > 0) {
if (containerLabel) {
[containerScore, containerMatches] = scoreFuzzy2(containerLabel, containerQuery);
}
@@ -195,7 +211,7 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider<ISymbo
return TriggerAction.CLOSE_PICKER;
},
accept: async (keyMods, event) => this.openSymbol(provider, symbol, token, { keyMods, preserveFocus: event.inBackground }),
accept: async (keyMods, event) => this.openSymbol(provider, symbol, token, { keyMods, preserveFocus: event.inBackground, forcePinned: event.inBackground }),
});
}
}
@@ -208,7 +224,7 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider<ISymbo
return symbolPicks;
}
private async openSymbol(provider: IWorkspaceSymbolProvider, symbol: IWorkspaceSymbol, token: CancellationToken, options: { keyMods: IKeyMods, forceOpenSideBySide?: boolean, preserveFocus?: boolean }): Promise<void> {
private async openSymbol(provider: IWorkspaceSymbolProvider, symbol: IWorkspaceSymbol, token: CancellationToken, options: { keyMods: IKeyMods, forceOpenSideBySide?: boolean, preserveFocus?: boolean, forcePinned?: boolean }): Promise<void> {
// Resolve actual symbol to open for providers that can resolve
let symbolToOpen = symbol;
@@ -231,7 +247,7 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider<ISymbo
resource: symbolToOpen.location.uri,
options: {
preserveFocus: options?.preserveFocus,
pinned: options.keyMods.alt || this.configuration.openEditorPinned,
pinned: options.keyMods.alt || options.forcePinned || this.configuration.openEditorPinned,
selection: symbolToOpen.location.range ? Range.collapseToStart(symbolToOpen.location.range) : undefined
}
}, options.keyMods.ctrlCmd || options?.forceOpenSideBySide ? SIDE_GROUP : ACTIVE_GROUP);

View File

@@ -85,7 +85,7 @@ import { InstallVSIXAction } from 'vs/workbench/contrib/extensions/browser/exten
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command,
when: ContextKeyExpr.equals('config.window.nativeTabs', 'true')
when: ContextKeyExpr.equals('config.window.nativeTabs', true)
});
});
}

View File

@@ -144,7 +144,7 @@ export class IntegrityServiceImpl implements IIntegrityService {
return new Promise<ChecksumPair>((resolve, reject) => {
fs.readFile(fileUri.fsPath, (err, buff) => {
if (err) {
return reject(err);
return resolve(IntegrityServiceImpl._createChecksumPair(fileUri, '', expected));
}
resolve(IntegrityServiceImpl._createChecksumPair(fileUri, this._computeChecksum(buff), expected));
});

View File

@@ -203,10 +203,15 @@ export class SearchService extends Disposable implements ISearchService {
this.fileSearchProviders.get(scheme) :
this.textSearchProviders.get(scheme);
if (!provider && scheme === 'file') {
if (!provider && scheme === Schemas.file) {
diskSearchQueries.push(...schemeFQs);
} else {
if (!provider) {
if (scheme !== Schemas.vscodeRemote) {
console.warn(`No search provider registered for scheme: ${scheme}`);
return;
}
console.warn(`No search provider registered for scheme: ${scheme}, waiting`);
provider = await this.waitForProvider(query.type, scheme);
}