Merge from vscode e3b9b8eefc062d68ba8a4b6a817162d132f3b533 (#6932)

* Merge from vscode e3b9b8eefc062d68ba8a4b6a817162d132f3b533

* skip failing test

* add comment
This commit is contained in:
Anthony Dresser
2019-08-24 00:19:48 -07:00
committed by GitHub
parent 023d06d114
commit 92a3acbfe8
77 changed files with 992 additions and 559 deletions

View File

@@ -21,7 +21,6 @@ import { Selection } from 'vs/editor/common/core/selection';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { mixin } from 'vs/base/common/objects';
import { fromArray } from 'vs/base/common/map';
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesShape {
@@ -331,7 +330,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
return {
label: data.a,
kind: data.b,
kindModifier: data.n && fromArray(data.n),
tags: data.n,
detail: data.c,
documentation: data.d,
sortText: data.e,

View File

@@ -544,9 +544,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
};
// namespace: workspace
let warnedRootPathDeprecated = false;
const workspace: typeof vscode.workspace = {
get rootPath() {
console.warn(`[Deprecation Warning] 'workspace.rootPath' is deprecated and should no longer be used. Please use 'workspace.workspaceFolders' instead. (${extension.publisher}.${extension.name})`);
if (extension.isUnderDevelopment && !warnedRootPathDeprecated) {
warnedRootPathDeprecated = true;
console.warn(`[Deprecation Warning] 'workspace.rootPath' is deprecated and should no longer be used. Please use 'workspace.workspaceFolders' instead. More details: https://aka.ms/vscode-eliminating-rootpath`);
}
return extHostWorkspace.getPath();
},
set rootPath(value) {
@@ -815,7 +820,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
CommentMode: extHostTypes.CommentMode,
CompletionItem: extHostTypes.CompletionItem,
CompletionItemKind: extHostTypes.CompletionItemKind,
CompletionItemKindModifier: extHostTypes.CompletionItemKindModifier,
CompletionItemTag: extHostTypes.CompletionItemTag,
CompletionList: extHostTypes.CompletionList,
CompletionTriggerKind: extHostTypes.CompletionTriggerKind,
ConfigurationTarget: extHostTypes.ConfigurationTarget,
@@ -870,6 +875,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
StatusBarAlignment: extHostTypes.StatusBarAlignment,
SymbolInformation: extHostTypes.SymbolInformation,
SymbolKind: extHostTypes.SymbolKind,
SymbolTag: extHostTypes.SymbolTag,
Task: extHostTypes.Task,
Task2: extHostTypes.Task,
TaskGroup: extHostTypes.TaskGroup,

View File

@@ -940,7 +940,7 @@ export interface ISuggestDataDto {
k/* commitCharacters */?: string[];
l/* additionalTextEdits */?: ISingleEditOperation[];
m/* command */?: modes.Command;
n/* kindModifier */?: modes.CompletionItemKindModifier[];
n/* kindModifier */?: modes.CompletionItemTag[];
// not-standard
x?: ChainedCacheId;
}

View File

@@ -70,8 +70,8 @@ class DocumentSymbolAdapter {
const element = <modes.DocumentSymbol>{
name: info.name || '!!MISSING: name!!',
kind: typeConvert.SymbolKind.from(info.kind),
kindTags: [],
detail: undefined!, // Strict null override — avoid changing behavior
tags: info.tags && info.tags.map(typeConvert.SymbolTag.from),
detail: '',
containerName: info.containerName,
range: typeConvert.Range.from(info.location.range),
selectionRange: typeConvert.Range.from(info.location.range),
@@ -728,6 +728,7 @@ class SuggestAdapter {
//
a: item.label,
b: typeConvert.CompletionItemKind.from(item.kind),
n: item.tags && item.tags.map(typeConvert.CompletionItemTag.from),
c: item.detail,
d: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation),
e: item.sortText,
@@ -739,12 +740,6 @@ class SuggestAdapter {
m: this._commands.toInternal(item.command, disposables),
};
// kind2
if (typeof item.kind2 === 'object') {
result.b = typeConvert.CompletionItemKind.from(item.kind2.base);
result.n = item.kind2.modifier.map(typeConvert.CompletionItemKindModifier.from);
}
// 'insertText'-logic
if (item.textEdit) {
result.h = item.textEdit.newText;

View File

@@ -28,7 +28,7 @@ import * as marked from 'vs/base/common/marked/marked';
import { parse } from 'vs/base/common/marshalling';
import { cloneAndChange } from 'vs/base/common/objects';
import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log';
import { coalesce } from 'vs/base/common/arrays';
import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays';
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
export interface PositionLike {
@@ -556,22 +556,40 @@ export namespace SymbolKind {
}
}
export namespace SymbolTag {
export function from(kind: types.SymbolTag): modes.SymbolTag {
switch (kind) {
case types.SymbolTag.Deprecated: return modes.SymbolTag.Deprecated;
}
}
export function to(kind: modes.SymbolTag): types.SymbolTag {
switch (kind) {
case modes.SymbolTag.Deprecated: return types.SymbolTag.Deprecated;
}
}
}
export namespace WorkspaceSymbol {
export function from(info: vscode.SymbolInformation): search.IWorkspaceSymbol {
return <search.IWorkspaceSymbol>{
name: info.name,
kind: SymbolKind.from(info.kind),
tags: info.tags && info.tags.map(SymbolTag.from),
containerName: info.containerName,
location: location.from(info.location)
};
}
export function to(info: search.IWorkspaceSymbol): types.SymbolInformation {
return new types.SymbolInformation(
const result = new types.SymbolInformation(
info.name,
SymbolKind.to(info.kind),
info.containerName,
location.to(info.location)
);
result.tags = info.tags && info.tags.map(SymbolTag.to);
return result;
}
}
@@ -583,7 +601,7 @@ export namespace DocumentSymbol {
range: Range.from(info.range),
selectionRange: Range.from(info.selectionRange),
kind: SymbolKind.from(info.kind),
kindTags: []
tags: info.tags ? info.tags.map(SymbolTag.from) : []
};
if (info.children) {
result.children = info.children.map(from);
@@ -598,6 +616,9 @@ export namespace DocumentSymbol {
Range.to(info.range),
Range.to(info.selectionRange),
);
if (isNonEmptyArray(info.tags)) {
result.tags = info.tags.map(SymbolTag.to);
}
if (info.children) {
result.children = info.children.map(to) as any;
}
@@ -682,17 +703,17 @@ export namespace CompletionContext {
}
}
export namespace CompletionItemKindModifier {
export namespace CompletionItemTag {
export function from(kind: types.CompletionItemKindModifier): modes.CompletionItemKindModifier {
export function from(kind: types.CompletionItemTag): modes.CompletionItemTag {
switch (kind) {
case types.CompletionItemKindModifier.Deprecated: return modes.CompletionItemKindModifier.Deprecated;
case types.CompletionItemTag.Deprecated: return modes.CompletionItemTag.Deprecated;
}
}
export function to(kind: modes.CompletionItemKindModifier): types.CompletionItemKindModifier {
export function to(kind: modes.CompletionItemTag): types.CompletionItemTag {
switch (kind) {
case modes.CompletionItemKindModifier.Deprecated: return types.CompletionItemKindModifier.Deprecated;
case modes.CompletionItemTag.Deprecated: return types.CompletionItemTag.Deprecated;
}
}
}
@@ -768,6 +789,7 @@ export namespace CompletionItem {
const result = new types.CompletionItem(suggestion.label);
result.insertText = suggestion.insertText;
result.kind = CompletionItemKind.to(suggestion.kind);
result.tags = suggestion.tags && suggestion.tags.map(CompletionItemTag.to);
result.detail = suggestion.detail;
result.documentation = htmlContent.isMarkdownString(suggestion.documentation) ? MarkdownString.to(suggestion.documentation) : suggestion.documentation;
result.sortText = suggestion.sortText;

View File

@@ -979,6 +979,10 @@ export enum SymbolKind {
TypeParameter = 25
}
export enum SymbolTag {
Deprecated = 1,
}
@es5ClassCompat
export class SymbolInformation {
@@ -991,6 +995,7 @@ export class SymbolInformation {
name: string;
location!: Location;
kind: SymbolKind;
tags?: SymbolTag[];
containerName: string | undefined;
constructor(name: string, kind: SymbolKind, containerName: string | undefined, location: Location);
@@ -1041,6 +1046,7 @@ export class DocumentSymbol {
name: string;
detail: string;
kind: SymbolKind;
tags?: SymbolTag[];
range: Range;
selectionRange: Range;
children: DocumentSymbol[];
@@ -1308,7 +1314,7 @@ export enum CompletionItemKind {
TypeParameter = 24
}
export enum CompletionItemKindModifier {
export enum CompletionItemTag {
Deprecated = 1,
}
@@ -1317,7 +1323,7 @@ export class CompletionItem implements vscode.CompletionItem {
label: string;
kind?: CompletionItemKind;
kind2?: CompletionItemKind | { base: CompletionItemKind, modifier: CompletionItemKindModifier[] };
tags?: CompletionItemTag[];
detail?: string;
documentation?: string | MarkdownString;
sortText?: string;

View File

@@ -299,7 +299,24 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
}
public $onDidChangeWebviewPanelViewStates(newStates: WebviewPanelViewStateData): void {
for (const handle of Object.keys(newStates)) {
const handles = Object.keys(newStates);
// Notify webviews of state changes in the following order:
// - Non-visible
// - Visible
// - Active
handles.sort((a, b) => {
const stateA = newStates[a];
const stateB = newStates[b];
if (stateA.active) {
return 1;
}
if (stateB.active) {
return -1;
}
return (+stateA.visible) - (+stateB.visible);
});
for (const handle of handles) {
const panel = this.getWebviewPanel(handle);
if (!panel || panel._isDisposed) {
continue;

View File

@@ -40,7 +40,6 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
import { getThemeTypeSelector, DARK, HIGH_CONTRAST, LIGHT } from 'vs/platform/theme/common/themeService';
import { InMemoryUserDataProvider } from 'vs/workbench/services/userData/common/inMemoryUserDataProvider';
import { registerWindowDriver } from 'vs/platform/driver/browser/driver';
import { StaticExtensionsService, IStaticExtensionsService } from 'vs/workbench/services/extensions/common/staticExtensions';
import { BufferLogService } from 'vs/platform/log/common/bufferLog';
import { FileLogService } from 'vs/platform/log/common/fileLogService';
import { toLocalISOString } from 'vs/base/common/date';
@@ -90,7 +89,7 @@ class CodeRendererMain extends Disposable {
// Driver
if (this.configuration.driver) {
registerWindowDriver().then(d => this._register(d));
(async () => this._register(await registerWindowDriver()))();
}
// Startup
@@ -144,7 +143,7 @@ class CodeRendererMain extends Disposable {
serviceCollection.set(ISignService, signService);
// Remote Agent
const remoteAgentService = this._register(new RemoteAgentService(this.configuration.webSocketFactory, environmentService, productService, remoteAuthorityResolverService, signService));
const remoteAgentService = this._register(new RemoteAgentService(this.configuration.webSocketFactory, environmentService, productService, remoteAuthorityResolverService, signService, logService));
serviceCollection.set(IRemoteAgentService, remoteAgentService);
// Files
@@ -153,23 +152,24 @@ class CodeRendererMain extends Disposable {
// Logger
const indexedDBLogProvider = new IndexedDBLogProvider(logsPath.scheme);
indexedDBLogProvider.database.then(
() => fileService.registerProvider(logsPath.scheme, indexedDBLogProvider),
e => {
(async () => {
try {
await indexedDBLogProvider.database;
fileService.registerProvider(logsPath.scheme, indexedDBLogProvider);
} catch (error) {
(<ILogService>logService).info('Error while creating indexedDB log provider. Falling back to in-memory log provider.');
(<ILogService>logService).error(e);
(<ILogService>logService).error(error);
fileService.registerProvider(logsPath.scheme, new InMemoryLogProvider(logsPath.scheme));
}
).then(() => {
const consoleLogService = new ConsoleLogService(logService.getLevel());
const fileLogService = new FileLogService('window', environmentService.logFile, logService.getLevel(), fileService);
logService.logger = new MultiplexLogService([consoleLogService, fileLogService]);
});
// Static Extensions
const staticExtensions = new StaticExtensionsService(this.configuration.staticExtensions || []);
serviceCollection.set(IStaticExtensionsService, staticExtensions);
})();
// User Data Provider
let userDataProvider: IFileSystemProvider | undefined = this.configuration.userDataProvider;
const connection = remoteAgentService.getConnection();
if (connection) {
@@ -185,14 +185,12 @@ class CodeRendererMain extends Disposable {
}
}
}
if (!userDataProvider) {
userDataProvider = this._register(new InMemoryUserDataProvider());
}
// User Data Provider
fileService.registerProvider(Schemas.userData, userDataProvider);
// Long running services (workspace, config, storage)
const services = await Promise.all([
this.createWorkspaceService(payload, environmentService, fileService, remoteAgentService, logService).then(service => {

View File

@@ -7,7 +7,6 @@ import { URI } from 'vs/base/common/uri';
import { suggestFilename } from 'vs/base/common/mime';
import { memoize } from 'vs/base/common/decorators';
import { PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
import { basename } from 'vs/base/common/path';
import { basenameOrAuthority, dirname } from 'vs/base/common/resources';
import { EditorInput, IEncodingSupport, EncodingMode, ConfirmResult, Verbosity, IModeSupport } from 'vs/workbench/common/editor';
import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel';
@@ -64,7 +63,7 @@ export class UntitledEditorInput extends EditorInput implements IEncodingSupport
@memoize
private get shortDescription(): string {
return basename(this.labelService.getUriLabel(dirname(this.resource)));
return this.labelService.getUriBasenameLabel(dirname(this.resource));
}
@memoize

View File

@@ -170,7 +170,11 @@ export class FilesRenderer implements ITreeRenderer<ExplorerItem, FuzzyScore, IF
});
templateData.elementDisposable = templateData.label.onDidRender(() => {
this.updateWidth(stat);
try {
this.updateWidth(stat);
} catch (e) {
// noop since the element might no longer be in the tree, no update of width necessery
}
});
}

View File

@@ -5,7 +5,6 @@
import { localize } from 'vs/nls';
import { memoize } from 'vs/base/common/decorators';
import { basename } from 'vs/base/common/path';
import { dirname } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { EncodingMode, ConfirmResult, EditorInput, IFileEditorInput, ITextEditorModel, Verbosity, IRevertOptions } from 'vs/workbench/common/editor';
@@ -147,14 +146,14 @@ export class FileEditorInput extends EditorInput implements IFileEditorInput {
getName(): string {
if (!this.name) {
this.name = basename(this.labelService.getUriLabel(this.resource));
this.name = this.labelService.getUriBasenameLabel(this.resource);
}
return this.decorateLabel(this.name);
}
private get shortDescription(): string {
return basename(this.labelService.getUriLabel(dirname(this.resource)));
return this.labelService.getUriBasenameLabel(dirname(this.resource));
}
private get mediumDescription(): string {

View File

@@ -37,7 +37,7 @@ suite('Files - FileEditorInput', () => {
accessor = instantiationService.createInstance(ServiceAccessor);
});
test('Basics', async function () {
test.skip('Basics', async function () { // {{SQL CARBON EDIT}} skip test
let input = instantiationService.createInstance(FileEditorInput, toResource.call(this, '/foo/bar/file.js'), undefined, undefined);
const otherInput = instantiationService.createInstance(FileEditorInput, toResource.call(this, 'foo/bar/otherfile.js'), undefined, undefined);
const otherInputSame = instantiationService.createInstance(FileEditorInput, toResource.call(this, 'foo/bar/file.js'), undefined, undefined);

View File

@@ -16,15 +16,15 @@ import { IModelDecorationsChangeAccessor, OverviewRulerLane, IModelDeltaDecorati
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen';
import { DocumentSymbolProviderRegistry, DocumentSymbol, symbolKindToCssClass, SymbolKind } from 'vs/editor/common/modes';
import { DocumentSymbolProviderRegistry, DocumentSymbol, symbolKindToCssClass, SymbolKind, SymbolTag } from 'vs/editor/common/modes';
import { IRange } from 'vs/editor/common/core/range';
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
import { overviewRulerRangeHighlight } from 'vs/editor/common/view/editorColorRegistry';
import { GroupIdentifier, IEditorInput } from 'vs/workbench/common/editor';
import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { asPromise } from 'vs/base/common/async';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';
export const GOTO_SYMBOL_PREFIX = '@';
export const SCOPE_PREFIX = ':';
@@ -73,10 +73,8 @@ class OutlineModel extends QuickOpenModel {
applyFilter(searchValue: string): void {
// Normalize search
let normalizedSearchValue = searchValue;
if (searchValue.indexOf(SCOPE_PREFIX) === 0) {
normalizedSearchValue = normalizedSearchValue.substr(SCOPE_PREFIX.length);
}
const searchValueLow = searchValue.toLowerCase();
const searchValuePos = searchValue.indexOf(SCOPE_PREFIX) === 0 ? 1 : 0;
// Check for match and update visibility and group label
this.entries.forEach((entry: SymbolEntry) => {
@@ -84,34 +82,24 @@ class OutlineModel extends QuickOpenModel {
// Clear all state first
entry.setGroupLabel(undefined);
entry.setShowBorder(false);
entry.setHighlights([]);
entry.setScore(undefined);
entry.setHidden(false);
// Filter by search
if (normalizedSearchValue) {
const highlights = filters.matchesFuzzy2(normalizedSearchValue, entry.getLabel());
if (highlights) {
entry.setHighlights(highlights);
entry.setHidden(false);
} else if (!entry.isHidden()) {
entry.setHidden(true);
}
if (searchValue.length > searchValuePos) {
const score = filters.fuzzyScore(
searchValue.substr(searchValuePos), searchValueLow.substr(searchValuePos), 0,
entry.getLabel(), entry.getLabel().toLowerCase(), 0,
true
);
entry.setScore(score);
entry.setHidden(!score);
}
});
// Sort properly if actually searching
if (searchValue) {
if (searchValue.indexOf(SCOPE_PREFIX) === 0) {
this.entries.sort(this.sortScoped.bind(this, searchValue.toLowerCase()));
} else {
this.entries.sort(this.sortNormal.bind(this, searchValue.toLowerCase()));
}
}
this.entries.sort(SymbolEntry.compareByRank);
// Otherwise restore order as appearing in outline
else {
this.entries.sort((a: SymbolEntry, b: SymbolEntry) => a.getIndex() - b.getIndex());
}
// Mark all type groups
const visibleResults = <SymbolEntry[]>this.getEntries(true);
@@ -156,74 +144,6 @@ class OutlineModel extends QuickOpenModel {
}
}
private sortNormal(searchValue: string, elementA: SymbolEntry, elementB: SymbolEntry): number {
// Handle hidden elements
if (elementA.isHidden() && elementB.isHidden()) {
return 0;
} else if (elementA.isHidden()) {
return 1;
} else if (elementB.isHidden()) {
return -1;
}
const elementAName = elementA.getLabel().toLowerCase();
const elementBName = elementB.getLabel().toLowerCase();
// Compare by name
const r = elementAName.localeCompare(elementBName);
if (r !== 0) {
return r;
}
// If name identical sort by range instead
const elementARange = elementA.getRange();
const elementBRange = elementB.getRange();
return elementARange.startLineNumber - elementBRange.startLineNumber;
}
private sortScoped(searchValue: string, elementA: SymbolEntry, elementB: SymbolEntry): number {
// Handle hidden elements
if (elementA.isHidden() && elementB.isHidden()) {
return 0;
} else if (elementA.isHidden()) {
return 1;
} else if (elementB.isHidden()) {
return -1;
}
// Remove scope char
searchValue = searchValue.substr(SCOPE_PREFIX.length);
// Sort by type first if scoped search
const elementATypeLabel = NLS_SYMBOL_KIND_CACHE[elementA.getKind()] || FALLBACK_NLS_SYMBOL_KIND;
const elementBTypeLabel = NLS_SYMBOL_KIND_CACHE[elementB.getKind()] || FALLBACK_NLS_SYMBOL_KIND;
let r = elementATypeLabel.localeCompare(elementBTypeLabel);
if (r !== 0) {
return r;
}
// Special sort when searching in scoped mode
if (searchValue) {
const elementAName = elementA.getLabel().toLowerCase();
const elementBName = elementB.getLabel().toLowerCase();
// Compare by name
r = elementAName.localeCompare(elementBName);
if (r !== 0) {
return r;
}
}
// Default to sort by range
const elementARange = elementA.getRange();
const elementBRange = elementB.getRange();
return elementARange.startLineNumber - elementBRange.startLineNumber;
}
private renderGroupLabel(type: SymbolKind, count: number): string {
let pattern = NLS_SYMBOL_KIND_CACHE[type];
if (!pattern) {
@@ -235,33 +155,26 @@ class OutlineModel extends QuickOpenModel {
}
class SymbolEntry extends EditorQuickOpenEntryGroup {
private editorService: IEditorService;
private index: number;
private name: string;
private kind: SymbolKind;
private icon: string;
private description: string;
private range: IRange;
private revealRange: IRange;
private handler: GotoSymbolHandler;
constructor(index: number, name: string, kind: SymbolKind, description: string, icon: string, range: IRange, revealRange: IRange, highlights: IHighlight[], editorService: IEditorService, handler: GotoSymbolHandler) {
private score?: filters.FuzzyScore;
constructor(
private readonly index: number,
private readonly name: string,
private readonly kind: SymbolKind,
private readonly description: string,
private readonly icon: string,
private readonly deprecated: boolean,
private readonly range: IRange,
private readonly revealRange: IRange,
private readonly editorService: IEditorService,
private readonly handler: GotoSymbolHandler
) {
super();
this.index = index;
this.name = name;
this.kind = kind;
this.icon = icon;
this.description = description;
this.range = range;
this.revealRange = revealRange || range;
this.setHighlights(highlights);
this.editorService = editorService;
this.handler = handler;
}
getIndex(): number {
return this.index;
setScore(score: filters.FuzzyScore | undefined): void {
this.score = score;
}
getLabel(): string {
@@ -276,6 +189,18 @@ class SymbolEntry extends EditorQuickOpenEntryGroup {
return this.icon;
}
getLabelOptions(): IIconLabelValueOptions | undefined {
return this.deprecated ? { extraClasses: ['deprecated'] } : undefined;
}
getHighlights(): [IHighlight[], IHighlight[] | undefined, IHighlight[] | undefined] {
return [
this.deprecated ? [] : filters.createMatches(this.score),
undefined,
undefined
];
}
getDescription(): string {
return this.description;
}
@@ -294,7 +219,7 @@ class SymbolEntry extends EditorQuickOpenEntryGroup {
getOptions(pinned?: boolean): ITextEditorOptions {
return {
selection: this.toSelection(),
selection: this.revealRange,
pinned
};
}
@@ -317,7 +242,7 @@ class SymbolEntry extends EditorQuickOpenEntryGroup {
// Apply selection and focus
else {
const range = this.toSelection();
const range = this.revealRange;
const activeTextEditorWidget = this.editorService.activeTextEditorWidget;
if (activeTextEditorWidget) {
activeTextEditorWidget.setSelection(range);
@@ -331,7 +256,7 @@ class SymbolEntry extends EditorQuickOpenEntryGroup {
private runPreview(): boolean {
// Select Outline Position
const range = this.toSelection();
const range = this.revealRange;
const activeTextEditorWidget = this.editorService.activeTextEditorWidget;
if (activeTextEditorWidget) {
activeTextEditorWidget.revealRangeInCenter(range, ScrollType.Smooth);
@@ -345,13 +270,36 @@ class SymbolEntry extends EditorQuickOpenEntryGroup {
return false;
}
private toSelection(): IRange {
return {
startLineNumber: this.revealRange.startLineNumber,
startColumn: this.revealRange.startColumn || 1,
endLineNumber: this.revealRange.startLineNumber,
endColumn: this.revealRange.startColumn || 1
};
static compareByRank(a: SymbolEntry, b: SymbolEntry): number {
if (!a.score && b.score) {
return 1;
} else if (a.score && !b.score) {
return -1;
}
if (a.score && b.score) {
if (a.score[0] > b.score[0]) {
return -1;
} else if (a.score[0] < b.score[0]) {
return 1;
}
}
if (a.index < b.index) {
return -1;
} else if (a.index > b.index) {
return 1;
}
return 0;
}
static compareByKindAndRank(a: SymbolEntry, b: SymbolEntry): number {
// Sort by type first if scoped search
const kindA = NLS_SYMBOL_KIND_CACHE[a.getKind()] || FALLBACK_NLS_SYMBOL_KIND;
const kindB = NLS_SYMBOL_KIND_CACHE[b.getKind()] || FALLBACK_NLS_SYMBOL_KIND;
let r = kindA.localeCompare(kindB);
if (r === 0) {
r = this.compareByRank(a, b);
}
return r;
}
}
@@ -466,11 +414,11 @@ export class GotoSymbolHandler extends QuickOpenHandler {
};
}
private toQuickOpenEntries(flattened: DocumentSymbol[]): SymbolEntry[] {
private toQuickOpenEntries(symbols: DocumentSymbol[]): SymbolEntry[] {
const results: SymbolEntry[] = [];
for (let i = 0; i < flattened.length; i++) {
const element = flattened[i];
for (let i = 0; i < symbols.length; i++) {
const element = symbols[i];
const label = strings.trim(element.name);
// Show parent scope as description
@@ -479,8 +427,8 @@ export class GotoSymbolHandler extends QuickOpenHandler {
// Add
results.push(new SymbolEntry(i,
label, element.kind, description, `symbol-icon ${icon}`,
element.range, element.selectionRange, [], this.editorService, this
label, element.kind, description, `symbol-icon ${icon}`, element.tags && element.tags.indexOf(SymbolTag.Deprecated) >= 0,
element.range, element.selectionRange, this.editorService, this
));
}
@@ -504,7 +452,7 @@ export class GotoSymbolHandler extends QuickOpenHandler {
}
if (model && types.isFunction((<ITextModel>model).getLanguageIdentifier)) {
const entries = await asPromise(() => getDocumentSymbols(<ITextModel>model, true, this.pendingOutlineRequest!.token));
const entries = await getDocumentSymbols(<ITextModel>model, true, this.pendingOutlineRequest!.token);
return new OutlineModel(this.toQuickOpenEntries(entries));
}

View File

@@ -7,8 +7,7 @@ import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as
import { Registry } from 'vs/platform/registry/common/platform';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { ILabelService } from 'vs/platform/label/common/label';
import { isWeb, OperatingSystem } from 'vs/base/common/platform';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { OperatingSystem } from 'vs/base/common/platform';
import { Schemas } from 'vs/base/common/network';
import { IRemoteAgentService, RemoteExtensionLogFileName } from 'vs/workbench/services/remote/common/remoteAgentService';
import { ILogService } from 'vs/platform/log/common/log';
@@ -49,28 +48,24 @@ export const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry
export class LabelContribution implements IWorkbenchContribution {
constructor(
@ILabelService private readonly labelService: ILabelService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService) {
this.registerFormatters();
}
private registerFormatters(): void {
if (isWeb) {
this.remoteAgentService.getEnvironment().then(remoteEnvironment => {
if (remoteEnvironment) {
this.labelService.registerFormatter({
scheme: Schemas.vscodeRemote,
authority: this.environmentService.configuration.remoteAuthority,
formatting: {
label: '${path}',
separator: remoteEnvironment.os === OperatingSystem.Windows ? '\\' : '/',
tildify: remoteEnvironment.os !== OperatingSystem.Windows,
normalizeDriveLetter: remoteEnvironment.os === OperatingSystem.Windows
}
});
}
});
}
this.remoteAgentService.getEnvironment().then(remoteEnvironment => {
if (remoteEnvironment) {
this.labelService.registerFormatter({
scheme: Schemas.vscodeRemote,
formatting: {
label: '${path}',
separator: remoteEnvironment.os === OperatingSystem.Windows ? '\\' : '/',
tildify: remoteEnvironment.os !== OperatingSystem.Windows,
normalizeDriveLetter: remoteEnvironment.os === OperatingSystem.Windows
}
});
}
});
}
}

View File

@@ -309,7 +309,8 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
@IRemoteAgentService remoteAgentService: IRemoteAgentService,
@IProgressService progressService: IProgressService,
@IDialogService dialogService: IDialogService,
@ICommandService commandService: ICommandService
@ICommandService commandService: ICommandService,
@IContextKeyService contextKeyService: IContextKeyService
) {
const connection = remoteAgentService.getConnection();
if (connection) {
@@ -318,6 +319,7 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
let lastLocation: ProgressLocation | null = null;
let currentTimer: ReconnectionTimer | null = null;
let reconnectWaitEvent: ReconnectionWaitEvent | null = null;
let disposableListener: IDisposable | null = null;
function showProgress(location: ProgressLocation, buttons?: string[]) {
if (currentProgressPromiseResolve) {
@@ -331,7 +333,7 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
// Show dialog
progressService!.withProgress(
{ location: ProgressLocation.Dialog, buttons },
(progress) => { progressReporter = new ProgressReporter(progress); return promise; },
(progress) => { if (progressReporter) { progressReporter.currentProgress = progress; } return promise; },
(choice?) => {
// Handle choice from dialog
if (choice === 0 && buttons && reconnectWaitEvent) {
@@ -351,7 +353,6 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
// Handle choice from notification
if (choice === 0 && buttons && reconnectWaitEvent) {
reconnectWaitEvent.skipWait();
progressReporter!.report();
} else {
hideProgress();
}
@@ -365,7 +366,6 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
}
currentProgressPromiseResolve = null;
progressReporter = null;
}
connection.onDidStateChange((e) => {
@@ -373,9 +373,15 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
currentTimer.dispose();
currentTimer = null;
}
if (disposableListener) {
disposableListener.dispose();
disposableListener = null;
}
switch (e.type) {
case PersistentConnectionEventType.ConnectionLost:
if (!currentProgressPromiseResolve) {
progressReporter = new ProgressReporter(null);
showProgress(ProgressLocation.Dialog, [nls.localize('reconnectNow', "Reconnect Now")]);
}
@@ -391,9 +397,24 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
hideProgress();
showProgress(lastLocation || ProgressLocation.Notification);
progressReporter!.report(nls.localize('reconnectionRunning', "Attempting to reconnect..."));
// Register to listen for quick input is opened
disposableListener = contextKeyService.onDidChangeContext((contextKeyChangeEvent) => {
const reconnectInteraction = new Set<string>(['inQuickOpen']);
if (contextKeyChangeEvent.affectsSome(reconnectInteraction)) {
// Need to move from dialog if being shown and user needs to type in a prompt
if (lastLocation === ProgressLocation.Dialog && progressReporter !== null) {
hideProgress();
showProgress(ProgressLocation.Notification);
progressReporter.report();
}
}
});
break;
case PersistentConnectionEventType.ReconnectionPermanentFailure:
hideProgress();
progressReporter = null;
dialogService.show(Severity.Error, nls.localize('reconnectionPermanentFailure', "Cannot reconnect. Please reload the window."), [nls.localize('reloadWindow', "Reload Window"), nls.localize('cancel', "Cancel")], { cancelId: 1 }).then(choice => {
// Reload the window
@@ -404,6 +425,7 @@ class RemoteAgentConnectionStatusListener implements IWorkbenchContribution {
break;
case PersistentConnectionEventType.ConnectionGain:
hideProgress();
progressReporter = null;
break;
}
});

View File

@@ -8,13 +8,13 @@ import { URI } from 'vs/base/common/uri';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ThrottledDelayer } from 'vs/base/common/async';
import { QuickOpenHandler, EditorQuickOpenEntry } from 'vs/workbench/browser/quickopen';
import { QuickOpenModel, QuickOpenEntry, compareEntries } from 'vs/base/parts/quickopen/browser/quickOpenModel';
import { QuickOpenModel, QuickOpenEntry, IHighlight } from 'vs/base/parts/quickopen/browser/quickOpenModel';
import { IAutoFocus, Mode, IEntryRunContext } from 'vs/base/parts/quickopen/common/quickOpen';
import * as filters from 'vs/base/common/filters';
import * as strings from 'vs/base/common/strings';
import { Range } from 'vs/editor/common/core/range';
import { IWorkbenchEditorConfiguration } from 'vs/workbench/common/editor';
import { symbolKindToCssClass } from 'vs/editor/common/modes';
import { symbolKindToCssClass, SymbolTag } from 'vs/editor/common/modes';
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -25,9 +25,12 @@ import { ILabelService } from 'vs/platform/label/common/label';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Schemas } from 'vs/base/common/network';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IIconLabelValueOptions } from 'vs/base/browser/ui/iconLabel/iconLabel';
class SymbolEntry extends EditorQuickOpenEntry {
private bearingResolve: Promise<this | undefined> | undefined;
private bearingResolve?: Promise<this | undefined>;
private score?: filters.FuzzyScore;
constructor(
private bearing: IWorkspaceSymbol,
@@ -40,6 +43,14 @@ class SymbolEntry extends EditorQuickOpenEntry {
super(editorService);
}
setScore(score: filters.FuzzyScore | undefined) {
this.score = score;
}
getHighlights(): [IHighlight[] /* Label */, IHighlight[] | undefined /* Description */, IHighlight[] | undefined /* Detail */] {
return [this.isDeprecated() ? [] : filters.createMatches(this.score), undefined, undefined];
}
getLabel(): string {
return this.bearing.name;
}
@@ -65,10 +76,18 @@ class SymbolEntry extends EditorQuickOpenEntry {
return symbolKindToCssClass(this.bearing.kind);
}
getLabelOptions(): IIconLabelValueOptions | undefined {
return this.isDeprecated() ? { extraClasses: ['deprecated'] } : undefined;
}
getResource(): URI {
return this.bearing.location.uri;
}
private isDeprecated(): boolean {
return this.bearing.tags ? this.bearing.tags.indexOf(SymbolTag.Deprecated) >= 0 : false;
}
run(mode: Mode, context: IEntryRunContext): boolean {
// resolve this type bearing if neccessary
@@ -111,18 +130,24 @@ class SymbolEntry extends EditorQuickOpenEntry {
return input;
}
static compare(elementA: SymbolEntry, elementB: SymbolEntry, searchValue: string): number {
// Sort by Type if name is identical
const elementAName = elementA.getLabel().toLowerCase();
const elementBName = elementB.getLabel().toLowerCase();
if (elementAName === elementBName) {
let elementAType = symbolKindToCssClass(elementA.bearing.kind);
let elementBType = symbolKindToCssClass(elementB.bearing.kind);
return elementAType.localeCompare(elementBType);
static compare(a: SymbolEntry, b: SymbolEntry, searchValue: string): number {
// order: score, name, kind
if (a.score && b.score) {
if (a.score[0] > b.score[0]) {
return -1;
} else if (a.score[0] < b.score[0]) {
return 1;
}
}
return compareEntries(elementA, elementB, searchValue);
const aName = a.getLabel().toLowerCase();
const bName = b.getLabel().toLowerCase();
let res = aName.localeCompare(bName);
if (res !== 0) {
return res;
}
let aKind = symbolKindToCssClass(a.bearing.kind);
let bKind = symbolKindToCssClass(b.bearing.kind);
return aKind.localeCompare(bKind);
}
}
@@ -198,6 +223,9 @@ export class OpenSymbolHandler extends QuickOpenHandler {
private fillInSymbolEntries(bucket: SymbolEntry[], provider: IWorkspaceSymbolProvider, types: IWorkspaceSymbol[], searchValue: string): void {
const pattern = strings.stripWildcards(searchValue);
const patternLow = pattern.toLowerCase();
// Convert to Entries
for (let element of types) {
if (this.options.skipLocalSymbols && !!element.containerName) {
@@ -205,7 +233,11 @@ export class OpenSymbolHandler extends QuickOpenHandler {
}
const entry = this.instantiationService.createInstance(SymbolEntry, element, provider);
entry.setHighlights(filters.matchesFuzzy2(searchValue, entry.getLabel()) || []);
entry.setScore(filters.fuzzyScore(
pattern, patternLow, 0,
entry.getLabel(), entry.getLabel().toLowerCase(), 0,
true
));
bucket.push(entry);
}
}

View File

@@ -6,7 +6,7 @@
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable } from 'vs/base/common/lifecycle';
import { ISearchConfiguration, ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search';
import { SymbolKind, Location, ProviderResult } from 'vs/editor/common/modes';
import { SymbolKind, Location, ProviderResult, SymbolTag } from 'vs/editor/common/modes';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { URI } from 'vs/base/common/uri';
import { toResource, SideBySideEditor } from 'vs/workbench/common/editor';
@@ -19,6 +19,7 @@ export interface IWorkspaceSymbol {
name: string;
containerName?: string;
kind: SymbolKind;
tags?: SymbolTag[];
location: Location;
}

View File

@@ -340,9 +340,7 @@ export class TerminalTaskSystem implements ITaskSystem {
private async executeTask(task: Task, resolver: ITaskResolver, trigger: string): Promise<ITaskSummary> {
let promises: Promise<ITaskSummary>[] = [];
if (task.configurationProperties.dependsOn) {
// tslint:disable-next-line: no-for-in-array
for (let index in task.configurationProperties.dependsOn) {
const dependency = task.configurationProperties.dependsOn[index];
for (const dependency of task.configurationProperties.dependsOn) {
let dependencyTask = resolver.resolve(dependency.workspaceFolder, dependency.task!);
if (dependencyTask) {
let key = dependencyTask.getMapKey();

View File

@@ -216,11 +216,11 @@ export async function getResource(filename: string, matcher: ProblemMatcher, fil
if (fullPath === undefined) {
throw new Error('FileLocationKind is not actionable. Does the matcher have a filePrefix? This should never happen.');
}
fullPath = normalize(fullPath);
fullPath = fullPath.replace(/\\/g, '/');
if (fullPath[0] !== '/') {
fullPath = '/' + fullPath;
}
fullPath = normalize(fullPath);
if (matcher.uriProvider !== undefined) {
return matcher.uriProvider(fullPath);
} else {

View File

@@ -27,9 +27,10 @@ const dotnetBuild: TaskEntry = {
'\t"tasks": [',
'\t\t{',
'\t\t\t"label": "build",',
'\t\t\t"command": "dotnet build",',
'\t\t\t"command": "dotnet",',
'\t\t\t"type": "shell",',
'\t\t\t"args": [',
'\t\t\t\t"build",',
'\t\t\t\t// Ask dotnet build to generate full paths for file names.',
'\t\t\t\t"/property:GenerateFullPaths=true",',
'\t\t\t\t// Do not generate summary otherwise it leads to duplicate errors in Problems panel',

View File

@@ -985,15 +985,14 @@ export namespace KeyedTaskIdentifier {
function sortedStringify(literal: any): string {
const keys = Object.keys(literal).sort();
let result: string = '';
// tslint:disable-next-line: no-for-in-array
for (let position in keys) {
let stringified = literal[keys[position]];
for (const key of keys) {
let stringified = literal[key];
if (stringified instanceof Object) {
stringified = sortedStringify(stringified);
} else if (typeof stringified === 'string') {
stringified = stringified.replace(/,/g, ',,');
}
result += keys[position] + ',' + stringified + ',';
result += key + ',' + stringified + ',';
}
return result;
}

View File

@@ -52,7 +52,10 @@ Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions).registe
const DEAFULT_TRUSTED_DOMAINS = [
'https://code.visualstudio.com',
'https://go.microsoft.com'
'https://go.microsoft.com',
'https://github.com',
'https://marketplace.visualstudio.com',
'https://vscode-auth.github.com'
];
const configureTrustedDomainsHandler = async (

View File

@@ -194,7 +194,7 @@ class CodeRendererMain extends Disposable {
const signService = new SignService();
serviceCollection.set(ISignService, signService);
const remoteAgentService = this._register(new RemoteAgentService(this.environmentService.configuration, this.environmentService, remoteAuthorityResolverService, signService));
const remoteAgentService = this._register(new RemoteAgentService(this.environmentService.configuration, this.environmentService, remoteAuthorityResolverService, signService, logService));
serviceCollection.set(IRemoteAgentService, remoteAgentService);
// Files

View File

@@ -55,7 +55,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR
if (activeEditor instanceof DiffEditorInput) {
activeEditor = activeEditor.modifiedInput;
}
const fileResource = toResource(activeEditor, { filterByScheme: Schemas.file });
const fileResource = toResource(activeEditor, { filterByScheme: [Schemas.file, Schemas.userData] });
if (!fileResource) {
return undefined;
}

View File

@@ -79,7 +79,8 @@ export class RemoteExtensionHostClient extends Disposable implements IExtensionH
return { host: authority.host, port: authority.port };
}
},
signService: this._signService
signService: this._signService,
logService: this._logService
};
return this.remoteAuthorityResolverService.resolveAuthority(this._initDataProvider.remoteAuthority).then((resolverResult) => {

View File

@@ -4,8 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionDescription, IExtensionManifest, ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { UriComponents, URI } from 'vs/base/common/uri';
import { IExtensionDescription, ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { URI } from 'vs/base/common/uri';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
export const IStaticExtensionsService = createDecorator<IStaticExtensionsService>('IStaticExtensionsService');
@@ -20,7 +22,9 @@ export class StaticExtensionsService implements IStaticExtensionsService {
private readonly _descriptions: IExtensionDescription[] = [];
constructor(staticExtensions: { packageJSON: IExtensionManifest, extensionLocation: UriComponents }[]) {
constructor(@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService) {
const staticExtensions = environmentService.options && Array.isArray(environmentService.options.staticExtensions) ? environmentService.options.staticExtensions : [];
this._descriptions = staticExtensions.map(data => <IExtensionDescription>{
identifier: new ExtensionIdentifier(`${data.packageJSON.publisher}.${data.packageJSON.name}`),
extensionLocation: URI.revive(data.extensionLocation),
@@ -32,3 +36,5 @@ export class StaticExtensionsService implements IStaticExtensionsService {
return this._descriptions;
}
}
registerSingleton(IStaticExtensionsService, StaticExtensionsService, true);

View File

@@ -7,9 +7,9 @@ import * as nativeWatchdog from 'native-watchdog';
import * as net from 'net';
import * as minimist from 'vscode-minimist';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Event, Emitter } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { PersistentProtocol, ProtocolConstants, createBufferedEvent } from 'vs/base/parts/ipc/common/ipc.net';
import { PersistentProtocol, ProtocolConstants, BufferedEmitter } from 'vs/base/parts/ipc/common/ipc.net';
import { NodeSocket, WebSocketNodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
import product from 'vs/platform/product/node/product';
import { IInitData } from 'vs/workbench/api/common/extHost.protocol';
@@ -164,8 +164,8 @@ async function createExtHostProtocol(): Promise<IMessagePassingProtocol> {
return new class implements IMessagePassingProtocol {
private readonly _onMessage = new Emitter<VSBuffer>();
readonly onMessage: Event<VSBuffer> = createBufferedEvent(this._onMessage.event);
private readonly _onMessage = new BufferedEmitter<VSBuffer>();
readonly onMessage: Event<VSBuffer> = this._onMessage.event;
private _terminating: boolean;

View File

@@ -12,15 +12,31 @@ import { ExtensionHostMain } from 'vs/workbench/services/extensions/common/exten
import { IHostUtils } from 'vs/workbench/api/common/extHostExtensionService';
import 'vs/workbench/services/extensions/worker/extHost.services';
// worker-self
//#region --- Define, capture, and override some globals
//todo@joh do not allow extensions to call postMessage and other globals...
declare namespace self {
function close(): void;
let close: any;
let postMessage: any;
let addEventLister: any;
let indexedDB: any;
let caches: any;
}
// do not allow extensions to call terminate
const nativeClose = self.close.bind(self);
self.close = () => console.trace('An extension called terminate and this was prevented');
let onTerminate = nativeClose;
self.close = () => console.trace(`'close' has been blocked`);
const nativePostMessage = postMessage.bind(self);
self.postMessage = () => console.trace(`'postMessage' has been blocked`);
const nativeAddEventLister = addEventListener.bind(self);
self.addEventLister = () => console.trace(`'addEventListener' has been blocked`);
// readonly, cannot redefine...
// self.indexedDB = undefined;
// self.caches = undefined;
//#endregion ---
const hostUtil = new class implements IHostUtils {
_serviceBrand: any;
@@ -35,7 +51,6 @@ const hostUtil = new class implements IHostUtils {
}
};
//todo@joh do not allow extensions to call postMessage and other globals...
class ExtensionWorker {
@@ -47,7 +62,8 @@ class ExtensionWorker {
let emitter = new Emitter<VSBuffer>();
let terminating = false;
onmessage = event => {
nativeAddEventLister('message', event => {
const { data } = event;
if (!(data instanceof ArrayBuffer)) {
console.warn('UNKNOWN data received', data);
@@ -64,14 +80,14 @@ class ExtensionWorker {
// emit non-terminate messages to the outside
emitter.fire(msg);
};
});
this.protocol = {
onMessage: emitter.event,
send: vsbuf => {
if (!terminating) {
const data = vsbuf.buffer.buffer.slice(vsbuf.buffer.byteOffset, vsbuf.buffer.byteOffset + vsbuf.buffer.byteLength);
postMessage(data, [data]);
nativePostMessage(data, [data]);
}
}
};
@@ -94,6 +110,8 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRenderer
});
}
let onTerminate = nativeClose;
(function create(): void {
const res = new ExtensionWorker();

View File

@@ -6,6 +6,7 @@
import { localize } from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as paths from 'vs/base/common/path';
import { Event, Emitter } from 'vs/base/common/event';
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry, IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -159,6 +160,16 @@ export class LabelService implements ILabelService {
return options.endWithSeparator ? this.appendSeparatorIfMissing(label, formatting) : label;
}
getUriBasenameLabel(resource: URI): string {
const label = this.getUriLabel(resource);
const formatting = this.findFormatting(resource);
if (formatting && formatting.separator === '\\') {
return paths.win32.basename(label);
}
return paths.posix.basename(label);
}
getWorkspaceLabel(workspace: (IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWorkspace), options?: { verbose: boolean }): string {
if (IWorkspace.isIWorkspace(workspace)) {
const identifier = toWorkspaceIdentifier(workspace);

View File

@@ -33,9 +33,11 @@ suite('URI Label', () => {
const uri1 = TestWorkspace.folders[0].uri.with({ path: TestWorkspace.folders[0].uri.path.concat('/a/b/c/d') });
assert.equal(labelService.getUriLabel(uri1, { relative: true }), isWindows ? 'a\\b\\c\\d' : 'a/b/c/d');
assert.equal(labelService.getUriLabel(uri1, { relative: false }), isWindows ? 'C:\\testWorkspace\\a\\b\\c\\d' : '/testWorkspace/a/b/c/d');
assert.equal(labelService.getUriBasenameLabel(uri1), 'd');
const uri2 = URI.file('c:\\1/2/3');
assert.equal(labelService.getUriLabel(uri2, { relative: false }), isWindows ? 'C:\\1\\2\\3' : '/c:\\1/2/3');
assert.equal(labelService.getUriBasenameLabel(uri2), '3');
});
test('custom scheme', function () {
@@ -51,6 +53,23 @@ suite('URI Label', () => {
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5');
assert.equal(labelService.getUriLabel(uri1, { relative: false }), 'LABEL//1/2/3/4/5/microsoft.com/END');
assert.equal(labelService.getUriBasenameLabel(uri1), 'END');
});
test('separator', function () {
labelService.registerFormatter({
scheme: 'vscode',
formatting: {
label: 'LABEL\\${path}\\${authority}\\END',
separator: '\\',
tildify: true,
normalizeDriveLetter: true
}
});
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5');
assert.equal(labelService.getUriLabel(uri1, { relative: false }), 'LABEL\\\\1\\2\\3\\4\\5\\microsoft.com\\END');
assert.equal(labelService.getUriBasenameLabel(uri1), 'END');
});
test('custom authority', function () {
@@ -65,6 +84,7 @@ suite('URI Label', () => {
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5');
assert.equal(labelService.getUriLabel(uri1, { relative: false }), 'LABEL//1/2/3/4/5/microsoft.com/END');
assert.equal(labelService.getUriBasenameLabel(uri1), 'END');
});
test('mulitple authority', function () {
@@ -96,6 +116,7 @@ suite('URI Label', () => {
// Make sure the most specific authority is picked
const uri1 = URI.parse('vscode://microsoft.com/1/2/3/4/5');
assert.equal(labelService.getUriLabel(uri1, { relative: false }), 'second');
assert.equal(labelService.getUriBasenameLabel(uri1), 'second');
});
test('custom query', function () {

View File

@@ -11,6 +11,7 @@ import { IProductService } from 'vs/platform/product/common/product';
import { IWebSocketFactory, BrowserSocketFactory } from 'vs/platform/remote/browser/browserSocketFactory';
import { ISignService } from 'vs/platform/sign/common/sign';
import { ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
import { ILogService } from 'vs/platform/log/common/log';
export class RemoteAgentService extends AbstractRemoteAgentService implements IRemoteAgentService {
@@ -23,12 +24,13 @@ export class RemoteAgentService extends AbstractRemoteAgentService implements IR
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@IProductService productService: IProductService,
@IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService,
@ISignService signService: ISignService
@ISignService signService: ISignService,
@ILogService logService: ILogService
) {
super(environmentService);
this.socketFactory = new BrowserSocketFactory(webSocketFactory);
this._connection = this._register(new RemoteAgentConnection(environmentService.configuration.remoteAuthority!, productService.commit, this.socketFactory, remoteAuthorityResolverService, signService));
this._connection = this._register(new RemoteAgentConnection(environmentService.configuration.remoteAuthority!, productService.commit, this.socketFactory, remoteAuthorityResolverService, signService, logService));
}
getConnection(): IRemoteAgentConnection | null {

View File

@@ -20,6 +20,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
import { IDiagnosticInfoOptions, IDiagnosticInfo } from 'vs/platform/diagnostics/common/diagnostics';
import { Emitter } from 'vs/base/common/event';
import { ISignService } from 'vs/platform/sign/common/sign';
import { ILogService } from 'vs/platform/log/common/log';
export abstract class AbstractRemoteAgentService extends Disposable {
@@ -86,7 +87,8 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon
private readonly _commit: string | undefined,
private readonly _socketFactory: ISocketFactory,
private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService,
private readonly _signService: ISignService
private readonly _signService: ISignService,
private readonly _logService: ILogService
) {
super();
this.remoteAuthority = remoteAuthority;
@@ -124,7 +126,8 @@ export class RemoteAgentConnection extends Disposable implements IRemoteAgentCon
return { host: authority.host, port: authority.port };
}
},
signService: this._signService
signService: this._signService,
logService: this._logService
};
const connection = this._register(await connectRemoteAgentManagement(options, this.remoteAuthority, `renderer`));
this._register(connection.onDidStateChange(e => this._onDidStateChange.fire(e)));

View File

@@ -12,6 +12,7 @@ import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory';
import { AbstractRemoteAgentService, RemoteAgentConnection } from 'vs/workbench/services/remote/common/abstractRemoteAgentService';
import { ISignService } from 'vs/platform/sign/common/sign';
import { ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
import { ILogService } from 'vs/platform/log/common/log';
export class RemoteAgentService extends AbstractRemoteAgentService implements IRemoteAgentService {
@@ -22,12 +23,13 @@ export class RemoteAgentService extends AbstractRemoteAgentService implements IR
constructor({ remoteAuthority }: IWindowConfiguration,
@IEnvironmentService environmentService: IEnvironmentService,
@IRemoteAuthorityResolverService remoteAuthorityResolverService: IRemoteAuthorityResolverService,
@ISignService signService: ISignService
@ISignService signService: ISignService,
@ILogService logService: ILogService
) {
super(environmentService);
this.socketFactory = nodeSocketFactory;
if (remoteAuthority) {
this._connection = this._register(new RemoteAgentConnection(remoteAuthority, product.commit, nodeSocketFactory, remoteAuthorityResolverService, signService));
this._connection = this._register(new RemoteAgentConnection(remoteAuthority, product.commit, nodeSocketFactory, remoteAuthorityResolverService, signService, logService));
}
}

View File

@@ -15,6 +15,7 @@ import { ITunnelService, RemoteTunnel } from 'vs/platform/remote/common/tunnel';
import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory';
import { ISignService } from 'vs/platform/sign/common/sign';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ILogService } from 'vs/platform/log/common/log';
export async function createRemoteTunnel(options: IConnectionOptions, tunnelRemotePort: number): Promise<RemoteTunnel> {
const tunnel = new NodeRemoteTunnel(options, tunnelRemotePort);
@@ -90,7 +91,8 @@ export class TunnelService implements ITunnelService {
public constructor(
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IRemoteAuthorityResolverService private readonly remoteAuthorityResolverService: IRemoteAuthorityResolverService,
@ISignService private readonly signService: ISignService
@ISignService private readonly signService: ISignService,
@ILogService private readonly logService: ILogService
) {
}
@@ -109,7 +111,8 @@ export class TunnelService implements ITunnelService {
return { host: authority.host, port: authority.port };
}
},
signService: this.signService
signService: this.signService,
logService: this.logService
};
return createRemoteTunnel(options, remotePort);
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { TextFileService } from 'vs/workbench/services/textfile/common/textFileService';
import { ITextFileService, IResourceEncodings, IResourceEncoding } from 'vs/workbench/services/textfile/common/textfiles';
import { ITextFileService, IResourceEncodings, IResourceEncoding, ModelState } from 'vs/workbench/services/textfile/common/textfiles';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ShutdownReason } from 'vs/platform/lifecycle/common/lifecycle';
import { Schemas } from 'vs/base/common/network';
@@ -26,6 +26,10 @@ export class BrowserTextFileService extends TextFileService {
}
private doBeforeShutdownSync(): boolean {
if (this.models.getAll().some(model => model.hasState(ModelState.PENDING_SAVE) || model.hasState(ModelState.PENDING_AUTO_SAVE))) {
return true; // files are pending to be saved: veto
}
const dirtyResources = this.getDirty();
if (!dirtyResources.length) {
return false; // no dirty: no veto

View File

@@ -593,6 +593,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
// Create new save timer and store it for disposal as needed
const handle = setTimeout(() => {
// Clear the timeout now that we are running
this.autoSaveDisposable.clear();
// Only trigger save if the version id has not changed meanwhile
if (versionId === this.versionId) {
this.doSave(versionId, { reason: SaveReason.AUTO }); // Very important here to not return the promise because if the timeout promise is canceled it will bubble up the error otherwise - do not change
@@ -943,6 +946,8 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
return this.inOrphanMode;
case ModelState.PENDING_SAVE:
return this.saveSequentializer.hasPendingSave();
case ModelState.PENDING_AUTO_SAVE:
return !!this.autoSaveDisposable.value;
case ModelState.SAVED:
return !this.dirty;
}

View File

@@ -248,10 +248,15 @@ export const enum ModelState {
DIRTY,
/**
* A model is transitioning from dirty to saved.
* A model is currently being saved but this operation has not completed yet.
*/
PENDING_SAVE,
/**
* A model is marked for being saved after a specific timeout.
*/
PENDING_AUTO_SAVE,
/**
* A model is in conflict mode when changes cannot be saved because the
* underlying file has changed. Models in conflict mode are always dirty.

View File

@@ -52,6 +52,7 @@ suite('Files - TextFileEditorModel', () => {
model.textEditorModel!.setValue('bar');
assert.ok(getLastModifiedTime(model) <= Date.now());
assert.ok(model.hasState(ModelState.DIRTY));
let savedEvent = false;
model.onDidStateChange(e => {
@@ -60,9 +61,13 @@ suite('Files - TextFileEditorModel', () => {
}
});
await model.save();
const pendingSave = model.save();
assert.ok(model.hasState(ModelState.PENDING_SAVE));
await pendingSave;
assert.ok(model.getLastSaveAttemptTime() <= Date.now());
assert.ok(model.hasState(ModelState.SAVED));
assert.ok(!model.isDirty());
assert.ok(savedEvent);

View File

@@ -75,6 +75,7 @@ import 'vs/workbench/services/themes/browser/workbenchThemeService';
import 'vs/workbench/services/label/common/labelService';
import 'vs/workbench/services/extensionManagement/common/extensionEnablementService';
import 'vs/workbench/services/notification/common/notificationService';
import 'vs/workbench/services/extensions/common/staticExtensions';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';

View File

@@ -71,7 +71,6 @@ import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { WorkspacesService } from 'vs/platform/workspaces/electron-browser/workspacesService';
import { IMenubarService } from 'vs/platform/menubar/node/menubar';
import { MenubarService } from 'vs/platform/menubar/electron-browser/menubarService';
import { StaticExtensionsService, IStaticExtensionsService } from 'vs/workbench/services/extensions/common/staticExtensions';
registerSingleton(IClipboardService, ClipboardService, true);
registerSingleton(IRequestService, RequestService, true);
@@ -83,7 +82,6 @@ registerSingleton(IUpdateService, UpdateService);
registerSingleton(IIssueService, IssueService);
registerSingleton(IWorkspacesService, WorkspacesService);
registerSingleton(IMenubarService, MenubarService);
registerSingleton(IStaticExtensionsService, class extends StaticExtensionsService { constructor() { super([]); } });
//#endregion

View File

@@ -4,6 +4,3 @@
*--------------------------------------------------------------------------------------------*/
/* NOTE: THIS FILE WILL BE OVERWRITTEN DURING BUILD TIME, DO NOT EDIT */
div.monaco.main.css {
}

View File

@@ -4,5 +4,3 @@
*--------------------------------------------------------------------------------------------*/
// NOTE: THIS FILE WILL BE OVERWRITTEN DURING BUILD TIME, DO NOT EDIT
define([], {});