Skip to content
This repository has been archived by the owner on Oct 10, 2018. It is now read-only.

Feat/logging and error handling #326

Merged
merged 9 commits into from
Oct 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"${workspaceRoot}/test/_workspace",
"--extensionDevelopmentPath=${workspaceRoot}"
],
"env": {
"EXT_DEBUG": "true"
},
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
Expand All @@ -25,6 +28,9 @@
"${workspaceRoot}/test/multi-root.code-workspace",
"--extensionDevelopmentPath=${workspaceRoot}"
],
"env": {
"EXT_DEBUG": "true"
},
"stopOnEntry": false,
"sourceMaps": true,
"outFiles": [
Expand Down
15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@
"reflect-metadata": "^0.1.10",
"tslib": "^1.7.1",
"typescript": "~2.5.3",
"typescript-parser": "^2.0.0"
"typescript-parser": "^2.0.0",
"winston": "^3.0.0-rc1"
},
"activationEvents": [
"onLanguage:typescript",
Expand Down Expand Up @@ -195,13 +196,13 @@
"properties": {
"typescriptHero.verbosity": {
"enum": [
"Nothing",
"Errors",
"Warnings",
"All"
"error",
"warn",
"info",
"debug"
],
"default": "Warnings",
"description": "Defines the log output level in the output window.",
"default": "warn",
"description": "Defines the log output level in the output window. In the log file, it's always info or debug.",
"scope": "window"
},
"typescriptHero.codeCompletion.completionSortMode": {
Expand Down
4 changes: 2 additions & 2 deletions src/common/config/ExtensionConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ export interface ExtensionConfig {
* The actual log level.
*
* @readonly
* @type {string}
* @type {'error' | 'warn' | 'info' | 'debug'}
* @memberof ExtensionConfig
*/
verbosity: string;
verbosity: 'error' | 'warn' | 'info' | 'debug';

/**
* Returns a list of possible language IDs that are registered within this extension.
Expand Down
12 changes: 0 additions & 12 deletions src/common/utilities/LogLevel.ts

This file was deleted.

53 changes: 0 additions & 53 deletions src/common/utilities/Logger.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/common/utilities/index.ts

This file was deleted.

19 changes: 8 additions & 11 deletions src/extension/IoC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { ExtensionContext, Uri } from 'vscode';

import { ExtensionConfig } from '../common/config';
import { ConfigFactory } from '../common/factories';
import { Logger } from '../common/utilities';
import { CodeActionCreator, MissingImplementationInClassCreator, MissingImportCreator } from './code-actions';
import { VscodeExtensionConfig } from './config/VscodeExtensionConfig';
import { BaseExtension } from './extensions/BaseExtension';
Expand All @@ -17,7 +16,7 @@ import { OrganizeImportsOnSaveExtension } from './extensions/OrganizeImportsOnSa
import { iocSymbols } from './IoCSymbols';
import { TypeScriptHero } from './TypeScriptHero';
import { DeclarationIndexMapper } from './utilities/DeclarationIndexMapper';
import { VscodeLogger } from './utilities/VscodeLogger';
import winstonLogger, { Logger } from './utilities/winstonLogger';

const container = new IoCContainer();

Expand Down Expand Up @@ -51,15 +50,13 @@ container.bind<BaseExtension>(iocSymbols.extensions).to(OrganizeImportsOnSaveExt

// Logging
container
.bind<interfaces.Factory<Logger>>(iocSymbols.loggerFactory)
.toFactory<Logger>((context: interfaces.Context) => {
return (prefix?: string) => {
const extContext = context.container.get<ExtensionContext>(iocSymbols.extensionContext);
const config = context.container.get<ConfigFactory>(iocSymbols.configuration)();

return new VscodeLogger(extContext, config, prefix);
};
});
.bind<Logger>(iocSymbols.logger)
.toDynamicValue((context: interfaces.Context) => {
const extContext = context.container.get<ExtensionContext>(iocSymbols.extensionContext);
const config = context.container.get<ConfigFactory>(iocSymbols.configuration)();
return winstonLogger(config.verbosity, extContext);
})
.inSingletonScope();

// Code Action Extension (action creators)
container.bind<CodeActionCreator>(iocSymbols.codeActionCreators).to(MissingImportCreator);
Expand Down
2 changes: 1 addition & 1 deletion src/extension/IoCSymbols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const iocSymbols = {
configuration: Symbol('config'),
extensionContext: Symbol('context'),
extensions: Symbol('extensions'),
loggerFactory: Symbol('loggerFactory'),
logger: Symbol('logger'),
generatorFactory: Symbol('generatorFactory'),
codeActionCreators: Symbol('codeActionCreators'),
declarationIndexMapper: Symbol('declarationIndexMapper'),
Expand Down
17 changes: 8 additions & 9 deletions src/extension/TypeScriptHero.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,39 @@
import { inject, injectable, multiInject } from 'inversify';
import { Disposable } from 'vscode';

import { Logger, LoggerFactory } from '../common/utilities';
import { BaseExtension } from './extensions/BaseExtension';
import { iocSymbols } from './IoCSymbols';
import { Logger } from './utilities/winstonLogger';

/**
* TypeScript Hero vscode extension.
* Central entrypoint.
*
*
* @export
* @class TypeScriptHero
* @implements {Disposable}
*/
@injectable()
export class TypeScriptHero implements Disposable {
private logger: Logger;

constructor(
@inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory,
@inject(iocSymbols.logger) private logger: Logger,
@multiInject(iocSymbols.extensions) private extensions: BaseExtension[],
) {
this.logger = loggerFactory('TypescriptHero');
this.logger.info('Activation event called. TypeScriptHero instantiated.');
this.logger.debug('[%s] activation event, initializing', TypeScriptHero.name);
this.extensions.forEach(o => o.initialize());
this.logger.info('[%s] initialized', TypeScriptHero.name);
}

/**
* Disposes TypeScript Hero.
*
*
* @memberof TypeScriptHero
*/
public dispose(): void {
this.logger.info('Deactivation event called. Disposing TypeScriptHero.');
this.logger.debug('[%s] deactivation event, disposing', TypeScriptHero.name);
for (const ext of this.extensions) {
ext.dispose();
}
this.logger.info('[%s] disposed', TypeScriptHero.name);
}
}
61 changes: 46 additions & 15 deletions src/extension/code-actions/CodeAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,68 +7,89 @@ import {
} from 'typescript-parser';
import { TextDocument } from 'vscode';

import { Container } from '../IoC';
import { iocSymbols } from '../IoCSymbols';
import { ClassManager } from '../managers/ClassManager';
import { ImportManager } from '../managers/ImportManager';
import { Logger } from '../utilities/winstonLogger';

/**
* Interface for all codeactions that are generated by the typescript code action provider.
*
*
* @export
* @interface CodeAction
*/
export interface CodeAction {

/**
* Executes the code action. Depending on the action, there are several actions performed.
*
*
* @returns {Promise<boolean>}
*
*
* @memberof CodeAction
*/
execute(): Promise<boolean>;
}

/**
* Code action that adds a missing import the the actual document.
*
*
* @export
* @class AddImportCodeAction
* @implements {CodeAction}
*/
export class AddImportCodeAction implements CodeAction {
private static get logger(): Logger {
return Container.get(iocSymbols.logger);
}

constructor(private document: TextDocument, private importToAdd: DeclarationInfo) { }

/**
* Executes the code action. Depending on the action, there are several actions performed.
*
*
* @returns {Promise<boolean>}
*
*
* @memberof AddImportCodeAction
*/
public async execute(): Promise<boolean> {
AddImportCodeAction.logger.debug(
'[%s] add import for declaration "%s"',
AddImportCodeAction.name,
this.importToAdd.declaration.name,
);
const controller = await ImportManager.create(this.document);
return controller.addDeclarationImport(this.importToAdd).commit();
}
}

/**
* Code action that adds all missing imports to the actual document, based on the non-local usages.
*
*
* @export
* @class AddMissingImportsCodeAction
* @implements {CodeAction}
*/
export class AddMissingImportsCodeAction implements CodeAction {
private static get logger(): Logger {
return Container.get(iocSymbols.logger);
}

constructor(private document: TextDocument, private resolveIndex: DeclarationIndex) { }

/**
* Executes the code action. Depending on the action, there are several actions performed.
*
*
* @returns {Promise<boolean>}
*
*
* @memberof AddMissingImportsCodeAction
*/
public async execute(): Promise<boolean> {
AddMissingImportsCodeAction.logger.debug(
'[%s] add all missing imports for document "%s"',
AddMissingImportsCodeAction.name,
this.document.fileName,
);
const controller = await ImportManager.create(this.document);
return controller.addMissingImports(this.resolveIndex).commit();
}
Expand All @@ -77,17 +98,17 @@ export class AddMissingImportsCodeAction implements CodeAction {
/**
* Code action that does literally nothing. Is used to "communicate" with the user. E.g. if
* an import cannot be resolved, the lightbulb will show "cannot resolve <CLASS>".
*
*
* @export
* @class NoopCodeAction
* @implements {CodeAction}
*/
export class NoopCodeAction implements CodeAction {
/**
* Executes the code action. Depending on the action, there are several actions performed.
*
*
* @returns {Promise<boolean>}
*
*
* @memberof NoopCodeAction
*/
public execute(): Promise<boolean> {
Expand All @@ -97,12 +118,16 @@ export class NoopCodeAction implements CodeAction {

/**
* Code action that does implement missing properties and methods from interfaces or abstract classes.
*
*
* @export
* @class ImplementPolymorphElements
* @implements {CodeAction}
*/
export class ImplementPolymorphElements implements CodeAction {
private static get logger(): Logger {
return Container.get(iocSymbols.logger);
}

constructor(
private document: TextDocument,
private managedClass: string,
Expand All @@ -112,12 +137,18 @@ export class ImplementPolymorphElements implements CodeAction {

/**
* Executes the code action. Depending on the action, there are several actions performed.
*
*
* @returns {Promise<boolean>}
*
*
* @memberof ImplementPolymorphElements
*/
public async execute(): Promise<boolean> {
ImplementPolymorphElements.logger.debug(
'[%s] implement polymorph elements for class "%s"',
ImplementPolymorphElements.name,
this.managedClass,
{ file: this.document.fileName },
);
const controller = await ClassManager.create(this.document, this.managedClass);
let typeKeys;

Expand Down
Loading