Vscode merge (#4582)

* Merge from vscode 37cb23d3dd4f9433d56d4ba5ea3203580719a0bd

* fix issues with merges

* bump node version in azpipe

* replace license headers

* remove duplicate launch task

* fix build errors

* fix build errors

* fix tslint issues

* working through package and linux build issues

* more work

* wip

* fix packaged builds

* working through linux build errors

* wip

* wip

* wip

* fix mac and linux file limits

* iterate linux pipeline

* disable editor typing

* revert series to parallel

* remove optimize vscode from linux

* fix linting issues

* revert testing change

* add work round for new node

* readd packaging for extensions

* fix issue with angular not resolving decorator dependencies
This commit is contained in:
Anthony Dresser
2019-03-19 17:44:35 -07:00
committed by GitHub
parent 833d197412
commit 87765e8673
1879 changed files with 54505 additions and 38058 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-2 -2 16 16" enable-background="new -2 -2 16 16"><polygon fill="#C5C5C5" points="9,0 4.5,9 3,6 0,6 3,12 6,12 12,0"/></svg>

After

Width:  |  Height:  |  Size: 194 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><polygon points="5.382,13 2.382,7 6.618,7 7,7.764 9.382,3 13.618,3 8.618,13" fill="#F6F6F6"/><path d="M12 4l-4 8h-2l-2-4h2l1 2 3-6h2z" fill="#424242"/></svg>

After

Width:  |  Height:  |  Size: 220 B

View File

@@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-editor .dirty-diff-glyph {
margin-left: 5px;
cursor: pointer;
z-index: 5;
}
.monaco-editor .dirty-diff-deleted:after {
content: '';
position: absolute;
bottom: -4px;
box-sizing: border-box;
width: 4px;
height: 0;
z-index: 9;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
transition: border-top-width 80ms linear, border-bottom-width 80ms linear, bottom 80ms linear;
pointer-events: none;
}
.monaco-editor .dirty-diff-glyph:before {
position: absolute;
content: '';
height: 100%;
width: 0;
left: -2px;
transition: width 80ms linear, left 80ms linear;
}
.monaco-editor .dirty-diff-deleted:before {
margin-left: 3px;
height: 0;
bottom: 0;
transition: height 80ms linear;
}
.monaco-editor .margin-view-overlays > div:hover > .dirty-diff-glyph:before {
position: absolute;
content: '';
height: 100%;
width: 9px;
left: -6px;
}
.monaco-editor .margin-view-overlays > div:hover > .dirty-diff-deleted:after {
bottom: 0;
border-top-width: 0;
border-bottom-width: 0;
}
/* Hide glyph decorations when inside the inline diff editor */
.monaco-editor.modified-in-monaco-diff-editor .margin-view-overlays > div > .dirty-diff-glyph {
display: none;
}

View File

@@ -0,0 +1 @@
<svg fill="none" height="28" viewBox="0 0 28 28" width="28" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m20 0c-2.22 0-4 1.78-4 4 0 1.46.82 2.76 2 3.44v2.56l-4 4-4-4v-2.56c1.18-.68 2-1.96 2-3.44 0-2.22-1.78-4-4-4s-4 1.78-4 4c0 1.46.82 2.76 2 3.44v3.56l6 6v3.56c-1.18.68-2 1.96-2 3.44 0 2.22 1.78 4 4 4s4-1.78 4-4c0-1.46-.82-2.76-2-3.44v-3.56l6-6v-3.56c1.18-.68 2-1.96 2-3.44 0-2.22-1.78-4-4-4zm-12 6.4c-1.32 0-2.4-1.1-2.4-2.4s1.1-2.4 2.4-2.4 2.4 1.1 2.4 2.4-1.1 2.4-2.4 2.4zm6 20c-1.32 0-2.4-1.1-2.4-2.4s1.1-2.4 2.4-2.4 2.4 1.1 2.4 2.4-1.1 2.4-2.4 2.4zm6-20c-1.32 0-2.4-1.1-2.4-2.4s1.1-2.4 2.4-2.4 2.4 1.1 2.4 2.4-1.1 2.4-2.4 2.4z" fill="#fff" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 690 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="10px" height="16px" viewBox="0 0 10 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.3 (33839) - http://www.bohemiancoding.com/sketch -->
<title>repo-forked</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Octicons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="repo-forked" fill="#424242">
<path d="M8,1 C6.89,1 6,1.89 6,3 C6,3.73 6.41,4.38 7,4.72 L7,6 L5,8 L3,6 L3,4.72 C3.59,4.38 4,3.74 4,3 C4,1.89 3.11,1 2,1 C0.89,1 0,1.89 0,3 C0,3.73 0.41,4.38 1,4.72 L1,6.5 L4,9.5 L4,11.28 C3.41,11.62 3,12.26 3,13 C3,14.11 3.89,15 5,15 C6.11,15 7,14.11 7,13 C7,12.27 6.59,11.62 6,11.28 L6,9.5 L9,6.5 L9,4.72 C9.59,4.38 10,3.74 10,3 C10,1.89 9.11,1 8,1 L8,1 Z M2,4.2 C1.34,4.2 0.8,3.65 0.8,3 C0.8,2.35 1.35,1.8 2,1.8 C2.65,1.8 3.2,2.35 3.2,3 C3.2,3.65 2.65,4.2 2,4.2 L2,4.2 Z M5,14.2 C4.34,14.2 3.8,13.65 3.8,13 C3.8,12.35 4.35,11.8 5,11.8 C5.65,11.8 6.2,12.35 6.2,13 C6.2,13.65 5.65,14.2 5,14.2 L5,14.2 Z M8,4.2 C7.34,4.2 6.8,3.65 6.8,3 C6.8,2.35 7.35,1.8 8,1.8 C8.65,1.8 9.2,2.35 9.2,3 C9.2,3.65 8.65,4.2 8,4.2 L8,4.2 Z" id="Shape"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,164 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-workbench .activitybar > .content .monaco-action-bar .action-label.scm {
-webkit-mask: url('icon-dark.svg') no-repeat 50% 50%;
}
.monaco-workbench .viewlet.scm-viewlet .collapsible.header .actions {
width: initial;
flex: 1;
}
.scm-viewlet .empty-message {
box-sizing: border-box;
height: 100%;
padding: 10px 22px 0 22px;
}
.scm-viewlet:not(.empty) .empty-message,
.scm-viewlet.empty .monaco-panel-view {
display: none;
}
.scm-viewlet .scm-status {
height: 100%;
position: relative;
}
.scm-viewlet .monaco-list-row > .scm-provider {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.scm-viewlet .monaco-list-row > .scm-provider > .monaco-action-bar {
flex: 1;
}
.scm-viewlet .monaco-list-row > .scm-provider > .monaco-action-bar .action-item {
overflow: hidden;
text-overflow: ellipsis;
}
.scm-viewlet .scm-provider > .count {
margin: 0 0.5em;
}
.scm-viewlet .scm-provider > .count.hidden {
display: none;
}
.scm-viewlet .scm-provider > .type,
.scm-viewlet .scm-provider > .name > .type {
opacity: 0.7;
margin-left: 0.5em;
font-size: 0.9em;
}
.scm-viewlet .monaco-list-row {
padding: 0 12px 0 20px;
line-height: 22px;
}
.scm-viewlet .monaco-list-row > .resource-group {
display: flex;
height: 100%;
}
.scm-viewlet .monaco-list-row > .resource-group > .name {
flex: 1;
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
overflow: hidden;
text-overflow: ellipsis;
}
.scm-viewlet .monaco-list-row > .resource {
display: flex;
height: 100%;
}
.scm-viewlet .monaco-list-row > .resource.faded {
opacity: 0.7;
}
.scm-viewlet .monaco-list-row > .resource > .name {
flex: 1;
overflow: hidden;
}
.scm-viewlet .monaco-list-row > .resource > .name.strike-through > .monaco-icon-label > .monaco-icon-label-description-container > .label-name {
text-decoration: line-through;
}
.scm-viewlet .monaco-list-row > .resource > .name > .monaco-icon-label::after {
padding: 0 4px;
}
.scm-viewlet .monaco-list-row > .resource > .decoration-icon {
width: 16px;
height: 100%;
background-repeat: no-repeat;
background-position: 50% 50%;
}
.scm-viewlet .monaco-list .monaco-list-row > .resource > .name > .monaco-icon-label > .actions {
flex-grow: 100;
}
.scm-viewlet .monaco-list .monaco-list-row > .resource-group > .actions,
.scm-viewlet .monaco-list .monaco-list-row > .resource > .name > .monaco-icon-label > .actions {
display: none;
}
.scm-viewlet .monaco-list .monaco-list-row:hover > .resource-group > .actions,
.scm-viewlet .monaco-list .monaco-list-row:hover > .resource > .name > .monaco-icon-label > .actions,
.scm-viewlet .monaco-list .monaco-list-row.selected > .resource-group > .actions,
.scm-viewlet .monaco-list .monaco-list-row.focused > .resource-group > .actions,
.scm-viewlet .monaco-list .monaco-list-row.selected > .resource > .name > .monaco-icon-label > .actions,
.scm-viewlet .monaco-list .monaco-list-row.focused > .resource > .name > .monaco-icon-label > .actions,
.scm-viewlet .monaco-list:not(.selection-multiple) .monaco-list-row > .resource:hover > .actions {
display: block;
}
.scm-viewlet .scm-status.show-actions > .monaco-list .monaco-list-row > .resource-group > .actions,
.scm-viewlet .scm-status.show-actions > .monaco-list .monaco-list-row > .resource > .name > .monaco-icon-label > .actions {
display: block;
}
.scm-viewlet .monaco-list-row > .resource > .name > .monaco-icon-label > .actions .action-label,
.scm-viewlet .monaco-list-row > .resource-group > .actions .action-label {
width: 16px;
height: 100%;
background-position: 50% 50%;
background-repeat: no-repeat;
}
.scm-viewlet .scm-editor {
box-sizing: border-box;
padding: 5px 9px 5px 16px;
}
.scm-viewlet .scm-editor.hidden {
display: none;
}
.scm-viewlet .scm-editor > .monaco-inputbox {
width: 100%;
}
.scm-viewlet .scm-editor > .monaco-inputbox > .wrapper > .mirror {
max-height: 134px;
}
.scm-viewlet .scm-editor > .monaco-inputbox > .wrapper > textarea.input {
min-height: 26px;
}
.scm-viewlet .scm-editor.scroll > .monaco-inputbox > .wrapper > textarea.input {
overflow-y: scroll;
}

View File

@@ -0,0 +1,139 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { DirtyDiffWorkbenchController } from './dirtydiffDecorator';
import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor, ShowViewletAction } from 'vs/workbench/browser/viewlet';
import { VIEWLET_ID, ISCMRepository, ISCMService } from 'vs/workbench/contrib/scm/common/scm';
import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions } from 'vs/workbench/common/actions';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { SyncActionDescriptor, MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { StatusUpdater, StatusBarController } from './scmActivity';
import { SCMViewlet } from 'vs/workbench/contrib/scm/browser/scmViewlet';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { ContextKeyDefinedExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { SCMService } from 'vs/workbench/contrib/scm/common/scmService';
class OpenSCMViewletAction extends ShowViewletAction {
static readonly ID = VIEWLET_ID;
static LABEL = localize('toggleGitViewlet', "Show Git");
constructor(id: string, label: string, @IViewletService viewletService: IViewletService, @IEditorGroupsService editorGroupService: IEditorGroupsService, @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService) {
super(id, label, VIEWLET_ID, viewletService, editorGroupService, layoutService);
}
}
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(DirtyDiffWorkbenchController, LifecyclePhase.Restored);
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(new ViewletDescriptor(
SCMViewlet,
VIEWLET_ID,
localize('source control', "Source Control"),
'scm',
// {{SQL CARBON EDIT}}
12
));
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(StatusUpdater, LifecyclePhase.Restored);
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(StatusBarController, LifecyclePhase.Restored);
// Register Action to Open Viewlet
Registry.as<IWorkbenchActionRegistry>(WorkbenchActionExtensions.WorkbenchActions).registerWorkbenchAction(
new SyncActionDescriptor(OpenSCMViewletAction, VIEWLET_ID, localize('toggleSCMViewlet', "Show SCM"), {
primary: 0,
win: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G },
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_G },
mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.KEY_G }
}),
'View: Show SCM',
localize('view', "View")
);
Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).registerConfiguration({
id: 'scm',
order: 5,
title: localize('scmConfigurationTitle', "SCM"),
type: 'object',
properties: {
'scm.alwaysShowProviders': {
type: 'boolean',
description: localize('alwaysShowProviders', "Controls whether to always show the Source Control Provider section."),
default: false
},
'scm.providers.visible': {
type: 'number',
description: localize('providersVisible', "Controls how many providers are visible in the Source Control Provider section. Set to `0` to be able to manually resize the view."),
default: 10
},
'scm.diffDecorations': {
type: 'string',
enum: ['all', 'gutter', 'overview', 'none'],
default: 'all',
description: localize('diffDecorations', "Controls diff decorations in the editor.")
},
'scm.diffDecorationsGutterWidth': {
type: 'number',
enum: [1, 2, 3, 4, 5],
default: 3,
description: localize('diffGutterWidth', "Controls the width(px) of diff decorations in gutter (added & modified).")
},
'scm.alwaysShowActions': {
type: 'boolean',
description: localize('alwaysShowActions', "Controls whether inline actions are always visible in the Source Control view."),
default: false
}
}
});
// View menu
MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
group: '3_views',
command: {
id: VIEWLET_ID,
title: localize({ key: 'miViewSCM', comment: ['&& denotes a mnemonic'] }, "S&&CM")
},
// {{SQL CARBON EDIT}} - Change the order
order: 5
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'scm.acceptInput',
description: { description: localize('scm accept', "SCM: Accept Input"), args: [] },
weight: KeybindingWeight.WorkbenchContrib,
when: new ContextKeyDefinedExpr('scmRepository'),
primary: KeyMod.CtrlCmd | KeyCode.Enter,
handler: accessor => {
const contextKeyService = accessor.get(IContextKeyService);
const context = contextKeyService.getContext(document.activeElement);
const repository = context.getValue<ISCMRepository>('scmRepository');
if (!repository || !repository.provider.acceptInputCommand) {
return Promise.resolve(null);
}
const id = repository.provider.acceptInputCommand.id;
const args = repository.provider.acceptInputCommand.arguments;
const commandService = accessor.get(ICommandService);
return commandService.executeCommand(id, ...(args || []));
}
});
registerSingleton(ISCMService, SCMService);

