mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
Merge pull request #1831 from Microsoft/joh/registerTextDocumentProvider
register text document provider
This commit is contained in:
commit
a19740d091
|
@ -11,4 +11,4 @@ build_script:
|
|||
- gulp compile
|
||||
|
||||
test_script:
|
||||
- mocha
|
||||
- .\scripts\test.bat
|
||||
|
|
|
@ -33,7 +33,7 @@ var baseModules = [
|
|||
'events', 'fs', 'getmac', 'glob', 'graceful-fs', 'http', 'http-proxy-agent',
|
||||
'https', 'https-proxy-agent', 'iconv-lite', 'electron', 'net',
|
||||
'os', 'path', 'readline', 'sax', 'semver', 'stream', 'string_decoder', 'url',
|
||||
'vscode-textmate', 'winreg', 'yauzl', 'native-keymap'
|
||||
'vscode-textmate', 'winreg', 'yauzl', 'native-keymap', 'weak'
|
||||
];
|
||||
|
||||
// Build
|
||||
|
|
|
@ -119,6 +119,96 @@ suite('workspace-namespace', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, simple', function() {
|
||||
|
||||
let registration = workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
return uri.toString();
|
||||
}
|
||||
});
|
||||
|
||||
const uri = Uri.parse('foo://testing/virtual.js');
|
||||
return workspace.openTextDocument(uri).then(doc => {
|
||||
assert.equal(doc.getText(), uri.toString());
|
||||
assert.equal(doc.isDirty, false);
|
||||
assert.equal(doc.uri.toString(), uri.toString());
|
||||
registration.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, constrains', function() {
|
||||
|
||||
// built-in
|
||||
assert.throws(function() {
|
||||
workspace.registerTextDocumentContentProvider('untitled', { provideTextDocumentContent() { return null; } });
|
||||
});
|
||||
// built-in
|
||||
assert.throws(function() {
|
||||
workspace.registerTextDocumentContentProvider('file', { provideTextDocumentContent() { return null; } });
|
||||
});
|
||||
|
||||
// duplicate registration
|
||||
let registration = workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
return uri.toString();
|
||||
}
|
||||
});
|
||||
assert.throws(function() {
|
||||
workspace.registerTextDocumentContentProvider('foo', { provideTextDocumentContent() { return null; } });
|
||||
});
|
||||
|
||||
// unregister & register
|
||||
registration.dispose();
|
||||
registration = workspace.registerTextDocumentContentProvider('foo', { provideTextDocumentContent() { return null; } });
|
||||
registration.dispose();
|
||||
|
||||
// missing scheme
|
||||
return workspace.openTextDocument(Uri.parse('notThere://foo/far/boo/bar')).then(() => {
|
||||
assert.ok(false, 'expected failure')
|
||||
}, err => {
|
||||
// expected
|
||||
})
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, show virtual document', function() {
|
||||
|
||||
let registration = workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
return 'I am virtual';
|
||||
}
|
||||
});
|
||||
|
||||
return workspace.openTextDocument(Uri.parse('foo://something/path')).then(doc => {
|
||||
return window.showTextDocument(doc).then(editor => {
|
||||
|
||||
assert.ok(editor.document === doc);
|
||||
assert.equal(editor.document.getText(), 'I am virtual');
|
||||
registration.dispose();
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, open/open document', function() {
|
||||
|
||||
let callCount = 0;
|
||||
let registration = workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
callCount += 1;
|
||||
return 'I am virtual';
|
||||
}
|
||||
});
|
||||
|
||||
const uri = Uri.parse('foo://testing/path');
|
||||
|
||||
return Promise.all([workspace.openTextDocument(uri), workspace.openTextDocument(uri)]).then(docs => {
|
||||
let [first, second] = docs;
|
||||
assert.ok(first === second);
|
||||
assert.ok(workspace.textDocuments.some(doc => doc.uri.toString() === uri.toString()));
|
||||
assert.equal(callCount, 1);
|
||||
registration.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('findFiles', () => {
|
||||
return workspace.findFiles('*.js', null).then((res) => {
|
||||
assert.equal(res.length, 1);
|
||||
|
|
5
npm-shrinkwrap.json
generated
5
npm-shrinkwrap.json
generated
|
@ -449,6 +449,11 @@
|
|||
"from": "native-keymap@0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/native-keymap/-/native-keymap-0.1.2.tgz"
|
||||
},
|
||||
"weak":{
|
||||
"version": "1.0.1",
|
||||
"from": "weak@1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/weak/-/weak-1.0.1.tgz"
|
||||
},
|
||||
"winreg": {
|
||||
"version": "0.0.12",
|
||||
"from": "winreg@0.0.12",
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
"vscode-debugprotocol": "^1.2.1",
|
||||
"vscode-textmate": "^1.0.9",
|
||||
"native-keymap": "^0.1.2",
|
||||
"weak": "^1.0.1",
|
||||
"winreg": "0.0.12",
|
||||
"yauzl": "^2.3.1"
|
||||
},
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
set ATOM_SHELL_INTERNAL_RUN_AS_NODE=1
|
||||
|
||||
pushd %~dp0\..
|
||||
.\.build\electron\Code.exe .\node_modules\mocha\bin\_mocha %*
|
||||
.\.build\electron\CodeOSS.exe .\node_modules\mocha\bin\_mocha %*
|
||||
popd
|
||||
|
|
28
src/typings/weak.d.ts
vendored
Normal file
28
src/typings/weak.d.ts
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare namespace weak {
|
||||
interface WeakRef {
|
||||
// tagging
|
||||
}
|
||||
}
|
||||
|
||||
declare const weak: WeakFunction;
|
||||
|
||||
interface WeakFunction {
|
||||
<T>(obj: T, callback?: () => any): T & weak.WeakRef;
|
||||
(obj: any, callback?: () => any): any & weak.WeakRef;
|
||||
|
||||
get(ref: weak.WeakRef): any;
|
||||
get<T>(ref: weak.WeakRef): T;
|
||||
|
||||
isDead(ref: weak.WeakRef): boolean;
|
||||
isNearDeath(ref: weak.WeakRef): boolean;
|
||||
isWeakRef(obj: any): boolean;
|
||||
}
|
||||
|
||||
declare module 'weak' {
|
||||
export = weak;
|
||||
}
|
|
@ -7,6 +7,26 @@
|
|||
import * as errors from 'vs/base/common/errors';
|
||||
import { Promise, TPromise, ValueCallback, ErrorCallback, ProgressCallback } from 'vs/base/common/winjs.base';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import {CancellationToken, CancellationTokenSource} from 'vs/base/common/cancellation';
|
||||
|
||||
|
||||
function isThenable<T>(obj: any): obj is Thenable<T> {
|
||||
return obj && typeof (<Thenable<any>>obj).then === 'function';
|
||||
}
|
||||
|
||||
export function asWinJsPromise<T>(callback: (token: CancellationToken) => T | Thenable<T>): TPromise<T> {
|
||||
let source = new CancellationTokenSource();
|
||||
return new TPromise<T>((resolve, reject) => {
|
||||
let item = callback(source.token);
|
||||
if (isThenable<T>(item)) {
|
||||
item.then(resolve, reject);
|
||||
} else {
|
||||
resolve(item);
|
||||
}
|
||||
}, () => {
|
||||
source.cancel();
|
||||
});
|
||||
}
|
||||
|
||||
export interface ITask<T> {
|
||||
(): T;
|
||||
|
|
144
src/vs/editor/common/model/mirrorModel2.ts
Normal file
144
src/vs/editor/common/model/mirrorModel2.ts
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 URI from 'vs/base/common/uri';
|
||||
import {IModelContentChangedEvent2, IRange, IPosition} from 'vs/editor/common/editorCommon';
|
||||
import {PrefixSumComputer} from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
|
||||
export class MirrorModel2 {
|
||||
|
||||
protected _uri: URI;
|
||||
protected _lines: string[];
|
||||
protected _eol: string;
|
||||
protected _versionId: number;
|
||||
protected _lineStarts: PrefixSumComputer;
|
||||
|
||||
constructor(uri: URI, lines: string[], eol: string, versionId: number) {
|
||||
this._uri = uri;
|
||||
this._lines = lines;
|
||||
this._eol = eol;
|
||||
this._versionId = versionId;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._lines.length = 0;
|
||||
}
|
||||
|
||||
get version(): number {
|
||||
return this._versionId;
|
||||
}
|
||||
|
||||
getText(): string {
|
||||
return this._lines.join(this._eol);
|
||||
}
|
||||
|
||||
onEvents(events: IModelContentChangedEvent2[]): void {
|
||||
// Update my lines
|
||||
let lastVersionId = -1;
|
||||
for (let i = 0, len = events.length; i < len; i++) {
|
||||
let e = events[i];
|
||||
|
||||
this._acceptDeleteRange(e.range);
|
||||
this._acceptInsertText({
|
||||
lineNumber: e.range.startLineNumber,
|
||||
column: e.range.startColumn
|
||||
}, e.text);
|
||||
lastVersionId = Math.max(lastVersionId, e.versionId);
|
||||
}
|
||||
if (lastVersionId !== -1) {
|
||||
this._versionId = lastVersionId;
|
||||
}
|
||||
}
|
||||
|
||||
protected _ensureLineStarts(): void {
|
||||
if (!this._lineStarts) {
|
||||
const lineStartValues:number[] = [];
|
||||
const eolLength = this._eol.length;
|
||||
for (let i = 0, len = this._lines.length; i < len; i++) {
|
||||
lineStartValues.push(this._lines[i].length + eolLength);
|
||||
}
|
||||
this._lineStarts = new PrefixSumComputer(lineStartValues);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All changes to a line's text go through this method
|
||||
*/
|
||||
private _setLineText(lineIndex:number, newValue:string): void {
|
||||
this._lines[lineIndex] = newValue;
|
||||
if (this._lineStarts) {
|
||||
// update prefix sum
|
||||
this._lineStarts.changeValue(lineIndex, this._lines[lineIndex].length + this._eol.length);
|
||||
}
|
||||
}
|
||||
|
||||
private _acceptDeleteRange(range: IRange): void {
|
||||
|
||||
if (range.startLineNumber === range.endLineNumber) {
|
||||
if (range.startColumn === range.endColumn) {
|
||||
// Nothing to delete
|
||||
return;
|
||||
}
|
||||
// Delete text on the affected line
|
||||
this._setLineText(range.startLineNumber - 1,
|
||||
this._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)
|
||||
+ this._lines[range.startLineNumber - 1].substring(range.endColumn - 1)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Take remaining text on last line and append it to remaining text on first line
|
||||
this._setLineText(range.startLineNumber - 1,
|
||||
this._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)
|
||||
+ this._lines[range.endLineNumber - 1].substring(range.endColumn - 1)
|
||||
);
|
||||
|
||||
// Delete middle lines
|
||||
this._lines.splice(range.startLineNumber, range.endLineNumber - range.startLineNumber);
|
||||
if (this._lineStarts) {
|
||||
// update prefix sum
|
||||
this._lineStarts.removeValues(range.startLineNumber, range.endLineNumber - range.startLineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
private _acceptInsertText(position: IPosition, insertText:string): void {
|
||||
if (insertText.length === 0) {
|
||||
// Nothing to insert
|
||||
return;
|
||||
}
|
||||
let insertLines = insertText.split(/\r\n|\r|\n/);
|
||||
if (insertLines.length === 1) {
|
||||
// Inserting text on one line
|
||||
this._setLineText(position.lineNumber - 1,
|
||||
this._lines[position.lineNumber - 1].substring(0, position.column - 1)
|
||||
+ insertLines[0]
|
||||
+ this._lines[position.lineNumber - 1].substring(position.column - 1)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Append overflowing text from first line to the end of text to insert
|
||||
insertLines[insertLines.length - 1] += this._lines[position.lineNumber - 1].substring(position.column - 1);
|
||||
|
||||
// Delete overflowing text from first line and insert text on first line
|
||||
this._setLineText(position.lineNumber - 1,
|
||||
this._lines[position.lineNumber - 1].substring(0, position.column - 1)
|
||||
+ insertLines[0]
|
||||
);
|
||||
|
||||
// Insert new lines & store lengths
|
||||
let newLengths:number[] = new Array<number>(insertLines.length - 1);
|
||||
for (let i = 1; i < insertLines.length; i++) {
|
||||
this._lines.splice(position.lineNumber + i - 1, 0, insertLines[i]);
|
||||
newLengths[i - 1] = insertLines[i].length + this._eol.length;
|
||||
}
|
||||
|
||||
if (this._lineStarts) {
|
||||
// update prefix sum
|
||||
this._lineStarts.insertValues(position.lineNumber, newLengths);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import {EditableTextModel, IValidatedEditOperation} from 'vs/editor/common/model
|
|||
import {TextModel} from 'vs/editor/common/model/textModel';
|
||||
import {LineMarker, TextModelWithMarkers} from 'vs/editor/common/model/textModelWithMarkers';
|
||||
import {ILineMarker} from 'vs/editor/common/model/modelLine';
|
||||
import {ExtHostDocument} from 'vs/workbench/api/common/extHostDocuments';
|
||||
import {MirrorModel2} from 'vs/editor/common/model/mirrorModel2';
|
||||
import {MirrorModel, IMirrorModelEvents} from 'vs/editor/common/model/mirrorModel';
|
||||
|
||||
suite('EditorModel - EditableTextModel._getInverseEdits', () => {
|
||||
|
@ -1185,7 +1185,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => {
|
|||
var mirrorModel1 = new MirrorModel(null, model.getVersionId(), model.toRawText(), null);
|
||||
var mirrorModel1PrevVersionId = model.getVersionId();
|
||||
|
||||
var mirrorModel2 = new ExtHostDocument(null, null, model.toRawText().lines, model.toRawText().EOL, null, model.getVersionId(), false);
|
||||
var mirrorModel2 = new MirrorModel2(null, model.toRawText().lines, model.toRawText().EOL, model.getVersionId());
|
||||
var mirrorModel2PrevVersionId = model.getVersionId();
|
||||
|
||||
model.addListener(EditorCommon.EventType.ModelContentChanged, (e:EditorCommon.IModelContentChangedEvent) => {
|
||||
|
@ -1207,7 +1207,7 @@ suite('EditorModel - EditableTextModel.applyEdits', () => {
|
|||
console.warn('Model version id did not advance between edits (2)');
|
||||
}
|
||||
mirrorModel2PrevVersionId = versionId;
|
||||
mirrorModel2._acceptEvents([e]);
|
||||
mirrorModel2.onEvents([e]);
|
||||
});
|
||||
|
||||
var assertMirrorModels = () => {
|
||||
|
|
22
src/vs/vscode.d.ts
vendored
22
src/vs/vscode.d.ts
vendored
|
@ -1017,6 +1017,23 @@ declare namespace vscode {
|
|||
onDidDelete: Event<Uri>;
|
||||
}
|
||||
|
||||
export interface TextDocumentContentProvider {
|
||||
|
||||
/**
|
||||
* An event to signal a resource has changed.
|
||||
*/
|
||||
onDidChange?: Event<Uri>;
|
||||
|
||||
/**
|
||||
* Provide textual content for a given uri.
|
||||
*
|
||||
* @param uri An uri which scheme matches the scheme this provider was [registered](#workspace.registerTextDocumentContentProvider) for.
|
||||
* @param token A cancellation token.
|
||||
* @return A string or a thenable that resolves to such.
|
||||
*/
|
||||
provideTextDocumentContent(uri: Uri, token: CancellationToken): string | Thenable<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an item that can be selected from
|
||||
* a list of items.
|
||||
|
@ -3004,6 +3021,11 @@ declare namespace vscode {
|
|||
*/
|
||||
export function openTextDocument(fileName: string): Thenable<TextDocument>;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export function registerTextDocumentContentProvider(scheme: string, provider: TextDocumentContentProvider): Disposable;
|
||||
|
||||
/**
|
||||
* An event that is emitted when a [text document](#TextDocument) is opened.
|
||||
*/
|
||||
|
|
|
@ -8,21 +8,21 @@ import {IBracketElectricCharacterContribution} from 'vs/editor/common/modes/supp
|
|||
import {score} from 'vs/editor/common/modes/languageSelector';
|
||||
import {Remotable, IThreadService} from 'vs/platform/thread/common/thread';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import {ExtHostFileSystemEventService} from 'vs/workbench/api/common/extHostFileSystemEventService';
|
||||
import {ExtHostModelService, setWordDefinitionFor} from 'vs/workbench/api/common/extHostDocuments';
|
||||
import {ExtHostConfiguration} from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import {ExtHostDiagnostics} from 'vs/workbench/api/common/extHostDiagnostics';
|
||||
import {ExtHostWorkspace} from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import {ExtHostQuickOpen} from 'vs/workbench/api/common/extHostQuickOpen';
|
||||
import {ExtHostStatusBar} from 'vs/workbench/api/common/extHostStatusBar';
|
||||
import {ExtHostCommands} from 'vs/workbench/api/common/extHostCommands';
|
||||
import {ExtHostOutputService} from 'vs/workbench/api/common/extHostOutputService';
|
||||
import {ExtHostMessageService} from 'vs/workbench/api/common/extHostMessageService';
|
||||
import {ExtHostEditors} from 'vs/workbench/api/common/extHostEditors';
|
||||
import {ExtHostLanguages} from 'vs/workbench/api/common/extHostLanguages';
|
||||
import {ExtHostLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import {registerApiCommands} from 'vs/workbench/api/common/extHostApiCommands';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import {ExtHostFileSystemEventService} from 'vs/workbench/api/node/extHostFileSystemEventService';
|
||||
import {ExtHostModelService, setWordDefinitionFor} from 'vs/workbench/api/node/extHostDocuments';
|
||||
import {ExtHostConfiguration} from 'vs/workbench/api/node/extHostConfiguration';
|
||||
import {ExtHostDiagnostics} from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import {ExtHostWorkspace} from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import {ExtHostQuickOpen} from 'vs/workbench/api/node/extHostQuickOpen';
|
||||
import {ExtHostStatusBar} from 'vs/workbench/api/node/extHostStatusBar';
|
||||
import {ExtHostCommands} from 'vs/workbench/api/node/extHostCommands';
|
||||
import {ExtHostOutputService} from 'vs/workbench/api/node/extHostOutputService';
|
||||
import {ExtHostMessageService} from 'vs/workbench/api/node/extHostMessageService';
|
||||
import {ExtHostEditors} from 'vs/workbench/api/node/extHostEditors';
|
||||
import {ExtHostLanguages} from 'vs/workbench/api/node/extHostLanguages';
|
||||
import {ExtHostLanguageFeatures} from 'vs/workbench/api/node/extHostLanguageFeatures';
|
||||
import {registerApiCommands} from 'vs/workbench/api/node/extHostApiCommands';
|
||||
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
|
||||
import Modes = require('vs/editor/common/modes');
|
||||
import {IModeService} from 'vs/editor/common/services/modeService';
|
||||
import {ICommentsSupportContribution, ITokenTypeClassificationSupportContribution} from 'vs/editor/common/modes/supports';
|
||||
|
@ -37,7 +37,7 @@ import {TPromise} from 'vs/base/common/winjs.base';
|
|||
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
|
||||
import {CancellationTokenSource} from 'vs/base/common/cancellation';
|
||||
import vscode = require('vscode');
|
||||
import {TextEditorRevealType} from 'vs/workbench/api/common/mainThreadEditors';
|
||||
import {TextEditorRevealType} from 'vs/workbench/api/node/mainThreadEditors';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
|
||||
/**
|
||||
|
@ -244,16 +244,27 @@ export class ExtHostAPIImplementation {
|
|||
return pluginHostFileSystemEvent.createFileSystemWatcher(pattern, ignoreCreate, ignoreChange, ignoreDelete);
|
||||
},
|
||||
get textDocuments() {
|
||||
return pluginHostDocuments.getDocuments();
|
||||
return pluginHostDocuments.getAllDocumentData().map(data => data.document);
|
||||
},
|
||||
set textDocuments(value) {
|
||||
throw errors.readonly();
|
||||
},
|
||||
// createTextDocument(text: string, fileName?: string, language?: string): Thenable<vscode.TextDocument> {
|
||||
// return pluginHostDocuments.createDocument(text, fileName, language);
|
||||
// },
|
||||
openTextDocument(uriOrFileName:vscode.Uri | string) {
|
||||
return pluginHostDocuments.openDocument(uriOrFileName);
|
||||
openTextDocument(uriOrFileName: vscode.Uri | string) {
|
||||
let uri: URI;
|
||||
if (typeof uriOrFileName === 'string') {
|
||||
uri = URI.file(uriOrFileName);
|
||||
} else if (uriOrFileName instanceof URI) {
|
||||
uri = <URI>uriOrFileName;
|
||||
} else {
|
||||
throw new Error('illegal argument - uriOrFileName');
|
||||
}
|
||||
return pluginHostDocuments.ensureDocumentData(uri).then(() => {
|
||||
const data = pluginHostDocuments.getDocumentData(uri);
|
||||
return data && data.document;
|
||||
});
|
||||
},
|
||||
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {
|
||||
return pluginHostDocuments.registerTextDocumentContentProvider(scheme, provider);
|
||||
},
|
||||
onDidOpenTextDocument: (listener, thisArgs?, disposables?) => {
|
||||
return pluginHostDocuments.onDidAddDocument(listener, thisArgs, disposables);
|
|
@ -8,12 +8,12 @@ import URI from 'vs/base/common/uri';
|
|||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
||||
import * as vscode from 'vscode';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import * as types from 'vs/workbench/api/node/extHostTypes';
|
||||
import {ISingleEditOperation} from 'vs/editor/common/editorCommon';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import {ICommandHandlerDescription} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {ExtHostCommands} from 'vs/workbench/api/common/extHostCommands';
|
||||
import {ExtHostCommands} from 'vs/workbench/api/node/extHostCommands';
|
||||
import {IQuickFix2} from 'vs/editor/contrib/quickFix/common/quickFix';
|
||||
import {IOutline} from 'vs/editor/contrib/quickOpen/common/quickOpen';
|
||||
import {ITypeBearing} from 'vs/workbench/parts/search/common/search';
|
|
@ -9,9 +9,9 @@ import {validateConstraint} from 'vs/base/common/types';
|
|||
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import {IKeybindingService, ICommandHandlerDescription} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {ExtHostEditors} from 'vs/workbench/api/common/extHostEditors';
|
||||
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as extHostTypeConverter from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import {ExtHostEditors} from 'vs/workbench/api/node/extHostEditors';
|
||||
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
|
||||
import * as extHostTypeConverter from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import {cloneAndChange} from 'vs/base/common/objects';
|
||||
|
||||
interface CommandHandler {
|
|
@ -7,15 +7,16 @@
|
|||
import {toErrorMessage} from 'vs/base/common/errors';
|
||||
import {IEmitterEvent} from 'vs/base/common/eventEmitter';
|
||||
import {IModelService} from 'vs/editor/common/services/modelService';
|
||||
import {PrefixSumComputer, IPrefixSumIndexOfResult} from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
import * as EditorCommon from 'vs/editor/common/editorCommon';
|
||||
import {IPrefixSumIndexOfResult} from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
import {MirrorModel2} from 'vs/editor/common/model/mirrorModel2';
|
||||
import {Remotable, IThreadService} from 'vs/platform/thread/common/thread';
|
||||
import Event, {Emitter} from 'vs/base/common/event';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import {IDisposable, disposeAll} from 'vs/base/common/lifecycle';
|
||||
import {Range, Position} from 'vs/workbench/api/common/extHostTypes';
|
||||
import {Range, Position, Disposable} from 'vs/workbench/api/node/extHostTypes';
|
||||
import {IEventService} from 'vs/platform/event/common/event';
|
||||
import {IEditorService} from 'vs/platform/editor/common/editor';
|
||||
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
|
||||
import {EventType as FileEventType, LocalFileChangeEvent, ITextFileService} from 'vs/workbench/parts/files/common/files';
|
||||
import * as TypeConverters from './extHostTypeConverters';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
|
@ -23,6 +24,13 @@ import * as vscode from 'vscode';
|
|||
import {WordHelper} from 'vs/editor/common/model/textModelWithTokensHelpers';
|
||||
import {IFileService} from 'vs/platform/files/common/files';
|
||||
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
import {asWinJsPromise} from 'vs/base/common/async';
|
||||
import {EditorModel, EditorInput} from 'vs/workbench/common/editor';
|
||||
import {IEditorInput, IResourceInput} from 'vs/platform/editor/common/editor';
|
||||
import {IMode} from 'vs/editor/common/modes';
|
||||
import {IModeService} from 'vs/editor/common/services/modeService';
|
||||
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
|
||||
import * as weak from 'weak';
|
||||
|
||||
export interface IModelAddedData {
|
||||
url: URI;
|
||||
|
@ -47,127 +55,157 @@ export function getWordDefinitionFor(modeId:string):RegExp {
|
|||
@Remotable.PluginHostContext('ExtHostModelService')
|
||||
export class ExtHostModelService {
|
||||
|
||||
private _onDidAddDocumentEventEmitter: Emitter<BaseTextDocument>;
|
||||
public onDidAddDocument: Event<BaseTextDocument>;
|
||||
private _onDidAddDocumentEventEmitter: Emitter<vscode.TextDocument>;
|
||||
public onDidAddDocument: Event<vscode.TextDocument>;
|
||||
|
||||
private _onDidRemoveDocumentEventEmitter: Emitter<BaseTextDocument>;
|
||||
public onDidRemoveDocument: Event<BaseTextDocument>;
|
||||
private _onDidRemoveDocumentEventEmitter: Emitter<vscode.TextDocument>;
|
||||
public onDidRemoveDocument: Event<vscode.TextDocument>;
|
||||
|
||||
private _onDidChangeDocumentEventEmitter: Emitter<vscode.TextDocumentChangeEvent>;
|
||||
public onDidChangeDocument: Event<vscode.TextDocumentChangeEvent>;
|
||||
|
||||
private _onDidSaveDocumentEventEmitter: Emitter<BaseTextDocument>;
|
||||
public onDidSaveDocument: Event<BaseTextDocument>;
|
||||
private _onDidSaveDocumentEventEmitter: Emitter<vscode.TextDocument>;
|
||||
public onDidSaveDocument: Event<vscode.TextDocument>;
|
||||
|
||||
private _documents: {[modelUri:string]:ExtHostDocument;};
|
||||
private _documentData: { [modelUri: string]: ExtHostDocumentData; };
|
||||
private _documentLoader: { [modelUri: string]: TPromise<ExtHostDocumentData> };
|
||||
private _documentContentProviders: { [scheme: string]: vscode.TextDocumentContentProvider };
|
||||
|
||||
private _proxy: MainThreadDocuments;
|
||||
|
||||
constructor(@IThreadService threadService: IThreadService) {
|
||||
this._proxy = threadService.getRemotable(MainThreadDocuments);
|
||||
|
||||
this._onDidAddDocumentEventEmitter = new Emitter<BaseTextDocument>();
|
||||
this._onDidAddDocumentEventEmitter = new Emitter<vscode.TextDocument>();
|
||||
this.onDidAddDocument = this._onDidAddDocumentEventEmitter.event;
|
||||
|
||||
this._onDidRemoveDocumentEventEmitter = new Emitter<BaseTextDocument>();
|
||||
this._onDidRemoveDocumentEventEmitter = new Emitter<vscode.TextDocument>();
|
||||
this.onDidRemoveDocument = this._onDidRemoveDocumentEventEmitter.event;
|
||||
|
||||
this._onDidChangeDocumentEventEmitter = new Emitter<vscode.TextDocumentChangeEvent>();
|
||||
this.onDidChangeDocument = this._onDidChangeDocumentEventEmitter.event;
|
||||
|
||||
this._onDidSaveDocumentEventEmitter = new Emitter<BaseTextDocument>();
|
||||
this._onDidSaveDocumentEventEmitter = new Emitter<vscode.TextDocument>();
|
||||
this.onDidSaveDocument = this._onDidSaveDocumentEventEmitter.event;
|
||||
|
||||
this._documents = Object.create(null);
|
||||
this._documentData = Object.create(null);
|
||||
this._documentLoader = Object.create(null);
|
||||
this._documentContentProviders = Object.create(null);
|
||||
}
|
||||
|
||||
public getDocuments(): BaseTextDocument[] {
|
||||
let r: BaseTextDocument[] = [];
|
||||
for (let key in this._documents) {
|
||||
r.push(this._documents[key]);
|
||||
public getAllDocumentData(): ExtHostDocumentData[] {
|
||||
const result: ExtHostDocumentData[] = [];
|
||||
for (let key in this._documentData) {
|
||||
result.push(this._documentData[key]);
|
||||
}
|
||||
return r;
|
||||
return result;
|
||||
}
|
||||
|
||||
public getDocument(resource: vscode.Uri): BaseTextDocument {
|
||||
public getDocumentData(resource: vscode.Uri): ExtHostDocumentData {
|
||||
if (!resource) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
const data = this._documentData[resource.toString()];
|
||||
if (data) {
|
||||
return data;
|
||||
}
|
||||
return this._documents[resource.toString()] || null;
|
||||
}
|
||||
|
||||
public openDocument(uriOrFileName: vscode.Uri | string): TPromise<vscode.TextDocument> {
|
||||
public ensureDocumentData(uri: URI): TPromise<ExtHostDocumentData> {
|
||||
|
||||
let uri: URI;
|
||||
if (typeof uriOrFileName === 'string') {
|
||||
uri = URI.file(uriOrFileName);
|
||||
} else if (uriOrFileName instanceof URI) {
|
||||
uri = <URI>uriOrFileName;
|
||||
} else {
|
||||
throw new Error('illegal argument - uriOrFileName');
|
||||
}
|
||||
|
||||
let cached = this._documents[uri.toString()];
|
||||
let cached = this._documentData[uri.toString()];
|
||||
if (cached) {
|
||||
return TPromise.as(cached);
|
||||
}
|
||||
return this._proxy._tryOpenDocument(uri).then(() => {
|
||||
return this._documents[uri.toString()];
|
||||
|
||||
let promise = this._documentLoader[uri.toString()];
|
||||
if (!promise) {
|
||||
promise = this._proxy._tryOpenDocument(uri).then(() => {
|
||||
delete this._documentLoader[uri.toString()];
|
||||
return this._documentData[uri.toString()];
|
||||
}, err => {
|
||||
delete this._documentLoader[uri.toString()];
|
||||
return TPromise.wrapError(err);
|
||||
});
|
||||
this._documentLoader[uri.toString()] = promise;
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
public registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider): vscode.Disposable {
|
||||
if (scheme === 'file' || scheme === 'untitled' || this._documentContentProviders[scheme]) {
|
||||
throw new Error(`scheme '${scheme}' already registered`);
|
||||
}
|
||||
this._documentContentProviders[scheme] = provider;
|
||||
return new Disposable(() => delete this._documentContentProviders[scheme]);
|
||||
}
|
||||
|
||||
$provideTextDocumentContent(uri: URI): TPromise<string> {
|
||||
const provider = this._documentContentProviders[uri.scheme];
|
||||
if (!provider) {
|
||||
return TPromise.wrapError<string>(`unsupported uri-scheme: ${uri.scheme}`);
|
||||
}
|
||||
return asWinJsPromise(token => provider.provideTextDocumentContent(uri, token)).then(value => {
|
||||
if (typeof value !== 'string') {
|
||||
return TPromise.wrapError('received illegal value from text document provider');
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
public _acceptModelAdd(data:IModelAddedData): void {
|
||||
let document = new ExtHostDocument(this._proxy, data.url, data.value.lines, data.value.EOL, data.modeId, data.versionId, data.isDirty);
|
||||
let key = document.uri.toString();
|
||||
if (this._documents[key]) {
|
||||
public _acceptModelAdd(initData:IModelAddedData): void {
|
||||
let data = new ExtHostDocumentData(this._proxy, initData.url, initData.value.lines, initData.value.EOL, initData.modeId, initData.versionId, initData.isDirty);
|
||||
let key = data.document.uri.toString();
|
||||
if (this._documentData[key]) {
|
||||
throw new Error('Document `' + key + '` already exists.');
|
||||
}
|
||||
this._documents[key] = document;
|
||||
this._onDidAddDocumentEventEmitter.fire(document);
|
||||
this._documentData[key] = data;
|
||||
this._onDidAddDocumentEventEmitter.fire(data.document);
|
||||
}
|
||||
|
||||
public _acceptModelModeChanged(url: URI, oldModeId:string, newModeId:string): void {
|
||||
let document = this._documents[url.toString()];
|
||||
let data = this._documentData[url.toString()];
|
||||
|
||||
// Treat a mode change as a remove + add
|
||||
|
||||
this._onDidRemoveDocumentEventEmitter.fire(document);
|
||||
document._acceptLanguageId(newModeId);
|
||||
this._onDidAddDocumentEventEmitter.fire(document);
|
||||
this._onDidRemoveDocumentEventEmitter.fire(data.document);
|
||||
data._acceptLanguageId(newModeId);
|
||||
this._onDidAddDocumentEventEmitter.fire(data.document);
|
||||
}
|
||||
|
||||
public _acceptModelSaved(url: URI): void {
|
||||
let document = this._documents[url.toString()];
|
||||
document._acceptIsDirty(false);
|
||||
this._onDidSaveDocumentEventEmitter.fire(document);
|
||||
let data = this._documentData[url.toString()];
|
||||
data._acceptIsDirty(false);
|
||||
this._onDidSaveDocumentEventEmitter.fire(data.document);
|
||||
}
|
||||
|
||||
public _acceptModelDirty(url: URI): void {
|
||||
let document = this._documents[url.toString()];
|
||||
let document = this._documentData[url.toString()];
|
||||
document._acceptIsDirty(true);
|
||||
}
|
||||
|
||||
public _acceptModelReverted(url: URI): void {
|
||||
let document = this._documents[url.toString()];
|
||||
let document = this._documentData[url.toString()];
|
||||
document._acceptIsDirty(false);
|
||||
}
|
||||
|
||||
public _acceptModelRemoved(url: URI): void {
|
||||
let key = url.toString();
|
||||
if (!this._documents[key]) {
|
||||
if (!this._documentData[key]) {
|
||||
throw new Error('Document `' + key + '` does not exist.');
|
||||
}
|
||||
let document = this._documents[key];
|
||||
delete this._documents[key];
|
||||
this._onDidRemoveDocumentEventEmitter.fire(document);
|
||||
document.dispose();
|
||||
let data = this._documentData[key];
|
||||
delete this._documentData[key];
|
||||
this._onDidRemoveDocumentEventEmitter.fire(data.document);
|
||||
data.dispose();
|
||||
}
|
||||
|
||||
public _acceptModelChanged(url: URI, events: EditorCommon.IModelContentChangedEvent2[]): void {
|
||||
let document = this._documents[url.toString()];
|
||||
document._acceptEvents(events);
|
||||
let data = this._documentData[url.toString()];
|
||||
data.onEvents(events);
|
||||
this._onDidChangeDocumentEventEmitter.fire({
|
||||
document: document,
|
||||
document: data.document,
|
||||
contentChanges: events.map((e) => {
|
||||
return {
|
||||
range: TypeConverters.toRange(e.range),
|
||||
|
@ -179,69 +217,72 @@ export class ExtHostModelService {
|
|||
}
|
||||
}
|
||||
|
||||
export class BaseTextDocument implements vscode.TextDocument {
|
||||
protected _uri: URI;
|
||||
protected _lines: string[];
|
||||
protected _eol: string;
|
||||
protected _languageId: string;
|
||||
protected _versionId: number;
|
||||
protected _isDirty: boolean;
|
||||
protected _textLines: vscode.TextLine[];
|
||||
protected _lineStarts: PrefixSumComputer;
|
||||
export class ExtHostDocumentData extends MirrorModel2 {
|
||||
|
||||
constructor(uri: URI, lines: string[], eol: string, languageId: string, versionId: number, isDirty:boolean) {
|
||||
this._uri = uri;
|
||||
this._lines = lines;
|
||||
this._textLines = [];
|
||||
this._eol = eol;
|
||||
private _proxy: MainThreadDocuments;
|
||||
private _languageId: string;
|
||||
private _isDirty: boolean;
|
||||
private _textLines: vscode.TextLine[];
|
||||
private _documentRef: weak.WeakRef & vscode.TextDocument;
|
||||
|
||||
constructor(proxy: MainThreadDocuments, uri: URI, lines: string[], eol: string,
|
||||
languageId: string, versionId: number, isDirty: boolean) {
|
||||
|
||||
super(uri, lines, eol, versionId);
|
||||
this._proxy = proxy;
|
||||
this._languageId = languageId;
|
||||
this._versionId = versionId;
|
||||
this._isDirty = isDirty;
|
||||
this._textLines = [];
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._lines.length = 0;
|
||||
this._textLines.length = 0;
|
||||
this._isDirty = false;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
get uri(): URI {
|
||||
return this._uri;
|
||||
}
|
||||
get document(): vscode.TextDocument {
|
||||
// dereferences or creates the actual document for this
|
||||
// document data. keeps a weak reference only such that
|
||||
// we later when a document isn't needed anymore
|
||||
|
||||
get fileName(): string {
|
||||
return this._uri.fsPath;
|
||||
}
|
||||
|
||||
get isUntitled(): boolean {
|
||||
return this._uri.scheme !== 'file';
|
||||
}
|
||||
|
||||
get languageId(): string {
|
||||
return this._languageId;
|
||||
}
|
||||
|
||||
get version(): number {
|
||||
return this._versionId;
|
||||
}
|
||||
|
||||
get isDirty(): boolean {
|
||||
return this._isDirty;
|
||||
}
|
||||
|
||||
save(): Thenable<boolean> {
|
||||
return Promise.reject<boolean>('Not implemented');
|
||||
}
|
||||
|
||||
getText(range?: Range): string {
|
||||
if (range) {
|
||||
return this._getTextInRange(range);
|
||||
} else {
|
||||
return this._lines.join(this._eol);
|
||||
if (!this.isDocumentReferenced) {
|
||||
const data = this;
|
||||
const doc = {
|
||||
get uri() { return data._uri },
|
||||
get fileName() { return data._uri.fsPath },
|
||||
get isUntitled() { return data._uri.scheme !== 'file' },
|
||||
get languageId() { return data._languageId },
|
||||
get version() { return data._versionId },
|
||||
get isDirty() { return data._isDirty },
|
||||
save() { return data._proxy._trySaveDocument(data._uri) },
|
||||
getText(range?) { return range ? data._getTextInRange(range) : data.getText() },
|
||||
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) { return data.getWordRangeAtPosition(pos) }
|
||||
};
|
||||
this._documentRef = weak(doc);
|
||||
}
|
||||
return weak.get(this._documentRef);
|
||||
}
|
||||
|
||||
private _getTextInRange(_range: Range): string {
|
||||
get isDocumentReferenced(): boolean {
|
||||
return this._documentRef && !weak.isDead(this._documentRef);
|
||||
}
|
||||
|
||||
_acceptLanguageId(newLanguageId:string): void {
|
||||
this._languageId = newLanguageId;
|
||||
}
|
||||
|
||||
_acceptIsDirty(isDirty:boolean): void {
|
||||
this._isDirty = isDirty;
|
||||
}
|
||||
|
||||
private _getTextInRange(_range: vscode.Range): string {
|
||||
let range = this.validateRange(_range);
|
||||
|
||||
if (range.isEmpty) {
|
||||
|
@ -266,10 +307,6 @@ export class BaseTextDocument implements vscode.TextDocument {
|
|||
return resultLines.join(lineEnding);
|
||||
}
|
||||
|
||||
get lineCount(): number {
|
||||
return this._lines.length;
|
||||
}
|
||||
|
||||
lineAt(lineOrPosition: number | vscode.Position): vscode.TextLine {
|
||||
|
||||
let line: number;
|
||||
|
@ -306,13 +343,13 @@ export class BaseTextDocument implements vscode.TextDocument {
|
|||
return result;
|
||||
}
|
||||
|
||||
offsetAt(position: Position): number {
|
||||
offsetAt(position: vscode.Position): number {
|
||||
position = this.validatePosition(position);
|
||||
this._ensureLineStarts();
|
||||
return this._lineStarts.getAccumulatedValue(position.line - 1) + position.character;
|
||||
}
|
||||
|
||||
positionAt(offset: number): Position {
|
||||
positionAt(offset: number): vscode.Position {
|
||||
offset = Math.floor(offset);
|
||||
offset = Math.max(0, offset);
|
||||
|
||||
|
@ -326,20 +363,9 @@ export class BaseTextDocument implements vscode.TextDocument {
|
|||
return new Position(out.index, Math.min(out.remainder, lineLength));
|
||||
}
|
||||
|
||||
private _ensureLineStarts(): void {
|
||||
if (!this._lineStarts) {
|
||||
const lineStartValues:number[] = [];
|
||||
const eolLength = this._eol.length;
|
||||
for (let i = 0, len = this._lines.length; i < len; i++) {
|
||||
lineStartValues.push(this._lines[i].length + eolLength);
|
||||
}
|
||||
this._lineStarts = new PrefixSumComputer(lineStartValues);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- range math
|
||||
|
||||
validateRange(range:Range): Range {
|
||||
validateRange(range:vscode.Range): vscode.Range {
|
||||
if (!(range instanceof Range)) {
|
||||
throw new Error('Invalid argument');
|
||||
}
|
||||
|
@ -350,10 +376,10 @@ export class BaseTextDocument implements vscode.TextDocument {
|
|||
if (start === range.start && end === range.end) {
|
||||
return range;
|
||||
}
|
||||
return new Range(start, end);
|
||||
return new Range(start.line, start.character, end.line, end.character);
|
||||
}
|
||||
|
||||
validatePosition(position:Position): Position {
|
||||
validatePosition(position:vscode.Position): vscode.Position {
|
||||
if (!(position instanceof Position)) {
|
||||
throw new Error('Invalid argument');
|
||||
}
|
||||
|
@ -388,7 +414,7 @@ export class BaseTextDocument implements vscode.TextDocument {
|
|||
return new Position(line, character);
|
||||
}
|
||||
|
||||
getWordRangeAtPosition(_position:Position): Range {
|
||||
getWordRangeAtPosition(_position: vscode.Position): vscode.Range {
|
||||
let position = this.validatePosition(_position);
|
||||
|
||||
let wordAtText = WordHelper._getWordAtText(
|
||||
|
@ -404,129 +430,12 @@ export class BaseTextDocument implements vscode.TextDocument {
|
|||
}
|
||||
}
|
||||
|
||||
export class ExtHostDocument extends BaseTextDocument {
|
||||
|
||||
private _proxy: MainThreadDocuments;
|
||||
|
||||
constructor(proxy: MainThreadDocuments, uri: URI, lines: string[],
|
||||
eol: string, languageId: string, versionId: number, isDirty:boolean) {
|
||||
super(uri, lines, eol, languageId, versionId, isDirty);
|
||||
this._proxy = proxy;
|
||||
}
|
||||
|
||||
save(): Thenable<boolean> {
|
||||
return this._proxy._trySaveDocument(this._uri);
|
||||
}
|
||||
|
||||
_acceptLanguageId(newLanguageId:string): void {
|
||||
this._languageId = newLanguageId;
|
||||
}
|
||||
|
||||
_acceptIsDirty(isDirty:boolean): void {
|
||||
this._isDirty = isDirty;
|
||||
}
|
||||
|
||||
_acceptEvents(events: EditorCommon.IModelContentChangedEvent2[]): void {
|
||||
// Update my lines
|
||||
let lastVersionId = -1;
|
||||
for (let i = 0, len = events.length; i < len; i++) {
|
||||
let e = events[i];
|
||||
|
||||
this._acceptDeleteRange(e.range);
|
||||
this._acceptInsertText({
|
||||
lineNumber: e.range.startLineNumber,
|
||||
column: e.range.startColumn
|
||||
}, e.text);
|
||||
lastVersionId = Math.max(lastVersionId, e.versionId);
|
||||
}
|
||||
if (lastVersionId !== -1) {
|
||||
this._versionId = lastVersionId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All changes to a line's text go through this method
|
||||
*/
|
||||
private _setLineText(lineIndex:number, newValue:string): void {
|
||||
this._lines[lineIndex] = newValue;
|
||||
if (this._lineStarts) {
|
||||
// update prefix sum
|
||||
this._lineStarts.changeValue(lineIndex, this._lines[lineIndex].length + this._eol.length);
|
||||
}
|
||||
}
|
||||
|
||||
private _acceptDeleteRange(range: EditorCommon.IRange): void {
|
||||
|
||||
if (range.startLineNumber === range.endLineNumber) {
|
||||
if (range.startColumn === range.endColumn) {
|
||||
// Nothing to delete
|
||||
return;
|
||||
}
|
||||
// Delete text on the affected line
|
||||
this._setLineText(range.startLineNumber - 1,
|
||||
this._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)
|
||||
+ this._lines[range.startLineNumber - 1].substring(range.endColumn - 1)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Take remaining text on last line and append it to remaining text on first line
|
||||
this._setLineText(range.startLineNumber - 1,
|
||||
this._lines[range.startLineNumber - 1].substring(0, range.startColumn - 1)
|
||||
+ this._lines[range.endLineNumber - 1].substring(range.endColumn - 1)
|
||||
);
|
||||
|
||||
// Delete middle lines
|
||||
this._lines.splice(range.startLineNumber, range.endLineNumber - range.startLineNumber);
|
||||
if (this._lineStarts) {
|
||||
// update prefix sum
|
||||
this._lineStarts.removeValues(range.startLineNumber, range.endLineNumber - range.startLineNumber);
|
||||
}
|
||||
}
|
||||
|
||||
private _acceptInsertText(position: EditorCommon.IPosition, insertText:string): void {
|
||||
if (insertText.length === 0) {
|
||||
// Nothing to insert
|
||||
return;
|
||||
}
|
||||
let insertLines = insertText.split(/\r\n|\r|\n/);
|
||||
if (insertLines.length === 1) {
|
||||
// Inserting text on one line
|
||||
this._setLineText(position.lineNumber - 1,
|
||||
this._lines[position.lineNumber - 1].substring(0, position.column - 1)
|
||||
+ insertLines[0]
|
||||
+ this._lines[position.lineNumber - 1].substring(position.column - 1)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Append overflowing text from first line to the end of text to insert
|
||||
insertLines[insertLines.length - 1] += this._lines[position.lineNumber - 1].substring(position.column - 1);
|
||||
|
||||
// Delete overflowing text from first line and insert text on first line
|
||||
this._setLineText(position.lineNumber - 1,
|
||||
this._lines[position.lineNumber - 1].substring(0, position.column - 1)
|
||||
+ insertLines[0]
|
||||
);
|
||||
|
||||
// Insert new lines & store lengths
|
||||
let newLengths:number[] = new Array<number>(insertLines.length - 1);
|
||||
for (let i = 1; i < insertLines.length; i++) {
|
||||
this._lines.splice(position.lineNumber + i - 1, 0, insertLines[i]);
|
||||
newLengths[i - 1] = insertLines[i].length + this._eol.length;
|
||||
}
|
||||
|
||||
if (this._lineStarts) {
|
||||
// update prefix sum
|
||||
this._lineStarts.insertValues(position.lineNumber, newLengths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Remotable.MainContext('MainThreadDocuments')
|
||||
export class MainThreadDocuments {
|
||||
private _modelService: IModelService;
|
||||
private _modeService: IModeService;
|
||||
private _textFileService: ITextFileService;
|
||||
private _editorService: IEditorService;
|
||||
private _editorService: IWorkbenchEditorService;
|
||||
private _fileService: IFileService;
|
||||
private _untitledEditorService: IUntitledEditorService;
|
||||
private _toDispose: IDisposable[];
|
||||
|
@ -536,13 +445,16 @@ export class MainThreadDocuments {
|
|||
|
||||
constructor(
|
||||
@IThreadService threadService: IThreadService,
|
||||
@IModelService modelService:IModelService,
|
||||
@IModelService modelService: IModelService,
|
||||
@IModeService modeService: IModeService,
|
||||
@IEventService eventService:IEventService,
|
||||
@ITextFileService textFileService: ITextFileService,
|
||||
@IEditorService editorService: IEditorService,
|
||||
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
|
||||
@IFileService fileService: IFileService,
|
||||
@IUntitledEditorService untitledEditorService: IUntitledEditorService
|
||||
) {
|
||||
this._modelService = modelService;
|
||||
this._modeService = modeService;
|
||||
this._textFileService = textFileService;
|
||||
this._editorService = editorService;
|
||||
this._fileService = fileService;
|
||||
|
@ -650,7 +562,7 @@ export class MainThreadDocuments {
|
|||
promise = this._handleUnititledScheme(uri);
|
||||
break;
|
||||
default:
|
||||
promise = TPromise.wrapError<boolean>('unsupported URI-scheme: ' + uri.scheme);
|
||||
promise = this._handleAnyScheme(uri);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -686,4 +598,20 @@ export class MainThreadDocuments {
|
|||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _handleAnyScheme(uri: URI): TPromise<boolean> {
|
||||
|
||||
if (this._modelService.getModel(uri)) {
|
||||
return TPromise.as(true);
|
||||
}
|
||||
|
||||
return this._proxy.$provideTextDocumentContent(uri).then(value => {
|
||||
const firstLineText = value.substr(0, 1 + value.search(/\r?\n/));
|
||||
const mode = this._modeService.getOrCreateModeByFilenameOrFirstLine(uri.fsPath, firstLineText);
|
||||
return this._modelService.createModel(value, mode, uri);
|
||||
|
||||
}).then(() => {
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -9,17 +9,18 @@ import Event, {Emitter} from 'vs/base/common/event';
|
|||
import {IDisposable, disposeAll} from 'vs/base/common/lifecycle';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {Remotable, IThreadService} from 'vs/platform/thread/common/thread';
|
||||
import {ExtHostModelService} from 'vs/workbench/api/common/extHostDocuments';
|
||||
import {ExtHostModelService, ExtHostDocumentData} from 'vs/workbench/api/node/extHostDocuments';
|
||||
import {Selection, Range, Position, EditorOptions} from './extHostTypes';
|
||||
import {ISingleEditOperation, ISelection, IRange, IInternalIndentationOptions, IEditor, EditorType, ICommonCodeEditor, ICommonDiffEditor, IDecorationRenderOptions, IRangeWithMessage} from 'vs/editor/common/editorCommon';
|
||||
import {ICodeEditorService} from 'vs/editor/common/services/codeEditorService';
|
||||
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
|
||||
import {IEditor as IPlatformEditor, Position as EditorPosition} from 'vs/platform/editor/common/editor';
|
||||
import {IModelService} from 'vs/editor/common/services/modelService';
|
||||
import {MainThreadEditorsTracker, TextEditorRevealType, MainThreadTextEditor, ITextEditorConfiguration} from 'vs/workbench/api/common/mainThreadEditors';
|
||||
import {MainThreadEditorsTracker, TextEditorRevealType, MainThreadTextEditor, ITextEditorConfiguration} from 'vs/workbench/api/node/mainThreadEditors';
|
||||
import * as TypeConverters from './extHostTypeConverters';
|
||||
import {TextDocument, TextEditorSelectionChangeEvent, TextEditorOptionsChangeEvent, TextEditorOptions, ViewColumn} from 'vscode';
|
||||
import {EventType} from 'vs/workbench/common/events';
|
||||
import {EditorOptions as WorkbenchEditorOptions} from 'vs/workbench/common/editor';
|
||||
import {IEventService} from 'vs/platform/event/common/event';
|
||||
import {equals as arrayEquals} from 'vs/base/common/arrays';
|
||||
|
||||
|
@ -93,7 +94,7 @@ export class ExtHostEditors {
|
|||
// --- called from main thread
|
||||
|
||||
_acceptTextEditorAdd(data:ITextEditorAddData): void {
|
||||
let document = this._modelService.getDocument(data.document);
|
||||
let document = this._modelService.getDocumentData(data.document);
|
||||
let newEditor = new ExtHostTextEditor(this._proxy, data.id, document, data.selections.map(TypeConverters.toSelection), data.options);
|
||||
this._editors[data.id] = newEditor;
|
||||
}
|
||||
|
@ -267,20 +268,20 @@ class ExtHostTextEditor implements vscode.TextEditor {
|
|||
private _proxy: MainThreadEditors;
|
||||
private _id: string;
|
||||
|
||||
private _document: vscode.TextDocument;
|
||||
private _documentData: ExtHostDocumentData;
|
||||
private _selections: Selection[];
|
||||
private _options: TextEditorOptions;
|
||||
|
||||
constructor(proxy: MainThreadEditors, id: string, document: TextDocument, selections: Selection[], options: EditorOptions) {
|
||||
constructor(proxy: MainThreadEditors, id: string, document: ExtHostDocumentData, selections: Selection[], options: EditorOptions) {
|
||||
this._proxy = proxy;
|
||||
this._id = id;
|
||||
this._document = document;
|
||||
this._documentData = document;
|
||||
this._selections = selections;
|
||||
this._options = options;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._document = null;
|
||||
this._documentData = null;
|
||||
}
|
||||
|
||||
@deprecated('TextEditor.show') show(column: vscode.ViewColumn) {
|
||||
|
@ -294,7 +295,7 @@ class ExtHostTextEditor implements vscode.TextEditor {
|
|||
// ---- the document
|
||||
|
||||
get document(): vscode.TextDocument {
|
||||
return this._document;
|
||||
return this._documentData.document;
|
||||
}
|
||||
|
||||
set document(value) {
|
||||
|
@ -378,7 +379,7 @@ class ExtHostTextEditor implements vscode.TextEditor {
|
|||
// ---- editing
|
||||
|
||||
edit(callback:(edit:TextEditorEdit)=>void): Thenable<boolean> {
|
||||
let edit = new TextEditorEdit(this._document);
|
||||
let edit = new TextEditorEdit(this._documentData.document);
|
||||
callback(edit);
|
||||
return this._applyEdit(edit);
|
||||
}
|
||||
|
@ -527,8 +528,7 @@ export class MainThreadEditors {
|
|||
|
||||
_tryShowTextDocument(resource: URI, position: EditorPosition, preserveFocus: boolean): TPromise<string> {
|
||||
|
||||
// the input we want to open
|
||||
let input = {
|
||||
const input = {
|
||||
resource,
|
||||
options: { preserveFocus }
|
||||
};
|
|
@ -11,14 +11,14 @@ import {IDisposable, disposeAll} from 'vs/base/common/lifecycle';
|
|||
import {Remotable, IThreadService} from 'vs/platform/thread/common/thread';
|
||||
import {Range as EditorRange} from 'vs/editor/common/core/range';
|
||||
import * as vscode from 'vscode';
|
||||
import * as TypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import {Range, DocumentHighlightKind, Disposable, Diagnostic, SignatureHelp} from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import {Range, DocumentHighlightKind, Disposable, Diagnostic, SignatureHelp} from 'vs/workbench/api/node/extHostTypes';
|
||||
import {IPosition, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import {CancellationTokenSource} from 'vs/base/common/cancellation';
|
||||
import {ExtHostModelService} from 'vs/workbench/api/common/extHostDocuments';
|
||||
import {ExtHostModelService} from 'vs/workbench/api/node/extHostDocuments';
|
||||
import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers';
|
||||
import {ExtHostCommands} from 'vs/workbench/api/common/extHostCommands';
|
||||
import {ExtHostCommands} from 'vs/workbench/api/node/extHostCommands';
|
||||
import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration';
|
||||
import {ExtraInfoRegistry} from 'vs/editor/contrib/hover/common/hover';
|
||||
import {OccurrencesRegistry} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter';
|
||||
|
@ -31,24 +31,7 @@ import {FormatRegistry, FormatOnTypeRegistry} from 'vs/editor/contrib/format/com
|
|||
import {CodeLensRegistry} from 'vs/editor/contrib/codelens/common/codelens';
|
||||
import {ParameterHintsRegistry} from 'vs/editor/contrib/parameterHints/common/parameterHints';
|
||||
import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest';
|
||||
|
||||
function isThenable<T>(obj: any): obj is Thenable<T> {
|
||||
return obj && typeof (<Thenable<any>>obj).then === 'function';
|
||||
}
|
||||
|
||||
function asWinJsPromise<T>(callback: (token: vscode.CancellationToken) => T | Thenable<T>): TPromise<T> {
|
||||
let source = new CancellationTokenSource();
|
||||
return new TPromise<T>((resolve, reject) => {
|
||||
let item = callback(source.token);
|
||||
if (isThenable<T>(item)) {
|
||||
item.then(resolve, reject);
|
||||
} else {
|
||||
resolve(item);
|
||||
}
|
||||
}, () => {
|
||||
source.cancel();
|
||||
});
|
||||
}
|
||||
import {asWinJsPromise} from 'vs/base/common/async';
|
||||
|
||||
// --- adapter
|
||||
|
||||
|
@ -63,7 +46,7 @@ class OutlineAdapter implements IOutlineSupport {
|
|||
}
|
||||
|
||||
getOutline(resource: URI): TPromise<IOutlineEntry[]> {
|
||||
let doc = this._documents.getDocument(resource);
|
||||
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);
|
||||
|
@ -93,7 +76,7 @@ class CodeLensAdapter implements modes.ICodeLensSupport {
|
|||
}
|
||||
|
||||
findCodeLensSymbols(resource: URI): TPromise<modes.ICodeLensSymbol[]> {
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
const version = doc.version;
|
||||
const key = resource.toString();
|
||||
|
||||
|
@ -197,7 +180,7 @@ class DeclarationAdapter implements modes.IDeclarationSupport {
|
|||
}
|
||||
|
||||
findDeclaration(resource: URI, position: IPosition): TPromise<modes.IReference[]> {
|
||||
let doc = this._documents.getDocument(resource);
|
||||
let doc = this._documents.getDocumentData(resource).document;
|
||||
let pos = TypeConverters.toPosition(position);
|
||||
return asWinJsPromise(token => this._provider.provideDefinition(doc, pos, token)).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
|
@ -231,7 +214,7 @@ class ExtraInfoAdapter implements modes.IExtraInfoSupport {
|
|||
|
||||
computeInfo(resource: URI, position: IPosition): TPromise<modes.IComputeExtraInfoResult> {
|
||||
|
||||
let doc = this._documents.getDocument(resource);
|
||||
let doc = this._documents.getDocumentData(resource).document;
|
||||
let pos = TypeConverters.toPosition(position);
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideHover(doc, pos, token)).then(value => {
|
||||
|
@ -262,7 +245,7 @@ class OccurrencesAdapter implements modes.IOccurrencesSupport {
|
|||
|
||||
findOccurrences(resource: URI, position: IPosition): TPromise<modes.IOccurence[]> {
|
||||
|
||||
let doc = this._documents.getDocument(resource);
|
||||
let doc = this._documents.getDocumentData(resource).document;
|
||||
let pos = TypeConverters.toPosition(position);
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideDocumentHighlights(doc, pos, token)).then(value => {
|
||||
|
@ -295,7 +278,7 @@ class ReferenceAdapter implements modes.IReferenceSupport {
|
|||
}
|
||||
|
||||
findReferences(resource: URI, position: IPosition, includeDeclaration: boolean): TPromise<modes.IReference[]> {
|
||||
let doc = this._documents.getDocument(resource);
|
||||
let doc = this._documents.getDocumentData(resource).document;
|
||||
let pos = TypeConverters.toPosition(position);
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideReferences(doc, pos, { includeDeclaration }, token)).then(value => {
|
||||
|
@ -329,7 +312,7 @@ class QuickFixAdapter implements modes.IQuickFixSupport {
|
|||
|
||||
getQuickFixes(resource: URI, range: IRange, markers?: IMarker[]): TPromise<modes.IQuickFix[]> {
|
||||
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
const ran = TypeConverters.toRange(range);
|
||||
const diagnostics = markers.map(marker => {
|
||||
const diag = new Diagnostic(TypeConverters.toRange(marker), marker.message);
|
||||
|
@ -372,7 +355,7 @@ class DocumentFormattingAdapter implements modes.IFormattingSupport {
|
|||
|
||||
formatDocument(resource: URI, options: modes.IFormattingOptions): TPromise<ISingleEditOperation[]> {
|
||||
|
||||
let doc = this._documents.getDocument(resource);
|
||||
let doc = this._documents.getDocumentData(resource).document;
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideDocumentFormattingEdits(doc, <any>options, token)).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
|
@ -394,7 +377,7 @@ class RangeFormattingAdapter implements modes.IFormattingSupport {
|
|||
|
||||
formatRange(resource: URI, range: IRange, options: modes.IFormattingOptions): TPromise<ISingleEditOperation[]> {
|
||||
|
||||
let doc = this._documents.getDocument(resource);
|
||||
let doc = this._documents.getDocumentData(resource).document;
|
||||
let ran = TypeConverters.toRange(range);
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideDocumentRangeFormattingEdits(doc, ran, <any>options, token)).then(value => {
|
||||
|
@ -419,7 +402,7 @@ class OnTypeFormattingAdapter implements modes.IFormattingSupport {
|
|||
|
||||
formatAfterKeystroke(resource: URI, position: IPosition, ch: string, options: modes.IFormattingOptions): TPromise<ISingleEditOperation[]> {
|
||||
|
||||
let doc = this._documents.getDocument(resource);
|
||||
let doc = this._documents.getDocumentData(resource).document;
|
||||
let pos = TypeConverters.toPosition(position);
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideOnTypeFormattingEdits(doc, pos, ch, <any> options, token)).then(value => {
|
||||
|
@ -459,7 +442,7 @@ class RenameAdapter implements modes.IRenameSupport {
|
|||
|
||||
rename(resource: URI, position: IPosition, newName: string): TPromise<modes.IRenameResult> {
|
||||
|
||||
let doc = this._documents.getDocument(resource);
|
||||
let doc = this._documents.getDocumentData(resource).document;
|
||||
let pos = TypeConverters.toPosition(position);
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => {
|
||||
|
@ -514,7 +497,7 @@ class SuggestAdapter implements modes.ISuggestSupport {
|
|||
|
||||
suggest(resource: URI, position: IPosition): TPromise<modes.ISuggestResult[]> {
|
||||
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
const pos = TypeConverters.toPosition(position);
|
||||
const ran = doc.getWordRangeAtPosition(pos);
|
||||
|
||||
|
@ -525,7 +508,7 @@ class SuggestAdapter implements modes.ISuggestSupport {
|
|||
|
||||
let defaultSuggestions: modes.ISuggestResult = {
|
||||
suggestions: [],
|
||||
currentWord: ran ? doc.getText(new Range(ran.start, pos)) : '',
|
||||
currentWord: ran ? doc.getText(new Range(ran.start.line, ran.start.character, pos.line, pos.character)) : '',
|
||||
};
|
||||
let allSuggestions: modes.ISuggestResult[] = [defaultSuggestions];
|
||||
|
||||
|
@ -613,7 +596,7 @@ class ParameterHintsAdapter implements modes.IParameterHintsSupport {
|
|||
|
||||
getParameterHints(resource: URI, position: IPosition, triggerCharacter?: string): TPromise<modes.IParameterHints> {
|
||||
|
||||
const doc = this._documents.getDocument(resource);
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
const pos = TypeConverters.toPosition(position);
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideSignatureHelp(doc, pos, token)).then(value => {
|
|
@ -10,7 +10,7 @@ import {Remotable, IThreadService} from 'vs/platform/thread/common/thread';
|
|||
import {IOutputService, OUTPUT_EDITOR_INPUT_ID} from 'vs/workbench/parts/output/common/output';
|
||||
import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService';
|
||||
import {Position} from 'vs/platform/editor/common/editor';
|
||||
import * as TypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
|
||||
export class ExtHostOutputChannel implements vscode.OutputChannel {
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {ExtHostCommands} from 'vs/workbench/api/common/extHostCommands';
|
||||
import {ExtHostCommands} from 'vs/workbench/api/node/extHostCommands';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import {isFalsyOrEmpty} from 'vs/base/common/arrays';
|
||||
import {IDisposable} from 'vs/base/common/lifecycle';
|
|
@ -15,7 +15,7 @@ import {ITextFileService} from 'vs/workbench/parts/files/common/files';
|
|||
import {ICommonCodeEditor} from 'vs/editor/common/editorCommon';
|
||||
import {bulkEdit, IResourceEdit} from 'vs/editor/common/services/bulkEdit';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {fromRange} from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import {fromRange} from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import {Uri, CancellationToken} from 'vscode';
|
||||
|
||||
export class ExtHostWorkspace {
|
|
@ -49,26 +49,26 @@ import {IModelService} from 'vs/editor/common/services/modelService';
|
|||
import {ModelServiceImpl} from 'vs/editor/common/services/modelServiceImpl';
|
||||
import {CodeEditorServiceImpl} from 'vs/editor/browser/services/codeEditorServiceImpl';
|
||||
import {ICodeEditorService} from 'vs/editor/common/services/codeEditorService';
|
||||
import {MainProcessVSCodeAPIHelper} from 'vs/workbench/api/common/extHost.api.impl';
|
||||
import {MainProcessVSCodeAPIHelper} from 'vs/workbench/api/node/extHost.api.impl';
|
||||
import {MainProcessPluginService} from 'vs/platform/plugins/common/nativePluginService';
|
||||
import {MainThreadDocuments} from 'vs/workbench/api/common/extHostDocuments';
|
||||
import {MainThreadDocuments} from 'vs/workbench/api/node/extHostDocuments';
|
||||
import {MainProcessTextMateSyntax} from 'vs/editor/node/textMate/TMSyntax';
|
||||
import {MainProcessTextMateSnippet} from 'vs/editor/node/textMate/TMSnippets';
|
||||
import {JSONValidationExtensionPoint} from 'vs/platform/jsonschemas/common/jsonValidationExtensionPoint';
|
||||
import {LanguageConfigurationFileHandler} from 'vs/editor/node/languageConfiguration';
|
||||
import {MainThreadFileSystemEventService} from 'vs/workbench/api/common/extHostFileSystemEventService';
|
||||
import {MainThreadQuickOpen} from 'vs/workbench/api/common/extHostQuickOpen';
|
||||
import {MainThreadStatusBar} from 'vs/workbench/api/common/extHostStatusBar';
|
||||
import {MainThreadCommands} from 'vs/workbench/api/common/extHostCommands';
|
||||
import {MainThreadFileSystemEventService} from 'vs/workbench/api/node/extHostFileSystemEventService';
|
||||
import {MainThreadQuickOpen} from 'vs/workbench/api/node/extHostQuickOpen';
|
||||
import {MainThreadStatusBar} from 'vs/workbench/api/node/extHostStatusBar';
|
||||
import {MainThreadCommands} from 'vs/workbench/api/node/extHostCommands';
|
||||
import {RemoteTelemetryServiceHelper} from 'vs/platform/telemetry/common/abstractRemoteTelemetryService';
|
||||
import {MainThreadDiagnostics} from 'vs/workbench/api/common/extHostDiagnostics';
|
||||
import {MainThreadOutputService} from 'vs/workbench/api/common/extHostOutputService';
|
||||
import {MainThreadMessageService} from 'vs/workbench/api/common/extHostMessageService';
|
||||
import {MainThreadLanguages} from 'vs/workbench/api/common/extHostLanguages';
|
||||
import {MainThreadEditors} from 'vs/workbench/api/common/extHostEditors';
|
||||
import {MainThreadWorkspace} from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import {MainThreadConfiguration} from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import {MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import {MainThreadDiagnostics} from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import {MainThreadOutputService} from 'vs/workbench/api/node/extHostOutputService';
|
||||
import {MainThreadMessageService} from 'vs/workbench/api/node/extHostMessageService';
|
||||
import {MainThreadLanguages} from 'vs/workbench/api/node/extHostLanguages';
|
||||
import {MainThreadEditors} from 'vs/workbench/api/node/extHostEditors';
|
||||
import {MainThreadWorkspace} from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import {MainThreadConfiguration} from 'vs/workbench/api/node/extHostConfiguration';
|
||||
import {MainThreadLanguageFeatures} from 'vs/workbench/api/node/extHostLanguageFeatures';
|
||||
import {EventService} from 'vs/platform/event/common/eventService';
|
||||
import {IOptions} from 'vs/workbench/common/options';
|
||||
import themes = require('vs/platform/theme/common/themes');
|
||||
|
|
|
@ -18,15 +18,15 @@ import {TPromise} from 'vs/base/common/winjs.base';
|
|||
import paths = require('vs/base/common/paths');
|
||||
import {IPluginService, IPluginDescription} from 'vs/platform/plugins/common/plugins';
|
||||
import {PluginsRegistry, PluginsMessageCollector, IPluginsMessageCollector} from 'vs/platform/plugins/common/pluginsRegistry';
|
||||
import {ExtHostAPIImplementation} from 'vs/workbench/api/common/extHost.api.impl';
|
||||
import {ExtHostAPIImplementation} from 'vs/workbench/api/node/extHost.api.impl';
|
||||
import { create as createIPC, IPluginsIPC } from 'vs/platform/plugins/common/ipcRemoteCom';
|
||||
import {ExtHostModelService} from 'vs/workbench/api/common/extHostDocuments';
|
||||
import {ExtHostModelService} from 'vs/workbench/api/node/extHostDocuments';
|
||||
import {IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import InstantiationService = require('vs/platform/instantiation/common/instantiationService');
|
||||
import {PluginHostPluginService} from 'vs/platform/plugins/common/nativePluginService';
|
||||
import {PluginHostThreadService} from 'vs/platform/thread/common/pluginHostThreadService';
|
||||
import marshalling = require('vs/base/common/marshalling');
|
||||
import {ExtHostTelemetryService} from 'vs/workbench/api/common/extHostTelemetry';
|
||||
import {ExtHostTelemetryService} from 'vs/workbench/api/node/extHostTelemetry';
|
||||
import {BaseRequestService} from 'vs/platform/request/common/baseRequestService';
|
||||
import {BaseWorkspaceContextService} from 'vs/platform/workspace/common/baseWorkspaceContextService';
|
||||
import {ModeServiceImpl} from 'vs/editor/common/services/modeServiceImpl';
|
||||
|
|
|
@ -14,6 +14,7 @@ import {IDiffEditor, ICodeEditor} from 'vs/editor/browser/editorBrowser';
|
|||
import {ICommonCodeEditor, IModel, EditorType, IEditor as ICommonEditor} from 'vs/editor/common/editorCommon';
|
||||
import {BaseEditor, IEditorRegistry, Extensions} from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import {EditorInput, EditorOptions, IFileEditorInput, TextEditorOptions} from 'vs/workbench/common/editor';
|
||||
import {ResourceEditorInput} from 'vs/workbench/common/editor/resourceEditorInput';
|
||||
import {UntitledEditorInput} from 'vs/workbench/common/editor/untitledEditorInput';
|
||||
import {DiffEditorInput} from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import {IUntitledEditorService} from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||
|
@ -288,6 +289,10 @@ export class WorkbenchEditorService implements IWorkbenchEditorService {
|
|||
return this.createFileInput(resourceInput.resource, resourceInput.mime);
|
||||
}
|
||||
|
||||
else if (URI.isURI(resourceInput.resource)) {
|
||||
return TPromise.as(this.instantiationService.createInstance(ResourceEditorInput, resourceInput.resource.fsPath, undefined, resourceInput.resource));
|
||||
}
|
||||
|
||||
return TPromise.as<EditorInput>(null);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import {setUnexpectedErrorHandler, errorHandler} from 'vs/base/common/errors';
|
|||
import {create} from 'vs/base/common/types';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as types from 'vs/workbench/api/node/extHostTypes';
|
||||
import {Range as CodeEditorRange} from 'vs/editor/common/core/range';
|
||||
import * as EditorCommon from 'vs/editor/common/editorCommon';
|
||||
import {Model as EditorModel} from 'vs/editor/common/model/model';
|
||||
|
@ -22,10 +22,10 @@ import {IThreadService} from 'vs/platform/thread/common/thread';
|
|||
import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService';
|
||||
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import {IModelService} from 'vs/editor/common/services/modelService';
|
||||
import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import {registerApiCommands} from 'vs/workbench/api/common/extHostApiCommands';
|
||||
import {ExtHostCommands, MainThreadCommands} from 'vs/workbench/api/common/extHostCommands';
|
||||
import {ExtHostModelService} from 'vs/workbench/api/common/extHostDocuments';
|
||||
import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/node/extHostLanguageFeatures';
|
||||
import {registerApiCommands} from 'vs/workbench/api/node/extHostApiCommands';
|
||||
import {ExtHostCommands, MainThreadCommands} from 'vs/workbench/api/node/extHostCommands';
|
||||
import {ExtHostModelService} from 'vs/workbench/api/node/extHostDocuments';
|
||||
|
||||
const defaultSelector = { scheme: 'far' };
|
||||
const model: EditorCommon.IModel = new EditorModel(
|
||||
|
|
|
@ -7,30 +7,30 @@
|
|||
|
||||
import * as assert from 'assert';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import {ExtHostDocument} from 'vs/workbench/api/common/extHostDocuments';
|
||||
import {Position} from 'vs/workbench/api/common/extHostTypes';
|
||||
import {ExtHostDocumentData} from 'vs/workbench/api/node/extHostDocuments';
|
||||
import {Position} from 'vs/workbench/api/node/extHostTypes';
|
||||
import {Range as CodeEditorRange} from 'vs/editor/common/core/range';
|
||||
import * as EditorCommon from 'vs/editor/common/editorCommon';
|
||||
|
||||
|
||||
suite("PluginHostDocument", () => {
|
||||
|
||||
let doc: ExtHostDocument;
|
||||
let data: ExtHostDocumentData;
|
||||
|
||||
function assertPositionAt(offset: number, line: number, character: number) {
|
||||
let position = doc.positionAt(offset);
|
||||
let position = data.positionAt(offset);
|
||||
assert.equal(position.line, line);
|
||||
assert.equal(position.character, character);
|
||||
}
|
||||
|
||||
function assertOffsetAt(line: number, character: number, offset: number) {
|
||||
let pos = new Position(line, character);
|
||||
let actual = doc.offsetAt(pos);
|
||||
let actual = data.offsetAt(pos);
|
||||
assert.equal(actual, offset);
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
doc = new ExtHostDocument(undefined, URI.file(''), [
|
||||
data = new ExtHostDocumentData(undefined, URI.file(''), [
|
||||
'This is line one', //16
|
||||
'and this is line number two', //27
|
||||
'it is followed by #3', //20
|
||||
|
@ -40,33 +40,33 @@ suite("PluginHostDocument", () => {
|
|||
|
||||
test('readonly-ness', function() {
|
||||
|
||||
assert.throws(() => doc.uri = null);
|
||||
assert.throws(() => doc.fileName = 'foofile');
|
||||
assert.throws(() => doc.isDirty = false);
|
||||
assert.throws(() => doc.isUntitled = false);
|
||||
assert.throws(() => doc.languageId = 'dddd');
|
||||
assert.throws(() => doc.lineCount = 9);
|
||||
assert.throws(() => data.document.uri = null);
|
||||
assert.throws(() => data.document.fileName = 'foofile');
|
||||
assert.throws(() => data.document.isDirty = false);
|
||||
assert.throws(() => data.document.isUntitled = false);
|
||||
assert.throws(() => data.document.languageId = 'dddd');
|
||||
assert.throws(() => data.document.lineCount = 9);
|
||||
})
|
||||
|
||||
test('lines', function() {
|
||||
|
||||
assert.equal(doc.lineCount, 4);
|
||||
assert.throws(() => doc.lineCount = 9);
|
||||
assert.equal(data.document.lineCount, 4);
|
||||
assert.throws(() => data.document.lineCount = 9);
|
||||
|
||||
assert.throws(() => doc.lineAt(-1));
|
||||
assert.throws(() => doc.lineAt(doc.lineCount));
|
||||
assert.throws(() => doc.lineAt(Number.MAX_VALUE));
|
||||
assert.throws(() => doc.lineAt(Number.MIN_VALUE));
|
||||
assert.throws(() => doc.lineAt(0.8));
|
||||
assert.throws(() => data.lineAt(-1));
|
||||
assert.throws(() => data.lineAt(data.document.lineCount));
|
||||
assert.throws(() => data.lineAt(Number.MAX_VALUE));
|
||||
assert.throws(() => data.lineAt(Number.MIN_VALUE));
|
||||
assert.throws(() => data.lineAt(0.8));
|
||||
|
||||
let line = doc.lineAt(0);
|
||||
let line = data.lineAt(0);
|
||||
assert.equal(line.lineNumber, 0);
|
||||
assert.equal(line.text.length, 16);
|
||||
assert.equal(line.text, 'This is line one');
|
||||
assert.equal(line.isEmptyOrWhitespace, false);
|
||||
assert.equal(line.firstNonWhitespaceCharacterIndex, 0);
|
||||
|
||||
doc._acceptEvents([{
|
||||
data.onEvents([{
|
||||
range: { startLineNumber: 1, startColumn: 1, endLineNumber: 1, endColumn: 1 },
|
||||
text: '\t ',
|
||||
isRedoing: undefined,
|
||||
|
@ -80,7 +80,7 @@ suite("PluginHostDocument", () => {
|
|||
assert.equal(line.firstNonWhitespaceCharacterIndex, 0);
|
||||
|
||||
// fetch line again
|
||||
line = doc.lineAt(0);
|
||||
line = data.lineAt(0);
|
||||
assert.equal(line.text, '\t This is line one');
|
||||
assert.equal(line.firstNonWhitespaceCharacterIndex, 2);
|
||||
});
|
||||
|
@ -102,7 +102,7 @@ suite("PluginHostDocument", () => {
|
|||
|
||||
test('offsetAt, after remove', function() {
|
||||
|
||||
doc._acceptEvents([{
|
||||
data.onEvents([{
|
||||
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 },
|
||||
text: '',
|
||||
isRedoing: undefined,
|
||||
|
@ -118,7 +118,7 @@ suite("PluginHostDocument", () => {
|
|||
|
||||
test('offsetAt, after replace', function() {
|
||||
|
||||
doc._acceptEvents([{
|
||||
data.onEvents([{
|
||||
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 },
|
||||
text: 'is could be',
|
||||
isRedoing: undefined,
|
||||
|
@ -134,7 +134,7 @@ suite("PluginHostDocument", () => {
|
|||
|
||||
test('offsetAt, after insert line', function() {
|
||||
|
||||
doc._acceptEvents([{
|
||||
data.onEvents([{
|
||||
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 1, endColumn: 6 },
|
||||
text: 'is could be\na line with number',
|
||||
isRedoing: undefined,
|
||||
|
@ -153,7 +153,7 @@ suite("PluginHostDocument", () => {
|
|||
|
||||
test('offsetAt, after remove line', function() {
|
||||
|
||||
doc._acceptEvents([{
|
||||
data.onEvents([{
|
||||
range: { startLineNumber: 1, startColumn: 3, endLineNumber: 2, endColumn: 6 },
|
||||
text: '',
|
||||
isRedoing: undefined,
|
||||
|
@ -189,11 +189,11 @@ enum AssertDocumentLineMappingDirection {
|
|||
|
||||
suite("PluginHostDocument updates line mapping", () => {
|
||||
|
||||
function positionToStr(position:Position): string {
|
||||
function positionToStr(position: { line: number; character: number;}): string {
|
||||
return '(' + position.line + ',' + position.character + ')';
|
||||
}
|
||||
|
||||
function assertDocumentLineMapping(doc:ExtHostDocument, direction:AssertDocumentLineMappingDirection): void {
|
||||
function assertDocumentLineMapping(doc:ExtHostDocumentData, direction:AssertDocumentLineMappingDirection): void {
|
||||
let allText = doc.getText();
|
||||
|
||||
let line = 0, character = 0, previousIsCarriageReturn = false;
|
||||
|
@ -234,10 +234,10 @@ suite("PluginHostDocument updates line mapping", () => {
|
|||
}
|
||||
|
||||
function testLineMappingDirectionAfterEvents(lines:string[], eol: string, direction:AssertDocumentLineMappingDirection, events:EditorCommon.IModelContentChangedEvent2[]): void {
|
||||
let myDocument = new ExtHostDocument(undefined, URI.file(''), lines.slice(0), eol, 'text', 1, false);
|
||||
let myDocument = new ExtHostDocumentData(undefined, URI.file(''), lines.slice(0), eol, 'text', 1, false);
|
||||
assertDocumentLineMapping(myDocument, direction);
|
||||
|
||||
myDocument._acceptEvents(events);
|
||||
myDocument.onEvents(events);
|
||||
assertDocumentLineMapping(myDocument, direction);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import * as assert from 'assert';
|
|||
import {setUnexpectedErrorHandler, errorHandler} from 'vs/base/common/errors';
|
||||
import {create} from 'vs/base/common/types';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as types from 'vs/workbench/api/node/extHostTypes';
|
||||
import {Range as CodeEditorRange} from 'vs/editor/common/core/range';
|
||||
import * as EditorCommon from 'vs/editor/common/editorCommon';
|
||||
import {Model as EditorModel} from 'vs/editor/common/model/model';
|
||||
|
@ -18,9 +18,9 @@ import {create as createInstantiationService} from 'vs/platform/instantiation/co
|
|||
import {MarkerService} from 'vs/platform/markers/common/markerService';
|
||||
import {IMarkerService} from 'vs/platform/markers/common/markers';
|
||||
import {IThreadService} from 'vs/platform/thread/common/thread';
|
||||
import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures';
|
||||
import {ExtHostCommands, MainThreadCommands} from 'vs/workbench/api/common/extHostCommands';
|
||||
import {ExtHostModelService} from 'vs/workbench/api/common/extHostDocuments';
|
||||
import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/node/extHostLanguageFeatures';
|
||||
import {ExtHostCommands, MainThreadCommands} from 'vs/workbench/api/node/extHostCommands';
|
||||
import {ExtHostModelService} from 'vs/workbench/api/node/extHostDocuments';
|
||||
import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/common/quickOpen';
|
||||
import {getCodeLensData} from 'vs/editor/contrib/codelens/common/codelens';
|
||||
import {getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import * as assert from 'assert';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as types from 'vs/workbench/api/node/extHostTypes';
|
||||
|
||||
function assertToJSON(a: any, expected: any) {
|
||||
const raw = JSON.stringify(a);
|
||||
|
|
Loading…
Reference in a new issue