提交 c9a89ffa 编写于 作者: A Alex Dima

Remove OutputMode, clean up link computation

上级 6c45ea53
......@@ -16,9 +16,6 @@ function createModuleDescription(name, exclude) {
}
exports.collectModules = function(excludes) {
var languageMainExcludes = ['vs/editor/common/languages.common'];
var languageWorkerExcludes = ['vs/base/common/worker/workerServer', 'vs/editor/common/worker/editorWorkerServer'];
var modules = [
createModuleDescription('vs/workbench/parts/search/browser/searchViewlet', excludes),
createModuleDescription('vs/workbench/parts/search/browser/openAnythingHandler', excludes),
......@@ -27,8 +24,6 @@ exports.collectModules = function(excludes) {
createModuleDescription('vs/workbench/parts/git/node/gitApp', []),
createModuleDescription('vs/workbench/parts/git/node/askpass', []),
createModuleDescription('vs/workbench/parts/output/common/outputMode', languageMainExcludes),
createModuleDescription('vs/workbench/parts/output/common/outputWorker', languageWorkerExcludes),
createModuleDescription('vs/workbench/parts/output/common/outputLinkComputer', ['vs/base/common/worker/simpleWorker', 'vs/editor/common/services/editorSimpleWorker']),
createModuleDescription('vs/workbench/parts/output/browser/outputPanel', excludes),
......
......@@ -32,15 +32,6 @@ ModesRegistry.registerLanguage({
mimetypes: [OUTPUT_MIME]
});
// ModesRegistry.registerCompatMode({
// id: OUTPUT_MODE_ID,
// extensions: [],
// aliases: [null],
// mimetypes: [OUTPUT_MIME],
// moduleId: 'vs/workbench/parts/output/common/outputMode',
// ctorName: 'OutputMode'
// });
// Register Output Panel
(<panel.PanelRegistry>platform.Registry.as(panel.Extensions.Panels)).registerPanel(new panel.PanelDescriptor(
'vs/workbench/parts/output/browser/outputPanel',
......
......@@ -5,16 +5,22 @@
'use strict';
import {IMirrorModel, IWorkerContext} from 'vs/editor/common/services/editorSimpleWorker';
import {OutputWorker, IResourceCreator} from 'vs/workbench/parts/output/common/outputWorker';
import {ILink} from 'vs/editor/common/modes';
import {TPromise} from 'vs/base/common/winjs.base';
import URI from 'vs/base/common/uri';
import paths = require('vs/base/common/paths');
import strings = require('vs/base/common/strings');
import arrays = require('vs/base/common/arrays');
import {Range} from 'vs/editor/common/core/range';
export interface ICreateData {
workspaceResourceUri: string;
}
export interface IResourceCreator {
toResource: (workspaceRelativePath: string) => URI;
}
export class OutputLinkComputer {
private _ctx:IWorkerContext;
......@@ -24,7 +30,7 @@ export class OutputLinkComputer {
constructor(ctx:IWorkerContext, createData:ICreateData) {
this._ctx = ctx;
this._workspaceResource = URI.parse(createData.workspaceResourceUri);
this._patterns = OutputWorker.createPatterns(this._workspaceResource);
this._patterns = OutputLinkComputer.createPatterns(this._workspaceResource);
}
private _getModel(uri:string): IMirrorModel {
......@@ -57,11 +63,102 @@ export class OutputLinkComputer {
let lines = model.getValue().split(/\r\n|\r|\n/);
for (let i = 0, len = lines.length; i < len; i++) {
links.push(...OutputWorker.detectLinks(lines[i], i + 1, this._patterns, resourceCreator));
links.push(...OutputLinkComputer.detectLinks(lines[i], i + 1, this._patterns, resourceCreator));
}
return TPromise.as(links);
}
public static createPatterns(workspaceResource: URI): RegExp[] {
let patterns: RegExp[] = [];
let workspaceRootVariants = arrays.distinct([
paths.normalize(workspaceResource.fsPath, true),
paths.normalize(workspaceResource.fsPath, false)
]);
workspaceRootVariants.forEach((workspaceRoot) => {
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\express\server.js on line 8, column 13
patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceRoot) + '(\\S*) on line ((\\d+)(, column (\\d+))?)', 'gi'));
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\express\server.js:line 8, column 13
patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceRoot) + '(\\S*):line ((\\d+)(, column (\\d+))?)', 'gi'));
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Features.ts(45): error
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Features.ts (45): error
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Features.ts(45,18): error
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Features.ts (45,18): error
patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceRoot) + '([^\\s\\(\\)]*)(\\s?\\((\\d+)(,(\\d+))?)\\)', 'gi'));
// Example: at C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Game.ts
// Example: at C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Game.ts:336
// Example: at C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Game.ts:336:9
patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceRoot) + '([^:\\s\\(\\)<>\'\"\\[\\]]*)(:(\\d+))?(:(\\d+))?', 'gi'));
});
return patterns;
}
/**
* Detect links. Made public static to allow for tests.
*/
public static detectLinks(line: string, lineIndex: number, patterns: RegExp[], contextService: IResourceCreator): ILink[] {
let links: ILink[] = [];
patterns.forEach((pattern) => {
pattern.lastIndex = 0; // the holy grail of software development
let match: RegExpExecArray;
let offset = 0;
while ((match = pattern.exec(line)) !== null) {
// Convert the relative path information to a resource that we can use in links
let workspaceRelativePath = strings.rtrim(match[1], '.').replace(/\\/g, '/'); // remove trailing "." that likely indicate end of sentence
let resource:string;
try {
resource = contextService.toResource(workspaceRelativePath).toString();
} catch (error) {
continue; // we might find an invalid URI and then we dont want to loose all other links
}
// Append line/col information to URI if matching
if (match[3]) {
let lineNumber = match[3];
if (match[5]) {
let columnNumber = match[5];
resource = strings.format('{0}#{1},{2}', resource, lineNumber, columnNumber);
} else {
resource = strings.format('{0}#{1}', resource, lineNumber);
}
}
let fullMatch = strings.rtrim(match[0], '.'); // remove trailing "." that likely indicate end of sentence
let index = line.indexOf(fullMatch, offset);
offset += index + fullMatch.length;
var linkRange = {
startColumn: index + 1,
startLineNumber: lineIndex,
endColumn: index + 1 + fullMatch.length,
endLineNumber: lineIndex
};
if (links.some((link) => Range.areIntersectingOrTouching(link.range, linkRange))) {
return; // Do not detect duplicate links
}
links.push({
range: linkRange,
url: resource
});
}
});
return links;
}
}
export function create(ctx:IWorkerContext, createData:ICreateData): OutputLinkComputer {
......
/*---------------------------------------------------------------------------------------------
* 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 {IModeDescriptor} from 'vs/editor/common/modes';
import {IInstantiationService} from 'vs/platform/instantiation/common/instantiation';
import {OutputWorker} from 'vs/workbench/parts/output/common/outputWorker';
import {TPromise} from 'vs/base/common/winjs.base';
import URI from 'vs/base/common/uri';
import * as modes from 'vs/editor/common/modes';
import {CompatMode, ModeWorkerManager} from 'vs/editor/common/modes/abstractMode';
import {wireCancellationToken} from 'vs/base/common/async';
import {ICompatWorkerService, CompatWorkerAttr} from 'vs/editor/common/services/compatWorkerService';
import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace';
export class OutputMode extends CompatMode {
private _modeWorkerManager: ModeWorkerManager<OutputWorker>;
constructor(
descriptor: IModeDescriptor,
@IInstantiationService instantiationService: IInstantiationService,
@ICompatWorkerService compatWorkerService: ICompatWorkerService,
@IWorkspaceContextService contextService:IWorkspaceContextService
) {
super(descriptor.id, compatWorkerService);
this._modeWorkerManager = new ModeWorkerManager<OutputWorker>(descriptor, 'vs/workbench/parts/output/common/outputWorker', 'OutputWorker', null, instantiationService);
let workspaceResource: URI = null;
if (compatWorkerService.isInMainThread) {
let workspace = contextService.getWorkspace();
if (workspace) {
workspaceResource = workspace.resource;
}
}
if (workspaceResource) {
modes.LinkProviderRegistry.register(this.getId(), {
provideLinks: (model, token): Thenable<modes.ILink[]> => {
return wireCancellationToken(token, this._provideLinks(workspaceResource, model.uri));
}
});
}
}
private _worker<T>(runner: (worker: OutputWorker) => TPromise<T>): TPromise<T> {
return this._modeWorkerManager.worker(runner);
}
static $_provideLinks = CompatWorkerAttr(OutputMode, OutputMode.prototype._provideLinks);
private _provideLinks(workspaceResource: URI, resource: URI): TPromise<modes.ILink[]> {
return this._worker((w) => w.provideLinks(workspaceResource, resource));
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {TPromise} from 'vs/base/common/winjs.base';
import {IResourceService} from 'vs/editor/common/services/resourceService';
import URI from 'vs/base/common/uri';
import strings = require('vs/base/common/strings');
import arrays = require('vs/base/common/arrays');
import paths = require('vs/base/common/paths');
import {ILink} from 'vs/editor/common/modes';
import {Range} from 'vs/editor/common/core/range';
export interface IResourceCreator {
toResource: (workspaceRelativePath: string) => URI;
}
function equals(a:URI, b:URI): boolean {
if (!a && !b) {
return true;
}
if ((a && !b) || (!a && b)) {
return false;
}
return a.toString() === b.toString();
}
/**
* A base class of text editor worker that helps with detecting links in the text that point to files in the workspace.
*/
export class OutputWorker {
private resourceService:IResourceService;
private _cachedWorkspaceResource: URI;
private _cachedPatterns: RegExp[];
constructor(
modeId: string,
@IResourceService resourceService: IResourceService
) {
this.resourceService = resourceService;
this._cachedWorkspaceResource = null;
this._cachedPatterns = [];
}
private _getPatterns(workspaceResource: URI): RegExp[] {
if (!equals(this._cachedWorkspaceResource, workspaceResource)) {
this._cachedWorkspaceResource = workspaceResource;
this._cachedPatterns = OutputWorker.createPatterns(this._cachedWorkspaceResource);
}
return this._cachedPatterns;
}
public provideLinks(workspaceResource: URI, resource: URI): TPromise<ILink[]> {
let patterns = this._getPatterns(workspaceResource);
let links: ILink[] = [];
let model = this.resourceService.get(resource);
let resourceCreator: IResourceCreator = {
toResource: (workspaceRelativePath: string): URI => {
if (typeof workspaceRelativePath === 'string') {
return URI.file(paths.join(workspaceResource.fsPath, workspaceRelativePath));
}
return null;
}
};
for (let i = 1, lineCount = model.getLineCount(); i <= lineCount; i++) {
links.push(...OutputWorker.detectLinks(model.getLineContent(i), i, patterns, resourceCreator));
}
return TPromise.as(links);
}
public static createPatterns(workspaceResource: URI): RegExp[] {
let patterns: RegExp[] = [];
let workspaceRootVariants = arrays.distinct([
paths.normalize(workspaceResource.fsPath, true),
paths.normalize(workspaceResource.fsPath, false)
]);
workspaceRootVariants.forEach((workspaceRoot) => {
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\express\server.js on line 8, column 13
patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceRoot) + '(\\S*) on line ((\\d+)(, column (\\d+))?)', 'gi'));
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\express\server.js:line 8, column 13
patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceRoot) + '(\\S*):line ((\\d+)(, column (\\d+))?)', 'gi'));
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Features.ts(45): error
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Features.ts (45): error
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Features.ts(45,18): error
// Example: C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Features.ts (45,18): error
patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceRoot) + '([^\\s\\(\\)]*)(\\s?\\((\\d+)(,(\\d+))?)\\)', 'gi'));
// Example: at C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Game.ts
// Example: at C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Game.ts:336
// Example: at C:\Users\someone\AppData\Local\Temp\_monacodata_9888\workspaces\mankala\Game.ts:336:9
patterns.push(new RegExp(strings.escapeRegExpCharacters(workspaceRoot) + '([^:\\s\\(\\)<>\'\"\\[\\]]*)(:(\\d+))?(:(\\d+))?', 'gi'));
});
return patterns;
}
/**
* Detect links. Made public static to allow for tests.
*/
public static detectLinks(line: string, lineIndex: number, patterns: RegExp[], contextService: IResourceCreator): ILink[] {
let links: ILink[] = [];
patterns.forEach((pattern) => {
pattern.lastIndex = 0; // the holy grail of software development
let match: RegExpExecArray;
let offset = 0;
while ((match = pattern.exec(line)) !== null) {
// Convert the relative path information to a resource that we can use in links
let workspaceRelativePath = strings.rtrim(match[1], '.').replace(/\\/g, '/'); // remove trailing "." that likely indicate end of sentence
let resource:string;
try {
resource = contextService.toResource(workspaceRelativePath).toString();
} catch (error) {
continue; // we might find an invalid URI and then we dont want to loose all other links
}
// Append line/col information to URI if matching
if (match[3]) {
let lineNumber = match[3];
if (match[5]) {
let columnNumber = match[5];
resource = strings.format('{0}#{1},{2}', resource, lineNumber, columnNumber);
} else {
resource = strings.format('{0}#{1}', resource, lineNumber);
}
}
let fullMatch = strings.rtrim(match[0], '.'); // remove trailing "." that likely indicate end of sentence
let index = line.indexOf(fullMatch, offset);
offset += index + fullMatch.length;
var linkRange = {
startColumn: index + 1,
startLineNumber: lineIndex,
endColumn: index + 1 + fullMatch.length,
endLineNumber: lineIndex
};
if (links.some((link) => Range.areIntersectingOrTouching(link.range, linkRange))) {
return; // Do not detect duplicate links
}
links.push({
range: linkRange,
url: resource
});
}
});
return links;
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册