Skip to content
This repository has been archived by the owner on Dec 8, 2020. It is now read-only.

Commit

Permalink
Fixed diagnostic publishing for Legacy Mode (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
KalitaAlexey authored Feb 18, 2017
1 parent 9752a00 commit 8ee2f83
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 58 deletions.
50 changes: 0 additions & 50 deletions src/components/cargo/diagnostic_publisher.ts

This file was deleted.

55 changes: 55 additions & 0 deletions src/components/cargo/diagnostic_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { isAbsolute, join } from 'path';

import { Diagnostic, DiagnosticCollection, Uri } from 'vscode';

import { FileDiagnostic } from './file_diagnostic';

/**
* The path of a diagnostic must be absolute.
* The function prepends the path of the project to the path of the diagnostic.
* @param diagnosticPath The path of the diagnostic
* @param projectPath The path of the project
*/
export function normalizeDiagnosticPath(diagnosticPath: string, projectPath: string): string {
if (isAbsolute(diagnosticPath)) {
return diagnosticPath;
} else {
return join(projectPath, diagnosticPath);
}
}

/**
* Adds the diagnostic to the diagnostics only if the diagnostic isn't in the diagnostics.
* @param diagnostic The diagnostic to add
* @param diagnostics The collection of diagnostics to take the diagnostic
*/
export function addUniqueDiagnostic(diagnostic: FileDiagnostic, diagnostics: DiagnosticCollection): void {
const uri = Uri.file(diagnostic.filePath);

const fileDiagnostics = diagnostics.get(uri);

if (fileDiagnostics === undefined) {
// No diagnostics for the file
// The diagnostic is unique
diagnostics.set(uri, [diagnostic.diagnostic]);
} else if (isUniqueDiagnostic(diagnostic.diagnostic, fileDiagnostics)) {
const newFileDiagnostics = fileDiagnostics.concat([diagnostic.diagnostic]);
diagnostics.set(uri, newFileDiagnostics);
}
}

export function isUniqueDiagnostic(diagnostic: Diagnostic, diagnostics: Diagnostic[]): boolean {
const foundDiagnostic = diagnostics.find(uniqueDiagnostic => {
if (!diagnostic.range.isEqual(uniqueDiagnostic.range)) {
return false;
}

if (diagnostic.message !== uniqueDiagnostic.message) {
return false;
}

return true;
});

return foundDiagnostic === undefined;
}
17 changes: 9 additions & 8 deletions src/components/cargo/output_channel_task_manager.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { window } from 'vscode';
import { DiagnosticCollection, languages, window } from 'vscode';

import { ConfigurationManager } from '../configuration/configuration_manager';

import ChildLogger from '../logging/child_logger';

import { DiagnosticParser } from './diagnostic_parser';

import { DiagnosticPublisher } from './diagnostic_publisher';
import { normalizeDiagnosticPath, addUniqueDiagnostic } from './diagnostic_utils';

import { OutputChannelWrapper } from './output_channel_wrapper';

Expand All @@ -23,9 +23,9 @@ export class OutputChannelTaskManager {

private runningTask: Task | undefined;

private diagnosticParser: DiagnosticParser;
private diagnostics: DiagnosticCollection;

private diagnosticPublisher: DiagnosticPublisher;
private diagnosticParser: DiagnosticParser;

private statusBarItem: OutputChannelTaskStatusBarItem;

Expand All @@ -40,9 +40,9 @@ export class OutputChannelTaskManager {

this.logger = logger;

this.diagnosticParser = new DiagnosticParser();
this.diagnostics = languages.createDiagnosticCollection('rust');

this.diagnosticPublisher = new DiagnosticPublisher();
this.diagnosticParser = new DiagnosticParser();

this.statusBarItem = new OutputChannelTaskStatusBarItem(stopCommandName);
}
Expand Down Expand Up @@ -84,15 +84,16 @@ export class OutputChannelTaskManager {
this.channel.clear();
this.channel.append(`Started cargo ${args.join(' ')}\n\n`);

this.diagnosticPublisher.clearDiagnostics();
this.diagnostics.clear();
});

this.runningTask.setLineReceivedInStdout(line => {
if (parseOutput && line.startsWith('{')) {
const fileDiagnostics = this.diagnosticParser.parseLine(line);

for (const fileDiagnostic of fileDiagnostics) {
this.diagnosticPublisher.publishDiagnostic(fileDiagnostic, cwd);
fileDiagnostic.filePath = normalizeDiagnosticPath(fileDiagnostic.filePath, cwd);
addUniqueDiagnostic(fileDiagnostic, this.diagnostics);
}
} else {
this.channel.append(`${line}\n`);
Expand Down
142 changes: 142 additions & 0 deletions test/components/cargo/diagnostic_utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import * as assert from 'assert';

import { Diagnostic, Range, Uri, languages } from 'vscode';

import { addUniqueDiagnostic, isUniqueDiagnostic, normalizeDiagnosticPath } from '../../../src/components/cargo/diagnostic_utils';

import { FileDiagnostic } from '../../../src/components/cargo/file_diagnostic';

suite('Diagnostic Utils Tests', () => {
suite('normalizeDiagnosticPath', () => {
test('It works for a relative path', () => {
if (process.platform === 'win32') {
assert.equal(normalizeDiagnosticPath('src\\main.rs', 'C:\\Project'), 'C:\\Project\\src\\main.rs');
} else {
assert.equal(normalizeDiagnosticPath('src/main.rs', '/project'), '/project/src/main.rs');
}
});

test('It works for an absolute path', () => {
if (process.platform === 'win32') {
assert.equal(normalizeDiagnosticPath('C:\\Library\\src\\lib.rs', 'C:\\Project'), 'C:\\Library\\src\\lib.rs');
} else {
assert.equal(normalizeDiagnosticPath('/library/src/lib.rs', '/project'), '/library/src/lib.rs');
}
});
});

suite('isUniqueDiagnostic', () => {
test('It returns true for empty diagnostics', () => {
const result = isUniqueDiagnostic(new Diagnostic(new Range(0, 0, 0, 0), '', undefined), []);

assert.equal(result, true);
});

test('It returns true is the diagnostics do not contain any similar diagnostic', () => {
const diagnostics = [
new Diagnostic(new Range(0, 0, 0, 0), '', undefined)
];

const result = isUniqueDiagnostic(new Diagnostic(new Range(1, 2, 3, 4), 'Hello', undefined), diagnostics);

assert.equal(result, true);
});

test('It returns true is the diagnostics contain a diagnostic with same range, but different message', () => {
const diagnostics = [
new Diagnostic(new Range(0, 0, 0, 0), '', undefined)
];

const result = isUniqueDiagnostic(new Diagnostic(new Range(0, 0, 0, 0), 'Hello', undefined), diagnostics);

assert.equal(result, true);
});

test('It returns true is the diagnostics contain a diagnostic with same message, but different range', () => {
const diagnostics = [
new Diagnostic(new Range(0, 0, 0, 0), 'Hello', undefined)
];

const result = isUniqueDiagnostic(new Diagnostic(new Range(1, 2, 3, 4), 'Hello', undefined), diagnostics);

assert.equal(result, true);
});

test('It returns false is the diagnostics contain a diagnostic with the same message and range', () => {
const diagnostics = [
new Diagnostic(new Range(1, 2, 3, 4), 'Hello', undefined)
];

const result = isUniqueDiagnostic(new Diagnostic(new Range(1, 2, 3, 4), 'Hello', undefined), diagnostics);

assert.equal(result, false);
});
});

test('addUniqueDiagnostic adds the diagnostic to the empty diagnostics', () => {
const diagnostic: FileDiagnostic = {
filePath: '/1',
diagnostic: new Diagnostic(new Range(1, 2, 3, 4), 'Hello', undefined)
};

const diagnostics = languages.createDiagnosticCollection('rust');

addUniqueDiagnostic(diagnostic, diagnostics);

const fileDiagnostics = diagnostics.get(Uri.file('/1'));

if (fileDiagnostics === undefined) {
assert.notEqual(fileDiagnostics, undefined);
} else {
assert.equal(fileDiagnostics.length, 1);
}
});

suite('addUniqueDiagnostic', () => {
test('It adds the diagnostic to the diagnostics which do not contain any similar diagnostic', () => {
const diagnostic: FileDiagnostic = {
filePath: '/1',
diagnostic: new Diagnostic(new Range(1, 2, 3, 4), 'Hello', undefined)
};

const diagnostics = languages.createDiagnosticCollection('rust');
diagnostics.set(Uri.file('/1'), [
new Diagnostic(new Range(2, 3, 3, 4), 'Hello', undefined),
new Diagnostic(new Range(1, 2, 3, 4), 'Hell', undefined)
]);

addUniqueDiagnostic(diagnostic, diagnostics);

const fileDiagnostics = diagnostics.get(Uri.file('/1'));

if (fileDiagnostics === undefined) {
assert.notEqual(fileDiagnostics, undefined);
} else {
assert.equal(fileDiagnostics.length, 3);
}
});

test('It does not add the diagnostic to the diagnostics which contain any similar diagnostic', () => {
const diagnostic: FileDiagnostic = {
filePath: '/1',
diagnostic: new Diagnostic(new Range(1, 2, 3, 4), 'Hello', undefined)
};

const diagnostics = languages.createDiagnosticCollection('rust');
diagnostics.set(Uri.file('/1'), [
new Diagnostic(new Range(1, 2, 3, 4), 'Hello', undefined),
new Diagnostic(new Range(1, 2, 3, 4), 'Hell', undefined)
]);

addUniqueDiagnostic(diagnostic, diagnostics);

const fileDiagnostics = diagnostics.get(Uri.file('/1'));

if (fileDiagnostics === undefined) {
assert.notEqual(fileDiagnostics, undefined);
} else {
assert.equal(fileDiagnostics.length, 2);
}
});
});
});

0 comments on commit 8ee2f83

Please sign in to comment.