Skip to content

Commit

Permalink
Add visible editor watch and cleanup dispose / tests (#50)
Browse files Browse the repository at this point in the history
* bump vscode engine to latest version

* remove config metrics and use env var

* update docs and package

* add visible editor feature and rework tests

* increment extension version and add vscodeVersion

* add changelog and increment package version
  • Loading branch information
ryanluker authored Apr 23, 2017
1 parent b1030e0 commit 4dfe134
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 73 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
### 0.5.0
[Github Milestone](https://github.com/ryanluker/vscode-coverage-gutters/milestone/5?closed=1)
- added file watch and render feature
- added metrics for vscodeVersion
- use environment variables for ga tracking id
- cleanup tests

### 0.4.0
[Github Milestone](https://github.com/ryanluker/vscode-coverage-gutters/milestone/4?closed=1)
- added keybindings and shortcuts
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
- colour compatibility with light and dark themes

## Requirements
- vscode 1.9.0 and up
- vscode 1.11.x and up
- macos, linux or windows

## Extension Settings
Expand All @@ -42,9 +42,11 @@
|`coverage-gutters.showGutterCoverage`|Show or hide the gutter coverage
|`coverage-gutters.customizable.menus-editor-context-displayCoverage-enabled`|Setting this to false will remove the command from the editor context menu and vice versa
|`coverage-gutters.customizable.menus-editor-context-watchLcovFile-enabled`|Setting this to false will remove the command from the editor context menu and vice versa
|`coverage-gutters.customizable.menus-editor-context-watchVisibleEditors-enabled`|Setting this to false will remove the command from the editor context menu and vice versa
|`coverage-gutters.customizable.menus-editor-context-removeCoverage-enabled`|Setting this to false will remove the command from the editor context menu and vice versa
|`coverage-gutters.customizable.keybindings-displayCoverage-enabled`|Setting this to false will remove the shortcut and vice versa
|`coverage-gutters.customizable.keybindings-watchLcovFile-enabled`|Setting this to false will remove the shortcut and vice versa
|`coverage-gutters.customizable.keybindings-watchVisibleEditors-enabled`|Setting this to false will remove the shortcut and vice versa
|`coverage-gutters.customizable.keybindings-removeCoverage-enabled`|Setting this to false will remove the shortcut and vice versa

Some examples for the highlight colour are as follows:
Expand Down
33 changes: 29 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vscode-coverage-gutters",
"displayName": "Coverage Gutters",
"description": "Display test coverage generated by lcov - works with many languages",
"version": "0.4.0",
"version": "0.5.0",
"license": "MIT",
"repository": {
"type": "git",
Expand All @@ -16,7 +16,7 @@
"bugs": "https://github.com/ryanluker/vscode-coverage-gutters/issues",
"publisher": "ryanluker",
"engines": {
"vscode": "^1.9.0"
"vscode": "^1.11.x"
},
"categories": [
"Other"
Expand Down Expand Up @@ -128,6 +128,11 @@
"default": true,
"description": "enable or disable the watchLcovFile command in the editor/context menu"
},
"coverage-gutters.customizable.menus-editor-context-watchVisibleEditors-enabled": {
"type": "boolean",
"default": true,
"description": "enable or disable the watchVisibleEditors command in the editor/context menu"
},
"coverage-gutters.customizable.menus-editor-context-removeCoverage-enabled": {
"type": "boolean",
"default": true,
Expand All @@ -143,6 +148,11 @@
"default": true,
"description": "enable or disable the keybinding shortcut for watching the lcov file"
},
"coverage-gutters.customizable.keybindings-watchVisibleEditors-enabled": {
"type": "boolean",
"default": true,
"description": "enable or disable the keybinding shortcut for watching visible editors"
},
"coverage-gutters.customizable.keybindings-removeCoverage-enabled": {
"type": "boolean",
"default": true,
Expand All @@ -159,6 +169,10 @@
"command": "extension.watchLcovFile",
"title": "Coverage Gutters: Watch Lcov and Render Changes"
},
{
"command": "extension.watchVisibleEditors",
"title": "Coverage Gutters: Watch Visible Editors and Render Coverage"
},
{
"command": "extension.removeCoverage",
"title": "Coverage Gutters: Remove File Coverage"
Expand All @@ -178,9 +192,15 @@
"when": "config.coverage-gutters.customizable.keybindings-watchLcovFile-enabled"
},
{
"command": "extension.removeCoverage",
"command": "extension.watchVisibleEditors",
"key": "ctrl+shift+9",
"mac": "shift+cmd+9",
"when": "config.coverage-gutters.customizable.keybindings-watchVisibleEditors-enabled"
},
{
"command": "extension.removeCoverage",
"key": "ctrl+shift+0",
"mac": "shift+cmd+0",
"when": "config.coverage-gutters.customizable.keybindings-removeCoverage-enabled"
}
],
Expand All @@ -196,10 +216,15 @@
"command": "extension.watchLcovFile",
"group": "Coverage-Gutters@2"
},
{
"when": "config.coverage-gutters.customizable.menus-editor-context-watchVisibleEditors-enabled",
"command": "extension.watchVisibleEditors",
"group": "Coverage-Gutters@3"
},
{
"when": "config.coverage-gutters.customizable.menus-editor-context-removeCoverage-enabled",
"command": "extension.removeCoverage",
"group": "Coverage-Gutters@3"
"group": "Coverage-Gutters@4"
}
]
}
Expand Down
8 changes: 0 additions & 8 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export class Config {

public setup(): IConfigStore {
const rootCustomConfig = this.vscode.getConfiguration("coverage-gutters.customizable");
this.sendConfigMetrics(rootCustomConfig, "customConfig");

// Customizable UI configurations
const configsCustom = Object.keys(rootCustomConfig);
Expand All @@ -57,7 +56,6 @@ export class Config {
}

const rootConfig = this.vscode.getConfiguration("coverage-gutters");
this.sendConfigMetrics(rootConfig, "config");

// Basic configurations
this.lcovFileName = rootConfig.get("lcovname") as string;
Expand Down Expand Up @@ -133,10 +131,4 @@ export class Config {

return this.get();
}

private sendConfigMetrics(config: WorkspaceConfiguration, category: string) {
Object.keys(config).forEach((configElement) => {
this.reporter.sendEvent(category, configElement, config.get(configElement) as string);
});
}
}
5 changes: 5 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ export function activate(context: vscode.ExtensionContext) {
gutters.watchLcovFile();
});

