Skip to content

Commit

Permalink
chore: cleanup internal services
Browse files Browse the repository at this point in the history
  • Loading branch information
sibiraj-s committed Mar 24, 2020
1 parent ea7d02c commit 8952533
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 158 deletions.
99 changes: 72 additions & 27 deletions src/FormatterProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,80 @@ import {
TextEdit, workspace, WorkspaceConfiguration
} from 'vscode';

import { safeExecution } from './errorHandler';

async function formatDocument(document: TextDocument): Promise<string> {
const workspaceConfiguration: WorkspaceConfiguration = workspace.getConfiguration('scssFormatter');
const rawDocumentText = document.getText();
const { fileName, languageId } = document;

const options: PrettierOptions = {
...Object.assign({}, workspaceConfiguration),
parser: languageId as BuiltInParserName
};

return safeExecution(
() => format(rawDocumentText, options),
rawDocumentText,
fileName
);
}
import LoggingService from './LoggingService';
import StatusBarService from './StatusBarService';

// get range for the current document
function fullDocumentRange(document: TextDocument): Range {
const rangeStart: Position = document.lineAt(0).range.start;
const rangeEnd: Position = document.lineAt(document.lineCount - 1).range.end;
return new Range(rangeStart, rangeEnd);
}
import { EXTENSION_NAME } from './utils';

class SCSSFormatter implements DocumentFormattingEditProvider {
private loggingService: LoggingService;
private statusbarService: StatusBarService;

constructor(loggingService: LoggingService, statusbarService: StatusBarService) {
this.loggingService = loggingService;
this.statusbarService = statusbarService;
}

// add filepath to the output message
private addFilePathToMesssage(message: string, fileName: string): string {
const lines = message.split('\n');
if (lines.length > 0) {
lines[0] = lines[0].replace(/(\d*):(\d*)/g, `${fileName}:$1:$2`);
return lines.join('\n');
}
return message;
}

/**
* Runs prettier and updates the status on the statusbarItem
*
* @param cb callback function to execute prettier
* @param rawDocumentText unformatted source document
* @param fileName name/path of the file formatted
*
* @returns {string} string with either formatted/raw document
*/
private safeExecution(cb: (() => string), rawDocumentText: string, fileName: string): string {
try {
const returnValue = cb();
this.loggingService.addToOutput(`${fileName} : Formatted Successfully`);
this.statusbarService.updateStatusBarItem(`${EXTENSION_NAME}: $(check)`);
return returnValue;
} catch (err) {
this.loggingService.addToOutput(this.addFilePathToMesssage(err.message, fileName));
this.statusbarService.updateStatusBarItem(`${EXTENSION_NAME}: $(x)`);
return rawDocumentText;
}
}

// get range for the current document
private fullDocumentRange(document: TextDocument): Range {
const rangeStart: Position = document.lineAt(0).range.start;
const rangeEnd: Position = document.lineAt(document.lineCount - 1).range.end;
return new Range(rangeStart, rangeEnd);
}

private async formatDocument(document: TextDocument): Promise<string> {
const workspaceConfiguration: WorkspaceConfiguration = workspace.getConfiguration('scssFormatter');
const rawDocumentText = document.getText();
const { fileName, languageId } = document;

const options: PrettierOptions = {
...Object.assign({}, workspaceConfiguration),
parser: languageId as BuiltInParserName
};

return this.safeExecution(
() => format(rawDocumentText, options),
rawDocumentText,
fileName
);
}

export class SCSSFormatter implements DocumentFormattingEditProvider {
public async provideDocumentFormattingEdits(document: TextDocument): Promise<TextEdit[]> {
const formattedDocument = await formatDocument(document);
return [TextEdit.replace(fullDocumentRange(document), formattedDocument)];
const formattedDocument = await this.formatDocument(document);
return [TextEdit.replace(this.fullDocumentRange(document), formattedDocument)];
}
}

export default SCSSFormatter;
44 changes: 44 additions & 0 deletions src/LoggingService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { commands, Disposable, OutputChannel, window } from 'vscode';

import StatusBarService from './StatusBarService';

import { EXTENSION_NAME } from './utils';

class LoggingService {
private outputChannel: OutputChannel;
private statusbarService: StatusBarService;

constructor(statusbarService: StatusBarService) {
this.outputChannel = window.createOutputChannel(EXTENSION_NAME);
this.statusbarService = statusbarService;
}

// add message to the output channel
public addToOutput(message: string): void {
const title = `${new Date().toLocaleString()}:`;

// Create a sort of title, to differentiate between messages
this.outputChannel.appendLine(title);
this.outputChannel.appendLine('-'.repeat(title.length));

// Append actual output
this.outputChannel.appendLine(`${message}\n`);
}

public registerDisposables(): Disposable[] {
return [
commands.registerCommand('scss-formatter.open-output', () => {
this.outputChannel.show();
}),
commands.registerCommand('scss-formatter.show-output', () => {
this.outputChannel.show();
}),
commands.registerCommand('scss-formatter.clear-output', () => {
this.outputChannel.clear();
this.statusbarService.reset();
})
];
}
}

export default LoggingService;
65 changes: 65 additions & 0 deletions src/StatusBarService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
Disposable, languages, StatusBarAlignment,
StatusBarItem, TextEditor, window
} from 'vscode';