View File

@@ -0,0 +1,205 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { basename } from 'vs/base/common/resources';
import { IDisposable, dispose, Disposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { Event } from 'vs/base/common/event';
import { VIEWLET_ID, ISCMService, ISCMRepository } from 'vs/workbench/contrib/scm/common/scm';
import { IActivityService, NumberBadge } from 'vs/workbench/services/activity/common/activity';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IStatusbarService, StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/statusbar/common/statusbar';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { commonPrefixLength } from 'vs/base/common/strings';
import { ILogService } from 'vs/platform/log/common/log';
export class StatusUpdater implements IWorkbenchContribution {
private badgeDisposable: IDisposable = Disposable.None;
private disposables: IDisposable[] = [];
constructor(
@ISCMService private readonly scmService: ISCMService,
@IActivityService private readonly activityService: IActivityService,
@ILogService private readonly logService: ILogService
) {
for (const repository of this.scmService.repositories) {
this.onDidAddRepository(repository);
}
this.scmService.onDidAddRepository(this.onDidAddRepository, this, this.disposables);
this.render();
}
private onDidAddRepository(repository: ISCMRepository): void {
const provider = repository.provider;
const onDidChange = Event.any(provider.onDidChange, provider.onDidChangeResources);
const changeDisposable = onDidChange(() => this.render());
const onDidRemove = Event.filter(this.scmService.onDidRemoveRepository, e => e === repository);
const removeDisposable = onDidRemove(() => {
disposable.dispose();
this.disposables = this.disposables.filter(d => d !== removeDisposable);
this.render();
});
const disposable = combinedDisposable([changeDisposable, removeDisposable]);
this.disposables.push(disposable);
}
private render(): void {
this.badgeDisposable.dispose();
const count = this.scmService.repositories.reduce((r, repository) => {
if (typeof repository.provider.count === 'number') {
return r + repository.provider.count;
} else {
return r + repository.provider.groups.elements.reduce<number>((r, g) => r + g.elements.length, 0);
}
}, 0);
// TODO@joao: remove
this.logService.trace('SCM#StatusUpdater.render', count);
if (count > 0) {
const badge = new NumberBadge(count, num => localize('scmPendingChangesBadge', '{0} pending changes', num));
this.badgeDisposable = this.activityService.showActivity(VIEWLET_ID, badge, 'scm-viewlet-label');
} else {
this.badgeDisposable = Disposable.None;
}
}
dispose(): void {
this.badgeDisposable.dispose();
this.disposables = dispose(this.disposables);
}
}
export class StatusBarController implements IWorkbenchContribution {
private statusBarDisposable: IDisposable = Disposable.None;
private focusDisposable: IDisposable = Disposable.None;
private focusedRepository: ISCMRepository | undefined = undefined;
private focusedProviderContextKey: IContextKey<string | undefined>;
private disposables: IDisposable[] = [];
constructor(
@ISCMService private readonly scmService: ISCMService,
@IStatusbarService private readonly statusbarService: IStatusbarService,
@IContextKeyService contextKeyService: IContextKeyService,
@IEditorService private readonly editorService: IEditorService
) {
this.focusedProviderContextKey = contextKeyService.createKey<string | undefined>('scmProvider', undefined);
this.scmService.onDidAddRepository(this.onDidAddRepository, this, this.disposables);
for (const repository of this.scmService.repositories) {
this.onDidAddRepository(repository);
}
editorService.onDidActiveEditorChange(this.onDidActiveEditorChange, this, this.disposables);
}
private onDidActiveEditorChange(): void {
if (!this.editorService.activeEditor) {
return;
}
const resource = this.editorService.activeEditor.getResource();
if (!resource || resource.scheme !== 'file') {
return;
}
let bestRepository: ISCMRepository | null = null;
let bestMatchLength = Number.NEGATIVE_INFINITY;
for (const repository of this.scmService.repositories) {
const root = repository.provider.rootUri;
if (!root) {
continue;
}
const rootFSPath = root.fsPath;
const prefixLength = commonPrefixLength(rootFSPath, resource.fsPath);
if (prefixLength === rootFSPath.length && prefixLength > bestMatchLength) {
bestRepository = repository;
bestMatchLength = prefixLength;
}
}
if (bestRepository) {
this.onDidFocusRepository(bestRepository);
}
}
private onDidAddRepository(repository: ISCMRepository): void {
const changeDisposable = repository.onDidFocus(() => this.onDidFocusRepository(repository));
const onDidRemove = Event.filter(this.scmService.onDidRemoveRepository, e => e === repository);
const removeDisposable = onDidRemove(() => {
disposable.dispose();
this.disposables = this.disposables.filter(d => d !== removeDisposable);
if (this.scmService.repositories.length === 0) {
this.onDidFocusRepository(undefined);
} else if (this.focusedRepository === repository) {
this.scmService.repositories[0].focus();
}
});
const disposable = combinedDisposable([changeDisposable, removeDisposable]);
this.disposables.push(disposable);
if (!this.focusedRepository) {
this.onDidFocusRepository(repository);
}
}
private onDidFocusRepository(repository: ISCMRepository | undefined): void {
if (this.focusedRepository === repository) {
return;
}
this.focusedRepository = repository;
this.focusedProviderContextKey.set(repository && repository.provider.id);
this.focusDisposable.dispose();
if (repository && repository.provider.onDidChangeStatusBarCommands) {
this.focusDisposable = repository.provider.onDidChangeStatusBarCommands(() => this.render(repository));
}
this.render(repository);
}
private render(repository: ISCMRepository | undefined): void {
this.statusBarDisposable.dispose();
if (!repository) {
return;
}
const commands = repository.provider.statusBarCommands || [];
const label = repository.provider.rootUri
? `${basename(repository.provider.rootUri)} (${repository.provider.label})`
: repository.provider.label;
const disposables = commands.map(c => this.statusbarService.addEntry({
text: c.title,
tooltip: `${label} - ${c.tooltip}`,
command: c.id,
arguments: c.arguments
}, MainThreadStatusBarAlignment.LEFT, 10000));
this.statusBarDisposable = combinedDisposable(disposables);
}
dispose(): void {
this.focusDisposable.dispose();
this.statusBarDisposable.dispose();
this.disposables = dispose(this.disposables);
}
}

View File

@@ -0,0 +1,173 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/scmViewlet';
import { Event, Emitter } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions';
import { IAction } from 'vs/base/common/actions';
import { fillInContextMenuActions, fillInActionBarActions } from 'vs/platform/actions/browser/menuItemActionItem';
import { ISCMProvider, ISCMResource, ISCMResourceGroup } from 'vs/workbench/contrib/scm/common/scm';
import { isSCMResource } from './scmUtil';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { equals } from 'vs/base/common/arrays';
import { ISplice } from 'vs/base/common/sequence';
function actionEquals(a: IAction, b: IAction): boolean {
return a.id === b.id;
}
interface ISCMResourceGroupMenuEntry extends IDisposable {
readonly group: ISCMResourceGroup;
}
interface ISCMMenus {
readonly resourceGroupMenu: IMenu;
readonly resourceMenu: IMenu;
}
export function getSCMResourceContextKey(resource: ISCMResourceGroup | ISCMResource): string {
return isSCMResource(resource) ? resource.resourceGroup.id : resource.id;
}
export class SCMMenus implements IDisposable {
private contextKeyService: IContextKeyService;
private titleMenu: IMenu;
private titleActions: IAction[] = [];
private titleSecondaryActions: IAction[] = [];
private readonly _onDidChangeTitle = new Emitter<void>();
readonly onDidChangeTitle: Event<void> = this._onDidChangeTitle.event;
private readonly resourceGroupMenuEntries: ISCMResourceGroupMenuEntry[] = [];
private readonly resourceGroupMenus = new Map<ISCMResourceGroup, ISCMMenus>();
private readonly disposables: IDisposable[] = [];
constructor(
provider: ISCMProvider | undefined,
@IContextKeyService contextKeyService: IContextKeyService,
@IMenuService private readonly menuService: IMenuService,
@IContextMenuService private readonly contextMenuService: IContextMenuService
) {
this.contextKeyService = contextKeyService.createScoped();
const scmProviderKey = this.contextKeyService.createKey<string | undefined>('scmProvider', undefined);
if (provider) {
scmProviderKey.set(provider.contextValue);
this.onDidSpliceGroups({ start: 0, deleteCount: 0, toInsert: provider.groups.elements });
provider.groups.onDidSplice(this.onDidSpliceGroups, this, this.disposables);
} else {
scmProviderKey.set('');
}
this.titleMenu = this.menuService.createMenu(MenuId.SCMTitle, this.contextKeyService);
this.disposables.push(this.titleMenu);
this.titleMenu.onDidChange(this.updateTitleActions, this, this.disposables);
this.updateTitleActions();
}
private updateTitleActions(): void {
const primary: IAction[] = [];
const secondary: IAction[] = [];
fillInActionBarActions(this.titleMenu, { shouldForwardArgs: true }, { primary, secondary });
if (equals(primary, this.titleActions, actionEquals) && equals(secondary, this.titleSecondaryActions, actionEquals)) {
return;
}
this.titleActions = primary;
this.titleSecondaryActions = secondary;
this._onDidChangeTitle.fire();
}
getTitleActions(): IAction[] {
return this.titleActions;
}
getTitleSecondaryActions(): IAction[] {
return this.titleSecondaryActions;
}
getResourceGroupContextActions(group: ISCMResourceGroup): IAction[] {
return this.getActions(MenuId.SCMResourceGroupContext, group).secondary;
}
getResourceContextActions(resource: ISCMResource): IAction[] {
return this.getActions(MenuId.SCMResourceContext, resource).secondary;
}
private getActions(menuId: MenuId, resource: ISCMResourceGroup | ISCMResource): { primary: IAction[]; secondary: IAction[]; } {
const contextKeyService = this.contextKeyService.createScoped();
contextKeyService.createKey('scmResourceGroup', getSCMResourceContextKey(resource));
const menu = this.menuService.createMenu(menuId, contextKeyService);
const primary: IAction[] = [];
const secondary: IAction[] = [];
const result = { primary, secondary };
fillInContextMenuActions(menu, { shouldForwardArgs: true }, result, this.contextMenuService, g => /^inline/.test(g));
menu.dispose();
contextKeyService.dispose();
return result;
}
getResourceGroupMenu(group: ISCMResourceGroup): IMenu {
if (!this.resourceGroupMenus.has(group)) {
throw new Error('SCM Resource Group menu not found');
}
return this.resourceGroupMenus.get(group)!.resourceGroupMenu;
}
getResourceMenu(group: ISCMResourceGroup): IMenu {
if (!this.resourceGroupMenus.has(group)) {
throw new Error('SCM Resource Group menu not found');
}
return this.resourceGroupMenus.get(group)!.resourceMenu;
}
private onDidSpliceGroups({ start, deleteCount, toInsert }: ISplice<ISCMResourceGroup>): void {
const menuEntriesToInsert = toInsert.map<ISCMResourceGroupMenuEntry>(group => {
const contextKeyService = this.contextKeyService.createScoped();
contextKeyService.createKey('scmProvider', group.provider.contextValue);
contextKeyService.createKey('scmResourceGroup', getSCMResourceContextKey(group));
const resourceGroupMenu = this.menuService.createMenu(MenuId.SCMResourceGroupContext, contextKeyService);
const resourceMenu = this.menuService.createMenu(MenuId.SCMResourceContext, contextKeyService);
this.resourceGroupMenus.set(group, { resourceGroupMenu, resourceMenu });
return {
group,
dispose() {
contextKeyService.dispose();
resourceGroupMenu.dispose();
resourceMenu.dispose();
}
};
});
const deleted = this.resourceGroupMenuEntries.splice(start, deleteCount, ...menuEntriesToInsert);
for (const entry of deleted) {
this.resourceGroupMenus.delete(entry.group);
entry.dispose();
}
}
dispose(): void {
dispose(this.disposables);
dispose(this.resourceGroupMenuEntries);
this.resourceGroupMenus.clear();
}
}

View File

@@ -0,0 +1,10 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ISCMResourceGroup, ISCMResource } from 'vs/workbench/contrib/scm/common/scm';
export function isSCMResource(element: ISCMResourceGroup | ISCMResource): element is ISCMResource {
return !!(element as ISCMResource).sourceUri;
}

File diff suppressed because it is too large Load Diff