Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix diagnostics not appearing for open files #945

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 40 additions & 34 deletions src/features/diagnosticsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

'use strict';

import {OmniSharpServer} from '../omnisharp/server';
import { OmniSharpServer } from '../omnisharp/server';
import AbstractSupport from './abstractProvider';
import * as protocol from '../omnisharp/protocol';
import * as serverUtils from '../omnisharp/utils';
import {toRange} from '../omnisharp/typeConvertion';
import {Disposable, Uri, CancellationTokenSource, TextDocument, Diagnostic, DiagnosticCollection, DiagnosticSeverity, workspace, languages} from 'vscode';
import { toRange } from '../omnisharp/typeConvertion';
import * as vscode from 'vscode';

export class Advisor {

private _disposable: Disposable;
private _disposable: vscode.Disposable;
private _server: OmniSharpServer;
private _packageRestoreCounter: number = 0;
private _projectSourceFileCounts: { [path: string]: number } = Object.create(null);
Expand All @@ -27,7 +25,7 @@ export class Advisor {
let d3 = server.onProjectRemoved(this._onProjectRemoved, this);
let d4 = server.onBeforePackageRestore(this._onBeforePackageRestore, this);
let d5 = server.onPackageRestore(this._onPackageRestore, this);
this._disposable = Disposable.from(d1, d2, d3, d4, d5);
this._disposable = vscode.Disposable.from(d1, d2, d3, d4, d5);
}

public dispose() {
Expand Down Expand Up @@ -112,29 +110,37 @@ export class Advisor {
}
}

export default function reportDiagnostics(server: OmniSharpServer, advisor: Advisor): Disposable {
export default function reportDiagnostics(server: OmniSharpServer, advisor: Advisor): vscode.Disposable {
return new DiagnosticsProvider(server, advisor);
}

class DiagnosticsProvider extends AbstractSupport {

private _validationAdvisor: Advisor;
private _disposable: Disposable;
private _documentValidations: { [uri: string]: CancellationTokenSource } = Object.create(null);
private _projectValidation: CancellationTokenSource;
private _diagnostics: DiagnosticCollection;
private _disposable: vscode.Disposable;
private _documentValidations: { [uri: string]: vscode.CancellationTokenSource } = Object.create(null);
private _projectValidation: vscode.CancellationTokenSource;
private _diagnostics: vscode.DiagnosticCollection;

constructor(server: OmniSharpServer, validationAdvisor: Advisor) {
super(server);
this._validationAdvisor = validationAdvisor;
this._diagnostics = languages.createDiagnosticCollection('csharp');
this._diagnostics = vscode.languages.createDiagnosticCollection('csharp');

let d1 = this._server.onPackageRestore(this._validateProject, this);
let d2 = this._server.onProjectChange(this._validateProject, this);
let d4 = workspace.onDidOpenTextDocument(event => this._onDocumentAddOrChange(event), this);
let d3 = workspace.onDidChangeTextDocument(event => this._onDocumentAddOrChange(event.document), this);
let d5 = workspace.onDidCloseTextDocument(this._onDocumentRemove, this);
this._disposable = Disposable.from(this._diagnostics, d1, d2, d3, d4, d5);
let d4 = vscode.workspace.onDidOpenTextDocument(event => this._onDocumentAddOrChange(event), this);
let d3 = vscode.workspace.onDidChangeTextDocument(event => this._onDocumentAddOrChange(event.document), this);
let d5 = vscode.workspace.onDidCloseTextDocument(this._onDocumentRemove, this);
this._disposable = vscode.Disposable.from(this._diagnostics, d1, d2, d3, d4, d5);

// Go ahead and check for diagnostics in the currently visible editors.
for (let editor of vscode.window.visibleTextEditors) {
let document = editor.document;
if (document.languageId === 'csharp' && document.uri.scheme === 'file') {
this._validateDocument(document);
}
}
}

public dispose(): void {
Expand All @@ -149,14 +155,14 @@ class DiagnosticsProvider extends AbstractSupport {
this._disposable.dispose();
}

private _onDocumentAddOrChange(document: TextDocument): void {
private _onDocumentAddOrChange(document: vscode.TextDocument): void {
if (document.languageId === 'csharp' && document.uri.scheme === 'file') {
this._validateDocument(document);
this._validateProject();
}
}

private _onDocumentRemove(document: TextDocument) {
private _onDocumentRemove(document: vscode.TextDocument) {
let key = document.uri.toString();
let didChange = false;
if (this._diagnostics[key]) {
Expand All @@ -174,8 +180,7 @@ class DiagnosticsProvider extends AbstractSupport {
}
}

private _validateDocument(document: TextDocument): void {

private _validateDocument(document: vscode.TextDocument): void {
// If we've already started computing for this document, cancel that work.
let key = document.uri.toString();
if (this._documentValidations[key]) {
Expand All @@ -186,9 +191,10 @@ class DiagnosticsProvider extends AbstractSupport {
return;
}

let source = new CancellationTokenSource();
let source = new vscode.CancellationTokenSource();
let handle = setTimeout(() => {
serverUtils.codeCheck(this._server, { Filename: document.fileName }, source.token).then(value => {

// Easy case: If there are no diagnostics in the file, we can clear it quickly.
if (value.QuickFixes.length === 0) {
if (this._diagnostics.has(document.uri)) {
Expand All @@ -197,7 +203,7 @@ class DiagnosticsProvider extends AbstractSupport {

return;
}

// (re)set new diagnostics for this document
let diagnostics = value.QuickFixes.map(DiagnosticsProvider._asDiagnostic);

Expand All @@ -219,19 +225,19 @@ class DiagnosticsProvider extends AbstractSupport {
return;
}

this._projectValidation = new CancellationTokenSource();
this._projectValidation = new vscode.CancellationTokenSource();
let handle = setTimeout(() => {

serverUtils.codeCheck(this._server, { Filename: null }, this._projectValidation.token).then(value => {

let quickFixes = value.QuickFixes.sort((a, b) => a.FileName.localeCompare(b.FileName));
let entries: [Uri, Diagnostic[]][] = [];
let lastEntry: [Uri, Diagnostic[]];
let entries: [vscode.Uri, vscode.Diagnostic[]][] = [];
let lastEntry: [vscode.Uri, vscode.Diagnostic[]];

for (let quickFix of quickFixes) {

let diag = DiagnosticsProvider._asDiagnostic(quickFix);
let uri = Uri.file(quickFix.FileName);
let uri = vscode.Uri.file(quickFix.FileName);

if (lastEntry && lastEntry[0].toString() === uri.toString()) {
lastEntry[1].push(diag);
Expand Down Expand Up @@ -265,21 +271,21 @@ class DiagnosticsProvider extends AbstractSupport {

// --- data converter

private static _asDiagnostic(quickFix: protocol.QuickFix): Diagnostic {
private static _asDiagnostic(quickFix: protocol.QuickFix): vscode.Diagnostic {
let severity = DiagnosticsProvider._asDiagnosticSeverity(quickFix.LogLevel);
let message = `${quickFix.Text} [${quickFix.Projects.map(n => DiagnosticsProvider._asProjectLabel(n)).join(', ') }]`;
return new Diagnostic(toRange(quickFix), message, severity);
let message = `${quickFix.Text} [${quickFix.Projects.map(n => DiagnosticsProvider._asProjectLabel(n)).join(', ')}]`;
return new vscode.Diagnostic(toRange(quickFix), message, severity);
}

private static _asDiagnosticSeverity(logLevel: string): DiagnosticSeverity {
private static _asDiagnosticSeverity(logLevel: string): vscode.DiagnosticSeverity {
switch (logLevel.toLowerCase()) {
case 'warning':
case 'warn':
return DiagnosticSeverity.Warning;
return vscode.DiagnosticSeverity.Warning;
case 'hidden':
return DiagnosticSeverity.Information;
return vscode.DiagnosticSeverity.Information;
default:
return DiagnosticSeverity.Error;
return vscode.DiagnosticSeverity.Error;
}
}

Expand Down