/*--------------------------------------------------------------------------------------------- * 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 {Remotable, IThreadService} from 'vs/platform/thread/common/thread'; import {IMarkerService, IResourceMarker, IMarkerData} from 'vs/platform/markers/common/markers'; import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; import Severity from 'vs/base/common/severity'; import * as vscode from 'vscode'; class DiagnosticCollection implements vscode.DiagnosticCollection { private static _maxDiagnosticsPerFile: number = 250; private _name: string; private _proxy: MainThreadDiagnostics; private _isDisposed: boolean; constructor(name: string, proxy: MainThreadDiagnostics) { this._name = name; this._proxy = proxy; } dispose(): void { if (!this._isDisposed) { this._proxy._changeAll(this.name, undefined).then(() => { this._proxy = undefined; this._isDisposed = true; }); } } get name(): string { this._checkDisposed(); return this._name; } set(uri: vscode.Uri, diagnostics: vscode.Diagnostic[]): void; set(entries: [vscode.Uri, vscode.Diagnostic[]][]): void; set(first: vscode.Uri | [vscode.Uri, vscode.Diagnostic[]][], diagnostics?: vscode.Diagnostic[]) { this._checkDisposed(); if (first instanceof URI) { // change markers of resource only (max 500) let data: IMarkerData[]; if (diagnostics) { data = []; let len = diagnostics.length; if (len > DiagnosticCollection._maxDiagnosticsPerFile) { console.warn('diagnostics for %s will be capped to %d (actually is %d)', first.toString(), DiagnosticCollection._maxDiagnosticsPerFile, len); len = DiagnosticCollection._maxDiagnosticsPerFile; } for (let i = 0; i < len; i++) { data.push(DiagnosticCollection._toMarkerData(diagnostics[i])); } } // set or reset for this resource return this._proxy._changeOne(this.name, first, data); } else { // change all marker of owner let entries = <[vscode.Uri, vscode.Diagnostic[]][]>first; let data: IResourceMarker[]; if (entries) { let total = 0; data = []; for (let entry of entries) { let [uri, diagnostics] = entry; if (diagnostics) { let len = diagnostics.length; if (len > DiagnosticCollection._maxDiagnosticsPerFile) { console.warn('diagnostics for %s will be capped to %d (actually is %d)', uri.toString(), DiagnosticCollection._maxDiagnosticsPerFile, len); len = DiagnosticCollection._maxDiagnosticsPerFile; } for (let i = 0; i < len; i++) { data.push({ resource: uri, marker: DiagnosticCollection._toMarkerData(diagnostics[i]) }); } total += len; if (total > 10 * DiagnosticCollection._maxDiagnosticsPerFile) { console.warn('too many diagnostics will cap to %d', 10 * DiagnosticCollection._maxDiagnosticsPerFile); break; } } } } // set or reset all this._proxy._changeAll(this.name, data); } } delete(uri: vscode.Uri): void { return this.set(uri, undefined); } clear(): void { return this.set(undefined); } private _checkDisposed() { if (this._isDisposed) { throw new Error('illegal state - object is disposed'); } } private static _toMarkerData(diagnostic: vscode.Diagnostic): IMarkerData { let range = diagnostic.range; return { startLineNumber: range.start.line + 1, startColumn: range.start.character + 1, endLineNumber: range.end.line + 1, endColumn: range.end.character + 1, message: diagnostic.message, source: diagnostic.source, severity: DiagnosticCollection._convertDiagnosticsSeverity(diagnostic.severity), code: String(diagnostic.code) }; } private static _convertDiagnosticsSeverity(severity: number): Severity { switch (severity) { case 0: return Severity.Error; case 1: return Severity.Warning; case 2: return Severity.Info; case 3: return Severity.Ignore; default: return Severity.Error; } } } export class ExtHostDiagnostics { private static _idPool: number = 0; private _proxy: MainThreadDiagnostics; constructor(threadService: IThreadService) { this._proxy = threadService.getRemotable(MainThreadDiagnostics); } createDiagnosticCollection(name: string): vscode.DiagnosticCollection { if (!name) { name = '_generated_diagnostic_collection_name_#' + ExtHostDiagnostics._idPool++; } return new DiagnosticCollection(name, this._proxy); } } @Remotable.MainContext('MainThreadDiagnostics') export class MainThreadDiagnostics { private _markerService: IMarkerService; constructor(@IMarkerService markerService: IMarkerService) { this._markerService = markerService; } _changeOne(owner: string, resource: URI, markers: IMarkerData[]): TPromise { this._markerService.changeOne(owner, resource, markers); return undefined; } _changeAll(owner: string, data: IResourceMarker[]): TPromise { this._markerService.changeAll(owner, data); return undefined; } }