Skip to content

Commit 5c85e26

Browse files
authored
Merge pull request #214 from pajoma/feat/208-constructor-injection
refactor(di): decompose Ctrl god object via constructor injection (#208)
2 parents 7cc196d + b0603f5 commit 5c85e26

23 files changed

Lines changed: 157 additions & 175 deletions

src/actions/inject.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,15 @@
2020

2121

2222
import * as vscode from 'vscode';
23-
import { JournalController, Input, InlineTemplate, InlineString, HeaderTemplate } from '../model';
23+
import { IConfiguration, ILogger, Input, InlineTemplate, InlineString, HeaderTemplate } from '../model';
2424
import { isNullOrUndefined } from '../util';
2525

2626

2727

2828

2929
export class Inject {
3030

31-
constructor(public ctrl: JournalController) {
32-
31+
constructor(private config: IConfiguration, private logger: ILogger) {
3332
}
3433

3534
/**
@@ -43,27 +42,27 @@ export class Inject {
4342
* @memberof Inject
4443
*/
4544
public async injectInput(doc: vscode.TextDocument, input: Input): Promise<vscode.TextDocument> {
46-
this.ctrl.logger.trace("Entering injectInput() in inject.ts with Input:", JSON.stringify(input));
45+
this.logger.trace("Entering injectInput() in inject.ts with Input:", JSON.stringify(input));
4746

4847
if (!input.hasMemo() || !input.hasFlags()) {
4948
return doc;
5049
}
5150

5251
try {
5352
if (input.flags.match("memo")) {
54-
const tplInfo = await this.ctrl.config.getMemoInlineTemplate();
53+
const tplInfo = await this.config.getMemoInlineTemplate();
5554
const val = await this.buildInlineString(doc, tplInfo, ["${input}", input.text]);
5655
return this.injectInlineString(val);
5756
} else if (input.flags.match(/task|todo/)) {
58-
const tplInfo = await this.ctrl.config.getTaskInlineTemplate();
57+
const tplInfo = await this.config.getTaskInlineTemplate();
5958
const val = await this.buildInlineString(doc, tplInfo, ["${input}", input.text]);
6059
return this.injectInlineString(val);
6160
} else {
6261
throw new Error("Failed to handle input");
6362
}
6463
} catch (error) {
6564
if (error instanceof Error) {
66-
this.ctrl.logger.error(error.message);
65+
this.logger.error(error.message);
6766
}
6867
throw error;
6968
}
@@ -85,7 +84,7 @@ export class Inject {
8584
* Updates: Fix for #55, always make sure there is a linebreak between the header and the injected text to stay markdown compliant
8685
*/
8786
public async buildInlineString(doc: vscode.TextDocument, tpl: InlineTemplate, ...values: string[][]): Promise<InlineString> {
88-
this.ctrl.logger.trace("Entering buildInlineString() in inject.ts with InlineTemplate: ", JSON.stringify(tpl), " and values ", JSON.stringify(values));
87+
this.logger.trace("Entering buildInlineString() in inject.ts with InlineTemplate: ", JSON.stringify(tpl), " and values ", JSON.stringify(values));
8988

9089
let content: string = tpl.value!;
9190
values.forEach((val: string[]) => {
@@ -149,10 +148,10 @@ export class Inject {
149148
*
150149
*/
151150
public async injectInlineString(content: InlineString, ...other: InlineString[]): Promise<vscode.TextDocument> {
152-
this.ctrl.logger.trace("Entering injectInlineString() in inject.ts with string: ", content.value.trim());
151+
this.logger.trace("Entering injectInlineString() in inject.ts with string: ", content.value.trim());
153152

154153
if (isNullOrUndefined(content)) {
155-
this.ctrl.logger.error("Content is null");
154+
this.logger.error("Content is null");
156155
throw new Error("Invalid call, no reference to document due to null content.");
157156
}
158157

@@ -167,13 +166,13 @@ export class Inject {
167166
}
168167

169168
if (isNullOrUndefined(edit) || edit.size === 0) {
170-
this.ctrl.logger.trace("No changes have been made to the document: ", content.document.fileName);
169+
this.logger.trace("No changes have been made to the document: ", content.document.fileName);
171170
return content.document;
172171
}
173172

174173
const applied = await vscode.workspace.applyEdit(edit);
175174
if (!applied) {
176-
this.ctrl.logger.error("Failed inject inline string '", content.value, "'");
175+
this.logger.error("Failed inject inline string '", content.value, "'");
177176
throw new Error("Failed to applied edit");
178177
}
179178
return content.document;
@@ -235,8 +234,8 @@ export class Inject {
235234
* @memberof Inject
236235
*/
237236
public async formatNote(input: Input): Promise<string> {
238-
this.ctrl.logger.trace("Entering formatNote() in inject.ts with input: ", JSON.stringify(input));
239-
const headerTemplate: HeaderTemplate = await this.ctrl.config.getNotesTemplate(input.scope);
237+
this.logger.trace("Entering formatNote() in inject.ts with input: ", JSON.stringify(input));
238+
const headerTemplate: HeaderTemplate = await this.config.getNotesTemplate(input.scope);
240239
headerTemplate.value = headerTemplate.value!.replace('${input}', input.text);
241240
headerTemplate.value = headerTemplate.value!.replace('${tags}', input.tags.join(" ") + '\n');
242241

src/actions/parser.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
'use strict';
1919

2020
import * as Path from 'path';
21-
import { JournalController, Input } from '../model';
21+
import { IConfiguration, ILogger, Input } from '../model';
2222
import { isNullOrUndefined, isNotNullOrUndefined, normalizeFilename, getCurrentISOWeek, getISOWeekYear } from '../util';
2323
import { SCOPE_DEFAULT } from '../ext';
2424
import { MatchInput } from '../provider/features/match-input';
@@ -28,7 +28,7 @@ import { MatchInput } from '../provider/features/match-input';
2828
*/
2929
export class Parser {
3030

31-
constructor(public ctrl: JournalController) {
31+
constructor(private config: IConfiguration, private logger: ILogger) {
3232
}
3333

3434
/**
@@ -44,49 +44,49 @@ export class Parser {
4444

4545

4646

47-
this.ctrl.logger.trace("Entering resolveNotePathForInput() in actions/parser.ts");
47+
this.logger.trace("Entering resolveNotePathForInput() in actions/parser.ts");
4848

4949
const date = new Date();
5050
input.scope = SCOPE_DEFAULT;
5151

5252
input.text.match(/#\w+\s/g)?.forEach(tag => {
5353
if (isNullOrUndefined(tag) || tag!.length === 0) { return; }
54-
this.ctrl.logger.trace("Tags in input string: " + tag);
54+
this.logger.trace("Tags in input string: " + tag);
5555
input.tags.push(tag.trim().substring(0, tag.length - 1));
5656
input.text = input.text.replace(tag, " ");
57-
this.ctrl.logger.trace("Scopes defined in configuration: " + this.ctrl.config.getScopes());
58-
const scope: string | undefined = this.ctrl.config.getScopes().filter((name: string) => name === tag.trim().substring(1, tag.length)).pop();
57+
this.logger.trace("Scopes defined in configuration: " + this.config.getScopes());
58+
const scope: string | undefined = this.config.getScopes().filter((name: string) => name === tag.trim().substring(1, tag.length)).pop();
5959
if (isNotNullOrUndefined(scope) && scope!.length > 0) {
6060
input.scope = scope!;
6161
}
62-
this.ctrl.logger.trace("Identified scope in input: " + input.scope);
62+
this.logger.trace("Identified scope in input: " + input.scope);
6363
});
6464

6565
const inputForFileName = normalizeFilename(input.text);
66-
const granularity = this.ctrl.config.getEntryGranularity(input.scope);
66+
const granularity = this.config.getEntryGranularity(input.scope);
6767
const filePromise = granularity === "weekly"
68-
? this.ctrl.config.getWeeklyNotesFilePattern(
68+
? this.config.getWeeklyNotesFilePattern(
6969
getCurrentISOWeek(date),
7070
getISOWeekYear(date),
7171
inputForFileName,
7272
input.scope,
7373
)
74-
: this.ctrl.config.getNotesFilePattern(date, inputForFileName, input.scope);
74+
: this.config.getNotesFilePattern(date, inputForFileName, input.scope);
7575
const pathPromise = granularity === "weekly"
76-
? this.ctrl.config.getResolvedWeeklyNotesPath(
76+
? this.config.getResolvedWeeklyNotesPath(
7777
getCurrentISOWeek(date),
7878
getISOWeekYear(date),
7979
input.scope,
8080
)
81-
: this.ctrl.config.getResolvedNotesPath(date, input.scope);
81+
: this.config.getResolvedNotesPath(date, input.scope);
8282

8383
try {
8484
const [fileTemplate, pathTemplate] = await Promise.all([filePromise, pathPromise]);
8585
const path = Path.join(pathTemplate.value!, fileTemplate.value!.trim());
86-
this.ctrl.logger.trace("Resolved path for note is", path);
86+
this.logger.trace("Resolved path for note is", path);
8787
return path;
8888
} catch (error) {
89-
this.ctrl.logger.error("Failed to resolve note path. Reason: ", error);
89+
this.logger.error("Failed to resolve note path. Reason: ", error);
9090
throw error;
9191
}
9292

@@ -103,9 +103,9 @@ export class Parser {
103103
*/
104104
public async parseInput(inputString: string): Promise<Input> {
105105
let inputMatcher = new MatchInput(
106-
this.ctrl.logger,
107-
this.ctrl.config.getLocale(),
108-
this.ctrl.config.getEntryGranularity(),
106+
this.logger,
107+
this.config.getLocale(),
108+
this.config.getEntryGranularity(),
109109
);
110110
return inputMatcher.parseInput(inputString);
111111

src/actions/reader.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
'use strict';
2020

2121
import * as vscode from 'vscode';
22-
import { JournalController, Input } from '../model';
22+
import { IConfiguration, IDialogues, ILogger, IWriter, Input } from '../model';
2323
import { isNullOrUndefined, resolvePath, fileExists } from '../util';
2424

2525
export class Reader {
2626
public onNotesInjected?: (doc: vscode.TextDocument, date: Date) => void;
2727

28-
constructor(public ctrl: JournalController) {
28+
constructor(private config: IConfiguration, private logger: ILogger, private writer: IWriter, private ui: IDialogues) {
2929
}
3030

3131

@@ -55,19 +55,19 @@ export class Reader {
5555
* @param week the week of the current year
5656
*/
5757
public async loadEntryForWeek(week: Number, scope?: string): Promise<vscode.TextDocument> {
58-
this.ctrl.logger.trace("Entering loadEntryForWeek() in actions/reader.ts for week " + week);
58+
this.logger.trace("Entering loadEntryForWeek() in actions/reader.ts for week " + week);
5959

6060
const [pathname, filename] = await Promise.all([
61-
this.ctrl.config.getWeekPathPattern(week, scope),
62-
this.ctrl.config.getWeekFilePattern(week, scope),
61+
this.config.getWeekPathPattern(week, scope),
62+
this.config.getWeekFilePattern(week, scope),
6363
]);
6464
const path = resolvePath(pathname.value!, filename.value!);
6565

6666
const doc = await this.openOrCreate(
6767
path,
68-
() => this.ctrl.writer.createWeeklyForPath(path, week),
68+
() => this.writer.createWeeklyForPath(path, week),
6969
);
70-
this.ctrl.logger.debug("loadEntryForWeek() - Loaded file in:", doc.uri.toString());
70+
this.logger.debug("loadEntryForWeek() - Loaded file in:", doc.uri.toString());
7171
return doc;
7272
}
7373

@@ -83,19 +83,19 @@ export class Reader {
8383
if (isNullOrUndefined(date) || date!.toString().includes("Invalid")) {
8484
throw new Error("Invalid date");
8585
}
86-
this.ctrl.logger.trace("Entering loadEntryforDate() in actions/reader.ts for date " + date.toISOString());
86+
this.logger.trace("Entering loadEntryforDate() in actions/reader.ts for date " + date.toISOString());
8787

8888
const [pathname, filename] = await Promise.all([
89-
this.ctrl.config.getResolvedEntryPath(date, scope),
90-
this.ctrl.config.getEntryFilePattern(date, scope),
89+
this.config.getResolvedEntryPath(date, scope),
90+
this.config.getEntryFilePattern(date, scope),
9191
]);
9292
const path = resolvePath(pathname.value!, filename.value!);
9393

9494
const doc = await this.openOrCreate(
9595
path,
96-
() => this.ctrl.writer.createEntryForPath(path, date),
96+
() => this.writer.createEntryForPath(path, date),
9797
);
98-
this.ctrl.logger.debug("loadEntryForDate() - Loaded file in:", doc.uri.toString());
98+
this.logger.debug("loadEntryForDate() - Loaded file in:", doc.uri.toString());
9999

100100
this.onNotesInjected?.(doc, date);
101101

@@ -108,7 +108,7 @@ export class Reader {
108108
): Promise<vscode.TextDocument> {
109109
const exists = await fileExists(vscode.Uri.file(path));
110110
if (exists) {
111-
return this.ctrl.ui.openDocument(path);
111+
return this.ui.openDocument(path);
112112
}
113113
return create();
114114
}

src/actions/writer.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@
1919
'use strict';
2020

2121
import * as vscode from 'vscode';
22-
import { JournalController } from '../model';
22+
import { IConfiguration, IInject, ILogger } from '../model';
2323

24-
/**
25-
* Anything which modifies the text documents goes here.
26-
*
24+
/**
25+
* Anything which modifies the text documents goes here.
26+
*
2727
*/
2828
export class Writer {
2929

3030

31-
constructor(public ctrl: JournalController) {
31+
constructor(private config: IConfiguration, private logger: ILogger, private inject: IInject) {
3232
}
3333

3434
public async saveDocument(doc: vscode.TextDocument): Promise<vscode.TextDocument> {
@@ -41,7 +41,7 @@ export class Writer {
4141
* Adds the given content at the start of text document
4242
*/
4343
public async writeHeader(doc: vscode.TextDocument, content: string): Promise<vscode.TextDocument> {
44-
return this.ctrl.inject.injectString(doc, content, new vscode.Position(0, 0));
44+
return this.inject.injectString(doc, content, new vscode.Position(0, 0));
4545
}
4646

4747

@@ -56,8 +56,8 @@ export class Writer {
5656
* @memberof Writer
5757
*/
5858
public async createEntryForPath(path: string, date: Date): Promise<vscode.TextDocument> {
59-
this.ctrl.logger.trace("Entering createEntryForPath() in ext/writer.ts for path: ", path);
60-
const tpl = await this.ctrl.config.getEntryTemplate(date);
59+
this.logger.trace("Entering createEntryForPath() in ext/writer.ts for path: ", path);
60+
const tpl = await this.config.getEntryTemplate(date);
6161
const content = tpl.value || "";
6262
return this.createSaveLoadTextDocument(path, content);
6363
}
@@ -71,8 +71,8 @@ export class Writer {
7171
* @memberof Writer
7272
*/
7373
public async createWeeklyForPath(path: string, week: Number): Promise<vscode.TextDocument> {
74-
this.ctrl.logger.trace("Entering createWeeklyForPath() in ext/writer.ts for path: ", path);
75-
const tpl = await this.ctrl.config.getWeeklyTemplate(week);
74+
this.logger.trace("Entering createWeeklyForPath() in ext/writer.ts for path: ", path);
75+
const tpl = await this.config.getWeeklyTemplate(week);
7676
const content = tpl.value || "";
7777
return this.createSaveLoadTextDocument(path, content);
7878
}
@@ -86,7 +86,7 @@ export class Writer {
8686
*/
8787
public async createSaveLoadTextDocument(path: string, content: string): Promise<vscode.TextDocument> {
8888

89-
this.ctrl.logger.trace("Entering createSaveLoadTextDocument() in ext/writer.ts for path: ", path);
89+
this.logger.trace("Entering createSaveLoadTextDocument() in ext/writer.ts for path: ", path);
9090

9191
const fileUri = vscode.Uri.file(path);
9292
const encoder = new TextEncoder();
@@ -96,7 +96,7 @@ export class Writer {
9696

9797
// Open the persisted document
9898
const doc = await vscode.workspace.openTextDocument(fileUri);
99-
this.ctrl.logger.debug("Opened new file with name: ", doc.fileName);
99+
this.logger.debug("Opened new file with name: ", doc.fileName);
100100
return doc;
101101

102102
}

0 commit comments

Comments
 (0)