import { EXTENSION_NAME, EXTENSION_VERSION, supportedLanguages } from './utils';

function checkForInConsoleTabSwitch(editor: TextEditor): boolean {
// output and debug console is also seen as an editor
// hence switching tabs will trigger the function
// this prevents hiding statusBarItem when switching between tabs
return ['debug', 'output'].some(
(part) => editor.document.uri.scheme === part);
}

class StatusBarService {
private statusBarItem: StatusBarItem;

constructor() {
this.statusBarItem = window.createStatusBarItem(StatusBarAlignment.Right, -1);
this.statusBarItem.text = EXTENSION_NAME;
this.statusBarItem.tooltip = `${EXTENSION_NAME}: v${EXTENSION_VERSION}`;
this.statusBarItem.command = 'scss-formatter.open-output';

this.toggleStatusBarItem(window.activeTextEditor);
}

public registerDisposables(): Disposable[] {
return [
// Keep track whether to show/hide the statusbar
window.onDidChangeActiveTextEditor((editor: TextEditor | undefined) => {
this.toggleStatusBarItem(editor);
})
];
}

// toggle statusBarItem when document changes
private toggleStatusBarItem(editor: TextEditor | undefined): void {
if (!this.statusBarItem) {
return;
}

if (editor !== undefined) {
if (checkForInConsoleTabSwitch(editor)) { return; }

// hide statusBarItem if document changes and doesn't match supported languages
const score = languages.match(supportedLanguages, editor.document);
score ? this.statusBarItem.show() : this.statusBarItem.hide();
} else {
this.statusBarItem.hide();
}
}

// update statusBarItem text and tooltip
public updateStatusBarItem(message: string): void {
this.statusBarItem.text = message;
this.statusBarItem.show();
}

public reset() {
this.statusBarItem.text = EXTENSION_NAME;
}
}

export default StatusBarService;
125 changes: 0 additions & 125 deletions src/errorHandler.ts

This file was deleted.

22 changes: 16 additions & 6 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { commands, Disposable, ExtensionContext, languages, window } from 'vscode';

import { registerErrorHandlerDisposables, setupErrorHandler } from './errorHandler';
import { SCSSFormatter } from './FormatterProvider';
import SCSSFormatter from './FormatterProvider';
import StatusBarService from './StatusBarService';
import LoggingService from './LoggingService';

import { languageSelector } from './utils';

const ACTIVATION_COMMAND: Disposable = commands.registerCommand('scss-formatter.activate', () => {
Expand All @@ -10,13 +12,21 @@ const ACTIVATION_COMMAND: Disposable = commands.registerCommand('scss-formatter.

// method is called when extension is activated
export function activate(context: ExtensionContext) {
const scssFormatter = new SCSSFormatter();

const statusbarService = new StatusBarService();
const loggingService = new LoggingService(statusbarService);

const scssFormatter = new SCSSFormatter(
loggingService,
statusbarService
);

context.subscriptions.push(languages.registerDocumentFormattingEditProvider(languageSelector, scssFormatter));
context.subscriptions.push(ACTIVATION_COMMAND);
context.subscriptions.push(...setupErrorHandler());
context.subscriptions.push(...registerErrorHandlerDisposables());

context.subscriptions.push(...loggingService.registerDisposables());
context.subscriptions.push(...statusbarService.registerDisposables());
}

// method is called when extension is deactivated
export function deactivate() { } // tslint:disable-line:no-empty
export function deactivate() { }

0 comments on commit 8952533

Please sign in to comment.