const watchVisibleEditors = vscode.commands.registerCommand("extension.watchVisibleEditors", () => {
gutters.watchVisibleEditors();
});

const remove = vscode.commands.registerCommand("extension.removeCoverage", () => {
gutters.removeCoverageForActiveFile();
});

context.subscriptions.push(remove);
context.subscriptions.push(display);
context.subscriptions.push(watchLcovFile);
context.subscriptions.push(watchVisibleEditors);
context.subscriptions.push(gutters);
}
60 changes: 28 additions & 32 deletions src/gutters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
ExtensionContext,
FileSystemWatcher,
TextEditor,
version,
window,
} from "vscode";

Expand All @@ -20,24 +21,22 @@ const parseImpl = new LcovParse();

export class Gutters {
private configStore: IConfigStore;
private fileWatcher: FileSystemWatcher;
private lcovWatcher: FileSystemWatcher;
private lcov: Lcov;
private indicators: Indicators;
private reporter: Reporter;
private textEditors: TextEditor[];

constructor(context: ExtensionContext, reporter: Reporter) {
this.configStore = new Config(vscodeImpl, context, reporter).setup();
this.lcov = new Lcov(this.configStore, vscodeImpl, fsImpl);
this.indicators = new Indicators(parseImpl, vscodeImpl, this.configStore);
this.reporter = reporter;
this.textEditors = [];
this.reporter.sendEvent("user", "start");
this.reporter.sendEvent("user", "vscodeVersion", version);
}

public async displayCoverageForActiveFile() {
const textEditor = window.activeTextEditor;
this.addTextEditorToCache(textEditor);
try {
const lcovPath = await this.lcov.find();
await this.loadAndRenderCoverage(textEditor, lcovPath);
Expand All @@ -51,19 +50,14 @@ export class Gutters {
* Watch the lcov file and iterate over textEditors when changes occur
*/
public async watchLcovFile() {
if (this.fileWatcher) { return; }
if (this.lcovWatcher) { return; }

try {
const lcovPath = await this.lcov.find();
this.fileWatcher = vscodeImpl.watchFile(lcovPath);
this.fileWatcher.onDidChange(async (event) => {
this.textEditors.forEach(async (editor) => {
if (!editor.document) {
// editor can no longer display coverage, remove from cache
this.removeTextEditorFromCache(editor);
} else {
this.loadAndRenderCoverage(editor, lcovPath);
}
this.lcovWatcher = vscodeImpl.watchFile(lcovPath);
this.lcovWatcher.onDidChange(async (event) => {
window.visibleTextEditors.forEach(async (editor) => {
await this.loadAndRenderCoverage(editor, lcovPath);
});
});
this.reporter.sendEvent("user", "watch-lcov");
Expand All @@ -72,39 +66,40 @@ export class Gutters {
}
}

/**
* Watch the visible editors and render coverage when changes occur
*/
public async watchVisibleEditors() {
try {
const lcovPath = await this.lcov.find();
window.onDidChangeVisibleTextEditors(async (event) => {
window.visibleTextEditors.forEach(async (editor) => {
await this.loadAndRenderCoverage(editor, lcovPath);
});
});
this.reporter.sendEvent("user", "watch-editors");
} catch (error) {
this.handleError(error);
}
}

public removeCoverageForActiveFile() {
const activeEditor = window.activeTextEditor;
this.removeTextEditorFromCache(activeEditor);
this.removeDecorationsForTextEditor(activeEditor);
this.reporter.sendEvent("user", "remove-coverage");
}

public dispose() {
this.fileWatcher.dispose();
this.textEditors.forEach(this.removeDecorationsForTextEditor);
this.lcovWatcher.dispose();
this.reporter.sendEvent("cleanup", "dispose");
}

public getTextEditors(): TextEditor[] {
return this.textEditors;
}

private handleError(error: Error) {
const message = error.message ? error.message : error;
window.showErrorMessage(message.toString());
window.showWarningMessage(message.toString());
this.reporter.sendEvent("error", message.toString());
}

private addTextEditorToCache(editor: TextEditor) {
// keep textEditors a unique array by removing existing editors
this.textEditors = this.textEditors.filter((cache) => cache !== editor);
this.textEditors.push(editor);
}

private removeTextEditorFromCache(editor: TextEditor) {
this.textEditors = this.textEditors.filter((cache) => cache !== editor);
}

private removeDecorationsForTextEditor(editor: TextEditor) {
if (!editor) { return; }
editor.setDecorations(this.configStore.fullCoverageDecorationType, []);
Expand All @@ -117,5 +112,6 @@ export class Gutters {
const file = textEditor.document.fileName;
const coveredLines = await this.indicators.extract(lcovFile, file);
await this.indicators.renderToTextEditor(coveredLines, textEditor);
this.reporter.sendEvent("user", "loadAndRenderCoverage");
}
}
10 changes: 4 additions & 6 deletions src/reporter.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import {platform} from "os";
import {Request} from "./wrappers/request";
import {Uuid} from "./wrappers/uuid";

const PLATFORM = platform();
const GA_TRACKING_ID = ""; // add before a release;
const EXT_NAME = "vscode-coverage-gutters";
const EXT_VERSION = "0.4.0";
const EXT_VERSION = "0.5.0";

export class Reporter {
private readonly cid: string;
private readonly enableMetrics: boolean;
private readonly GA_TRACKING_ID: string;
private readonly request: Request;

constructor(request: Request, uuid: Uuid, enableMetrics: boolean) {
this.GA_TRACKING_ID = process.env.GA_TRACKING_ID || "";
this.request = request;
this.cid = uuid.get();
this.enableMetrics = enableMetrics;
Expand All @@ -34,8 +33,7 @@ export class Reporter {
el: label,
ev: value,
t: "event",
tid: GA_TRACKING_ID,
ua: PLATFORM,
tid: this.GA_TRACKING_ID,
v: "1",
};

Expand Down
22 changes: 0 additions & 22 deletions test/gutters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,9 @@ suite("Gutters Tests", function() {
} as any;

const gutters = new Gutters(ctx, reporter);
assert.equal(gutters.getTextEditors().length, 0);
return done();
} catch (e) {
return done(e);
}
});

test("Should remove the activeEditor from the textEditors array", async function() {
this.timeout(12000);
const ctx: vscode.ExtensionContext = {
asAbsolutePath() {
return "test";
},
subscriptions: [],
} as any;
const reporter: Reporter = {
sendEvent() {
return;
},
} as any;

const gutters = new Gutters(ctx, reporter);
await gutters.displayCoverageForActiveFile();
assert.equal(gutters.getTextEditors().length, 1);
gutters.removeCoverageForActiveFile();
assert.equal(gutters.getTextEditors().length, 0);
});
});
21 changes: 21 additions & 0 deletions test/reporter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,25 @@ suite("Reporter Tests", function() {
const reporter = new Reporter(fakeRequest, fakeUuid, true);
reporter.sendEvent("test", "action");
});

test("GA tracking id should be set by env variable", function() {
process.env.GA_TRACKING_ID = "123";

const fakeRequest = {
post(uri: string, options?: IOptions) {
// tslint:disable-next-line:no-string-literal
assert.equal(options.form["tid"], "123");
return;
},
};

const fakeUuid = {
get() {
return "fakeuuidhere";
},
};

const reporter = new Reporter(fakeRequest, fakeUuid, true);
reporter.sendEvent("test", "action");
});
});

0 comments on commit 4dfe134

Please sign in to comment.