Skip to content

Commit 30bfb12

Browse files
authored
Add show/hide coverage commands (#73)
This introduces commands to the extension. The first two commands will "hide" and "show" the diagnostics. It hides/shows the diagnostics by clearing them out and then repopulating them. Fixes #38
1 parent b4125c7 commit 30bfb12

File tree

5 files changed

+170
-83
lines changed

5 files changed

+170
-83
lines changed

package.json

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,21 @@
5959
"description": "Search location for lcov files"
6060
}
6161
}
62-
}
62+
},
63+
"activationEvents": [
64+
"onCommand:code-coverage.hide",
65+
"onCommand:code-coverage.show"
66+
],
67+
"commands": [
68+
{
69+
"command": "code-coverage.hide",
70+
"title": "Hide Code Coverage"
71+
},
72+
{
73+
"command": "code-coverage.show",
74+
"title": "Show Code Coverage"
75+
}
76+
]
6377
},
6478
"eslintConfig": {
6579
"env": {
@@ -91,10 +105,10 @@
91105
"vscode:prepublish": "tsc -p ./",
92106
"compile": "tsc -p ./",
93107
"compile:watch": "tsc -watch -p ./",
94-
"preformat": "prettier --write src/**/*.ts",
95-
"format": "eslint --fix src/**/*.ts",
96-
"prelint": "prettier --check src/**/*.ts",
97-
"lint": "eslint src/**/*.ts",
108+
"preformat": "prettier --write src/**/*.ts test/**/*.ts",
109+
"format": "eslint --fix src/**/*.ts test/**/*.ts",
110+
"prelint": "prettier --check src/**/*.ts test/**/*.ts",
111+
"lint": "eslint src/**/*.ts test/**/*.ts",
98112
"pretest": "npm run compile",
99113
"test": "node ./out/test/run-test.js"
100114
},

src/extension.ts

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { isAbsolute, join } from "path";
22
import {
3+
commands,
34
Diagnostic,
45
DiagnosticSeverity,
56
ExtensionContext,
@@ -21,11 +22,26 @@ import { parse as parseLcov } from "./parse-lcov";
2122

2223
const DEFAULT_SEARCH_CRITERIA = "coverage/lcov*.info";
2324

25+
export let onCommand: (cmd: string) => Promise<void> = noop;
26+
27+
export async function deactivate() {
28+
onCommand = noop;
29+
}
30+
2431
export async function activate(context: ExtensionContext) {
2532
const packageInfo = require(join(context.extensionPath, "package.json"));
2633
const diagnostics = languages.createDiagnosticCollection("coverage");
2734
const statusBar = window.createStatusBarItem();
35+
const hideCommand = commands.registerCommand(
36+
`${packageInfo.name}.hide`,
37+
onHideCoverage
38+
);
39+
const showCommand = commands.registerCommand(
40+
`${packageInfo.name}.show`,
41+
onShowCoverage
42+
);
2843
const coverageByFile = new Map<string, Coverage>();
44+
let showCoverage = true;
2945

3046
const config = workspace.getConfiguration("markiscodecoverage");
3147
const configSearchCriteria =
@@ -47,7 +63,7 @@ export async function activate(context: ExtensionContext) {
4763
}
4864
}
4965

50-
context.subscriptions.push(diagnostics, statusBar);
66+
context.subscriptions.push(diagnostics, statusBar, showCommand, hideCommand);
5167

5268
// Update status bar on changes to any open file
5369
workspace.onDidChangeTextDocument((e) => {
@@ -67,8 +83,31 @@ export async function activate(context: ExtensionContext) {
6783
});
6884

6985
// Run the main routine at activation time as well
70-
if (workspaceFolders) {
71-
await Promise.all(workspaceFolders.map(findDiagnostics));
86+
await findDiagnosticsInWorkspace();
87+
88+
onCommand = async function onCommand(cmd: string) {
89+
switch (cmd) {
90+
case `${packageInfo.name}.hide`:
91+
return onHideCoverage();
92+
case `${packageInfo.name}.show`:
93+
return onShowCoverage();
94+
}
95+
};
96+
97+
async function onHideCoverage() {
98+
showCoverage = false;
99+
diagnostics.clear();
100+
}
101+
102+
async function onShowCoverage() {
103+
showCoverage = true;
104+
await findDiagnosticsInWorkspace();
105+
}
106+
107+
async function findDiagnosticsInWorkspace() {
108+
if (workspaceFolders) {
109+
await Promise.all(workspaceFolders.map(findDiagnostics));
110+
}
72111
}
73112

74113
// Finds VSCode diagnostics to display based on a coverage file specified by the search pattern in each workspace folder
@@ -123,6 +162,8 @@ export async function activate(context: ExtensionContext) {
123162
coverages: CoverageCollection,
124163
workspaceFolder: string
125164
) {
165+
if (!showCoverage) return; // do nothing
166+
126167
for (const coverage of coverages) {
127168
if (coverage && coverage.lines && coverage.lines.details) {
128169
const fileName = !isAbsolute(coverage.file)
@@ -147,14 +188,14 @@ export async function activate(context: ExtensionContext) {
147188
details: LineCoverageInfo[],
148189
fileName: string
149190
) {
150-
const currentFile = window.activeTextEditor?.document.uri.fsPath;
191+
const doc = window.activeTextEditor?.document;
192+
const currentFile = doc?.uri.fsPath;
151193
const diagnosticsForFiles: Diagnostic[] = [];
152194
for (const detail of details) {
153195
const line = detail.line - 1;
154196
if (detail.hit === 0) {
155197
const range =
156-
(currentFile === fileName &&
157-
window.activeTextEditor?.document.lineAt(line).range) ||
198+
(currentFile === fileName && doc?.lineAt(line).range) ||
158199
new Range(new Position(line, 0), new Position(line, 1000));
159200
diagnosticsForFiles.push(
160201
new Diagnostic(
@@ -169,5 +210,7 @@ export async function activate(context: ExtensionContext) {
169210
}
170211

171212
// exports - accessible to tests
172-
return { statusBar };
213+
return { onCommand, statusBar };
173214
}
215+
216+
async function noop() {}

test/run-test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
import * as path from 'path';
1+
import * as path from "path";
22

3-
import { runTests } from '@vscode/test-electron';
3+
import { runTests } from "@vscode/test-electron";
44

55
async function main() {
66
try {
77
// The folder containing the Extension Manifest package.json
88
// Passed to `--extensionDevelopmentPath`
9-
const extensionDevelopmentPath = path.resolve(__dirname, '../../../');
9+
const extensionDevelopmentPath = path.resolve(__dirname, "../../../");
1010

1111
// The path to the extension test runner script
1212
// Passed to --extensionTestsPath
13-
const extensionTestsPath = path.resolve(__dirname, './suite/');
13+
const extensionTestsPath = path.resolve(__dirname, "./suite/");
1414

1515
// Download VS Code, unzip it and run the integration test
1616
await runTests({ extensionDevelopmentPath, extensionTestsPath });
1717
} catch (err) {
1818
console.error(err);
19-
console.error('Failed to run tests');
19+
console.error("Failed to run tests");
2020
process.exit(1);
2121
}
2222
}
2323

24-
main();
24+
main();

test/suite/extension.test.ts

Lines changed: 66 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,66 @@
1-
import * as assert from 'assert';
2-
import { join } from 'path';
3-
import { commands, extensions, languages, StatusBarItem, Uri, window, workspace } from 'vscode';
4-
5-
suite('code-coverage', () => {
6-
const exampleWorkspace = join(__dirname, '../../../', 'example');
7-
const exampleWorkspaceUri = Uri.file(exampleWorkspace);
8-
const exampleIndexFile = join(exampleWorkspace, 'index.ts');
9-
const extension = extensions.getExtension("markis.code-coverage");
10-
11-
setup(async () => {
12-
// Open the example workspace and open the example index file
13-
await commands.executeCommand('vscode.openFolder', exampleWorkspaceUri);
14-
const doc = await workspace.openTextDocument(exampleIndexFile);
15-
await window.showTextDocument(doc);
16-
});
17-
18-
teardown(async () => {
19-
// All done, close the editor
20-
commands.executeCommand('workbench.action.closeActiveEditor');
21-
});
22-
23-
test('check diagnostics exist', async () => {
24-
// Check to see if the diagnostics exist for the example file
25-
// there should only be one line not covered, and so only one diagnostic should exist
26-
const diagnostics = languages.getDiagnostics(Uri.file(exampleIndexFile));
27-
assert.strictEqual(diagnostics.length, 1);
28-
assert.strictEqual(diagnostics[0].range.start.line, 5);
29-
});
30-
31-
test('check status bar', async () => {
32-
// Check to see if the status bar is updated correctly
33-
// the example coverage should cover 3 out of 4 lines - "3/4"
34-
const statusBar: StatusBarItem = extension?.exports.statusBar;
35-
assert.ok(statusBar.text);
36-
assert.ok(statusBar.text.includes('3/4'))
37-
});
38-
});
1+
import * as assert from "assert";
2+
import { join } from "path";
3+
import {
4+
commands,
5+
extensions,
6+
languages,
7+
StatusBarItem,
8+
Uri,
9+
window,
10+
workspace,
11+
Extension,
12+
} from "vscode";
13+
14+
suite("code-coverage", function () {
15+
this.timeout(10000);
16+
const exampleWorkspace = join(__dirname, "../../../", "example");
17+
const exampleWorkspaceUri = Uri.file(exampleWorkspace);
18+
const exampleIndexUri = Uri.file(join(exampleWorkspace, "index.ts"));
19+
let extension: Extension<any> | undefined;
20+
let onCommand: (cmd: string) => Promise<void> | undefined;
21+
22+
setup(async () => {
23+
// Open the example workspace and open the example index file
24+
await commands.executeCommand("vscode.openFolder", exampleWorkspaceUri);
25+
const doc = await workspace.openTextDocument(exampleIndexUri);
26+
await window.showTextDocument(doc);
27+
extension = extensions.getExtension("markis.code-coverage");
28+
onCommand = extension?.exports.onCommand;
29+
});
30+
31+
teardown(async () => {
32+
// All done, close the editor
33+
commands.executeCommand("workbench.action.closeActiveEditor");
34+
});
35+
36+
test("check diagnostics exist", async () => {
37+
// Check to see if the diagnostics exist for the example file
38+
// there should only be one line not covered, and so only one diagnostic should exist
39+
const diagnostics = languages.getDiagnostics(exampleIndexUri);
40+
assert.strictEqual(diagnostics.length, 1);
41+
assert.strictEqual(diagnostics[0].range.start.line, 5);
42+
});
43+
44+
test("check status bar", async () => {
45+
// Check to see if the status bar is updated correctly
46+
// the example coverage should cover 3 out of 4 lines - "3/4"
47+
const statusBar: StatusBarItem = extension?.exports.statusBar;
48+
assert.ok(statusBar.text);
49+
assert.ok(statusBar.text.includes("3/4"));
50+
});
51+
52+
test("test commands hide coverage", async () => {
53+
// Ensure coverage exists
54+
assert.strictEqual(languages.getDiagnostics(exampleIndexUri).length, 1);
55+
56+
// Hide coverage
57+
await onCommand("code-coverage.hide");
58+
assert.strictEqual(languages.getDiagnostics(exampleIndexUri).length, 0);
59+
});
60+
61+
test("test commands show coverage", async () => {
62+
// Show coverage
63+
await onCommand("code-coverage.show");
64+
assert.strictEqual(languages.getDiagnostics(exampleIndexUri).length, 1);
65+
});
66+
});

test/suite/index.ts

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,33 @@
1+
import * as path from "path";
2+
import * as Mocha from "mocha";
3+
import * as glob from "glob";
14

2-
import * as path from 'path';
3-
import * as Mocha from 'mocha';
4-
import * as glob from 'glob';
5+
export function run(
6+
testsRoot: string,
7+
cb: (error: any, failures?: number) => void
8+
): void {
9+
// Create the mocha test
10+
const mocha = new Mocha({
11+
ui: "tdd",
12+
});
13+
mocha.useColors(true);
514

6-
export function run(testsRoot: string, cb: (error: any, failures?: number) => void): void {
7-
// Create the mocha test
8-
const mocha = new Mocha({
9-
ui: 'tdd'
10-
});
11-
mocha.useColors(true);
15+
glob("**/**.test.js", { cwd: testsRoot }, (err, files) => {
16+
if (err) {
17+
return cb(err);
18+
}
1219

13-
glob('**/**.test.js', { cwd: testsRoot }, (err, files) => {
14-
if (err) {
15-
return cb(err);
16-
}
20+
// Add files to the test suite
21+
files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f)));
1722

18-
// Add files to the test suite
19-
files.forEach(f => mocha.addFile(path.resolve(testsRoot, f)));
20-
21-
try {
22-
// Run the mocha test
23-
mocha.run(failures => {
24-
cb(null, failures);
25-
});
26-
} catch (err) {
27-
console.error(err);
28-
cb(err);
29-
}
30-
});
31-
}
23+
try {
24+
// Run the mocha test
25+
mocha.run((failures) => {
26+
cb(null, failures);
27+
});
28+
} catch (err) {
29+
console.error(err);
30+
cb(err);
31+
}
32+
});
33+
}

0 commit comments

Comments
 (0)