From 49ef9f88c829f27012a93381cceaa4f816a83bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Thu, 26 Oct 2017 17:08:46 +0200 Subject: [PATCH 1/9] adding winston as dep and setting level --- package.json | 15 ++++---- yarn.lock | 102 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 107 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index c87492b..13af5af 100644 --- a/package.json +++ b/package.json @@ -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", @@ -195,13 +196,13 @@ "properties": { "typescriptHero.verbosity": { "enum": [ - "Nothing", - "Errors", - "Warnings", - "All" + "Error", + "Warning", + "Info", + "Debug" ], - "default": "Warnings", - "description": "Defines the log output level in the output window.", + "default": "Warning", + "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": { diff --git a/yarn.lock b/yarn.lock index 8dff7d6..f51c361 100644 --- a/yarn.lock +++ b/yarn.lock @@ -213,7 +213,7 @@ assertion-error@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" -async@^1.4.0: +async@^1.0.0, async@^1.4.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -444,20 +444,48 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" +color-convert@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd" + color-convert@^1.9.0: version "1.9.0" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" dependencies: color-name "^1.1.1" -color-name@^1.1.1: +color-name@^1.0.0, color-name@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" +color-string@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" + dependencies: + color-name "^1.0.0" + +color@0.8.x: + version "0.8.0" + resolved "https://registry.yarnpkg.com/color/-/color-0.8.0.tgz#890c07c3fd4e649537638911cf691e5458b6fca5" + dependencies: + color-convert "^0.5.0" + color-string "^0.3.0" + +colornames@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/colornames/-/colornames-0.0.2.tgz#d811fd6c84f59029499a8ac4436202935b92be31" + colors@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" +colorspace@1.0.x: + version "1.0.1" + resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.0.1.tgz#c99c796ed31128b9876a52e1ee5ee03a4a719749" + dependencies: + color "0.8.x" + text-hex "0.0.x" + combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -634,6 +662,10 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@^1.28.5: + version "1.29.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" + dateformat@^1.0.11, dateformat@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" @@ -698,6 +730,14 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" +diagnostics@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.0.tgz#e1090900b49523e8527be20f081275205f2ae36a" + dependencies: + colorspace "1.0.x" + enabled "1.0.x" + kuler "0.0.x" + diff@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" @@ -754,12 +794,22 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" +enabled@1.0.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/enabled/-/enabled-1.0.2.tgz#965f6513d2c2d1c5f4652b64a2e3396467fc2f93" + dependencies: + env-variable "0.0.x" + end-of-stream@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206" dependencies: once "^1.4.0" +env-variable@0.0.x: + version "0.0.3" + resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.3.tgz#b86c1641be5610267d506f18071ea76d707097cb" + error-ex@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" @@ -1619,7 +1669,7 @@ isobject@^2.0.0: dependencies: isarray "1.0.0" -isstream@~0.1.2: +isstream@0.1.x, isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -1699,6 +1749,12 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" +kuler@0.0.x: + version "0.0.0" + resolved "https://registry.yarnpkg.com/kuler/-/kuler-0.0.0.tgz#b66bb46b934e550f59d818848e0abba4f7f5553c" + dependencies: + colornames "0.0.2" + latest-version@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" @@ -1884,6 +1940,13 @@ log-driver@1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" +logform@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/logform/-/logform-1.2.1.tgz#e707ef7b3f3a9f16c248ae57f1d015074fc66bf5" + dependencies: + colors "^1.1.2" + date-fns "^1.28.5" + lolex@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" @@ -2195,6 +2258,10 @@ once@^1.4.0: dependencies: wrappy "1" +one-time@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e" + optimist@^0.6.1, optimist@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -2828,6 +2895,10 @@ ssri@^4.1.2: dependencies: safe-buffer "^5.1.0" +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + stat-mode@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/stat-mode/-/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" @@ -2962,6 +3033,10 @@ text-extensions@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.6.0.tgz#771561b26022783a45f5b6c2e78ad6e7de9fe322" +text-hex@0.0.x: + version "0.0.0" + resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-0.0.0.tgz#578fbc85a6a92636e42dd17b41d0218cce9eb2b3" + through2-filter@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" @@ -3032,6 +3107,10 @@ trim-off-newlines@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" +triple-beam@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.1.0.tgz#2ac387c8c4bd04bd26c61df891a6079f8592fe10" + tslib@^1.0.0, tslib@^1.7.1: version "1.7.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec" @@ -3368,6 +3447,23 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" +winston-transport@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-3.0.1.tgz#8008b15eef5660c4fb3fa094d58ccbd08528c58d" + +winston@^3.0.0-rc1: + version "3.0.0-rc1" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.0.0-rc1.tgz#982bc0ad4ef5c53000ca68036d78a3deaa28cac5" + dependencies: + async "^1.0.0" + diagnostics "^1.0.1" + isstream "0.1.x" + logform "^1.2.1" + one-time "0.0.4" + stack-trace "0.0.x" + triple-beam "^1.0.1" + winston-transport "^3.0.1" + wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" From 1245af54c26dcafcad9ec42b2f6c2e9be053b21f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Fri, 27 Oct 2017 10:38:45 +0200 Subject: [PATCH 2/9] adding custom logger --- .vscode/launch.json | 6 + package.json | 10 +- src/common/config/ExtensionConfig.ts | 4 +- src/extension/IoC.ts | 16 ++- src/extension/IoCSymbols.ts | 1 + src/extension/config/VscodeExtensionConfig.ts | 10 +- .../extensions/ImportResolveExtension.ts | 12 +- src/extension/utilities/winstonLogger.ts | 112 ++++++++++++++++++ test/_workspace/.vscode/settings.json | 2 +- 9 files changed, 157 insertions(+), 16 deletions(-) create mode 100644 src/extension/utilities/winstonLogger.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 09c7f69..5af24ef 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,6 +10,9 @@ "${workspaceRoot}/test/_workspace", "--extensionDevelopmentPath=${workspaceRoot}" ], + "env": { + "EXT_DEBUG": "true" + }, "stopOnEntry": false, "sourceMaps": true, "outFiles": [ @@ -25,6 +28,9 @@ "${workspaceRoot}/test/multi-root.code-workspace", "--extensionDevelopmentPath=${workspaceRoot}" ], + "env": { + "EXT_DEBUG": "true" + }, "stopOnEntry": false, "sourceMaps": true, "outFiles": [ diff --git a/package.json b/package.json index 13af5af..07dbc19 100644 --- a/package.json +++ b/package.json @@ -196,12 +196,12 @@ "properties": { "typescriptHero.verbosity": { "enum": [ - "Error", - "Warning", - "Info", - "Debug" + "error", + "warn", + "info", + "debug" ], - "default": "Warning", + "default": "warn", "description": "Defines the log output level in the output window. In the log file, it's always info or debug.", "scope": "window" }, diff --git a/src/common/config/ExtensionConfig.ts b/src/common/config/ExtensionConfig.ts index 7111110..22e0e6c 100644 --- a/src/common/config/ExtensionConfig.ts +++ b/src/common/config/ExtensionConfig.ts @@ -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. diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index fd4545f..2e9d0ef 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -5,7 +5,7 @@ import { ExtensionContext, Uri } from 'vscode'; import { ExtensionConfig } from '../common/config'; import { ConfigFactory } from '../common/factories'; -import { Logger } from '../common/utilities'; +import { Logger as OldLogger } from '../common/utilities'; import { CodeActionCreator, MissingImplementationInClassCreator, MissingImportCreator } from './code-actions'; import { VscodeExtensionConfig } from './config/VscodeExtensionConfig'; import { BaseExtension } from './extensions/BaseExtension'; @@ -18,6 +18,7 @@ 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(); @@ -51,8 +52,8 @@ container.bind(iocSymbols.extensions).to(OrganizeImportsOnSaveExt // Logging container - .bind>(iocSymbols.loggerFactory) - .toFactory((context: interfaces.Context) => { + .bind>(iocSymbols.loggerFactory) + .toFactory((context: interfaces.Context) => { return (prefix?: string) => { const extContext = context.container.get(iocSymbols.extensionContext); const config = context.container.get(iocSymbols.configuration)(); @@ -61,6 +62,15 @@ container }; }); +container + .bind(iocSymbols.logger) + .toDynamicValue((context: interfaces.Context) => { + const extContext = context.container.get(iocSymbols.extensionContext); + const config = context.container.get(iocSymbols.configuration)(); + return winstonLogger(config.verbosity, extContext.extensionPath); + }) + .inSingletonScope(); + // Code Action Extension (action creators) container.bind(iocSymbols.codeActionCreators).to(MissingImportCreator); container.bind(iocSymbols.codeActionCreators).to(MissingImplementationInClassCreator); diff --git a/src/extension/IoCSymbols.ts b/src/extension/IoCSymbols.ts index 5fc8ef5..1434349 100644 --- a/src/extension/IoCSymbols.ts +++ b/src/extension/IoCSymbols.ts @@ -6,6 +6,7 @@ export const iocSymbols = { extensionContext: Symbol('context'), extensions: Symbol('extensions'), loggerFactory: Symbol('loggerFactory'), + logger: Symbol('logger'), generatorFactory: Symbol('generatorFactory'), codeActionCreators: Symbol('codeActionCreators'), declarationIndexMapper: Symbol('declarationIndexMapper'), diff --git a/src/extension/config/VscodeExtensionConfig.ts b/src/extension/config/VscodeExtensionConfig.ts index 35ac546..94fc225 100644 --- a/src/extension/config/VscodeExtensionConfig.ts +++ b/src/extension/config/VscodeExtensionConfig.ts @@ -36,11 +36,15 @@ export class VscodeExtensionConfig implements ExtensionConfig { * The actual log level. * * @readonly - * @type {string} + * @type {'error' | 'warn' | 'info' | 'debug'} * @memberof VscodeExtensionConfig */ - public get verbosity(): string { - return this.workspaceSection.get('verbosity', 'Warning'); + public get verbosity(): 'error' | 'warn' | 'info' | 'debug' { + const verbosity = this.workspaceSection.get<'error' | 'warn' | 'info' | 'debug'>('verbosity', 'warn'); + if (['error', 'warn', 'info', 'debug'].indexOf(verbosity) < 0) { + return 'warn'; + } + return verbosity; } /** diff --git a/src/extension/extensions/ImportResolveExtension.ts b/src/extension/extensions/ImportResolveExtension.ts index f906dd6..a4dcec7 100644 --- a/src/extension/extensions/ImportResolveExtension.ts +++ b/src/extension/extensions/ImportResolveExtension.ts @@ -1,10 +1,11 @@ +import { Logger } from '../utilities/winstonLogger'; import { inject, injectable } from 'inversify'; import { DeclarationInfo, TypescriptParser } from 'typescript-parser'; import { commands, ExtensionContext, StatusBarAlignment, StatusBarItem, window, workspace } from 'vscode'; import { getDeclarationsFilteredByImports } from '../../common/helpers'; import { ResolveQuickPickItem } from '../../common/quick-pick-items'; -import { Logger, LoggerFactory } from '../../common/utilities'; +import { Logger as OldLogger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; import { ImportManager } from '../managers'; import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; @@ -27,16 +28,23 @@ const resolverErr = 'TSH Resolver $(flame)'; */ @injectable() export class ImportResolveExtension extends BaseExtension { - private logger: Logger; + private logger: OldLogger; private statusBarItem: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 4); constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, + @inject(iocSymbols.logger) private loggerX: Logger, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, ) { super(context); + this.loggerX.debug('This is a debug message'); + this.loggerX.info('This is a info message', { more: 'data' }); + this.loggerX.warn('This is a warn message: %s', 'second string.'); + this.loggerX.error('This is a error message %s', new Error('TEST ERROR')); + this.loggerX.error('This is a error message', new Error('TEST ERROR')); + this.loggerX.error('This is a error message', { err: new Error('TEST ERROR') }); this.logger = loggerFactory('ImportResolveExtension'); } diff --git a/src/extension/utilities/winstonLogger.ts b/src/extension/utilities/winstonLogger.ts new file mode 100644 index 0000000..52fb518 --- /dev/null +++ b/src/extension/utilities/winstonLogger.ts @@ -0,0 +1,112 @@ +import { ExtensionContext } from 'vscode'; + +const { createLogger, format, transports } = require('winston'); +const transport = require('winston-transport'); +const { LEVEL, MESSAGE } = require('triple-beam'); + +const { combine, timestamp, printf } = format; +const Transport = transport as { new(...args: any[]): any; }; + +const levels = { + error: 0, + warn: 1, + info: 2, + debug: 3, +}; + +class OutputWindowTransport extends Transport { + constructor(opts?: any) { + super(opts); + } + + public log(info: any, callback: any): void { + setImmediate(() => { + this.emit('logged', info); + }); + const level = info[LEVEL]; + + switch (level) { + case 'error': + console.error(info[MESSAGE]); + break; + case 'warn': + console.warn(info[MESSAGE]); + break; + default: + console.log(info[MESSAGE]); + break; + } + callback(); + } +} + +class ConsoleLogTransport extends Transport { + constructor(opts?: any) { + super(opts); + } + + public log(info: any, callback: any): void { + setImmediate(() => { + this.emit('logged', info); + }); + const level = info[LEVEL]; + + switch (level) { + case 'error': + console.error(info[MESSAGE]); + break; + case 'warn': + console.warn(info[MESSAGE]); + break; + default: + console.log(info[MESSAGE]); + break; + } + callback(); + } +} + +export interface Logger { + error: (message: string, ...data: any[]) => void; + warn: (message: string, ...data: any[]) => void; + info: (message: string, ...data: any[]) => void; + debug: (message: string, ...data: any[]) => void; +} + +const loggerTransports = [ + new ConsoleLogTransport({ + level: !!process.env.CI ? 'error' : 'debug', + }), +]; + +export default function winstonLogger(verbosity: keyof typeof levels, context: ExtensionContext): Logger { + const level = !!process.env.CI ? 'error' : verbosity; + + if (!process.env.CI && !process.env.EXT_DEBUG) { + loggerTransports.push(new OutputWindowTransport()); + } + + return createLogger({ + level, + levels, + format: combine( + format.splat(), + timestamp(), + printf((info) => { + const message = `${info.timestamp} - ${info.level}: ${info.message}`; + const data = { + ...info, + level: undefined, + message: undefined, + splat: undefined, + timestamp: undefined, + }; + if (Object.keys(data).filter(key => !!data[key]).length > 0) { + return `${message} ${JSON.stringify(data)}`; + } + return message; + }), + ), + transports: loggerTransports, + }) as Logger; +} diff --git a/test/_workspace/.vscode/settings.json b/test/_workspace/.vscode/settings.json index c5f10cc..1705c40 100755 --- a/test/_workspace/.vscode/settings.json +++ b/test/_workspace/.vscode/settings.json @@ -9,7 +9,7 @@ "dist", "resourceParser" ], - "typescriptHero.verbosity": "Warnings", + "typescriptHero.verbosity": "All", "tslint.enable": false, "typescriptHero.codeOutline.enabled": true, "typescriptHero.resolver.organizeOnSave": false, From 653abe5ba4c92f2d6a4fc221789323deadbfc0a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Fri, 27 Oct 2017 11:43:09 +0200 Subject: [PATCH 3/9] adding winston logs --- src/extension/utilities/winstonLogger.ts | 76 ++++++++++++++++++------ 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/src/extension/utilities/winstonLogger.ts b/src/extension/utilities/winstonLogger.ts index 52fb518..223bb99 100644 --- a/src/extension/utilities/winstonLogger.ts +++ b/src/extension/utilities/winstonLogger.ts @@ -1,6 +1,7 @@ -import { ExtensionContext } from 'vscode'; +import { join } from 'path'; +import { ExtensionContext, OutputChannel, window, workspace } from 'vscode'; -const { createLogger, format, transports } = require('winston'); +const { createLogger, exceptions, format, transports } = require('winston'); const transport = require('winston-transport'); const { LEVEL, MESSAGE } = require('triple-beam'); @@ -15,7 +16,7 @@ const levels = { }; class OutputWindowTransport extends Transport { - constructor(opts?: any) { + constructor(opts: any, private channel: OutputChannel) { super(opts); } @@ -23,19 +24,7 @@ class OutputWindowTransport extends Transport { setImmediate(() => { this.emit('logged', info); }); - const level = info[LEVEL]; - - switch (level) { - case 'error': - console.error(info[MESSAGE]); - break; - case 'warn': - console.warn(info[MESSAGE]); - break; - default: - console.log(info[MESSAGE]); - break; - } + this.channel.appendLine(info[MESSAGE]); callback(); } } @@ -66,11 +55,38 @@ class ConsoleLogTransport extends Transport { } } +class HandleUncatchedException extends Transport { + constructor(private path: string) { + super(); + } + + public async log(info: any, callback: any): Promise { + setImmediate(() => { + this.emit('logged', info); + }); + + const result = await window.showErrorMessage( + 'There was an uncought exception, do you want to see the logfile?', + { modal: true }, + 'Yes, show me.', + ); + + if (result) { + const doc = await workspace.openTextDocument(join(this.path, 'typescript-hero.log')); + await window.showTextDocument(doc); + } + + callback(); + } +} + export interface Logger { error: (message: string, ...data: any[]) => void; warn: (message: string, ...data: any[]) => void; info: (message: string, ...data: any[]) => void; debug: (message: string, ...data: any[]) => void; + profile: (name: string) => void; + startTimer(): { done: (info: { message: string }) => void; }; } const loggerTransports = [ @@ -83,10 +99,28 @@ export default function winstonLogger(verbosity: keyof typeof levels, context: E const level = !!process.env.CI ? 'error' : verbosity; if (!process.env.CI && !process.env.EXT_DEBUG) { - loggerTransports.push(new OutputWindowTransport()); + const channel = window.createOutputChannel('TypeScript Hero'); + context.subscriptions.push(channel); + + const fileHandler = new transports.File({ + exitOnError: false, + filename: 'typescript-hero.log', + dirname: context.extensionPath, + maxsize: 1024 * 1024, + maxFiles: 1, + tailable: true, + }); + const outputHandler = new OutputWindowTransport({ exitOnError: false }, channel); + + loggerTransports.push(fileHandler); + loggerTransports.push(outputHandler); + + exceptions.handle(fileHandler); + exceptions.handle(outputHandler); + exceptions.handle(new HandleUncatchedException(context.extensionPath)); } - return createLogger({ + const logger = createLogger({ level, levels, format: combine( @@ -108,5 +142,9 @@ export default function winstonLogger(verbosity: keyof typeof levels, context: E }), ), transports: loggerTransports, - }) as Logger; + }); + + logger.exitOnError = false; + + return logger; } From 6feaf3632eae57d8cee6b87c466ed2eaee0b64e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Fri, 27 Oct 2017 11:44:12 +0200 Subject: [PATCH 4/9] add normal logging --- src/extension/IoC.ts | 2 +- src/extension/extensions/ImportResolveExtension.ts | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index 2e9d0ef..95a3f03 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -67,7 +67,7 @@ container .toDynamicValue((context: interfaces.Context) => { const extContext = context.container.get(iocSymbols.extensionContext); const config = context.container.get(iocSymbols.configuration)(); - return winstonLogger(config.verbosity, extContext.extensionPath); + return winstonLogger(config.verbosity, extContext); }) .inSingletonScope(); diff --git a/src/extension/extensions/ImportResolveExtension.ts b/src/extension/extensions/ImportResolveExtension.ts index a4dcec7..d785253 100644 --- a/src/extension/extensions/ImportResolveExtension.ts +++ b/src/extension/extensions/ImportResolveExtension.ts @@ -1,4 +1,3 @@ -import { Logger } from '../utilities/winstonLogger'; import { inject, injectable } from 'inversify'; import { DeclarationInfo, TypescriptParser } from 'typescript-parser'; import { commands, ExtensionContext, StatusBarAlignment, StatusBarItem, window, workspace } from 'vscode'; @@ -34,17 +33,10 @@ export class ImportResolveExtension extends BaseExtension { constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, - @inject(iocSymbols.logger) private loggerX: Logger, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, ) { super(context); - this.loggerX.debug('This is a debug message'); - this.loggerX.info('This is a info message', { more: 'data' }); - this.loggerX.warn('This is a warn message: %s', 'second string.'); - this.loggerX.error('This is a error message %s', new Error('TEST ERROR')); - this.loggerX.error('This is a error message', new Error('TEST ERROR')); - this.loggerX.error('This is a error message', { err: new Error('TEST ERROR') }); this.logger = loggerFactory('ImportResolveExtension'); } From 2dfc51da2cf5dafe8f04b66055b6d11c0d63dc0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Sat, 28 Oct 2017 00:12:11 +0200 Subject: [PATCH 5/9] remove the old logger --- src/common/utilities/LogLevel.ts | 12 -- src/common/utilities/Logger.ts | 53 --------- src/common/utilities/index.ts | 2 - src/extension/IoC.ts | 11 -- src/extension/IoCSymbols.ts | 1 - src/extension/utilities/VscodeLogger.ts | 148 ------------------------ 6 files changed, 227 deletions(-) delete mode 100644 src/common/utilities/LogLevel.ts delete mode 100644 src/common/utilities/Logger.ts delete mode 100644 src/common/utilities/index.ts delete mode 100644 src/extension/utilities/VscodeLogger.ts diff --git a/src/common/utilities/LogLevel.ts b/src/common/utilities/LogLevel.ts deleted file mode 100644 index 98f696b..0000000 --- a/src/common/utilities/LogLevel.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Enum for the log level. Determines if a message is logged into the output. - * - * @export - * @enum {number} - */ -export const enum LogLevel { - Nothing, - Errors, - Warnings, - All, -} diff --git a/src/common/utilities/Logger.ts b/src/common/utilities/Logger.ts deleted file mode 100644 index 647891c..0000000 --- a/src/common/utilities/Logger.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Factory type for IoC. - * - * @typedef LoggerFactory - */ -export type LoggerFactory = (prefix?: string) => Logger; - -/** - * Interface for logging instances, implement the basic methods needed for logging. - * If a prefix is provided, it should use it before all messages. - * - * @export - * @interface Logger - */ -export interface Logger { - /** - * The prefix used for the messages. - * - * @type {string} - * @memberof Logger - */ - readonly prefix?: string; - - /** - * Logs a message marked as error. If additional data is provided, it's logged as well. - * - * @param {string} message - * @param {*} [data] - * - * @memberof Logger - */ - error(message: string, data?: any): void; - - /** - * Logs a message marked as warning. If additional data is provided, it's logged as well. - * - * @param {string} message - * @param {*} [data] - * - * @memberof Logger - */ - warning(message: string, data?: any): void; - - /** - * Logs a message marked as info. If additional data is provided, it's logged as well. - * - * @param {string} message - * @param {*} [data] - * - * @memberof Logger - */ - info(message: string, data?: any): void; -} diff --git a/src/common/utilities/index.ts b/src/common/utilities/index.ts deleted file mode 100644 index 6df4e82..0000000 --- a/src/common/utilities/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './LogLevel'; -export * from './Logger'; diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index 95a3f03..389713e 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -51,17 +51,6 @@ container.bind(iocSymbols.extensions).to(CodeActionExtension).inS container.bind(iocSymbols.extensions).to(OrganizeImportsOnSaveExtension).inSingletonScope(); // Logging -container - .bind>(iocSymbols.loggerFactory) - .toFactory((context: interfaces.Context) => { - return (prefix?: string) => { - const extContext = context.container.get(iocSymbols.extensionContext); - const config = context.container.get(iocSymbols.configuration)(); - - return new VscodeLogger(extContext, config, prefix); - }; - }); - container .bind(iocSymbols.logger) .toDynamicValue((context: interfaces.Context) => { diff --git a/src/extension/IoCSymbols.ts b/src/extension/IoCSymbols.ts index 1434349..aac9c1f 100644 --- a/src/extension/IoCSymbols.ts +++ b/src/extension/IoCSymbols.ts @@ -5,7 +5,6 @@ export const iocSymbols = { configuration: Symbol('config'), extensionContext: Symbol('context'), extensions: Symbol('extensions'), - loggerFactory: Symbol('loggerFactory'), logger: Symbol('logger'), generatorFactory: Symbol('generatorFactory'), codeActionCreators: Symbol('codeActionCreators'), diff --git a/src/extension/utilities/VscodeLogger.ts b/src/extension/utilities/VscodeLogger.ts deleted file mode 100644 index 907d96a..0000000 --- a/src/extension/utilities/VscodeLogger.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { ExtensionConfig } from '../../common/config'; -import { Logger, LogLevel } from '../../common/utilities'; -import { inspect } from 'util'; -import { ExtensionContext, OutputChannel, window } from 'vscode'; - -/** - * Central logger instance of the extension. - * - * @export - * @class VscodeLogger - */ -export class VscodeLogger implements Logger { - private static channel: OutputChannel; - - constructor(context: ExtensionContext, private config: ExtensionConfig, public readonly prefix?: string) { - if (!VscodeLogger.channel) { - VscodeLogger.channel = window.createOutputChannel('TypeScript Hero Extension'); - context.subscriptions.push(VscodeLogger.channel); - } - } - - /** - * Logs an error message. Provided data is logged out after the message. - * - * @param {string} message - * @param {*} [data] - * - * @memberof VscodeLogger - */ - public error(message: string, data?: any): void { - this.log( - LogLevel.Errors, - 'Error', - message, - data, - ); - } - - /** - * Logs a warning message. Provided data is logged out after the message. - * - * @param {string} message - * @param {*} [data] - * - * @memberof VscodeLogger - */ - public warning(message: string, data?: any): void { - this.log( - LogLevel.Warnings, - 'Warn ', - message, - data, - ); - } - - /** - * Logs an info message. Provided data is logged out after the message. - * - * @param {string} message - * @param {*} [data] - * - * @memberof VscodeLogger - */ - public info(message: string, data?: any): void { - this.log( - LogLevel.All, - 'Info ', - message, - data, - ); - } - - /** - * Internal method to actually do the logging. Checks if the output should be done and logs - * the data into the output channel and the console (if debugging). - * - * @private - * @param {LogLevel} level - * @param {string} severity - * @param {string} message - * @param {*} [data] - * - * @memberof VscodeLogger - */ - private log(level: LogLevel, severity: string, message: string, data?: any): void { - if (this.getLogLevel() >= level) { - const msg = `[${severity} - ${this.getDate()}] ${this.prefix ? this.prefix + ' - ' : ''}${message}`; - // tslint:disable - if (data) { - console.log(msg, data); - } else { - console.log(msg); - } - // tslint:enable - VscodeLogger.channel.appendLine(msg); - if (data) { - VscodeLogger.channel.appendLine(`\tData:\t${inspect(data, {})}`); - } - } - } - - /** - * Returns a propper formatted date for logging. - * - * @private - * @returns {string} - * - * @memberof Logger - */ - private getDate(): string { - const date = new Date(); - let hours = date.getHours().toString(); - let minutes = date.getMinutes().toString(); - let seconds = date.getSeconds().toString(); - - if (hours.length < 2) { - hours = `0${hours}`; - } - if (minutes.length < 2) { - minutes = `0${minutes}`; - } - if (seconds.length < 2) { - seconds = `0${seconds}`; - } - return `${hours}:${minutes}:${seconds}`; - } - - /** - * Maps the configuration string to a propper enum value of LogLevel. - * - * @private - * @returns {LogLevel} - * - * @memberof VscodeLogger - */ - private getLogLevel(): LogLevel { - switch (this.config.verbosity) { - case 'Nothing': - return LogLevel.Nothing; - case 'Errors': - return LogLevel.Errors; - case 'All': - return LogLevel.All; - default: - return LogLevel.Warnings; - } - } -} From 761b1d50e701fbb22f115400ef40ba78e431f817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Sat, 28 Oct 2017 01:05:10 +0200 Subject: [PATCH 6/9] add proper logging for code actions and extensions --- src/extension/IoC.ts | 2 - src/extension/code-actions/CodeAction.ts | 61 +++++++++--- .../MissingImplementationInClassCreator.ts | 21 ++++ .../code-actions/MissingImportCreator.ts | 20 ++++ .../extensions/CodeActionExtension.ts | 22 +++-- .../extensions/CodeCompletionExtension.ts | 31 ++++-- .../DocumentSymbolStructureExtension.ts | 19 ++-- .../extensions/ImportResolveExtension.ts | 95 ++++++++++++++++--- .../OrganizeImportsOnSaveExtension.ts | 27 ++++-- 9 files changed, 235 insertions(+), 63 deletions(-) diff --git a/src/extension/IoC.ts b/src/extension/IoC.ts index 389713e..9c540e5 100644 --- a/src/extension/IoC.ts +++ b/src/extension/IoC.ts @@ -5,7 +5,6 @@ import { ExtensionContext, Uri } from 'vscode'; import { ExtensionConfig } from '../common/config'; import { ConfigFactory } from '../common/factories'; -import { Logger as OldLogger } from '../common/utilities'; import { CodeActionCreator, MissingImplementationInClassCreator, MissingImportCreator } from './code-actions'; import { VscodeExtensionConfig } from './config/VscodeExtensionConfig'; import { BaseExtension } from './extensions/BaseExtension'; @@ -17,7 +16,6 @@ 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(); diff --git a/src/extension/code-actions/CodeAction.ts b/src/extension/code-actions/CodeAction.ts index e86de6f..bf55f73 100644 --- a/src/extension/code-actions/CodeAction.ts +++ b/src/extension/code-actions/CodeAction.ts @@ -7,12 +7,15 @@ 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 */ @@ -20,9 +23,9 @@ export interface CodeAction { /** * Executes the code action. Depending on the action, there are several actions performed. - * + * * @returns {Promise} - * + * * @memberof CodeAction */ execute(): Promise; @@ -30,22 +33,31 @@ export interface CodeAction { /** * 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} - * + * * @memberof AddImportCodeAction */ public async execute(): Promise { + 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(); } @@ -53,22 +65,31 @@ export class AddImportCodeAction implements CodeAction { /** * 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} - * + * * @memberof AddMissingImportsCodeAction */ public async execute(): Promise { + 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(); } @@ -77,7 +98,7 @@ 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 ". - * + * * @export * @class NoopCodeAction * @implements {CodeAction} @@ -85,9 +106,9 @@ export class AddMissingImportsCodeAction implements CodeAction { export class NoopCodeAction implements CodeAction { /** * Executes the code action. Depending on the action, there are several actions performed. - * + * * @returns {Promise} - * + * * @memberof NoopCodeAction */ public execute(): Promise { @@ -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, @@ -112,12 +137,18 @@ export class ImplementPolymorphElements implements CodeAction { /** * Executes the code action. Depending on the action, there are several actions performed. - * + * * @returns {Promise} - * + * * @memberof ImplementPolymorphElements */ public async execute(): Promise { + 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; diff --git a/src/extension/code-actions/MissingImplementationInClassCreator.ts b/src/extension/code-actions/MissingImplementationInClassCreator.ts index 251f058..e3485fc 100644 --- a/src/extension/code-actions/MissingImplementationInClassCreator.ts +++ b/src/extension/code-actions/MissingImplementationInClassCreator.ts @@ -5,6 +5,7 @@ import { Command, Diagnostic, TextDocument, workspace } from 'vscode'; import { getAbsolutLibraryName } from '../../common/helpers'; import { iocSymbols } from '../IoCSymbols'; import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; +import { Logger } from '../utilities/winstonLogger'; import { ImplementPolymorphElements, NoopCodeAction } from './CodeAction'; import { CodeActionCreator } from './CodeActionCreator'; @@ -20,6 +21,7 @@ export class MissingImplementationInClassCreator extends CodeActionCreator { constructor( @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, + @inject(iocSymbols.logger) private logger: Logger, ) { super(); } @@ -55,6 +57,10 @@ export class MissingImplementationInClassCreator extends CodeActionCreator { const rootFolder = workspace.getWorkspaceFolder(document.uri); if (!match || !index || !rootFolder) { + this.logger.debug( + '[%s] cannot handle the diagnostic', + MissingImplementationInClassCreator.name, + ); return commands; } @@ -80,10 +86,19 @@ export class MissingImplementationInClassCreator extends CodeActionCreator { if (commands.some((o: Command) => o.title.indexOf(specifier) >= 0)) { // Do leave the method when a command with the found class is already added. + this.logger.debug( + '[%s] command with the found class is already added', + MissingImplementationInClassCreator.name, + ); return commands; } if (!declaration) { + this.logger.debug( + '[%s] class definition not found in the index', + MissingImplementationInClassCreator.name, + { specifier }, + ); commands.push(this.createCommand( `Cannot find "${specifier}" in the index or the actual file.`, new NoopCodeAction(), @@ -103,6 +118,12 @@ export class MissingImplementationInClassCreator extends CodeActionCreator { new ImplementPolymorphElements(document, match[1], declaration, typeParams), )); + this.logger.debug( + '[%s] adding commands to handle missing implementation', + MissingImplementationInClassCreator.name, + { specifier, types }, + ); + return commands; } } diff --git a/src/extension/code-actions/MissingImportCreator.ts b/src/extension/code-actions/MissingImportCreator.ts index bcdc634..dc0bded 100644 --- a/src/extension/code-actions/MissingImportCreator.ts +++ b/src/extension/code-actions/MissingImportCreator.ts @@ -1,3 +1,4 @@ +import { Logger } from '../utilities/winstonLogger'; import { inject, injectable } from 'inversify'; import { Command, Diagnostic, TextDocument } from 'vscode'; @@ -17,6 +18,7 @@ import { CodeActionCreator } from './CodeActionCreator'; export class MissingImportCreator extends CodeActionCreator { constructor( @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, + @inject(iocSymbols.logger) private logger: Logger, ) { super(); } @@ -48,6 +50,10 @@ export class MissingImportCreator extends CodeActionCreator { const index = this.indices.getIndexForFile(document.uri); if (!match || !index) { + this.logger.debug( + '[%s] cannot handle the diagnostic', + MissingImportCreator.name, + ); return commands; } @@ -58,6 +64,11 @@ export class MissingImportCreator extends CodeActionCreator { `Import "${info.declaration.name}" from "${info.from}".`, new AddImportCodeAction(document, info), )); + this.logger.debug( + '[%s] add command to import missing specifier', + MissingImportCreator.name, + { symbol: info.declaration.name, library: info.from }, + ); } if ( !commands.some(o => @@ -69,12 +80,21 @@ export class MissingImportCreator extends CodeActionCreator { 'Add all missing imports if possible.', new AddMissingImportsCodeAction(document, index), )); + this.logger.debug( + '[%s] add "import all missing imports" command', + MissingImportCreator.name, + ); } } else { commands.push(this.createCommand( `Cannot find "${match[1]}" in the index.`, new NoopCodeAction(), )); + this.logger.debug( + '[%s] class not found in index', + MissingImportCreator.name, + { specifier: match[1] }, + ); } return commands; diff --git a/src/extension/extensions/CodeActionExtension.ts b/src/extension/extensions/CodeActionExtension.ts index 2634847..328e0c5 100644 --- a/src/extension/extensions/CodeActionExtension.ts +++ b/src/extension/extensions/CodeActionExtension.ts @@ -12,11 +12,11 @@ import { window, } from 'vscode'; -import { Logger, LoggerFactory } from '../../common/utilities'; import { CodeAction } from '../code-actions/CodeAction'; import { CodeActionCreator } from '../code-actions/CodeActionCreator'; import { iocSymbols } from '../IoCSymbols'; import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; +import { Logger } from '../utilities/winstonLogger'; import { BaseExtension } from './BaseExtension'; /** @@ -30,16 +30,13 @@ import { BaseExtension } from './BaseExtension'; */ @injectable() export class CodeActionExtension extends BaseExtension implements CodeActionProvider { - private logger: Logger; - constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, - @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, + @inject(iocSymbols.logger) private logger: Logger, @multiInject(iocSymbols.codeActionCreators) private actionCreators: CodeActionCreator[], @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, ) { super(context); - this.logger = loggerFactory('CodeActionExtension'); } /** @@ -55,7 +52,7 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv this.context.subscriptions.push(languages.registerCodeActionsProvider('typescript', this)); this.context.subscriptions.push(languages.registerCodeActionsProvider('typescriptreact', this)); - this.logger.info('Initialized'); + this.logger.info('[%s] initialized', CodeActionCreator.name); } /** @@ -64,7 +61,7 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv * @memberof ImportResolveExtension */ public dispose(): void { - this.logger.info('Disposed'); + this.logger.info('[%s] disposed', CodeActionCreator.name); } /** @@ -89,6 +86,13 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv return []; } + this.logger.debug( + '[%s] provide code actions for file', + CodeActionCreator.name, + { file: document.fileName }, + ); + const profiler = this.logger.startTimer(); + let commands: Command[] = []; for (const diagnostic of context.diagnostics) { for (const creator of this.actionCreators) { @@ -98,6 +102,8 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv } } + profiler.done({ message: `[${CodeActionCreator.name}] calculated diagnostics` }); + return commands; } @@ -112,10 +118,12 @@ export class CodeActionExtension extends BaseExtension implements CodeActionProv */ private async executeCodeAction(codeAction: CodeAction | undefined): Promise { if (!codeAction) { + this.logger.warn('[%s] executeCodeAction used without param', CodeActionCreator.name); window.showWarningMessage('This command is for internal use only. It cannot be used from Cmd+P'); return; } if (!await codeAction.execute()) { + this.logger.warn('[%s] code action could not complete', CodeActionCreator.name, { codeAction }); window.showWarningMessage('The provided code action could not complete. Please see the logs.'); } } diff --git a/src/extension/extensions/CodeCompletionExtension.ts b/src/extension/extensions/CodeCompletionExtension.ts index 4a01f6d..4e94f3e 100644 --- a/src/extension/extensions/CodeCompletionExtension.ts +++ b/src/extension/extensions/CodeCompletionExtension.ts @@ -14,11 +14,11 @@ import { import { ConfigFactory } from '../../common/factories'; import { getDeclarationsFilteredByImports } from '../../common/helpers'; -import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; import { ImportManager } from '../managers/ImportManager'; import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; import { getItemKind } from '../utilities/utilityFunctions'; +import { Logger } from '../utilities/winstonLogger'; import { BaseExtension } from './BaseExtension'; /** @@ -31,17 +31,14 @@ import { BaseExtension } from './BaseExtension'; */ @injectable() export class CodeCompletionExtension extends BaseExtension implements CompletionItemProvider { - private logger: Logger; - constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, - @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, + @inject(iocSymbols.logger) private logger: Logger, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, @inject(iocSymbols.configuration) private config: ConfigFactory, ) { super(context); - this.logger = loggerFactory('CodeCompletionExtension'); } /** @@ -62,7 +59,7 @@ export class CodeCompletionExtension extends BaseExtension implements Completion ), ); - this.logger.info('Initialized'); + this.logger.info('[%s] initialized', CodeCompletionExtension.name); } /** @@ -71,7 +68,7 @@ export class CodeCompletionExtension extends BaseExtension implements Completion * @memberof CodeCompletionExtension */ public dispose(): void { - this.logger.info('Disposed'); + this.logger.info('[%s] disposed', CodeCompletionExtension.name); } /** @@ -98,6 +95,7 @@ export class CodeCompletionExtension extends BaseExtension implements Completion !config.resolver.resolverModeLanguages.some(lng => lng === document.languageId) || !rootFolder ) { + this.logger.debug('[%s] resolver not ready or no workspace folder selected', CodeCompletionExtension.name); return null; } @@ -118,10 +116,20 @@ export class CodeCompletionExtension extends BaseExtension implements Completion lineText.match(/^\s*(\/\/|\/\*\*|\*\/|\*)/g) || lineText.startsWith('import ') || lineText.substring(0, position.character).match(new RegExp(`(\w*[.])+${searchWord}`, 'g'))) { + this.logger.debug( + '[%s] did not match criteria to provide intellisense', + CodeCompletionExtension.name, + { searchWord, lineText, indexReady: index.indexReady }, + ); return Promise.resolve(null); } - this.logger.info('Search completion for word.', { searchWord }); + this.logger.debug( + '[%s] provide code completion for "%s"', + CodeCompletionExtension.name, + searchWord, + ); + const profiler = this.logger.startTimer(); const parsed = await this.parser.parseSource(document.getText()); const declarations = getDeclarationsFilteredByImports( @@ -150,6 +158,8 @@ export class CodeCompletionExtension extends BaseExtension implements Completion } items.push(item); } + + profiler.done({ message: `[${CodeCompletionExtension.name}] calculated code completions` }); return items; } @@ -164,6 +174,11 @@ export class CodeCompletionExtension extends BaseExtension implements Completion * @memberof CodeCompletionExtension */ private async executeIntellisenseItem(document: TextDocument, declaration: DeclarationInfo): Promise { + this.logger.debug( + '[%s] execute code completion action', + CodeCompletionExtension.name, + { specifier: declaration.declaration.name, library: declaration.from }, + ); const manager = await ImportManager.create(document); manager.addDeclarationImport(declaration); await manager.commit(); diff --git a/src/extension/extensions/DocumentSymbolStructureExtension.ts b/src/extension/extensions/DocumentSymbolStructureExtension.ts index 8332f6d..8eba072 100644 --- a/src/extension/extensions/DocumentSymbolStructureExtension.ts +++ b/src/extension/extensions/DocumentSymbolStructureExtension.ts @@ -14,7 +14,6 @@ import { } from 'vscode'; import { ConfigFactory } from '../../common/factories'; -import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; import { BaseStructureTreeItem } from '../provider-items/document-structure/BaseStructureTreeItem'; import { DeclarationStructureTreeItem } from '../provider-items/document-structure/DeclarationStructureTreeItem'; @@ -22,6 +21,7 @@ import { DisabledStructureTreeItem } from '../provider-items/document-structure/ import { ImportsStructureTreeItem } from '../provider-items/document-structure/ImportsStructureTreeItem'; import { NotParseableStructureTreeItem } from '../provider-items/document-structure/NotParseableStructureTreeItem'; import { ResourceStructureTreeItem } from '../provider-items/document-structure/ResourceStructureTreeItem'; +import { Logger } from '../utilities/winstonLogger'; import { BaseExtension } from './BaseExtension'; /** @@ -36,17 +36,15 @@ import { BaseExtension } from './BaseExtension'; export class DocumentSymbolStructureExtension extends BaseExtension implements TreeDataProvider { public readonly onDidChangeTreeData: Event; private _onDidChangeTreeData: EventEmitter; - private logger: Logger; private documentCache: File | undefined; constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, - @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, + @inject(iocSymbols.logger) private logger: Logger, @inject(iocSymbols.configuration) private config: ConfigFactory, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, ) { super(context); - this.logger = loggerFactory('DocumentSymbolStructureExtension'); this._onDidChangeTreeData = new EventEmitter(); this.onDidChangeTreeData = this._onDidChangeTreeData.event; } @@ -68,7 +66,7 @@ export class DocumentSymbolStructureExtension extends BaseExtension implements T this.context.subscriptions.push(window.onDidChangeActiveTextEditor(() => this.activeWindowChanged())); this.context.subscriptions.push(workspace.onDidSaveTextDocument(() => this.activeWindowChanged())); - this.logger.info('Initialized'); + this.logger.info('[%s] initialized', DocumentSymbolStructureExtension.name); } /** @@ -77,7 +75,7 @@ export class DocumentSymbolStructureExtension extends BaseExtension implements T * @memberof DocumentSymbolStructureExtension */ public dispose(): void { - this.logger.info('Disposed'); + this.logger.info('[%s] disposed', DocumentSymbolStructureExtension.name); } public getTreeItem(element: BaseStructureTreeItem): BaseStructureTreeItem { @@ -105,7 +103,11 @@ export class DocumentSymbolStructureExtension extends BaseExtension implements T try { this.documentCache = await this.parser.parseSource(window.activeTextEditor.document.getText()); } catch (e) { - this.logger.error('Document could not be parsed.', e); + this.logger.error( + '[%s] document could not be parsed, error: %s', + DocumentSymbolStructureExtension.name, + e, + ); return []; } } @@ -133,6 +135,7 @@ export class DocumentSymbolStructureExtension extends BaseExtension implements T */ private async jumpToNode(node: Node | undefined): Promise { if (!node) { + this.logger.warn('[%s] jumpToNode used without param', DocumentSymbolStructureExtension.name); window.showWarningMessage('This command is for internal use only. It cannot be used from Cmd+P'); return; } @@ -155,7 +158,7 @@ export class DocumentSymbolStructureExtension extends BaseExtension implements T * @memberof DocumentSymbolStructureExtension */ private activeWindowChanged(): void { - this.logger.info('Active window changed or document was saved. Reparse file.'); + this.logger.debug('[%s] activeWindowChanged, reparsing', DocumentSymbolStructureExtension.name); this.documentCache = undefined; this._onDidChangeTreeData.fire(); } diff --git a/src/extension/extensions/ImportResolveExtension.ts b/src/extension/extensions/ImportResolveExtension.ts index d785253..530094e 100644 --- a/src/extension/extensions/ImportResolveExtension.ts +++ b/src/extension/extensions/ImportResolveExtension.ts @@ -4,10 +4,10 @@ import { commands, ExtensionContext, StatusBarAlignment, StatusBarItem, window, import { getDeclarationsFilteredByImports } from '../../common/helpers'; import { ResolveQuickPickItem } from '../../common/quick-pick-items'; -import { Logger as OldLogger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; import { ImportManager } from '../managers'; import { DeclarationIndexMapper } from '../utilities/DeclarationIndexMapper'; +import { Logger } from '../utilities/winstonLogger'; import { BaseExtension } from './BaseExtension'; type DeclarationsForImportOptions = { cursorSymbol: string, documentSource: string, documentPath: string }; @@ -27,17 +27,15 @@ const resolverErr = 'TSH Resolver $(flame)'; */ @injectable() export class ImportResolveExtension extends BaseExtension { - private logger: OldLogger; private statusBarItem: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Left, 4); constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, - @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, + @inject(iocSymbols.logger) private logger: Logger, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.declarationIndexMapper) private indices: DeclarationIndexMapper, ) { super(context); - this.logger = loggerFactory('ImportResolveExtension'); } /** @@ -64,7 +62,7 @@ export class ImportResolveExtension extends BaseExtension { this.commandRegistrations(); - this.logger.info('Initialized'); + this.logger.info('[%s] initialized', ImportResolveExtension.name); } /** @@ -73,7 +71,7 @@ export class ImportResolveExtension extends BaseExtension { * @memberof ImportResolveExtension */ public dispose(): void { - this.logger.info('Disposed'); + this.logger.info('[%s] disposed', ImportResolveExtension.name); } /** @@ -100,11 +98,20 @@ export class ImportResolveExtension extends BaseExtension { { placeHolder: 'Add import to document:' }, ); if (selectedItem) { - this.logger.info('Add import to document', { resolveItem: selectedItem }); + this.logger.info( + '[%s] add import to document', + ImportResolveExtension.name, + { specifier: selectedItem.declarationInfo.declaration.name, library: selectedItem.declarationInfo.from }, + ); this.addImportToDocument(selectedItem.declarationInfo); } } catch (e) { - this.logger.error('An error happend during import picking', e); + this.logger.error( + '[%s] import could not be added to document, error: %s', + ImportResolveExtension.name, + e, + { file: window.activeTextEditor.document.fileName }, + ); window.showErrorMessage('The import cannot be completed, there was an error during the process.'); } } @@ -129,6 +136,7 @@ export class ImportResolveExtension extends BaseExtension { } try { const selectedSymbol = this.getSymbolUnderCursor(); + this.logger.debug('[%s] add import for symbol under cursor', ImportResolveExtension.name, { selectedSymbol }); if (!!!selectedSymbol) { return; } @@ -139,23 +147,47 @@ export class ImportResolveExtension extends BaseExtension { }); if (resolveItems.length < 1) { + this.logger.info( + '[%s] the symbol was not found or is already imported', + ImportResolveExtension.name, + { selectedSymbol }, + ); window.showInformationMessage( `The symbol '${selectedSymbol}' was not found in the index or is already imported.`, ); } else if (resolveItems.length === 1 && resolveItems[0].declaration.name === selectedSymbol) { - this.logger.info('Add import to document', { resolveItem: resolveItems[0] }); + this.logger.info( + '[%s] add import to document', + ImportResolveExtension.name, + { + specifier: resolveItems[0].declaration.name, + library: resolveItems[0].from, + }, + ); this.addImportToDocument(resolveItems[0]); } else { const selectedItem = await window.showQuickPick( resolveItems.map(o => new ResolveQuickPickItem(o)), { placeHolder: 'Multiple declarations found:' }, ); if (selectedItem) { - this.logger.info('Add import to document', { resolveItem: selectedItem }); + this.logger.info( + '[%s] add import to document', + ImportResolveExtension.name, + { + specifier: selectedItem.declarationInfo.declaration.name, + library: selectedItem.declarationInfo.from, + }, + ); this.addImportToDocument(selectedItem.declarationInfo); } } } catch (e) { - this.logger.error('An error happend during import picking', e); + this.logger.error( + '[%s] import could not be added to document, error: %s', + ImportResolveExtension.name, + e, + { file: window.activeTextEditor.document.fileName }, + ); window.showErrorMessage('The import cannot be completed, there was an error during the process.'); } } @@ -179,6 +211,11 @@ export class ImportResolveExtension extends BaseExtension { return; } try { + this.logger.debug( + '[%s] add all missing imports to the document', + ImportResolveExtension.name, + { file: window.activeTextEditor.document.fileName }, + ); const missing = await this.getMissingDeclarationsForFile({ documentSource: window.activeTextEditor.document.getText(), documentPath: window.activeTextEditor.document.fileName, @@ -190,7 +227,12 @@ export class ImportResolveExtension extends BaseExtension { await ctrl.commit(); } } catch (e) { - this.logger.error('An error happend during import fixing', e); + this.logger.error( + '[%s] missing imports could not be added, error: %s', + ImportResolveExtension.name, + e, + { file: window.activeTextEditor.document.fileName }, + ); window.showErrorMessage('The operation cannot be completed, there was an error during the process.'); } } @@ -208,10 +250,20 @@ export class ImportResolveExtension extends BaseExtension { return false; } try { + this.logger.debug( + '[%s] organize the imports in the document', + ImportResolveExtension.name, + { file: window.activeTextEditor.document.fileName }, + ); const ctrl = await ImportManager.create(window.activeTextEditor.document); return await ctrl.organizeImports().commit(); } catch (e) { - this.logger.error('An error happend during "organize imports".', { error: e }); + this.logger.error( + '[%s] imports could not be organized, error: %s', + ImportResolveExtension.name, + e, + { file: window.activeTextEditor.document.fileName }, + ); return false; } } @@ -260,6 +312,10 @@ export class ImportResolveExtension extends BaseExtension { * @memberof ImportResolveExtension */ private showCacheWarning(): void { + this.logger.warn( + '[%s] index was not ready or not index for this file found', + ImportResolveExtension.name, + ); window.showWarningMessage('Please wait a few seconds longer until the symbol cache has been build.'); } @@ -276,7 +332,6 @@ export class ImportResolveExtension extends BaseExtension { private async getDeclarationsForImport( { cursorSymbol, documentSource, documentPath }: DeclarationsForImportOptions, ): Promise { - this.logger.info(`Calculate possible imports for document with filter "${cursorSymbol}"`); if (!window.activeTextEditor) { return []; } @@ -288,6 +343,12 @@ export class ImportResolveExtension extends BaseExtension { return []; } + this.logger.debug( + '[%s] calculate possible imports for document', + ImportResolveExtension.name, + { cursorSymbol, file: documentPath }, + ); + const parsedSource = await this.parser.parseSource(documentSource); const activeDocumentDeclarations = parsedSource.declarations.map(o => o.name); const declarations = getDeclarationsFilteredByImports( @@ -327,6 +388,12 @@ export class ImportResolveExtension extends BaseExtension { return []; } + this.logger.debug( + '[%s] calculate missing imports for document', + ImportResolveExtension.name, + { file: documentPath }, + ); + const parsedDocument = await this.parser.parseSource(documentSource); const missingDeclarations: (DeclarationInfo)[] = []; const declarations = getDeclarationsFilteredByImports( diff --git a/src/extension/extensions/OrganizeImportsOnSaveExtension.ts b/src/extension/extensions/OrganizeImportsOnSaveExtension.ts index c13526f..e7791ef 100644 --- a/src/extension/extensions/OrganizeImportsOnSaveExtension.ts +++ b/src/extension/extensions/OrganizeImportsOnSaveExtension.ts @@ -2,9 +2,9 @@ import { inject, injectable } from 'inversify'; import { ExtensionContext, workspace } from 'vscode'; import { ConfigFactory } from '../../common/factories'; -import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../IoCSymbols'; import { ImportManager } from '../managers'; +import { Logger } from '../utilities/winstonLogger'; import { BaseExtension } from './BaseExtension'; /** @@ -22,15 +22,13 @@ export class OrganizeImportsOnSaveExtension extends BaseExtension { 'javascript', 'javascriptreact', ]; - private logger: Logger; constructor( @inject(iocSymbols.extensionContext) context: ExtensionContext, - @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, + @inject(iocSymbols.logger) private logger: Logger, @inject(iocSymbols.configuration) private config: ConfigFactory, ) { super(context); - this.logger = loggerFactory('OrganizeImportsOnSaveExtension'); } /** @@ -42,15 +40,26 @@ export class OrganizeImportsOnSaveExtension extends BaseExtension { this.context.subscriptions.push(workspace.onWillSaveTextDocument((event) => { const config = this.config(event.document.uri); if (!config.resolver.organizeOnSave) { - this.logger.info('Organize on save is deactivated through config.'); + this.logger.debug( + '[%s] organizeOnSave is deactivated through config', + OrganizeImportsOnSaveExtension.name, + ); return; } if (this.compatibleLanguages.indexOf(event.document.languageId) < 0) { - this.logger.info(`Organize imports for languageId "${event.document.languageId}" not possible.`); + this.logger.debug( + '[%s] organizeOnSave not possible for given language', + OrganizeImportsOnSaveExtension.name, + { language: event.document.languageId }, + ); return; } - this.logger.info(`Organize on save for document "${event.document.fileName}".`); + this.logger.info( + '[%s] organizeOnSave for file', + OrganizeImportsOnSaveExtension.name, + { file: event.document.fileName }, + ); event.waitUntil( ImportManager .create(event.document) @@ -58,7 +67,7 @@ export class OrganizeImportsOnSaveExtension extends BaseExtension { ); })); - this.logger.info('Initialized'); + this.logger.info('[%s] initialized', OrganizeImportsOnSaveExtension.name); } /** @@ -67,6 +76,6 @@ export class OrganizeImportsOnSaveExtension extends BaseExtension { * @memberof OrganizeImportsOnSaveExtension */ public dispose(): void { - this.logger.info('Disposed'); + this.logger.info('[%s] disposed', OrganizeImportsOnSaveExtension.name); } } From fca0f0c0f29795b7e47eb46a69c15e8352a62ded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Sat, 28 Oct 2017 01:25:22 +0200 Subject: [PATCH 7/9] adding propper logging --- src/extension/TypeScriptHero.ts | 17 +++-- src/extension/managers/ClassManager.ts | 35 +++++++++++ src/extension/managers/ImportManager.ts | 31 ++++++++++ .../utilities/DeclarationIndexMapper.ts | 62 +++++++++++++++---- 4 files changed, 124 insertions(+), 21 deletions(-) diff --git a/src/extension/TypeScriptHero.ts b/src/extension/TypeScriptHero.ts index 1403109..53b7e78 100644 --- a/src/extension/TypeScriptHero.ts +++ b/src/extension/TypeScriptHero.ts @@ -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); } } diff --git a/src/extension/managers/ClassManager.ts b/src/extension/managers/ClassManager.ts index 7b77859..c69fd3f 100644 --- a/src/extension/managers/ClassManager.ts +++ b/src/extension/managers/ClassManager.ts @@ -22,6 +22,7 @@ import { TypescriptCodeGeneratorFactory } from '../../common/factories'; import { Container } from '../IoC'; import { iocSymbols } from '../IoCSymbols'; import { Changeable } from '../proxy-objects/Changeable'; +import { Logger } from '../utilities/winstonLogger'; import { ObjectManager } from './ObjectManager'; type VisibleObject = { visibility?: DeclarationVisibility }; @@ -67,6 +68,10 @@ export class ClassManager implements ObjectManager { return Container.get(iocSymbols.generatorFactory)(); } + private static get logger(): Logger { + return Container.get(iocSymbols.logger); + } + private ctor: Changeable; private properties: Changeable[] = []; private methods: Changeable[] = []; @@ -76,6 +81,11 @@ export class ClassManager implements ObjectManager { public readonly parsedDocument: File, private readonly managedClass: ClassDeclaration, ) { + ClassManager.logger.debug( + '[%s] create class manager', + ClassManager.name, + { file: document.fileName, class: managedClass.name }, + ); this.ctor = new Changeable(managedClass.ctor); this.properties = managedClass.properties.map(o => new Changeable(o)); this.methods = managedClass.methods.map(o => new Changeable(o)); @@ -147,6 +157,11 @@ export class ClassManager implements ObjectManager { } this.properties.push(new Changeable(declaration, true)); + ClassManager.logger.debug( + '[%s] add property to class', + ClassManager.name, + { property: declaration.name, class: this.managedClass.name }, + ); return this; } @@ -171,6 +186,11 @@ export class ClassManager implements ObjectManager { if (property.isNew) { this.properties.splice(this.properties.indexOf(property), 1); } + ClassManager.logger.debug( + '[%s] remove property from class', + ClassManager.name, + { property: name, class: this.managedClass.name }, + ); return this; } @@ -219,6 +239,11 @@ export class ClassManager implements ObjectManager { } this.methods.push(new Changeable(declaration, true)); + ClassManager.logger.debug( + '[%s] add method to class', + ClassManager.name, + { property: declaration.name, class: this.managedClass.name }, + ); return this; } @@ -243,6 +268,11 @@ export class ClassManager implements ObjectManager { if (method.isNew) { this.methods.splice(this.methods.indexOf(method), 1); } + ClassManager.logger.debug( + '[%s] remove method from class', + ClassManager.name, + { property: name, class: this.managedClass.name }, + ); return this; } @@ -265,6 +295,11 @@ export class ClassManager implements ObjectManager { const workspaceEdit = new WorkspaceEdit(); workspaceEdit.set(this.document.uri, edits); + ClassManager.logger.debug( + '[%s] commit the class', + ClassManager.name, + { class: this.managedClass.name }, + ); return workspace.applyEdit(workspaceEdit); } diff --git a/src/extension/managers/ImportManager.ts b/src/extension/managers/ImportManager.ts index 9562ba7..9ce1622 100644 --- a/src/extension/managers/ImportManager.ts +++ b/src/extension/managers/ImportManager.ts @@ -30,6 +30,7 @@ import { ImportGroup } from '../import-grouping'; import { Container } from '../IoC'; import { iocSymbols } from '../IoCSymbols'; import { importSort, specifierSort } from '../utilities/utilityFunctions'; +import { Logger } from '../utilities/winstonLogger'; import { ObjectManager } from './ObjectManager'; function sameSpecifiers(specs1: SymbolSpecifier[], specs2: SymbolSpecifier[]): boolean { @@ -64,6 +65,10 @@ export class ImportManager implements ObjectManager { return Container.get<() => TypescriptCodeGenerator>(iocSymbols.generatorFactory)(); } + private static get logger(): Logger { + return Container.get(iocSymbols.logger); + } + private importGroups: ImportGroup[]; private imports: Import[] = []; private userImportDecisions: { [usage: string]: DeclarationInfo[] }[] = []; @@ -93,6 +98,11 @@ export class ImportManager implements ObjectManager { public readonly document: TextDocument, private _parsedDocument: File, ) { + ImportManager.logger.debug( + '[%s] create import manager', + ImportManager.name, + { file: document.fileName }, + ); this.reset(); } @@ -134,6 +144,11 @@ export class ImportManager implements ObjectManager { * @memberof ImportManager */ public addDeclarationImport(declarationInfo: DeclarationInfo): this { + ImportManager.logger.debug( + '[%s] add declaration as import', + ImportManager.name, + { file: this.document.fileName, specifier: declarationInfo.declaration.name, library: declarationInfo.from }, + ); // If there is something already imported, it must be a NamedImport const alreadyImported: NamedImport = this.imports.find( o => declarationInfo.from === getAbsolutLibraryName( @@ -185,6 +200,11 @@ export class ImportManager implements ObjectManager { * @memberof ImportManager */ public addMissingImports(index: DeclarationIndex): this { + ImportManager.logger.debug( + '[%s] add all missing imports', + ImportManager.name, + { file: this.document.fileName }, + ); const declarations = getDeclarationsFilteredByImports( index.declarationInfos, this.document.fileName, @@ -216,6 +236,11 @@ export class ImportManager implements ObjectManager { * @memberof ImportManager */ public organizeImports(): this { + ImportManager.logger.debug( + '[%s] organize the imports', + ImportManager.name, + { file: this.document.fileName }, + ); this.organize = true; let keep: Import[] = []; @@ -280,6 +305,12 @@ export class ImportManager implements ObjectManager { workspaceEdit.set(this.document.uri, edits); + ImportManager.logger.debug( + '[%s] commit the file', + ImportManager.name, + { file: this.document.fileName }, + ); + const result = await workspace.applyEdit(workspaceEdit); if (result) { diff --git a/src/extension/utilities/DeclarationIndexMapper.ts b/src/extension/utilities/DeclarationIndexMapper.ts index 122f784..698fa9a 100644 --- a/src/extension/utilities/DeclarationIndexMapper.ts +++ b/src/extension/utilities/DeclarationIndexMapper.ts @@ -14,8 +14,8 @@ import { import { ConfigFactory } from '../../common/factories'; import { findFiles } from '../../common/helpers'; -import { Logger, LoggerFactory } from '../../common/utilities'; import { iocSymbols } from '../../extension/IoCSymbols'; +import { Logger } from './winstonLogger'; interface WorkspaceIndex { index: DeclarationIndex; @@ -36,11 +36,10 @@ export class DeclarationIndexMapper { private _onFinishIndexing: EventEmitter; private _onIndexingError: EventEmitter<{ index: WorkspaceIndex, error: Error }>; - private logger: Logger; private indizes: { [uri: string]: WorkspaceIndex } = {}; constructor( - @inject(iocSymbols.loggerFactory) loggerFactory: LoggerFactory, + @inject(iocSymbols.logger) private logger: Logger, @inject(iocSymbols.extensionContext) private context: ExtensionContext, @inject(iocSymbols.typescriptParser) private parser: TypescriptParser, @inject(iocSymbols.configuration) private config: ConfigFactory, @@ -56,24 +55,28 @@ export class DeclarationIndexMapper { this.context.subscriptions.push(this._onFinishIndexing); this.context.subscriptions.push(this._onIndexingError); this.context.subscriptions.push(this._onStartIndexing); - - this.logger = loggerFactory('DeclarationIndexMapper'); } @postConstruct() public initialize(): void { this.context.subscriptions.push(workspace.onDidChangeWorkspaceFolders(e => this.workspaceChanged(e))); this.logger.info( - `Fired up index mapper, got ${(workspace.workspaceFolders || []).length} workspaces.`, - workspace.workspaceFolders, + '[%s] initializing index mapper for %d workspaces', + DeclarationIndexMapper.name, + (workspace.workspaceFolders || []).length, ); + for (const folder of (workspace.workspaceFolders || []).filter(workspace => workspace.uri.scheme === 'file')) { this.initializeIndex(folder); } - this.logger.info('Initialized'); + this.logger.info('[%s] initialized', DeclarationIndexMapper.name); } public rebuildAll(): void { + this.logger.info( + '[%s] rebuilding all indices', + DeclarationIndexMapper.name, + ); for (const index of Object.values(this.indizes)) { index.watcher.dispose(); index.index.reset(); @@ -87,6 +90,11 @@ export class DeclarationIndexMapper { public getIndexForFile(fileUri: Uri): DeclarationIndex | undefined { const workspaceFolder = workspace.getWorkspaceFolder(fileUri); if (!workspaceFolder || !this.indizes[workspaceFolder.uri.fsPath]) { + this.logger.debug( + '[%s] did not find index for file', + DeclarationIndexMapper.name, + { file: fileUri.fsPath }, + ); return; } @@ -94,16 +102,33 @@ export class DeclarationIndexMapper { } private workspaceChanged(event: WorkspaceFoldersChangeEvent): void { - this.logger.info('Workspaces changed.', event); + this.logger.info( + '[%s] workspaces changed, adjusting indices', + DeclarationIndexMapper.name, + ); for (const add of event.added) { + this.logger.debug( + '[%s] add workspace for "%s"', + DeclarationIndexMapper.name, + add.uri.fsPath, + ); if (this.indizes[add.uri.fsPath]) { - this.logger.warning(`The workspace with the path ${add.uri.fsPath} already exists. Skipping.`); + this.logger.warn( + '[%s] workspace index "%s" already exists, skipping', + DeclarationIndexMapper.name, + add.uri.fsPath, + ); continue; } this.initializeIndex(add); } for (const remove of event.removed) { + this.logger.debug( + '[%s] remove workspace for "%s"', + DeclarationIndexMapper.name, + remove.uri.fsPath, + ); this.indizes[remove.uri.fsPath].index.reset(); this.indizes[remove.uri.fsPath].watcher.dispose(); delete this.indizes[remove.uri.fsPath]; @@ -111,6 +136,12 @@ export class DeclarationIndexMapper { } private async initializeIndex(folder: WorkspaceFolder): Promise { + const profiler = this.logger.startTimer(); + this.logger.debug( + '[%s] initialize index for "%s"', + DeclarationIndexMapper.name, + folder.uri.fsPath, + ); const index = new DeclarationIndex(this.parser, folder.uri.fsPath); const config = this.config(folder.uri); const files = await findFiles(config, folder); @@ -164,10 +195,17 @@ export class DeclarationIndexMapper { try { await index.buildIndex(files); this.indizes[folder.uri.fsPath] = workspaceIndex; - this.logger.info(`Finished building index for workspace "${folder.name}".`); this._onFinishIndexing.fire(workspaceIndex); + profiler.done({ + message: `[${DeclarationIndexMapper.name}] built index for workspace "${folder.name}"`, + }); } catch (error) { - this.logger.error(`Error during build of index for workspace "${folder.name}"`, error); + this.logger.error( + '[%s] could not build index for workspace "%s", error: %s', + DeclarationIndexMapper.name, + folder.uri.fsPath, + error, + ); this._onIndexingError.fire({ error, index: workspaceIndex }); } } From 8a450126aa0e6f6508b121303900b174c7b805a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Sat, 28 Oct 2017 01:30:32 +0200 Subject: [PATCH 8/9] change log msg --- src/extension/utilities/DeclarationIndexMapper.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/extension/utilities/DeclarationIndexMapper.ts b/src/extension/utilities/DeclarationIndexMapper.ts index 698fa9a..15d51e7 100644 --- a/src/extension/utilities/DeclarationIndexMapper.ts +++ b/src/extension/utilities/DeclarationIndexMapper.ts @@ -178,9 +178,16 @@ export class DeclarationIndexMapper { timeout = setTimeout( async () => { if (events) { - this.logger.info(`Refreshing index for workspace ${folder.name}.`); + const profiler = this.logger.startTimer(); + this.logger.debug( + '[%s] rebuilding index for index "%s"', + DeclarationIndexMapper.name, + folder.uri.fsPath, + ); await index.reindexForChanges(events); - this.logger.info(`Finished indexing for workspace ${folder.name}.`); + profiler.done({ + message: `[${DeclarationIndexMapper.name}] rebuilt index for workspace "${folder.name}"`, + }); events = undefined; } }, From 62b67671f48cd0f8a85c3d373c9927b516cb92bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=BChler?= Date: Sat, 28 Oct 2017 10:44:28 +0200 Subject: [PATCH 9/9] correcting tests for injections --- .../extensions/CodeActionExtension.test.ts | 24 +++++++++---------- .../CodeCompletionExtension.test.ts | 6 ++--- .../DocumentSymbolStructureExtension.test.ts | 4 ++-- .../extensions/ImportResolveExtension.test.ts | 8 +++---- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts b/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts index d5f6b59..25df25f 100644 --- a/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/CodeActionExtension.test.ts @@ -6,7 +6,6 @@ import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; import { ExtensionContext, Position, Range, TextDocument, window, workspace } from 'vscode'; import { ConfigFactory } from '../../../../src/common/factories'; -import { LoggerFactory } from '../../../../src/common/utilities'; import { AddImportCodeAction, CodeAction, ImplementPolymorphElements } from '../../../../src/extension/code-actions'; import { MissingImplementationInClassCreator, @@ -16,6 +15,7 @@ import { CodeActionExtension } from '../../../../src/extension/extensions/CodeAc import { Container } from '../../../../src/extension/IoC'; import { iocSymbols } from '../../../../src/extension/IoCSymbols'; import { DeclarationIndexMapper } from '../../../../src/extension/utilities/DeclarationIndexMapper'; +import { Logger } from '../../../../src/extension/utilities/winstonLogger'; chai.should(); chai.use(sinonChai); @@ -36,7 +36,7 @@ describe('CodeActionExtension', () => { before(async () => { const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.loggerFactory); + const logger = Container.get(iocSymbols.logger); const parser = Container.get(iocSymbols.typescriptParser); const config = Container.get(iocSymbols.configuration); const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); @@ -66,8 +66,8 @@ describe('CodeActionExtension', () => { fakeMapper.getIndexForFile = sinon.spy(() => index); const creators = [ - new MissingImportCreator(fakeMapper), - new MissingImplementationInClassCreator(parser, fakeMapper), + new MissingImportCreator(fakeMapper, logger), + new MissingImplementationInClassCreator(parser, fakeMapper, logger), ]; extension = new CodeActionExtension(ctx, logger, creators, fakeMapper); @@ -194,7 +194,7 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: - `non-abstract class 'Foobar' implement inherited from class 'CodeFixImplementAbstract'.`, + `non-abstract class 'Foobar' implement inherited from class 'CodeFixImplementAbstract'.`, }, ], }, @@ -261,7 +261,7 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: `non-abstract class 'Foobar' ` + - `implement inherited from class 'GenericAbstractClass'.`, + `implement inherited from class 'GenericAbstractClass'.`, }, ], }, @@ -317,7 +317,7 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: `non-abstract class 'AbstractImplement' ` + - `implement inherited from class 'CodeFixImplementAbstract'.`, + `implement inherited from class 'CodeFixImplementAbstract'.`, }, ], }, @@ -365,8 +365,8 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: - `non-abstract class 'InternalAbstractImplement' ` + - `implement inherited from class 'InternalAbstract'.`, + `non-abstract class 'InternalAbstractImplement' ` + + `implement inherited from class 'InternalAbstract'.`, }, ], }, @@ -388,7 +388,7 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: `class 'ImplementGenericInterface' incorrectly ` + - `implements 'GenericInterface'.`, + `implements 'GenericInterface'.`, }, ], }, @@ -412,8 +412,8 @@ describe('CodeActionExtension', () => { diagnostics: [ { message: - `non-abstract class 'ImplementGenericAbstract' ` + - `implement inherited from class 'GenericAbstractClass'.`, + `non-abstract class 'ImplementGenericAbstract' ` + + `implement inherited from class 'GenericAbstractClass'.`, }, ], }, diff --git a/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts b/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts index a42c6ed..0580541 100644 --- a/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/CodeCompletionExtension.test.ts @@ -5,12 +5,12 @@ import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; import * as vscode from 'vscode'; import { ConfigFactory } from '../../../../src/common/factories'; -import { LoggerFactory } from '../../../../src/common/utilities'; +import { VscodeExtensionConfig } from '../../../../src/extension/config/VscodeExtensionConfig'; import { CodeCompletionExtension } from '../../../../src/extension/extensions/CodeCompletionExtension'; import { Container } from '../../../../src/extension/IoC'; import { iocSymbols } from '../../../../src/extension/IoCSymbols'; import { DeclarationIndexMapper } from '../../../../src/extension/utilities/DeclarationIndexMapper'; -import { VscodeExtensionConfig } from '../../../../src/extension/config/VscodeExtensionConfig'; +import { Logger } from '../../../../src/extension/utilities/winstonLogger'; const should = chai.should(); @@ -30,7 +30,7 @@ describe('CodeCompletionExtension', () => { await vscode.window.showTextDocument(document); const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.loggerFactory); + const logger = Container.get(iocSymbols.logger); const parser = Container.get(iocSymbols.typescriptParser); const config = Container.get(iocSymbols.configuration); const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); diff --git a/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts b/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts index 9930532..11d5588 100644 --- a/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/DocumentSymbolStructureExtension.test.ts @@ -3,7 +3,6 @@ import { TypescriptParser } from 'typescript-parser'; import * as vscode from 'vscode'; import { ConfigFactory } from '../../../../src/common/factories'; -import { LoggerFactory } from '../../../../src/common/utilities'; import { DocumentSymbolStructureExtension } from '../../../../src/extension/extensions/DocumentSymbolStructureExtension'; import { Container } from '../../../../src/extension/IoC'; import { iocSymbols } from '../../../../src/extension/IoCSymbols'; @@ -20,6 +19,7 @@ import { import { NotParseableStructureTreeItem, } from '../../../../src/extension/provider-items/document-structure/NotParseableStructureTreeItem'; +import { Logger } from '../../../../src/extension/utilities/winstonLogger'; describe('DocumentSymbolStructureExtension', () => { @@ -33,7 +33,7 @@ describe('DocumentSymbolStructureExtension', () => { before(async () => { const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.loggerFactory); + const logger = Container.get(iocSymbols.logger); const parser = Container.get(iocSymbols.typescriptParser); const config = Container.get(iocSymbols.configuration); diff --git a/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts b/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts index 906ec3e..7692492 100644 --- a/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts +++ b/test/single-workspace-tests/extension/extensions/ImportResolveExtension.test.ts @@ -5,11 +5,11 @@ import { DeclarationIndex, TypescriptParser } from 'typescript-parser'; import * as vscode from 'vscode'; import { ConfigFactory } from '../../../../src/common/factories'; -import { LoggerFactory } from '../../../../src/common/utilities'; import { ImportResolveExtension } from '../../../../src/extension/extensions/ImportResolveExtension'; import { Container } from '../../../../src/extension/IoC'; import { iocSymbols } from '../../../../src/extension/IoCSymbols'; import { DeclarationIndexMapper } from '../../../../src/extension/utilities/DeclarationIndexMapper'; +import { Logger } from '../../../../src/extension/utilities/winstonLogger'; chai.should(); @@ -29,7 +29,7 @@ describe('TypeScript Mode: ImportResolveExtension', () => { await vscode.window.showTextDocument(document); const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.loggerFactory); + const logger = Container.get(iocSymbols.logger); const config = Container.get(iocSymbols.configuration); const parser = Container.get(iocSymbols.typescriptParser); const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); @@ -241,7 +241,7 @@ describe('JavaScript Mode: ImportResolveExtension', () => { await vscode.window.showTextDocument(document); const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.loggerFactory); + const logger = Container.get(iocSymbols.logger); const config = Container.get(iocSymbols.configuration); const parser = Container.get(iocSymbols.typescriptParser); const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config); @@ -340,7 +340,7 @@ describe('Mixed Mode: ImportResolveExtension', () => { await vscode.window.showTextDocument(document); const ctx = Container.get(iocSymbols.extensionContext); - const logger = Container.get(iocSymbols.loggerFactory); + const logger = Container.get(iocSymbols.logger); const config = Container.get(iocSymbols.configuration); const parser = Container.get(iocSymbols.typescriptParser); const fakeMapper = new DeclarationIndexMapper(logger, ctx, parser, config);