提交 ecb0a5a7 编写于 作者: J Johannes Rieken

support for diagnostics

上级 466dc695
......@@ -6,11 +6,14 @@
import {TPromise} from 'vs/base/common/winjs.base';
import URI from 'vs/base/common/uri';
import Severity from 'vs/base/common/severity';
import * as editor from 'vs/editor/common/editorCommon';
import * as modes from 'vs/editor/common/modes';
import * as lifecycle from 'vs/base/common/lifecycle';
import * as ts from 'vs/languages/typescript/common/lib/typescriptServices';
import matches from 'vs/editor/common/modes/languageSelector';
import AbstractWorker from './worker/worker';
import {IMarkerService, IMarkerData} from 'vs/platform/markers/common/markers';
import {IModelService} from 'vs/editor/common/services/modelService';
import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest';
import {ParameterHintsRegistry} from 'vs/editor/contrib/parameterHints/common/parameterHints';
......@@ -21,7 +24,7 @@ import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goTo
import {OutlineRegistry} from 'vs/editor/contrib/quickOpen/common/quickOpen';
import {FormatRegistry, FormatOnTypeRegistry} from 'vs/editor/contrib/format/common/format';
export default function registerLanguageFeatures(selector: string, modelService: IModelService, worker: (first:URI, ...more:URI[]) => TPromise<AbstractWorker>): lifecycle.IDisposable {
export function registerLanguageFeatures(modelService: IModelService, markerService: IMarkerService, selector: string, worker: (first: URI, ...more: URI[]) => TPromise<AbstractWorker>): lifecycle.IDisposable {
const disposables: lifecycle.IDisposable[] = [];
disposables.push(SuggestRegistry.register(selector, new SuggestAdapter(modelService, worker)));
disposables.push(ParameterHintsRegistry.register(selector, new ParameterHintsAdapter(modelService, worker)));
......@@ -32,6 +35,8 @@ export default function registerLanguageFeatures(selector: string, modelService:
disposables.push(OutlineRegistry.register(selector, new OutlineAdapter(modelService, worker)));
disposables.push(FormatRegistry.register(selector, new FormatAdapter(modelService, worker)));
disposables.push(FormatOnTypeRegistry.register(selector, new FormatAdapter(modelService, worker)));
disposables.push(new DiagnostcsAdapter(selector, markerService, modelService, worker));
return lifecycle.combinedDispose2(disposables);
}
......@@ -73,6 +78,81 @@ abstract class Adapter {
}
}
// --- diagnostics --- ---
class DiagnostcsAdapter extends Adapter {
private _disposables: lifecycle.IDisposable[] = [];
private _listener: { [uri: string]: lifecycle.IDisposable } = Object.create(null);
constructor(private _selector:string, private _markerService: IMarkerService, modelService: IModelService, worker: (first: URI, ...more: URI[]) => TPromise<AbstractWorker>) {
super(modelService, worker);
const onModelAdd = (model: editor.IModel): void => {
if (!matches(_selector, model.getAssociatedResource(), model.getModeId())) {
return;
}
let handle: number;
this._listener[model.getAssociatedResource().toString()] = model.addListener2(editor.EventType.ModelContentChanged2, () => {
clearTimeout(handle);
handle = setTimeout(() => this._doValidate(model.getAssociatedResource()), 500);
});
this._doValidate(model.getAssociatedResource());
};
const onModelRemoved = (model: editor.IModel): void => {
delete this._listener[model.getAssociatedResource().toString()];
};
this._disposables.push(modelService.onModelAdded(onModelAdd));
this._disposables.push(modelService.onModelRemoved(onModelRemoved));
this._disposables.push(modelService.onModelModeChanged(event => {
onModelRemoved(event.model);
onModelAdd(event.model);
}));
this._disposables.push({
dispose: () => {
for (let key in this._listener) {
this._listener[key].dispose();
}
}
});
modelService.getModels().forEach(onModelAdd);
}
public dispose(): void {
this._disposables = lifecycle.disposeAll(this._disposables);
}
private _doValidate(resource: URI): void {
this._worker(resource).then(worker => TPromise.join([worker.getSyntacticDiagnostics(resource.toString()), worker.getSemanticDiagnostics(resource.toString())])).then(diagnostics => {
const [syntactic, semantic] = diagnostics;
const markers = syntactic.concat(semantic).map(d => this._convertDiagnostics(resource, d));
this._markerService.changeOne(this._selector, resource, markers);
}).done(undefined, err => {
console.error(err);
});
}
private _convertDiagnostics(resource: URI, diag: ts.Diagnostic): IMarkerData {
const {lineNumber: startLineNumber, column: startColumn} = this._offsetToPosition(resource, diag.start);
const {lineNumber: endLineNumber, column: endColumn} = this._offsetToPosition(resource, diag.start + diag.length);
return {
severity: Severity.Error,
startLineNumber,
startColumn,
endLineNumber,
endColumn,
message: ts.flattenDiagnosticMessageText(diag.messageText, '\n')
};
}
}
// --- suggest ------
class SuggestAdapter extends Adapter implements modes.ISuggestSupport {
......
......@@ -8,30 +8,29 @@ import Modes = require('vs/editor/common/modes');
import lifecycle = require('vs/base/common/lifecycle');
import tokenization = require('vs/languages/typescript/common/features/tokenization');
import {AbstractMode, createWordRegExp} from 'vs/editor/common/modes/abstractMode';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
import {IModelService} from 'vs/editor/common/services/modelService';
import {IMarkerService} from 'vs/platform/markers/common/markers';
import {IThreadService} from 'vs/platform/thread/common/thread';
import {RichEditSupport} from 'vs/editor/common/modes/supports/richEditSupport';
export class TypeScriptMode extends AbstractMode implements lifecycle.IDisposable {
public tokenizationSupport: Modes.ITokenizationSupport;
public richEditSupport: Modes.IRichEditSupport;
private _modelService: IModelService;
private _disposables: lifecycle.IDisposable[] = [];
constructor(
descriptor: Modes.IModeDescriptor,
@IModelService modelService: IModelService,
@IThreadService threadService: IThreadService
@IThreadService threadService: IThreadService,
@IModelService private _modelService: IModelService,
@IMarkerService private _markerService: IMarkerService
) {
super(descriptor.id);
this._modelService = modelService;
if (threadService.isInMainThread) {
require(['vs/languages/typescript/common/worker/workerManager'], manager => {
this._disposables.push(manager.create(this.getId(), this._modelService));
this._disposables.push(manager.create(this.getId(), this._modelService, this._markerService));
}, err => {
console.error(err);
});
......
......@@ -41,6 +41,14 @@ abstract class AbstractWorker implements IRequestHandler {
// --- language features
getSyntacticDiagnostics(fileName: string): TPromise<ts.Diagnostic[]> {
throw notImplemented();
}
getSemanticDiagnostics(fileName: string): TPromise<ts.Diagnostic[]> {
throw notImplemented();
}
getCompletionsAtPosition(uri: string, offset: number): TPromise<ts.CompletionInfo> {
throw notImplemented();
}
......
......@@ -108,6 +108,18 @@ class TypeScriptWorker extends AbstractWorker implements ts.LanguageServiceHost
// --- language features
getSyntacticDiagnostics(fileName: string): TPromise<ts.Diagnostic[]> {
const diagnostics = this._languageService.getSyntacticDiagnostics(fileName);
diagnostics.forEach(diag => diag.file = undefined); // diag.file cannot be JSON'yfied
return TPromise.as(diagnostics);
}
getSemanticDiagnostics(fileName: string): TPromise<ts.Diagnostic[]> {
const diagnostics = this._languageService.getSemanticDiagnostics(fileName);
diagnostics.forEach(diag => diag.file = undefined); // diag.file cannot be JSON'yfied
return TPromise.as(diagnostics);
}
getCompletionsAtPosition(fileName: string, position:number): TPromise<ts.CompletionInfo> {
return TPromise.as(this._languageService.getCompletionsAtPosition(fileName, position));
}
......
......@@ -9,10 +9,11 @@ import {TPromise} from 'vs/base/common/winjs.base';
import {IDisposable, disposeAll} from 'vs/base/common/lifecycle';
import {DefaultWorkerFactory} from 'vs/base/worker/defaultWorkerFactory';
import {SimpleWorkerClient} from 'vs/base/common/worker/simpleWorker';
import {IMarkerService} from 'vs/platform/markers/common/markers';
import {IModelService} from 'vs/editor/common/services/modelService';
import {EditorModelManager} from 'vs/editor/common/services/editorWorkerServiceImpl';
import {Defaults} from '../typescript';
import registerLanguageFeatures from '../languageFeatures';
import {registerLanguageFeatures} from '../languageFeatures';
import AbstractWorker from './worker';
class Client {
......@@ -72,11 +73,10 @@ class Client {
}
}
export function create(selector: string, modelService: IModelService) {
export function create(selector: string, modelService: IModelService, markerService: IMarkerService) {
const client = new Client(modelService);
const registration = registerLanguageFeatures(selector,
modelService,
const registration = registerLanguageFeatures(modelService, markerService, selector,
(first: URI, ...more: URI[]) => client.get([first].concat(more)));
return {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册