Merge branch 'master' into joh/eol

This commit is contained in:
Johannes Rieken
2017-03-24 12:37:38 +01:00
committed by GitHub
369 changed files with 15275 additions and 11456 deletions

View File

@@ -34,6 +34,7 @@ import { ExtHostLanguages } from 'vs/workbench/api/node/extHostLanguages';
import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures';
import { ExtHostApiCommands } from 'vs/workbench/api/node/extHostApiCommands';
import { computeDiff } from 'vs/workbench/api/node/extHostFunctions';
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
import URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
@@ -111,6 +112,7 @@ export function createApiFactory(initData: IInitData, threadService: IThreadServ
const extHostQuickOpen = col.define(ExtHostContext.ExtHostQuickOpen).set<ExtHostQuickOpen>(new ExtHostQuickOpen(threadService));
const extHostTerminalService = col.define(ExtHostContext.ExtHostTerminalService).set<ExtHostTerminalService>(new ExtHostTerminalService(threadService));
const extHostSCM = col.define(ExtHostContext.ExtHostSCM).set<ExtHostSCM>(new ExtHostSCM(threadService));
const extHostTask = col.define(ExtHostContext.ExtHostTask).set<ExtHostTask>(new ExtHostTask(threadService));
col.define(ExtHostContext.ExtHostExtensionService).set(extensionService);
col.finish(false, threadService);
@@ -412,7 +414,10 @@ export function createApiFactory(initData: IInitData, threadService: IThreadServ
},
getConfiguration: (section?: string): vscode.WorkspaceConfiguration => {
return extHostConfiguration.getConfiguration(section);
}
},
registerTaskProvider: proposedApiFunction(extension, (provider: vscode.TaskProvider) => {
return extHostTask.registerTaskProvider(extension, provider);
})
};
class SCM {
@@ -494,7 +499,12 @@ export function createApiFactory(initData: IInitData, threadService: IThreadServ
ViewColumn: extHostTypes.ViewColumn,
WorkspaceEdit: extHostTypes.WorkspaceEdit,
// functions
computeDiff
computeDiff,
FileLocationKind: extHostTypes.FileLocationKind,
ApplyToKind: extHostTypes.ApplyToKind,
RevealKind: extHostTypes.RevealKind,
ShellTask: extHostTypes.ShellTask,
ProcessTask: extHostTypes.ProcessTask
};
};
}

View File

