Skip to content

Commit

Permalink
Add status icon feature and cleanup (#56)
Browse files Browse the repository at this point in the history
* 54: remove process env GA method

* 55: use rel sf compare by default
add metric to judge the number of people swapping back

* 53: collapse watch commands and add remove

* cleanup tslint

* 53: add statusbar item and toggler

* 51: switch to DI for gutters

* cleanup tool tip naming

* add more tests to gutters

* cleanup textEditor being null

* cleanup error case on render coverage
  • Loading branch information
ryanluker authored May 1, 2017
1 parent 4dfe134 commit 09c3b4f
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 89 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
|Setting | Description
|--------|------------
|`coverage-gutters.lcovname`|Allows specification of a custom lcov file name
|`coverage-gutters.altSfCompare`|Uses a relative method of comparing lcov source file paths
|`coverage-gutters.altSfCompare`|Uses a relative method of comparing lcov source file paths (default true)
|`coverage-gutters.highlightlight`|Changes the highlight for light themes
|`coverage-gutters.highlightdark`|Changes the highlight for dark themes
|`coverage-gutters.partialHighlightLight`|Changes the partial highlight for light themes
Expand Down
42 changes: 21 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
},
"coverage-gutters.altSfCompare": {
"type": "boolean",
"default": false,
"default": true,
"description": "uses a relative method of comparing lcov source file paths"
},
"coverage-gutters.highlightlight": {
Expand Down Expand Up @@ -123,15 +123,15 @@
"default": true,
"description": "enable or disable the displayCoverage command in the editor/context menu"
},
"coverage-gutters.customizable.menus-editor-context-watchLcovFile-enabled": {
"coverage-gutters.customizable.menus-editor-context-watchLcovAndVisibleEditors-enabled": {
"type": "boolean",
"default": true,
"description": "enable or disable the watchLcovFile command in the editor/context menu"
"description": "enable or disable the watchLcovAndVisibleEditors command in the editor/context menu"
},
"coverage-gutters.customizable.menus-editor-context-watchVisibleEditors-enabled": {
"coverage-gutters.customizable.menus-editor-context-removeWatch-enabled": {
"type": "boolean",
"default": true,
"description": "enable or disable the watchVisibleEditors command in the editor/context menu"
"description": "enable or disable the removeWatch command in the editor/context menu"
},
"coverage-gutters.customizable.menus-editor-context-removeCoverage-enabled": {
"type": "boolean",
Expand All @@ -143,15 +143,15 @@
"default": true,
"description": "enable or disable the keybinding shortcut for enabling coverage on the active file"
},
"coverage-gutters.customizable.keybindings-watchLcovFile-enabled": {
"coverage-gutters.customizable.keybindings-watchLcovAndVisibleEditors-enabled": {
"type": "boolean",
"default": true,
"description": "enable or disable the keybinding shortcut for watching the lcov file"
"description": "enable or disable the keybinding shortcut for watching the lcov file and visible editors"
},
"coverage-gutters.customizable.keybindings-watchVisibleEditors-enabled": {
"coverage-gutters.customizable.keybindings-removeWatch-enabled": {
"type": "boolean",
"default": true,
"description": "enable or disable the keybinding shortcut for watching visible editors"
"description": "enable or disable the keybinding shortcut for removing the watch on lcov and editors"
},
"coverage-gutters.customizable.keybindings-removeCoverage-enabled": {
"type": "boolean",
Expand All @@ -166,12 +166,12 @@
"title": "Coverage Gutters: Display File Coverage"
},
{
"command": "extension.watchLcovFile",
"title": "Coverage Gutters: Watch Lcov and Render Changes"
"command": "extension.watchLcovAndVisibleEditors",
"title": "Coverage Gutters: Watch Lcov File and Visible Editors"
},
{
"command": "extension.watchVisibleEditors",
"title": "Coverage Gutters: Watch Visible Editors and Render Coverage"
"command": "extension.removeWatch",
"title": "Coverage Gutters: Remove Lcov and Editor Watch"
},
{
"command": "extension.removeCoverage",
Expand All @@ -186,16 +186,16 @@
"when": "config.coverage-gutters.customizable.keybindings-displayCoverage-enabled"
},
{
"command": "extension.watchLcovFile",
"command": "extension.watchLcovAndVisibleEditors",
"key": "ctrl+shift+8",
"mac": "shift+cmd+8",
"when": "config.coverage-gutters.customizable.keybindings-watchLcovFile-enabled"
"when": "config.coverage-gutters.customizable.keybindings-watchLcovAndVisibleEditors-enabled"
},
{
"command": "extension.watchVisibleEditors",
"command": "extension.removeWatch",
"key": "ctrl+shift+9",
"mac": "shift+cmd+9",
"when": "config.coverage-gutters.customizable.keybindings-watchVisibleEditors-enabled"
"when": "config.coverage-gutters.customizable.keybindings-removeWatch-enabled"
},
{
"command": "extension.removeCoverage",
Expand All @@ -212,13 +212,13 @@
"group": "Coverage-Gutters@1"
},
{
"when": "config.coverage-gutters.customizable.menus-editor-context-watchLcovFile-enabled",
"command": "extension.watchLcovFile",
"when": "config.coverage-gutters.customizable.menus-editor-context-watchLcovAndVisibleEditors-enabled",
"command": "extension.watchLcovAndVisibleEditors",
"group": "Coverage-Gutters@2"
},
{
"when": "config.coverage-gutters.customizable.menus-editor-context-watchVisibleEditors-enabled",
"command": "extension.watchVisibleEditors",
"when": "config.coverage-gutters.customizable.menus-editor-context-removeWatch-enabled",
"command": "extension.removeWatch",
"group": "Coverage-Gutters@3"
},
{
Expand Down
3 changes: 3 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class Config {
this.vscode = vscode;
this.context = context;
this.reporter = reporter;
this.setup();
}

public get(): IConfigStore {
Expand Down Expand Up @@ -60,6 +61,8 @@ export class Config {
// Basic configurations
this.lcovFileName = rootConfig.get("lcovname") as string;
this.altSfCompare = rootConfig.get("altSfCompare") as boolean;
this.reporter.sendEvent("config", "lcovFileName", this.lcovFileName);
this.reporter.sendEvent("config", "altSfCompare", this.altSfCompare.toString());

// Themes and icons
const coverageLightBackgroundColour = rootConfig.get("highlightlight") as string;
Expand Down
31 changes: 23 additions & 8 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
import * as vscode from "vscode";
import {Config} from "./config";
import {Gutters} from "./gutters";
import {Indicators} from "./indicators";
import {Lcov} from "./lcov";
import {Reporter} from "./reporter";
import {StatusBarToggler} from "./statusbartoggler";
import {Fs} from "./wrappers/fs";
import {LcovParse} from "./wrappers/lcov-parse";
import {Request} from "./wrappers/request";
import {Uuid} from "./wrappers/uuid";
import {Vscode} from "./wrappers/vscode";

const fsImpl = new Fs();
const parseImpl = new LcovParse();
const vscodeImpl = new Vscode();

export function activate(context: vscode.ExtensionContext) {
const enableMetrics = vscode.workspace.getConfiguration("telemetry").get("enableTelemetry") as boolean;
const reporter = new Reporter(new Request(), new Uuid(), enableMetrics);
const gutters = new Gutters(context, reporter);
const reporter = new Reporter(new Request(), new Uuid(), "", enableMetrics);
const statusBarToggler = new StatusBarToggler();
const configStore = new Config(vscodeImpl, context, reporter).get();
const lcov = new Lcov(configStore, vscodeImpl, fsImpl);
const indicators = new Indicators(parseImpl, vscodeImpl, configStore);
const gutters = new Gutters(configStore, lcov, indicators, reporter, statusBarToggler);

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

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

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

const remove = vscode.commands.registerCommand("extension.removeCoverage", () => {
Expand All @@ -27,7 +42,7 @@ export function activate(context: vscode.ExtensionContext) {

context.subscriptions.push(remove);
context.subscriptions.push(display);
context.subscriptions.push(watchLcovFile);
context.subscriptions.push(watchVisibleEditors);
context.subscriptions.push(watch);
context.subscriptions.push(removeWatch);
context.subscriptions.push(gutters);
}
96 changes: 55 additions & 41 deletions src/gutters.ts
Original file line number Diff line number Diff line change
@@ -1,117 +1,131 @@
import {
ExtensionContext,
Disposable,
FileSystemWatcher,
StatusBarItem,
TextEditor,
version,
window,
} from "vscode";

import {Fs} from "./wrappers/fs";
import {LcovParse} from "./wrappers/lcov-parse";
import {Vscode} from "./wrappers/vscode";

import {Config, IConfigStore} from "./config";
import {IConfigStore} from "./config";
import {Indicators} from "./indicators";
import {Lcov} from "./lcov";
import {Reporter} from "./reporter";
import {StatusBarToggler} from "./statusbartoggler";

const vscodeImpl = new Vscode();
const fsImpl = new Fs();
const parseImpl = new LcovParse();

export class Gutters {
private configStore: IConfigStore;
private lcovWatcher: FileSystemWatcher;
private editorWatcher: Disposable;
private statusBarItem: StatusBarItem;
private lcov: Lcov;
private indicators: Indicators;
private reporter: Reporter;
private statusBar: StatusBarToggler;

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);
constructor(
configStore: IConfigStore,
lcov: Lcov,
indicators: Indicators,
reporter: Reporter,
statusBar: StatusBarToggler,
) {
this.configStore = configStore;
this.lcov = lcov;
this.indicators = indicators;
this.statusBar = statusBar;
this.reporter = reporter;

this.reporter.sendEvent("user", "start");
this.reporter.sendEvent("user", "vscodeVersion", version);
}

public async displayCoverageForActiveFile() {
const textEditor = window.activeTextEditor;
try {
if (!textEditor) { return; }
const lcovPath = await this.lcov.find();
await this.loadAndRenderCoverage(textEditor, lcovPath);

this.reporter.sendEvent("user", "display-coverage");
} catch (error) {
this.handleError(error);
}
}

/**
* Watch the lcov file and iterate over textEditors when changes occur
*/
public async watchLcovFile() {
if (this.lcovWatcher) { return; }
public async watchLcovAndVisibleEditors() {
if (this.lcovWatcher && this.editorWatcher) { return; }

try {
const lcovPath = await this.lcov.find();
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");
this.lcovWatcher.onDidChange((event) => this.renderCoverageOnVisible(lcovPath));
this.editorWatcher = window.onDidChangeVisibleTextEditors(
(event) => this.renderCoverageOnVisible(lcovPath));
this.statusBar.toggle();

this.reporter.sendEvent("user", "watch-lcov-editors");
} catch (error) {
this.handleError(error);
}
}

/**
* 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 removeWatch() {
this.lcovWatcher.dispose();
this.editorWatcher.dispose();
this.lcovWatcher = null;
this.editorWatcher = null;
this.statusBar.toggle();

this.reporter.sendEvent("user", "remove-watch");
}

public removeCoverageForActiveFile() {
const activeEditor = window.activeTextEditor;
this.removeDecorationsForTextEditor(activeEditor);

this.reporter.sendEvent("user", "remove-coverage");
}

public dispose() {
this.lcovWatcher.dispose();
this.editorWatcher.dispose();
this.statusBar.dispose();

this.reporter.sendEvent("cleanup", "dispose");
}

private handleError(error: Error) {
const message = error.message ? error.message : error;
window.showWarningMessage(message.toString());

this.reporter.sendEvent("error", message.toString());
}

private removeDecorationsForTextEditor(editor: TextEditor) {
if (!editor) { return; }
editor.setDecorations(this.configStore.fullCoverageDecorationType, []);
editor.setDecorations(this.configStore.partialCoverageDecorationType, []);
editor.setDecorations(this.configStore.noCoverageDecorationType, []);
private removeDecorationsForTextEditor(textEditor: TextEditor) {
if (!textEditor) { return; }
textEditor.setDecorations(this.configStore.fullCoverageDecorationType, []);
textEditor.setDecorations(this.configStore.partialCoverageDecorationType, []);
textEditor.setDecorations(this.configStore.noCoverageDecorationType, []);
}

private async loadAndRenderCoverage(textEditor: TextEditor, lcovPath: string): Promise<void> {
const lcovFile = await this.lcov.load(lcovPath);
const file = textEditor.document.fileName;
const coveredLines = await this.indicators.extract(lcovFile, file);
await this.indicators.renderToTextEditor(coveredLines, textEditor);

this.reporter.sendEvent("user", "loadAndRenderCoverage");
}

private renderCoverageOnVisible(lcovPath: string) {
window.visibleTextEditors.forEach(async (editor) => {
if (!editor) { return; }
await this.loadAndRenderCoverage(editor, lcovPath);
});
}
}
8 changes: 4 additions & 4 deletions src/reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ 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 gaTrackingId: string;
private readonly request: Request;

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

Expand Down
Loading

0 comments on commit 09c3b4f

Please sign in to comment.