提交 8bbe383a 编写于 作者: A Alex Dima

Compute simple links on the editor simple worker

上级 ab014838
......@@ -37,7 +37,6 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode {
public autoValidateDelay:number;
public suggestSupport:Modes.ISuggestSupport;
public inplaceReplaceSupport:Modes.IInplaceReplaceSupport;
public linkSupport:Modes.ILinkSupport;
public configSupport:Modes.IConfigurationSupport;
public codeLensSupport:Modes.ICodeLensSupport;
......@@ -60,7 +59,6 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode {
this.autoValidateDelay = 500;
this.suggestSupport = this;
this.inplaceReplaceSupport = this;
this.linkSupport = this;
this.configSupport = this;
this._workerPiecePromise = null;
......@@ -189,11 +187,6 @@ export class AbstractMode<W extends AbstractModeWorker> implements Modes.IMode {
return this._worker((w) => w.inplaceReplaceSupport.navigateValueSet(resource, position, up));
}
static $computeLinks = OneWorkerAttr(AbstractMode, AbstractMode.prototype.computeLinks);
public computeLinks(resource:URI):TPromise<Modes.ILink[]> {
return this._worker((w) => w.computeLinks(resource));
}
public configure(options:any): TPromise<boolean> {
this._options = options;
......
......@@ -7,7 +7,6 @@
import URI from 'vs/base/common/uri';
import {IMarkerService} from 'vs/platform/markers/common/markers';
import {IResourceService} from 'vs/editor/common/services/resourceService';
import {computeLinks} from 'vs/editor/common/modes/linkComputer';
import {DefaultFilter} from 'vs/editor/common/modes/modesFilters';
import {ValidationHelper} from 'vs/editor/common/worker/validationHelper';
import EditorCommon = require('vs/editor/common/editorCommon');
......@@ -174,14 +173,6 @@ export class AbstractModeWorker {
return AbstractModeWorker.filter;
}
// ---- link detection ------------------------------------------------------------------
public computeLinks(resource:URI):TPromise<Modes.ILink[]> {
var model = this.resourceService.get(resource),
links = computeLinks(model);
return TPromise.as(links);
}
public configure(options:any): TPromise<boolean> {
var p = this._doConfigure(options);
......
......@@ -12,6 +12,8 @@ import {EditorSimpleWorker, IRawModelData} from 'vs/editor/common/services/edito
import {MirrorModel2} from 'vs/editor/common/model/mirrorModel2';
import URI from 'vs/base/common/uri';
import {DiffComputer} from 'vs/editor/common/diff/diffComputer';
import Modes = require('vs/editor/common/modes');
import {computeLinks} from 'vs/editor/common/modes/linkComputer';
class MirrorModel extends MirrorModel2 {
......@@ -19,6 +21,13 @@ class MirrorModel extends MirrorModel2 {
return this._lines.slice(0);
}
public getLineCount(): number {
return this._lines.length;
}
public getLineContent(lineNumber:number): string {
return this._lines[lineNumber - 1];
}
}
export class EditorSimpleWorkerImpl extends EditorSimpleWorker implements IRequestHandler {
......@@ -87,6 +96,15 @@ export class EditorSimpleWorkerImpl extends EditorSimpleWorker implements IReque
}
// ---- END diff --------------------------------------------------------------------------
public computeLinks(modelUrl:string):TPromise<Modes.ILink[]> {
let model = this._models[modelUrl];
if (!model) {
return null;
}
return TPromise.as(computeLinks(model));
}
}
/**
......
......@@ -6,6 +6,7 @@
import {TPromise} from 'vs/base/common/winjs.base';
import EditorCommon = require('vs/editor/common/editorCommon');
import Modes = require('vs/editor/common/modes');
export interface IRawModelData {
url:string;
......@@ -19,11 +20,11 @@ export abstract class EditorSimpleWorker {
throw new Error('Not implemented!');
}
public acceptModelChanged(strURL: string, events: EditorCommon.IModelContentChangedEvent2[]): void {
public acceptModelChanged(modelUrl: string, events: EditorCommon.IModelContentChangedEvent2[]): void {
throw new Error('Not implemented!');
}
public acceptRemovedModel(strURL: string): void {
public acceptRemovedModel(modelUrl: string): void {
throw new Error('Not implemented!');
}
......@@ -34,4 +35,8 @@ export abstract class EditorSimpleWorker {
public computeDirtyDiff(originalUrl:string, modifiedUrl:string, ignoreTrimWhitespace:boolean):TPromise<EditorCommon.IChange[]> {
throw new Error('Not implemented!');
}
public computeLinks(modelUrl:string):TPromise<Modes.ILink[]> {
throw new Error('Not implemented!');
}
}
......@@ -8,6 +8,7 @@ import {createDecorator, ServiceIdentifier} from 'vs/platform/instantiation/comm
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import EditorCommon = require('vs/editor/common/editorCommon');
import Modes = require('vs/editor/common/modes');
export var ID_EDITOR_WORKER_SERVICE = 'workerService';
export var IEditorWorkerService = createDecorator<IEditorWorkerService>(ID_EDITOR_WORKER_SERVICE);
......@@ -17,4 +18,5 @@ export interface IEditorWorkerService {
computeDiff(original:URI, modified:URI, ignoreTrimWhitespace:boolean):TPromise<EditorCommon.ILineChange[]>;
computeDirtyDiff(original:URI, modified:URI, ignoreTrimWhitespace:boolean):TPromise<EditorCommon.IChange[]>;
computeLinks(resource:URI):TPromise<Modes.ILink[]>;
}
......@@ -14,6 +14,7 @@ import {SimpleWorkerClient} from 'vs/base/common/worker/simpleWorker';
import {DefaultWorkerFactory} from 'vs/base/worker/defaultWorkerFactory';
import {EditorSimpleWorker} from 'vs/editor/common/services/editorSimpleWorkerCommon';
import {IntervalTimer} from 'vs/base/common/async';
import Modes = require('vs/editor/common/modes');
/**
* Stop syncing a model to the worker if it was not needed for 1 min.
......@@ -34,13 +35,17 @@ export class EditorWorkerServiceImpl implements IEditorWorkerService {
this._workerManager = new WorkerManager(modelService);
}
computeDiff(original:URI, modified:URI, ignoreTrimWhitespace:boolean):TPromise<EditorCommon.ILineChange[]> {
public computeDiff(original:URI, modified:URI, ignoreTrimWhitespace:boolean):TPromise<EditorCommon.ILineChange[]> {
return this._workerManager.withWorker().then(client => client.computeDiff(original, modified, ignoreTrimWhitespace));
}
computeDirtyDiff(original:URI, modified:URI, ignoreTrimWhitespace:boolean):TPromise<EditorCommon.IChange[]> {
public computeDirtyDiff(original:URI, modified:URI, ignoreTrimWhitespace:boolean):TPromise<EditorCommon.IChange[]> {
return this._workerManager.withWorker().then(client => client.computeDirtyDiff(original, modified, ignoreTrimWhitespace));
}
public computeLinks(resource:URI):TPromise<Modes.ILink[]> {
return this._workerManager.withWorker().then(client => client.computeLinks(resource));
}
}
class WorkerManager extends Disposable {
......@@ -148,6 +153,12 @@ class EditorWorkerClient extends Disposable {
});
}
public computeLinks(resource:URI):TPromise<Modes.ILink[]> {
return this._withSyncedResources([resource]).then(_ => {
return this._proxy.computeLinks(resource.toString());
});
}
private _withSyncedResources(resources:URI[]): TPromise<void> {
for (let i = 0; i < resources.length; i++) {
......
......@@ -22,6 +22,8 @@ import {IEditorService, IResourceInput} from 'vs/platform/editor/common/editor';
import {IMessageService} from 'vs/platform/message/common/message';
import Severity from 'vs/base/common/severity';
import {KeyCode} from 'vs/base/common/keyCodes';
import {Range} from 'vs/editor/common/core/range';
import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService';
class LinkOccurence {
......@@ -89,12 +91,19 @@ class LinkDetector {
private lastMouseEvent:EditorBrowser.IMouseEvent;
private editorService:IEditorService;
private messageService:IMessageService;
private editorWorkerService: IEditorWorkerService;
private currentOccurences:{ [decorationId:string]:LinkOccurence; };
constructor(editor:EditorCommon.ICommonCodeEditor, editorService:IEditorService, messageService:IMessageService) {
constructor(
editor:EditorCommon.ICommonCodeEditor,
editorService:IEditorService,
messageService:IMessageService,
editorWorkerService: IEditorWorkerService
) {
this.editor = editor;
this.editorService = editorService;
this.messageService = messageService;
this.editorWorkerService = editorWorkerService;
this.listenersToRemove = [];
this.listenersToRemove.push(editor.addListener('change', (e:EditorCommon.IModelContentChangedEvent) => this.onChange()));
this.listenersToRemove.push(editor.addListener(EditorCommon.EventType.ModelChanged, (e:EditorCommon.IModelContentChangedEvent) => this.onModelChanged()));
......@@ -146,14 +155,75 @@ class LinkDetector {
if (!this.editor.getModel()) {
return;
}
var mode = this.editor.getModel().getMode();
let modePromise:TPromise<Modes.ILink[]> = TPromise.as(null);
let mode = this.editor.getModel().getMode();
if (mode.linkSupport) {
this.computePromise = mode.linkSupport.computeLinks(this.editor.getModel().getAssociatedResource());
this.computePromise.then((links:Modes.ILink[]) => {
this.updateDecorations(links);
this.computePromise = null;
});
modePromise = mode.linkSupport.computeLinks(this.editor.getModel().getAssociatedResource());
}
let standardPromise:TPromise<Modes.ILink[]> = this.editorWorkerService.computeLinks(this.editor.getModel().getAssociatedResource());
this.computePromise = TPromise.join([modePromise, standardPromise]).then((r) => {
let a = r[0];
let b = r[1];
if (!a || a.length === 0) {
return b || [];
}
if (!b || b.length === 0) {
return a || [];
}
return LinkDetector._linksUnion(a, b);
});
this.computePromise.then((links:Modes.ILink[]) => {
this.updateDecorations(links);
this.computePromise = null;
});
}
private static _linksUnion(oldLinks: Modes.ILink[], newLinks: Modes.ILink[]): Modes.ILink[] {
// reunite oldLinks with newLinks and remove duplicates
var result: Modes.ILink[] = [],
oldIndex: number,
oldLen: number,
newIndex: number,
newLen: number,
oldLink: Modes.ILink,
newLink: Modes.ILink,
comparisonResult: number;
for (oldIndex = 0, newIndex = 0, oldLen = oldLinks.length, newLen = newLinks.length; oldIndex < oldLen && newIndex < newLen;) {
oldLink = oldLinks[oldIndex];
newLink = newLinks[newIndex];
if (Range.areIntersectingOrTouching(oldLink.range, newLink.range)) {
// Remove the oldLink
oldIndex++;
continue;
}
comparisonResult = Range.compareRangesUsingStarts(oldLink.range, newLink.range);
if (comparisonResult < 0) {
// oldLink is before
result.push(oldLink);
oldIndex++;
} else {
// newLink is before
result.push(newLink);
newIndex++;
}
}
for (; oldIndex < oldLen; oldIndex++) {
result.push(oldLinks[oldIndex]);
}
for (; newIndex < newLen; newIndex++) {
result.push(newLinks[newIndex]);
}
return result;
}
private updateDecorations(links:Modes.ILink[]):void {
......@@ -309,8 +379,7 @@ class LinkDetector {
private isEnabled(mouseEvent: EditorBrowser.IMouseEvent, withKey?:Keyboard.StandardKeyboardEvent):boolean {
return mouseEvent.target.type === EditorCommon.MouseTargetType.CONTENT_TEXT &&
(mouseEvent.event[LinkDetector.TRIGGER_MODIFIER] || (withKey && withKey.keyCode === LinkDetector.TRIGGER_KEY_VALUE)) &&
!!this.editor.getModel().getMode().linkSupport;
(mouseEvent.event[LinkDetector.TRIGGER_MODIFIER] || (withKey && withKey.keyCode === LinkDetector.TRIGGER_KEY_VALUE));
}
private stop():void {
......@@ -339,13 +408,16 @@ class OpenLinkAction extends EditorAction {
private _linkDetector: LinkDetector;
constructor(descriptor:EditorCommon.IEditorActionDescriptorData, editor:EditorCommon.ICommonCodeEditor,
constructor(
descriptor:EditorCommon.IEditorActionDescriptorData,
editor:EditorCommon.ICommonCodeEditor,
@IEditorService editorService:IEditorService,
@IMessageService messageService:IMessageService
) {
@IMessageService messageService:IMessageService,
@IEditorWorkerService editorWorkerService: IEditorWorkerService
) {
super(descriptor, editor, Behaviour.WidgetFocus | Behaviour.UpdateOnCursorPositionChange);
this._linkDetector = new LinkDetector(editor, editorService, messageService);
this._linkDetector = new LinkDetector(editor, editorService, messageService, editorWorkerService);
}
public dispose(): void {
......
......@@ -274,7 +274,7 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
public tokenizationSupport: Modes.ITokenizationSupport;
public richEditSupport: Modes.IRichEditSupport;
public linkSupport:Modes.ILinkSupport;
public extraInfoSupport:Modes.IExtraInfoSupport;
public occurrencesSupport:Modes.IOccurrencesSupport;
public referenceSupport: Modes.IReferenceSupport;
......@@ -296,7 +296,7 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
this.modeService = modeService;
this.tokenizationSupport = new TokenizationSupport(this, this, true, true);
this.linkSupport = this;
this.formattingSupport = this;
this.extraInfoSupport = this;
this.occurrencesSupport = this;
......@@ -468,6 +468,11 @@ export class HTMLMode<W extends htmlWorker.HTMLWorker> extends AbstractMode<W> i
return createAsyncDescriptor2('vs/languages/html/common/htmlWorker', 'HTMLWorker');
}
static $computeLinks = OneWorkerAttr(HTMLMode, HTMLMode.prototype.computeLinks);
public computeLinks(resource:URI):winjs.TPromise<Modes.ILink[]> {
return this._worker((w) => w.computeLinks(resource));
}
static $formatRange = OneWorkerAttr(HTMLMode, HTMLMode.prototype.formatRange);
public formatRange(resource:URI, range:EditorCommon.IRange, options:Modes.IFormattingOptions):winjs.TPromise<EditorCommon.ISingleEditOperation[]> {
return this._worker((w) => w.format(resource, range, options));
......
......@@ -13,7 +13,6 @@ import network = require('vs/base/common/network');
import EditorCommon = require('vs/editor/common/editorCommon');
import Modes = require('vs/editor/common/modes');
import strings = require('vs/base/common/strings');
import {Range} from 'vs/editor/common/core/range';
import {Position} from 'vs/editor/common/core/position';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
import {IMarkerService} from 'vs/platform/markers/common/markers';
......@@ -652,55 +651,8 @@ export class HTMLWorker extends AbstractModeWorker {
}
public computeLinks(resource: URI): winjs.TPromise<Modes.ILink[]> {
return super.computeLinks(resource).then((oldLinks) => {
var model = this.resourceService.get(resource);
var newLinks = this._computeHTMLLinks(model);
// reunite oldLinks with newLinks and remove duplicates
var result: Modes.ILink[] = [],
oldIndex: number,
oldLen: number,
newIndex: number,
newLen: number,
oldLink: Modes.ILink,
newLink: Modes.ILink,
comparisonResult: number;
for (oldIndex = 0, newIndex = 0, oldLen = oldLinks.length, newLen = newLinks.length; oldIndex < oldLen && newIndex < newLen;) {
oldLink = oldLinks[oldIndex];
newLink = newLinks[newIndex];
if (Range.areIntersectingOrTouching(oldLink.range, newLink.range)) {
// Remove the oldLink
oldIndex++;
continue;
}
comparisonResult = Range.compareRangesUsingStarts(oldLink.range, newLink.range);
if (comparisonResult < 0) {
// oldLink is before
result.push(oldLink);
oldIndex++;
} else {
// newLink is before
result.push(newLink);
newIndex++;
}
}
for (; oldIndex < oldLen; oldIndex++) {
result.push(oldLinks[oldIndex]);
}
for (; newIndex < newLen; newIndex++) {
result.push(newLinks[newIndex]);
}
return result;
});
let model = this.resourceService.get(resource);
return winjs.TPromise.as(this._computeHTMLLinks(model));
}
}
......
......@@ -14,6 +14,10 @@ import {IThreadService} from 'vs/platform/thread/common/thread';
import {IModelService} from 'vs/editor/common/services/modelService';
import {IModeService} from 'vs/editor/common/services/modeService';
import {OutputWorker} from 'vs/workbench/parts/output/common/outputWorker';
import winjs = require('vs/base/common/winjs.base');
import {OneWorkerAttr} from 'vs/platform/thread/common/threadService';
import URI from 'vs/base/common/uri';
import Modes = require('vs/editor/common/modes');
export const language: types.ILanguage = {
displayName: 'Log',
......@@ -41,6 +45,8 @@ export const language: types.ILanguage = {
export class OutputMode extends MonarchMode<OutputWorker> {
public linkSupport:Modes.ILinkSupport;
constructor(
descriptor:IModeDescriptor,
@IInstantiationService instantiationService: IInstantiationService,
......@@ -49,9 +55,16 @@ export class OutputMode extends MonarchMode<OutputWorker> {
@IModelService modelService: IModelService
) {
super(descriptor, compile(language), instantiationService, threadService, modeService, modelService);
this.linkSupport = this;
}
protected _getWorkerDescriptor(): AsyncDescriptor2<IMode, IWorkerParticipant[], OutputWorker> {
return createAsyncDescriptor2('vs/workbench/parts/output/common/outputWorker', 'OutputWorker');
}
static $computeLinks = OneWorkerAttr(OutputMode, OutputMode.prototype.computeLinks);
public computeLinks(resource:URI):winjs.TPromise<Modes.ILink[]> {
return this._worker((w) => w.computeLinks(resource));
}
}
......@@ -38,19 +38,18 @@ export class OutputWorker extends AbstractModeWorker {
}
public computeLinks(resource: URI): TPromise<ILink[]> {
return super.computeLinks(resource).then((links) => {
if (!this.patterns.length) {
return links;
}
let links: ILink[] = [];
if (!this.patterns.length) {
return TPromise.as(links);
}
let model = this.resourceService.get(resource);
let model = this.resourceService.get(resource);
for (let i = 1, lineCount = model.getLineCount(); i <= lineCount; i++) {
links.push(...OutputWorker.detectLinks(model.getLineContent(i), i, this.patterns, this._contextService));
}
for (let i = 1, lineCount = model.getLineCount(); i <= lineCount; i++) {
links.push(...OutputWorker.detectLinks(model.getLineContent(i), i, this.patterns, this._contextService));
}
return links;
});
return TPromise.as(links);
}
public static createPatterns(workspace: IWorkspace): RegExp[] {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册