@@ -33,6 +33,7 @@ import { MainThreadTerminalService } from './mainThreadTerminalService';
import { MainThreadWorkspace } from './mainThreadWorkspace';
import { MainProcessExtensionService } from './mainThreadExtensionService';
import { MainThreadFileSystemEventService } from './mainThreadFileSystemEventService';
import { MainThreadTask } from './mainThreadTask';
import { MainThreadSCM } from './mainThreadSCM';
// --- other interested parties
@@ -86,6 +87,7 @@ export class ExtHostContribution implements IWorkbenchContribution {
col.define(MainContext.MainThreadTerminalService).set(create(MainThreadTerminalService));
col.define(MainContext.MainThreadWorkspace).set(create(MainThreadWorkspace));
col.define(MainContext.MainThreadSCM).set(create(MainThreadSCM));
col.define(MainContext.MainThreadTask).set(create(MainThreadTask));
if (this.extensionService instanceof MainProcessExtensionService) {
col.define(MainContext.MainProcessExtensionService).set(<MainProcessExtensionService>this.extensionService);
}

View File

@@ -34,10 +34,10 @@ import { IWorkspaceConfigurationValues } from 'vs/workbench/services/configurati
import { IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { IWorkspaceSymbol } from 'vs/workbench/parts/search/common/search';
import { IApplyEditsOptions, IUndoStopOptions, TextEditorRevealType, ITextEditorConfigurationUpdate, IResolvedTextEditorConfiguration, ISelectionChangeEvent } from './mainThreadEditor';
import { InternalTreeExplorerNodeContent } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel';
import { TaskSet } from 'vs/workbench/parts/tasks/common/tasks';
export interface IEnvironment {
enableProposedApi: boolean;
@@ -237,6 +237,11 @@ export abstract class MainThreadWorkspaceShape {
$applyWorkspaceEdit(edits: IResourceEdit[]): TPromise<boolean> { throw ni(); }
}
export abstract class MainThreadTaskShape {
$registerTaskProvider(handle: number): TPromise<any> { throw ni(); }
$unregisterTaskProvider(handle: number): TPromise<any> { throw ni(); }
}
export abstract class MainProcessExtensionServiceShape {
$localShowMessage(severity: Severity, msg: string): void { throw ni(); }
$onExtensionActivated(extensionId: string): void { throw ni(); }
@@ -383,8 +388,8 @@ export abstract class ExtHostLanguageFeaturesShape {
$provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]> { throw ni(); }
$provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: editorCommon.IRange, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]> { throw ni(); }
$provideOnTypeFormattingEdits(handle: number, resource: URI, position: editorCommon.IPosition, ch: string, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]> { throw ni(); }
$provideWorkspaceSymbols(handle: number, search: string): TPromise<IWorkspaceSymbol[]> { throw ni(); }
$resolveWorkspaceSymbol(handle: number, symbol: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> { throw ni(); }
$provideWorkspaceSymbols(handle: number, search: string): TPromise<modes.SymbolInformation[]> { throw ni(); }
$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<modes.SymbolInformation> { throw ni(); }
$provideRenameEdits(handle: number, resource: URI, position: editorCommon.IPosition, newName: string): TPromise<modes.WorkspaceEdit> { throw ni(); }
$provideCompletionItems(handle: number, resource: URI, position: editorCommon.IPosition): TPromise<modes.ISuggestResult> { throw ni(); }
$resolveCompletionItem(handle: number, resource: URI, position: editorCommon.IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> { throw ni(); }
@@ -411,6 +416,10 @@ export abstract class ExtHostSCMShape {
$onInputBoxValueChange(value: string): TPromise<void> { throw ni(); }
}
export abstract class ExtHostTaskShape {
$provideTasks(handle: number): TPromise<TaskSet> { throw ni(); }
}
// --- proxy identifiers
export const MainContext = {
@@ -433,7 +442,8 @@ export const MainContext = {
MainThreadTerminalService: createMainId<MainThreadTerminalServiceShape>('MainThreadTerminalService', MainThreadTerminalServiceShape),
MainThreadWorkspace: createMainId<MainThreadWorkspaceShape>('MainThreadWorkspace', MainThreadWorkspaceShape),
MainProcessExtensionService: createMainId<MainProcessExtensionServiceShape>('MainProcessExtensionService', MainProcessExtensionServiceShape),
MainThreadSCM: createMainId<MainThreadSCMShape>('MainThreadSCM', MainThreadSCMShape)
MainThreadSCM: createMainId<MainThreadSCMShape>('MainThreadSCM', MainThreadSCMShape),
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask', MainThreadTaskShape)
};
export const ExtHostContext = {
@@ -451,5 +461,6 @@ export const ExtHostContext = {
ExtHostQuickOpen: createExtId<ExtHostQuickOpenShape>('ExtHostQuickOpen', ExtHostQuickOpenShape),
ExtHostExtensionService: createExtId<ExtHostExtensionServiceShape>('ExtHostExtensionService', ExtHostExtensionServiceShape),
ExtHostTerminalService: createExtId<ExtHostTerminalServiceShape>('ExtHostTerminalService', ExtHostTerminalServiceShape),
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM', ExtHostSCMShape)
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM', ExtHostSCMShape),
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask', ExtHostTaskShape)
};

View File

@@ -15,7 +15,7 @@ import * as modes from 'vs/editor/common/modes';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { IOutline } from 'vs/editor/contrib/quickOpen/common/quickOpen';
import { IWorkspaceSymbolProvider, IWorkspaceSymbol } from 'vs/workbench/parts/search/common/search';
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
import { ICodeLensData } from 'vs/editor/contrib/codelens/common/codelens';
export class ExtHostApiCommands {
@@ -171,18 +171,7 @@ export class ExtHostApiCommands {
description: `
Render the html of the resource in an editor view.
Links contained in the document will be handled by VS Code whereby it supports \`file\`-resources and
[virtual](https://github.com/Microsoft/vscode/blob/master/src/vs/vscode.d.ts#L3295)-resources
as well as triggering commands using the \`command\`-scheme. Use the query part of a command-uri to pass along JSON-encoded
arguments - note that URL-encoding must be applied. The snippet below defines a command-link that calls the _previewHtml_
command and passes along an uri:
\`\`\`
let href = encodeURI('command:vscode.previewHtml?' + JSON.stringify(someUri));
let html = '<a href="' + href + '">Show Resource...</a>.';
\`\`\`
The body element of the displayed html is dynamically annotated with one of the following css classes in order to
communicate the kind of color theme vscode is currently using: \`vscode-light\`, \`vscode-dark\`, or \`vscode-high-contrast\'.
See [working with the html preview](https://code.visualstudio.com/docs/extensionAPI/vscode-api-commands#working-with-the-html-preview) for more information about the html preview's intergration with the editor and for best practices for extension authors.
`,
args: [
{ name: 'uri', description: 'Uri of the resource to preview.', constraint: value => value instanceof URI || typeof value === 'string' },
@@ -250,7 +239,7 @@ export class ExtHostApiCommands {
* @return A promise that resolves to an array of symbol information.
*/
private _executeWorkspaceSymbolProvider(query: string): Thenable<types.SymbolInformation[]> {
return this._commands.executeCommand<[IWorkspaceSymbolProvider, IWorkspaceSymbol[]][]>('_executeWorkspaceSymbolProvider', { query }).then(value => {
return this._commands.executeCommand<[IWorkspaceSymbolProvider, modes.SymbolInformation[]][]>('_executeWorkspaceSymbolProvider', { query }).then(value => {
const result: types.SymbolInformation[] = [];
if (Array.isArray(value)) {
for (let tuple of value) {
@@ -382,7 +371,7 @@ export class ExtHostApiCommands {
};
return this._commands.executeCommand<IOutline>('_executeDocumentSymbolProvider', args).then(value => {
if (value && Array.isArray(value.entries)) {
return value.entries.map(typeConverters.SymbolInformation.fromOutlineEntry);
return value.entries.map(typeConverters.toSymbolInformation);
}
return undefined;
});

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ok } from 'vs/base/common/assert';
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
import { MirrorModel2 } from 'vs/editor/common/model/mirrorModel2';
import URI from 'vs/base/common/uri';
@@ -12,6 +13,7 @@ import * as vscode from 'vscode';
import { getWordAtText, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper';
import { MainThreadDocumentsShape } from './extHost.protocol';
import { ITextSource } from 'vs/editor/common/model/textSource';
import { TPromise } from 'vs/base/common/winjs.base';
const _modeId2WordDefinition = new Map<string, RegExp>();
export function setWordDefinitionFor(modeId: string, wordDefinition: RegExp): void {
@@ -26,23 +28,26 @@ export class ExtHostDocumentData extends MirrorModel2 {
private _proxy: MainThreadDocumentsShape;
private _languageId: string;
private _isDirty: boolean;
private _textLines: vscode.TextLine[];
private _document: vscode.TextDocument;
private _textLines: vscode.TextLine[] = [];
private _isDisposed: boolean = false;
constructor(proxy: MainThreadDocumentsShape, uri: URI, lines: string[], eol: string,
languageId: string, versionId: number, isDirty: boolean) {
languageId: string, versionId: number, isDirty: boolean
) {
super(uri, lines, eol, versionId);
this._proxy = proxy;
this._languageId = languageId;
this._isDirty = isDirty;
this._textLines = [];
}
dispose(): void {
this._textLines.length = 0;
// we don't really dispose documents but let
// extensions still read from them. some
// operations, live saving, will now error tho
ok(!this._isDisposed);
this._isDisposed = true;
this._isDirty = false;
super.dispose();
}
equalLines({ lines }: ITextSource): boolean {
@@ -68,31 +73,40 @@ export class ExtHostDocumentData extends MirrorModel2 {
get languageId() { return data._languageId; },
get version() { return data._versionId; },
get isDirty() { return data._isDirty; },
save() { return data._proxy.$trySaveDocument(data._uri); },
save() { return data._save(); },
getText(range?) { return range ? data._getTextInRange(range) : data.getText(); },
get eol() { return data._eol === '\n' ? EndOfLine.LF : EndOfLine.CRLF; },
get lineCount() { return data._lines.length; },
lineAt(lineOrPos) { return data.lineAt(lineOrPos); },
offsetAt(pos) { return data.offsetAt(pos); },
positionAt(offset) { return data.positionAt(offset); },
validateRange(ran) { return data.validateRange(ran); },
validatePosition(pos) { return data.validatePosition(pos); },
getWordRangeAtPosition(pos, regexp?) { return data.getWordRangeAtPosition(pos, regexp); }
lineAt(lineOrPos) { return data._lineAt(lineOrPos); },
offsetAt(pos) { return data._offsetAt(pos); },
positionAt(offset) { return data._positionAt(offset); },
validateRange(ran) { return data._validateRange(ran); },
validatePosition(pos) { return data._validatePosition(pos); },
getWordRangeAtPosition(pos, regexp?) { return data._getWordRangeAtPosition(pos, regexp); }
};
}
return this._document;
return Object.freeze(this._document);
}
_acceptLanguageId(newLanguageId: string): void {
ok(!this._isDisposed);
this._languageId = newLanguageId;
}
_acceptIsDirty(isDirty: boolean): void {
ok(!this._isDisposed);
this._isDirty = isDirty;
}
private _save(): TPromise<boolean> {
if (this._isDisposed) {
return TPromise.wrapError<boolean>('Document has been closed');
}
return this._proxy.$trySaveDocument(this._uri);
}
private _getTextInRange(_range: vscode.Range): string {
let range = this.validateRange(_range);
let range = this._validateRange(_range);
if (range.isEmpty) {
return '';
@@ -116,7 +130,7 @@ export class ExtHostDocumentData extends MirrorModel2 {
return resultLines.join(lineEnding);
}
lineAt(lineOrPosition: number | vscode.Position): vscode.TextLine {
private _lineAt(lineOrPosition: number | vscode.Position): vscode.TextLine {
let line: number;
if (lineOrPosition instanceof Position) {
@@ -154,13 +168,13 @@ export class ExtHostDocumentData extends MirrorModel2 {
return result;
}
offsetAt(position: vscode.Position): number {
position = this.validatePosition(position);
private _offsetAt(position: vscode.Position): number {
position = this._validatePosition(position);
this._ensureLineStarts();
return this._lineStarts.getAccumulatedValue(position.line - 1) + position.character;
}
positionAt(offset: number): vscode.Position {
private _positionAt(offset: number): vscode.Position {
offset = Math.floor(offset);
offset = Math.max(0, offset);
@@ -175,13 +189,13 @@ export class ExtHostDocumentData extends MirrorModel2 {
// ---- range math
validateRange(range: vscode.Range): vscode.Range {
private _validateRange(range: vscode.Range): vscode.Range {
if (!(range instanceof Range)) {
throw new Error('Invalid argument');
}
let start = this.validatePosition(range.start);
let end = this.validatePosition(range.end);
let start = this._validatePosition(range.start);
let end = this._validatePosition(range.end);
if (start === range.start && end === range.end) {
return range;
@@ -189,7 +203,7 @@ export class ExtHostDocumentData extends MirrorModel2 {
return new Range(start.line, start.character, end.line, end.character);
}
validatePosition(position: vscode.Position): vscode.Position {
private _validatePosition(position: vscode.Position): vscode.Position {
if (!(position instanceof Position)) {
throw new Error('Invalid argument');
}
@@ -225,8 +239,8 @@ export class ExtHostDocumentData extends MirrorModel2 {
return new Position(line, character);
}
getWordRangeAtPosition(_position: vscode.Position, regexp?: RegExp): vscode.Range {
let position = this.validatePosition(_position);
private _getWordRangeAtPosition(_position: vscode.Position, regexp?: RegExp): vscode.Range {
let position = this._validatePosition(_position);
if (!regexp || regExpLeadsToEndlessLoop(regexp)) {
regexp = getWordDefinitionFor(this._languageId);
}

View File

@@ -17,7 +17,7 @@ import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
import { IWorkspaceSymbolProvider, IWorkspaceSymbol } from 'vs/workbench/parts/search/common/search';
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
import { asWinJsPromise } from 'vs/base/common/async';
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier } from './extHost.protocol';
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
@@ -38,7 +38,7 @@ class OutlineAdapter {
let doc = this._documents.getDocumentData(resource).document;
return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => {
if (Array.isArray(value)) {
return value.map(TypeConverters.SymbolInformation.toOutlineEntry);
return value.map(TypeConverters.fromSymbolInformation);
}
return undefined;
});
@@ -311,7 +311,7 @@ class DocumentFormattingAdapter {
provideDocumentFormattingEdits(resource: URI, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
const {document} = this._documents.getDocumentData(resource);
const { document } = this._documents.getDocumentData(resource);
return asWinJsPromise(token => this._provider.provideDocumentFormattingEdits(document, <any>options, token)).then(value => {
if (Array.isArray(value)) {
@@ -334,7 +334,7 @@ class RangeFormattingAdapter {
provideDocumentRangeFormattingEdits(resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
const {document} = this._documents.getDocumentData(resource);
const { document } = this._documents.getDocumentData(resource);
const ran = TypeConverters.toRange(range);
return asWinJsPromise(token => this._provider.provideDocumentRangeFormattingEdits(document, ran, <any>options, token)).then(value => {
@@ -360,7 +360,7 @@ class OnTypeFormattingAdapter {
provideOnTypeFormattingEdits(resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
const {document} = this._documents.getDocumentData(resource);
const { document } = this._documents.getDocumentData(resource);
const pos = TypeConverters.toPosition(position);
return asWinJsPromise(token => this._provider.provideOnTypeFormattingEdits(document, pos, ch, <any>options, token)).then(value => {
@@ -383,7 +383,7 @@ class NavigateTypeAdapter implements IWorkspaceSymbolProvider {
this._heapService = heapService;
}
provideWorkspaceSymbols(search: string): TPromise<IWorkspaceSymbol[]> {
provideWorkspaceSymbols(search: string): TPromise<modes.SymbolInformation[]> {
return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
if (Array.isArray(value)) {
@@ -397,7 +397,7 @@ class NavigateTypeAdapter implements IWorkspaceSymbolProvider {
});
}
resolveWorkspaceSymbol(item: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> {
resolveWorkspaceSymbol(item: modes.SymbolInformation): TPromise<modes.SymbolInformation> {
if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
return TPromise.as(item);
@@ -889,11 +889,11 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideWorkspaceSymbols(handle: number, search: string): TPromise<IWorkspaceSymbol[]> {
$provideWorkspaceSymbols(handle: number, search: string): TPromise<modes.SymbolInformation[]> {
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search));
}
$resolveWorkspaceSymbol(handle: number, symbol: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> {
$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<modes.SymbolInformation> {
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol));
}
@@ -960,7 +960,7 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
// --- configuration
setLanguageConfiguration(languageId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {
let {wordPattern} = configuration;
let { wordPattern } = configuration;
// check for a valid word pattern
if (wordPattern && regExpLeadsToEndlessLoop(wordPattern)) {

View File

@@ -0,0 +1,479 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import * as UUID from 'vs/base/common/uuid';
import { asWinJsPromise } from 'vs/base/common/async';
import * as Problems from 'vs/platform/markers/common/problemMatcher';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { MainContext, MainThreadTaskShape, ExtHostTaskShape } from 'vs/workbench/api/node/extHost.protocol';
import { fromDiagnosticSeverity } from 'vs/workbench/api/node/extHostTypeConverters';
import * as types from 'vs/workbench/api/node/extHostTypes';
import * as vscode from 'vscode';
interface StringMap<V> {
[key: string]: V;
}
namespace ProblemPattern {
export function from(value: vscode.ProblemPattern | vscode.MultiLineProblemPattern): Problems.ProblemPattern | Problems.MultiLineProblemPattern {
if (value === void 0 || value === null) {
return undefined;
}
if (Array.isArray(value)) {
let result: Problems.ProblemPattern[] = [];
for (let pattern of value) {
let converted = fromSingle(pattern);
if (!converted) {
return undefined;
}
result.push(converted);
}
return result;
} else {
return fromSingle(value);
}
}
function copyProperty(target: Problems.ProblemPattern, source: vscode.ProblemPattern, tk: keyof Problems.ProblemPattern) {
let sk: keyof vscode.ProblemPattern = tk;
let value = source[sk];
if (typeof value === 'number') {
target[tk] = value;
}
}
function getValue(value: number, defaultValue: number): number {
if (value !== void 0 && value === null) {
return value;
}
return defaultValue;
}
function fromSingle(problemPattern: vscode.ProblemPattern): Problems.ProblemPattern {
if (problemPattern === void 0 || problemPattern === null || !(problemPattern.regexp instanceof RegExp)) {
return undefined;
}
let result: Problems.ProblemPattern = {
regexp: problemPattern.regexp
};
copyProperty(result, problemPattern, 'file');
copyProperty(result, problemPattern, 'location');
copyProperty(result, problemPattern, 'line');
copyProperty(result, problemPattern, 'character');
copyProperty(result, problemPattern, 'endLine');
copyProperty(result, problemPattern, 'endCharacter');
copyProperty(result, problemPattern, 'severity');
copyProperty(result, problemPattern, 'code');
copyProperty(result, problemPattern, 'message');
if (problemPattern.loop === true || problemPattern.loop === false) {
result.loop = problemPattern.loop;
}
if (result.location) {
result.file = getValue(result.file, 1);
result.message = getValue(result.message, 0);
} else {
result.file = getValue(result.file, 1);
result.line = getValue(result.line, 2);
result.character = getValue(result.character, 3);
result.message = getValue(result.message, 0);
}
return result;
}
}
namespace ApplyTo {
export function from(value: vscode.ApplyToKind): Problems.ApplyToKind {
if (value === void 0 || value === null) {
return Problems.ApplyToKind.allDocuments;
}
switch (value) {
case types.ApplyToKind.OpenDocuments:
return Problems.ApplyToKind.openDocuments;
case types.ApplyToKind.ClosedDocuments:
return Problems.ApplyToKind.closedDocuments;
}
return Problems.ApplyToKind.allDocuments;
}
}
namespace FileLocation {
export function from(value: vscode.FileLocationKind | string): { kind: Problems.FileLocationKind; prefix?: string } {
if (value === void 0 || value === null) {
return { kind: Problems.FileLocationKind.Auto };
}
if (typeof value === 'string') {
return { kind: Problems.FileLocationKind.Relative, prefix: value };
}
switch (value) {
case types.FileLocationKind.Absolute:
return { kind: Problems.FileLocationKind.Absolute };
case types.FileLocationKind.Relative:
return { kind: Problems.FileLocationKind.Relative, prefix: '${workspaceRoot}' };
}
return { kind: Problems.FileLocationKind.Auto };
}
}
namespace WatchingPattern {
export function from(value: RegExp | vscode.BackgroundPattern): Problems.WatchingPattern {
if (value === void 0 || value === null) {
return undefined;
}
if (value instanceof RegExp) {
return { regexp: value };
}
if (!(value.regexp instanceof RegExp)) {
return undefined;
}
let result: Problems.WatchingPattern = {
regexp: value.regexp
};
if (typeof value.file === 'number') {
result.file = value.file;
}
return result;
}
}
namespace WathingMatcher {
export function from(value: vscode.BackgroundMonitor): Problems.WatchingMatcher {
if (value === void 0 || value === null) {
return undefined;
}
let result: Problems.WatchingMatcher = {
activeOnStart: !!value.activeOnStart,
beginsPattern: WatchingPattern.from(value.beginsPattern),
endsPattern: WatchingPattern.from(value.endsPattern)
};
return result;
}
}
namespace ProblemMatcher {
export function from(values: vscode.ProblemMatcher[]): Problems.ProblemMatcher[] {
if (values === void 0 || values === null) {
return undefined;
}
let result: Problems.ProblemMatcher[];
for (let value of values) {
let converted = fromSingle(value);
if (converted) {
result.push(converted);
}
}
return result;
}
function fromSingle(problemMatcher: vscode.ProblemMatcher): Problems.ProblemMatcher {
if (problemMatcher === void 0 || problemMatcher === null) {
return undefined;
}
let location = FileLocation.from(problemMatcher.fileLocation);
let result: Problems.ProblemMatcher = {
owner: typeof problemMatcher.owner === 'string' ? problemMatcher.owner : UUID.generateUuid(),
applyTo: ApplyTo.from(problemMatcher.applyTo),
fileLocation: location.kind,
filePrefix: location.prefix,
pattern: ProblemPattern.from(problemMatcher.pattern),
severity: fromDiagnosticSeverity(problemMatcher.severity),
};
return result;
}
}
namespace RevealKind {
export function from(value: vscode.RevealKind): TaskSystem.ShowOutput {
if (value === void 0 || value === null) {
return TaskSystem.ShowOutput.Always;
}
switch (value) {
case types.RevealKind.Silent:
return TaskSystem.ShowOutput.Silent;
case types.RevealKind.Never:
return TaskSystem.ShowOutput.Never;
}
return TaskSystem.ShowOutput.Always;
}
}
namespace TerminalBehaviour {
export function from(value: vscode.TerminalBehaviour): { showOutput: TaskSystem.ShowOutput, echo: boolean } {
if (value === void 0 || value === null) {
return { showOutput: TaskSystem.ShowOutput.Always, echo: false };
}
return { showOutput: RevealKind.from(value.reveal), echo: !!value.echo };
}
}
namespace Strings {
export function from(value: string[]): string[] {
if (value === void 0 || value === null) {
return undefined;
}
for (let element of value) {
if (typeof element !== 'string') {
return [];
}
}
return value;
}
}
namespace CommandOptions {
export function from(value: { cwd?: string; env?: { [key: string]: string; } }): TaskSystem.CommandOptions {
if (value === void 0 || value === null) {
return undefined;
}
let result: TaskSystem.CommandOptions = {
};
if (typeof value.cwd === 'string') {
result.cwd = value.cwd;
}
if (value.env) {
result.env = Object.create(null);
Object.keys(value.env).forEach(key => {
let envValue = value.env[key];
if (typeof envValue === 'string') {
result.env[key] = envValue;
}
});
}
return result;
}
}
namespace ShellConfiguration {
export function from(value: { executable?: string, args?: string[] }): boolean | TaskSystem.ShellConfiguration {
if (value === void 0 || value === null || typeof value.executable !== 'string') {
return true;
}
let result: TaskSystem.ShellConfiguration = {
executable: value.executable,
args: Strings.from(value.args)
};
return result;
}
}
namespace Tasks {
export function from(tasks: vscode.Task[], uuidMap: UUIDMap): TaskSystem.Task[] {
if (tasks === void 0 || tasks === null) {
return [];
}
let result: TaskSystem.Task[] = [];
try {
uuidMap.start();
for (let task of tasks) {
let converted = fromSingle(task, uuidMap);
if (converted) {
result.push(converted);
}
}
} finally {
uuidMap.finish();
}
return result;
}
function fromSingle(task: vscode.Task, uuidMap: UUIDMap): TaskSystem.Task {
if (typeof task.name !== 'string' || typeof task.identifier !== 'string') {
return undefined;
}
let command: TaskSystem.CommandConfiguration;
if (task instanceof types.ProcessTask) {
command = getProcessCommand(task);
} else if (task instanceof types.ShellTask) {
command = getShellCommand(task);
} else {
return undefined;
}
if (command === void 0) {
return undefined;
}
let behaviour = TerminalBehaviour.from(task.terminal);
command.echo = behaviour.echo;
let result: TaskSystem.Task = {
_id: uuidMap.getUUID(task.identifier),
name: task.name,
identifier: task.identifier,
command: command,
showOutput: behaviour.showOutput,
isBackground: !!task.isBackground,
suppressTaskName: true,
problemMatchers: ProblemMatcher.from(task.problemMatchers)
};
return result;
}
function getProcessCommand(value: vscode.ProcessTask): TaskSystem.CommandConfiguration {
if (typeof value.process !== 'string') {
return undefined;
}
let result: TaskSystem.CommandConfiguration = {
name: value.process,
args: Strings.from(value.args),
isShellCommand: false,
echo: false,
};
if (value.options) {
result.options = CommandOptions.from(value.options);
}
return result;
}
function getShellCommand(value: vscode.ShellTask): TaskSystem.CommandConfiguration {
if (typeof value.commandLine !== 'string') {
return undefined;
}
let result: TaskSystem.CommandConfiguration = {
name: value.commandLine,
isShellCommand: ShellConfiguration.from(value.options),
echo: false
};
if (value.options) {
result.options = CommandOptions.from(value.options);
}
return result;
}
}
class UUIDMap {
private _map: StringMap<string>;
private _unused: StringMap<boolean>;
constructor() {
this._map = Object.create(null);
}
public start(): void {
this._unused = Object.create(null);
Object.keys(this._map).forEach(key => this._unused[key] = true);
}
public getUUID(identifier: string): string {
delete this._unused[identifier];
let result = this._map[identifier];
if (result) {
return result;
}
result = UUID.generateUuid();
this._map[identifier] = result;
return result;
}
public finish(): void {
Object.keys(this._unused).forEach(key => delete this._map[key]);
this._unused = null;
}
}
namespace TaskSet {
const idMaps: Map<string, UUIDMap> = new Map<string, UUIDMap>();
function getUUIDMap(extensionId: string): UUIDMap {
let result = idMaps.get(extensionId);
if (result) {
return result;
}
result = new UUIDMap();
idMaps.set(extensionId, result);
return result;
}
export function from(extension: IExtensionDescription, value: vscode.TaskSet): TaskSystem.TaskSet {
if (value === void 0 || value === null || !Array.isArray(value.tasks)) {
return { tasks: Object.create(null) };
}
let tasks = Tasks.from(value.tasks, getUUIDMap(extension.id));
let buildTasks: string[];
let testTasks: string[];
if (value.buildTasks || value.testTasks) {
let map: Map<string, TaskSystem.Task> = new Map<string, TaskSystem.Task>();
tasks.forEach(task => map.set(task.identifier, task));
if (Array.isArray(value.buildTasks)) {
buildTasks = [];
for (let elem of value.buildTasks) {
if (typeof elem === 'string' && map.has(elem)) {
buildTasks.push(map.get(elem)._id);
}
}
}
if (Array.isArray(value.testTasks)) {
testTasks = [];
for (let elem of value.testTasks) {
if (typeof elem === 'string' && map.has(elem)) {
testTasks.push(map.get(elem)._id);
}
}
}
}
return {
tasks,
buildTasks,
testTasks
};
}
}
interface HandlerData {
provider: vscode.TaskProvider;
extension: IExtensionDescription;
}
export class ExtHostTask extends ExtHostTaskShape {
private _proxy: MainThreadTaskShape;
private _handleCounter: number;
private _handlers: Map<number, HandlerData>;
constructor(threadService: IThreadService) {
super();
this._proxy = threadService.get(MainContext.MainThreadTask);
this._handleCounter = 0;
this._handlers = new Map<number, HandlerData>();
};
public registerTaskProvider(extension: IExtensionDescription, provider: vscode.TaskProvider): vscode.Disposable {
if (!provider) {
return new types.Disposable(() => { });
}
let handle = this.nextHandle();
this._handlers.set(handle, { provider, extension });
this._proxy.$registerTaskProvider(handle);
return new types.Disposable(() => {
this._handlers.delete(handle);
this._proxy.$unregisterTaskProvider(handle);
});
}
public $provideTasks(handle: number): TPromise<TaskSystem.TaskSet> {
let handler = this._handlers.get(handle);
if (!handler) {
return TPromise.wrapError<TaskSystem.TaskSet>(new Error('no handler found'));
}
return asWinJsPromise(token => handler.provider.provideTasks(token)).then(value => {
return TaskSet.from(handler.extension, value);
});
}
private nextHandle(): number {
return this._handleCounter++;
}
}

View File

@@ -5,6 +5,7 @@
'use strict';
import { ok } from 'vs/base/common/assert';
import { readonly, illegalArgument } from 'vs/base/common/errors';
import { IdGenerator } from 'vs/base/common/idGenerator';
import { TPromise } from 'vs/base/common/winjs.base';
@@ -308,19 +309,18 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
warnOnError(this._proxy.$trySetOptions(this._id, bulkConfigurationUpdate));
}
}
}
export class ExtHostTextEditor implements vscode.TextEditor {
private _proxy: MainThreadEditorsShape;
private _id: string;
private readonly _proxy: MainThreadEditorsShape;
private readonly _id: string;
private readonly _documentData: ExtHostDocumentData;
private _documentData: ExtHostDocumentData;
private _selections: Selection[];
private _options: ExtHostTextEditorOptions;
private _viewColumn: vscode.ViewColumn;
private _disposed: boolean = false;
constructor(proxy: MainThreadEditorsShape, id: string, document: ExtHostDocumentData, selections: Selection[], options: IResolvedTextEditorConfiguration, viewColumn: vscode.ViewColumn) {
this._proxy = proxy;
@@ -332,7 +332,8 @@ export class ExtHostTextEditor implements vscode.TextEditor {
}
dispose() {
this._documentData = null;
ok(!this._disposed);
this._disposed = true;
}
@deprecated('TextEditor.show') show(column: vscode.ViewColumn) {
@@ -346,9 +347,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
// ---- the document
get document(): vscode.TextDocument {
return this._documentData
? this._documentData.document
: undefined;
return this._documentData.document;
}
set document(value) {
@@ -362,10 +361,13 @@ export class ExtHostTextEditor implements vscode.TextEditor {
}
set options(value: vscode.TextEditorOptions) {
this._options.assign(value);
if (!this._disposed) {
this._options.assign(value);
}
}
_acceptOptions(options: IResolvedTextEditorConfiguration): void {
ok(!this._disposed);
this._options._accept(options);
}
@@ -380,6 +382,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
}
_acceptViewColumn(value: vscode.ViewColumn) {
ok(!this._disposed);
this._viewColumn = value;
}
@@ -437,18 +440,22 @@ export class ExtHostTextEditor implements vscode.TextEditor {
}
_acceptSelections(selections: Selection[]): void {
ok(!this._disposed);
this._selections = selections;
}
// ---- editing
edit(callback: (edit: TextEditorEdit) => void, options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Thenable<boolean> {
if (this._disposed) {
return TPromise.wrapError<boolean>('TextEditor#edit not possible on closed editors');
}
let edit = new TextEditorEdit(this._documentData.document, options);
callback(edit);
return this._applyEdit(edit);
}
_applyEdit(editBuilder: TextEditorEdit): TPromise<boolean> {
private _applyEdit(editBuilder: TextEditorEdit): TPromise<boolean> {
let editData = editBuilder.finalize();
// prepare data for serialization
@@ -468,7 +475,9 @@ export class ExtHostTextEditor implements vscode.TextEditor {
}
insertSnippet(snippet: SnippetString, where?: Position | Position[] | Range | Range[], options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Thenable<boolean> {
if (this._disposed) {
return TPromise.wrapError<boolean>('TextEditor#insertSnippet not possible on closed editors');
}
let ranges: IRange[];
if (!where || (Array.isArray(where) && where.length === 0)) {
@@ -498,6 +507,14 @@ export class ExtHostTextEditor implements vscode.TextEditor {
// ---- util
private _runOnProxy(callback: () => TPromise<any>, silent: boolean): TPromise<ExtHostTextEditor> {
if (this._disposed) {
if (!silent) {
return TPromise.wrapError(silent);
} else {
console.warn('TextEditor is closed/disposed');
return TPromise.as(undefined);
}
}
return callback().then(() => this, err => {
if (!silent) {
return TPromise.wrapError(silent);

View File

@@ -9,7 +9,7 @@ import * as modes from 'vs/editor/common/modes';
import * as types from './extHostTypes';
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
import { IPosition, ISelection, IRange, IDecorationOptions, ISingleEditOperation, EndOfLineSequence } from 'vs/editor/common/editorCommon';
import { IWorkspaceSymbol } from 'vs/workbench/parts/search/common/search';
import { IPosition, ISelection, IRange, IDecorationOptions, ISingleEditOperation } from 'vs/editor/common/editorCommon';
import * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
@@ -165,46 +165,63 @@ export const TextEdit = {
}
};
export namespace SymbolInformation {
export function fromOutlineEntry(entry: modes.SymbolInformation): types.SymbolInformation {
return new types.SymbolInformation(
entry.name,
entry.kind,
toRange(entry.location.range),
entry.location.uri,
entry.containerName
);
export namespace SymbolKind {
const _fromMapping: { [kind: number]: modes.SymbolKind } = Object.create(null);
_fromMapping[types.SymbolKind.File] = 'file';
_fromMapping[types.SymbolKind.Module] = 'module';
_fromMapping[types.SymbolKind.Namespace] = 'namespace';
_fromMapping[types.SymbolKind.Package] = 'package';
_fromMapping[types.SymbolKind.Class] = 'class';
_fromMapping[types.SymbolKind.Method] = 'method';
_fromMapping[types.SymbolKind.Property] = 'property';
_fromMapping[types.SymbolKind.Field] = 'field';
_fromMapping[types.SymbolKind.Constructor] = 'constructor';
_fromMapping[types.SymbolKind.Enum] = 'enum';
_fromMapping[types.SymbolKind.Interface] = 'interface';
_fromMapping[types.SymbolKind.Function] = 'function';
_fromMapping[types.SymbolKind.Variable] = 'variable';
_fromMapping[types.SymbolKind.Constant] = 'constant';
_fromMapping[types.SymbolKind.String] = 'string';
_fromMapping[types.SymbolKind.Number] = 'number';
_fromMapping[types.SymbolKind.Boolean] = 'boolean';
_fromMapping[types.SymbolKind.Array] = 'array';
_fromMapping[types.SymbolKind.Object] = 'object';
_fromMapping[types.SymbolKind.Key] = 'key';
_fromMapping[types.SymbolKind.Null] = 'null';
_fromMapping[types.SymbolKind.EnumMember] = 'enum-member';
_fromMapping[types.SymbolKind.Struct] = 'struct';
export function from(kind: vscode.SymbolKind): modes.SymbolKind {
return _fromMapping[kind] || 'property';
}
export function toOutlineEntry(symbol: vscode.SymbolInformation): modes.SymbolInformation {
return <modes.SymbolInformation>{
name: symbol.name,
kind: symbol.kind,
containerName: symbol.containerName,
location: {
uri: <URI>symbol.location.uri,
range: fromRange(symbol.location.range)
export function to(kind: modes.SymbolKind): vscode.SymbolKind {
for (let k in _fromMapping) {
if (_fromMapping[k] === kind) {
return Number(k);
}
};
}
return types.SymbolKind.Property;
}
}
export function fromSymbolInformation(info: vscode.SymbolInformation): IWorkspaceSymbol {
return <IWorkspaceSymbol>{
export function fromSymbolInformation(info: vscode.SymbolInformation): modes.SymbolInformation {
return <modes.SymbolInformation>{
name: info.name,
type: types.SymbolKind[info.kind || types.SymbolKind.Property].toLowerCase(),
kind: SymbolKind.from(info.kind),
containerName: info.containerName,
range: info.location && fromRange(info.location.range),
resource: info.location && info.location.uri,
location: location.from(info.location)
};
}
export function toSymbolInformation(bearing: IWorkspaceSymbol): types.SymbolInformation {
return new types.SymbolInformation(bearing.name,
types.SymbolKind[bearing.type.charAt(0).toUpperCase() + bearing.type.substr(1)],
export function toSymbolInformation(bearing: modes.SymbolInformation): types.SymbolInformation {
return new types.SymbolInformation(
bearing.name,
SymbolKind.to(bearing.kind),
bearing.containerName,
new types.Location(bearing.resource, toRange(bearing.range))
location.to(bearing.location)
);
}
@@ -247,11 +264,14 @@ export const CompletionItemKind = {
case types.CompletionItemKind.Variable: return 'variable';
case types.CompletionItemKind.Class: return 'class';
case types.CompletionItemKind.Interface: return 'interface';
case types.CompletionItemKind.Struct: return 'struct';
case types.CompletionItemKind.Module: return 'module';
case types.CompletionItemKind.Property: return 'property';
case types.CompletionItemKind.Unit: return 'unit';
case types.CompletionItemKind.Value: return 'value';
case types.CompletionItemKind.Constant: return 'constant';
case types.CompletionItemKind.Enum: return 'enum';
case types.CompletionItemKind.EnumMember: return 'enum-member';
case types.CompletionItemKind.Keyword: return 'keyword';
case types.CompletionItemKind.Snippet: return 'snippet';
case types.CompletionItemKind.Text: return 'text';

View File

@@ -718,27 +718,29 @@ export class DocumentHighlight {
}
export enum SymbolKind {
File,
Module,
Namespace,
Package,
Class,
Method,
Property,
Field,
Constructor,
Enum,
Interface,
Function,
Variable,
Constant,
String,
Number,
Boolean,
Array,
Object,
Key,
Null
File = 0,
Module = 1,
Namespace = 2,
Package = 3,
Class = 4,
Method = 5,
Property = 6,
Field = 7,
Constructor = 8,
Enum = 9,
Interface = 10,
Function = 11,
Variable = 12,
Constant = 13,
String = 14,
Number = 15,
Boolean = 16,
Array = 17,
Object = 18,
Key = 19,
Null = 20,
EnumMember = 21,
Struct = 22
}
export class SymbolInformation {
@@ -846,7 +848,10 @@ export enum CompletionItemKind {
Color = 15,
File = 16,
Reference = 17,
Folder = 18
Folder = 18,
EnumMember = 19,
Constant = 20,
Struct = 21
}
export class CompletionItem {
@@ -958,3 +963,227 @@ export class DocumentLink {
this.target = target;
}
}
export enum FileLocationKind {
Auto = 1,
Relative = 2,
Absolute = 3
}
export enum ApplyToKind {
AllDocuments = 1,
OpenDocuments = 2,
ClosedDocuments = 3
}
export enum RevealKind {
Always = 1,
Silent = 2,
Never = 3
}
export class BaseTask {
private _name: string;
private _problemMatchers: vscode.ProblemMatcher[];
private _identifier: string;
private _isBackground: boolean;
private _terminal: vscode.TerminalBehaviour;
constructor(name: string, problemMatchers: vscode.ProblemMatcher[]) {
if (typeof name !== 'string') {
throw illegalArgument('name');
}
this._name = name;
this._identifier = name;
this._problemMatchers = problemMatchers || [];
this._isBackground = false;
this._terminal = Object.create(null);
}
get identifier(): string {
return this._identifier;
}
set identifier(value: string) {
if (typeof name !== 'string') {
throw illegalArgument('identifier');
}
this._identifier = value;
}
get name(): string {
return this._name;
}
get isBackground(): boolean {
return this._isBackground;
}
set isBackground(value: boolean) {
if (value !== true && value !== false) {
value = false;
}
this._isBackground = value;
}
get terminal(): vscode.TerminalBehaviour {
return this._terminal;
}
set terminal(value: vscode.TerminalBehaviour) {
if (value === void 0 || value === null) {
value = Object.create(null);
}
this._terminal = value;
}
get problemMatchers(): vscode.ProblemMatcher[] {
return this._problemMatchers;
}
set problemMatchers(value: vscode.ProblemMatcher[]) {
if (!Array.isArray(value)) {
value = [];
}
this._problemMatchers = value;
}
}
namespace ProblemMatcher {
export function is(value: any): value is vscode.ProblemMatcher {
let candidate: vscode.ProblemMatcher = value;
return candidate && !!candidate.pattern;
}
}
export class ProcessTask extends BaseTask {
private _process: string;
private _args: string[];
private _options: vscode.ProcessOptions;
private static parseArguments(restArgs: any[]): { args: string[]; options: vscode.ProcessOptions; problemMatchers: vscode.ProblemMatcher[] } {
let args: string[] = [];
let options: vscode.ProcessOptions = undefined;
let problemMatchers: vscode.ProblemMatcher[] = [];
if (!restArgs || restArgs.length === 0) {
return { args, options, problemMatchers };
}
let current: any = restArgs[0];
if (Array.isArray(current)) {
args = current;
restArgs.shift();
current = restArgs[0];
}
if (ProblemMatcher.is(current)) {
problemMatchers = restArgs;
} else if (current) {
options = current;
restArgs.shift();
if (restArgs.length > 0) {
problemMatchers = restArgs;
}
}
return { args, options, problemMatchers };
}
constructor(name: string, process: string, ...problemMatchers: vscode.ProblemMatcher[]);
constructor(name: string, process: string, args: string[], ...problemMatchers: vscode.ProblemMatcher[]);
constructor(name: string, process: string, args: string[], options: vscode.ProcessOptions, ...problemMatchers: vscode.ProblemMatcher[]);
constructor(name: string, process: string, ...rest: any[]) {
if (typeof process !== 'string') {
throw illegalArgument('process');
}
let { args, options, problemMatchers } = ProcessTask.parseArguments(rest);
super(name, problemMatchers);
this._process = process;
this._args = args;
this._options = options || Object.create(null);
}
get process(): string {
return this._process;
}
get args(): string[] {
return this._args;
}
set args(value: string[]) {
if (!Array.isArray(value)) {
value = [];
}
this._args = value;
}
get options(): vscode.ProcessOptions {
return this._options;
}
set options(value: vscode.ProcessOptions) {
if (value === void 0 || value === null) {
value = Object.create(null);
}
this._options = value;
}
}
export class ShellTask extends BaseTask {
private _commandLine: string;
private _options: vscode.ShellOptions;
private static parseArguments(restArgs: any[]): { options: vscode.ShellOptions; problemMatchers: vscode.ProblemMatcher[] } {
let options: vscode.ShellOptions = undefined;
let problemMatchers: vscode.ProblemMatcher[] = [];
if (!restArgs || restArgs.length === 0) {
return { options, problemMatchers };
}
let current: any = restArgs[0];
if (current && !ProblemMatcher.is(current)) {
options = current;
restArgs.shift();
current = restArgs[0];
}
if (ProblemMatcher.is(current)) {
problemMatchers = restArgs;
}
return { options, problemMatchers };
}
constructor(name: string, commandLine: string, ...problemMatchers: vscode.ProblemMatcher[]);
constructor(name: string, commandLine: string, options: vscode.ShellOptions, ...problemMatchers: vscode.ProblemMatcher[]);
constructor(name: string, commandLine: string, ...rest: any[]) {
if (typeof commandLine !== 'string') {
throw illegalArgument('commandLine');
}
let { options, problemMatchers } = ShellTask.parseArguments(rest);
super(name, problemMatchers);
this._commandLine = commandLine;
this._options = options || Object.create(null);
}
get commandLine(): string {
return this._commandLine;
}
get options(): vscode.ShellOptions {
return this._options;
}
set options(value: vscode.ShellOptions) {
if (value === void 0 || value === null) {
value = Object.create(null);
}
this._options = value;
}
}

View File

@@ -7,7 +7,6 @@
import URI from 'vs/base/common/uri';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { EmitterEvent } from 'vs/base/common/eventEmitter';
import { setDisposableTimeout } from 'vs/base/common/async';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle';
@@ -25,48 +24,47 @@ import { MainThreadDocumentsAndEditors } from './mainThreadDocumentsAndEditors';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ITextEditorModel } from 'vs/workbench/common/editor';
class TimeoutReference {
export class BoundModelReferenceCollection {
private static _delay = 1000 * 60 * 3;
private _timer: IDisposable;
private _disposed = false;
private _data = new Array<{ length: number, dispose(): void }>();
private _length = 0;
constructor(
readonly codeEditorService: ICodeEditorService,
readonly editorGroupService: IEditorGroupService,
readonly reference: IReference<ITextEditorModel>
private _maxAge: number = 1000 * 60 * 3,
private _maxLength: number = 1024 * 1024 * 80
) {
const check = () => {
if (!this.isUsed()) {
this.dispose();
} else {
this._timer = setDisposableTimeout(check, TimeoutReference._delay);
}
};
this._timer = setDisposableTimeout(check, TimeoutReference._delay);
//
}
dispose(): void {
if (!this._disposed) {
this._disposed = true;
dispose(this.reference, this._timer);
}
this._data = dispose(this._data);
}
private isUsed(): boolean {
for (const editor of this.codeEditorService.listCodeEditors()) {
if (editor.getModel() === this.reference.object.textEditorModel) {
return true;
add(ref: IReference<ITextEditorModel>): void {
let length = ref.object.textEditorModel.getValueLength();
let handle: number;
let entry: { length: number, dispose(): void };
const dispose = () => {
let idx = this._data.indexOf(entry);
if (idx >= 0) {
this._length -= length;
ref.dispose();
clearTimeout(handle);
this._data.splice(idx, 1);
}
};
handle = setTimeout(dispose, this._maxAge);
entry = { length, dispose };
this._data.push(entry);
this._length += length;
this._cleanup();
}
private _cleanup(): void {
while (this._length > this._maxLength) {
this._data[0].dispose();
}
for (const group of this.editorGroupService.getStacksModel().groups) {
if (group.contains(this.reference.object.textEditorModel.uri)) {
return true;
}
}
return false;
}
}
@@ -86,6 +84,7 @@ export class MainThreadDocuments extends MainThreadDocumentsShape {
private _proxy: ExtHostDocumentsShape;
private _modelIsSynced: { [modelId: string]: boolean; };
private _resourceContentProvider: { [handle: number]: IDisposable };
private _modelReferenceCollection = new BoundModelReferenceCollection();
constructor(
documentsAndEditors: MainThreadDocumentsAndEditors,
@@ -113,6 +112,7 @@ export class MainThreadDocuments extends MainThreadDocumentsShape {
this._modelIsSynced = {};
this._toDispose = [];
this._toDispose.push(this._modelReferenceCollection);
this._toDispose.push(documentsAndEditors.onDocumentAdd(models => models.forEach(this._onModelAdded, this)));
this._toDispose.push(documentsAndEditors.onDocumentRemove(urls => urls.forEach(this._onModelRemoved, this)));
modelService.onModelModeChanged(this._onModelModeChanged, this, this._toDispose);
@@ -234,11 +234,7 @@ export class MainThreadDocuments extends MainThreadDocumentsShape {
private _handleAsResourceInput(uri: URI): TPromise<boolean> {
return this._textModelResolverService.createModelReference(uri).then(ref => {
// TimeoutReference will check every 3 min if the
// reference is still in use. This is quite harsh to
// extensions but we don't want them to make us hold
// on to model indefinitely
this._toDispose.push(new TimeoutReference(this._codeEditorService, this._editorGroupService, ref));
this._modelReferenceCollection.add(ref);
const result = !!ref.object;
return result;
});

View File

@@ -11,7 +11,7 @@ import { IThreadService } from 'vs/workbench/services/thread/common/threadServic
import * as vscode from 'vscode';
import { IReadOnlyModel, ISingleEditOperation } from 'vs/editor/common/editorCommon';
import * as modes from 'vs/editor/common/modes';
import { WorkspaceSymbolProviderRegistry, IWorkspaceSymbolProvider, IWorkspaceSymbol } from 'vs/workbench/parts/search/common/search';
import { WorkspaceSymbolProviderRegistry, IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
import { wireCancellationToken } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Position as EditorPosition } from 'vs/editor/common/core/position';
@@ -200,10 +200,10 @@ export class MainThreadLanguageFeatures extends MainThreadLanguageFeaturesShape
$registerNavigateTypeSupport(handle: number): TPromise<any> {
this._registrations[handle] = WorkspaceSymbolProviderRegistry.register(<IWorkspaceSymbolProvider>{
provideWorkspaceSymbols: (search: string): TPromise<IWorkspaceSymbol[]> => {
provideWorkspaceSymbols: (search: string): TPromise<modes.SymbolInformation[]> => {
return this._heapService.trackRecursive(this._proxy.$provideWorkspaceSymbols(handle, search));
},
resolveWorkspaceSymbol: (item: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> => {
resolveWorkspaceSymbol: (item: modes.SymbolInformation): TPromise<modes.SymbolInformation> => {
return this._proxy.$resolveWorkspaceSymbol(handle, item);
}
});

View File

@@ -43,7 +43,7 @@ export class MainThreadOutputService extends MainThreadOutputServiceShape {
}
private _getChannel(channelId: string, label: string): IOutputChannel {
if (Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).getChannels().every(channel => channel.id !== channelId)) {
if (!Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).getChannel(channelId)) {
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel(channelId, label);
}

View File

@@ -0,0 +1,36 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { ITaskService } from 'vs/workbench/parts/tasks/common/taskService';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape } from './extHost.protocol';
export class MainThreadTask extends MainThreadTaskShape {
private _proxy: ExtHostTaskShape;
constructor( @IThreadService threadService: IThreadService, @ITaskService private _taskService: ITaskService) {
super();
this._proxy = threadService.get(ExtHostContext.ExtHostTask);
}
public $registerTaskProvider(handle: number): TPromise<void> {
this._taskService.registerTaskProvider(handle, {
provideTasks: () => {
return this._proxy.$provideTasks(handle);
}
});
return TPromise.as<void>(undefined);
}
public $unregisterTaskProvider(handle: number): TPromise<any> {
this._taskService.unregisterTaskProvider(handle);
return TPromise.as<void>(undefined);
}
}