Skip to content

Commit 234fd62

Browse files
committed
chore: refactoring; adjusted cursorrules
1 parent 6bae36d commit 234fd62

File tree

10 files changed

+104
-47
lines changed

10 files changed

+104
-47
lines changed

.cursor/rules/commands.mdc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
---
22
description: Describes how to create and register new commands
3-
globs:
3+
globs: src/command/*.ts
44
alwaysApply: false
55
---
6-
- Commands are located in src/command directory
6+
- Commands are located in `src/command` directory
77
- Commands must extend the [Command.ts](mdc:src/command/Command.ts) abstract class or any other class that inherits it
8+
- Command name must be defined in format: `magentoToolbox.commandName`
89
- New commands must be added to [index.ts](mdc:src/command/index.ts) file so that they are loaded. Commands also need to be added to [package.json](mdc:package.json) under contributes -> commands
910
- Commands that only generate files based on a pre-defined template can extend the [SimpleTemplateGeneratorCommand.ts](mdc:src/command/SimpleTemplateGeneratorCommand.ts) class

.cursor/rules/tests.mdc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
description: Describes how to write tests
3+
globs: *.test.ts
4+
alwaysApply: false
5+
---
6+
- Tests are located in the src/test directory
7+
- Utilities for tests can be found in this file [util.ts](mdc:src/test/util.ts)
8+
- Some parts of the extension require the ExtensionContext to be present. To make sure it's set, tests should run the setup function from [setup.ts](mdc:src/test/setup.ts)
9+
- Tests are written using Mocha framework (`mocha` package) in Typescript and must end with .test.ts file extension. Do NOT use `chai`
10+
- Test spies, stubs and mocks can be written using the Sinon.js library
11+
- Reference files for tests are stored in the test-resources directory

src/command/SimpleTemplateGeneratorCommand.ts

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import IndexManager from 'indexer/IndexManager';
22
import { Command } from './Command';
3-
import { Uri, window } from 'vscode';
3+
import { Uri, WorkspaceFolder } from 'vscode';
44
import ModuleIndexer from 'indexer/module/ModuleIndexer';
55
import FileGeneratorManager from 'generator/FileGeneratorManager';
66
import TemplateGenerator from 'generator/TemplateGenerator';
@@ -36,28 +36,50 @@ export abstract class SimpleTemplateGeneratorCommand extends Command {
3636
return data;
3737
}
3838

39-
public async execute(uri?: Uri): Promise<void> {
40-
const moduleIndex = IndexManager.getIndexData(ModuleIndexer.KEY);
41-
let contextModule: string | undefined;
39+
public async getWizardData(contextModule: string | undefined): Promise<TemplateWizardData> {
40+
const wizard = new SimpleTemplateWizard();
41+
const data = await wizard.show(
42+
this.getWizardTitle(),
43+
contextModule,
44+
this.getAreas(),
45+
this.getWizardFields(),
46+
this.getWizardValidation()
47+
);
4248

43-
const contextUri = uri || window.activeTextEditor?.document.uri;
49+
return data;
50+
}
51+
52+
public getContextModule(contextUri: Uri | undefined): string | undefined {
53+
if (!contextUri) {
54+
return undefined;
55+
}
56+
57+
const moduleIndex = IndexManager.getIndexData(ModuleIndexer.KEY);
4458

4559
if (moduleIndex && contextUri) {
4660
const module = moduleIndex.getModuleByUri(contextUri);
4761

4862
if (module) {
49-
contextModule = module.name;
63+
return module.name;
5064
}
5165
}
5266

53-
const wizard = new SimpleTemplateWizard();
54-
const data = await wizard.show(
55-
this.getWizardTitle(),
56-
contextModule,
57-
this.getAreas(),
58-
this.getWizardFields(),
59-
this.getWizardValidation()
60-
);
67+
return undefined;
68+
}
69+
70+
protected getWorkspaceFolder(): WorkspaceFolder {
71+
const workspaceFolder = Common.getActiveWorkspaceFolder();
72+
73+
if (!workspaceFolder) {
74+
throw new Error('No active workspace folder');
75+
}
76+
77+
return workspaceFolder;
78+
}
79+
80+
public async execute(uri?: Uri): Promise<void> {
81+
const contextModule = this.getContextModule(uri);
82+
const data = await this.getWizardData(contextModule);
6183

6284
const manager = new FileGeneratorManager([
6385
new TemplateGenerator(this.getFilePath(data), this.getTemplateName(data), {
@@ -66,12 +88,7 @@ export abstract class SimpleTemplateGeneratorCommand extends Command {
6688
}),
6789
]);
6890

69-
const workspaceFolder = Common.getActiveWorkspaceFolder();
70-
71-
if (!workspaceFolder) {
72-
window.showErrorMessage('No active workspace folder');
73-
return;
74-
}
91+
const workspaceFolder = this.getWorkspaceFolder();
7592

7693
await manager.generate(workspaceFolder.uri);
7794
await manager.writeFiles();

src/generator/util/GenerateFromTemplate.ts renamed to src/generator/HandlebarsTemplateRenderer.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,20 @@ import FileSystem from 'util/FileSystem';
44
import { Uri } from 'vscode';
55
import Logger from 'util/Logger';
66

7-
export default class GenerateFromTemplate {
8-
public static async generate(template: string, data?: Record<string, any>): Promise<string> {
7+
export default class HandlebarsTemplateRenderer {
8+
protected handlebars: typeof Handlebars;
9+
10+
public constructor() {
11+
this.handlebars = create();
12+
this.registerHelpers();
13+
this.registerPartials();
14+
}
15+
16+
public async render(template: string, data?: Record<string, any>): Promise<string> {
917
try {
1018
const templatePath = this.getTemplatePath(template);
1119
const templateContent = await FileSystem.readFile(Uri.file(templatePath));
12-
const handlebars = create();
13-
this.registerHelpers(handlebars);
14-
this.registerPartials(handlebars);
15-
const compiledTemplate = handlebars.compile(templateContent);
20+
const compiledTemplate = this.handlebars.compile(templateContent);
1621
const content = compiledTemplate(data);
1722
return content;
1823
} catch (error) {
@@ -21,20 +26,20 @@ export default class GenerateFromTemplate {
2126
}
2227
}
2328

24-
protected static getTemplatePath(templateName: string): string {
29+
public getTemplatePath(templateName: string): string {
2530
return resolve(FileSystem.getExtensionPath('templates/handlebars'), templateName + '.hbs');
2631
}
2732

28-
protected static registerHelpers(handlebars: typeof Handlebars): void {
29-
handlebars.registerHelper('ifeq', (a: string, b: string, options: any) => {
33+
protected registerHelpers(): void {
34+
this.handlebars.registerHelper('ifeq', (a: string, b: string, options: any) => {
3035
if (a === b) {
3136
return options.fn(this);
3237
}
3338
return options.inverse(this);
3439
});
3540
}
3641

37-
protected static registerPartials(handlebars: typeof Handlebars): void {
38-
handlebars.registerPartial('fileHeader', '{{#if fileHeader}}\n{{{fileHeader}}}\n{{/if}}');
42+
protected registerPartials(): void {
43+
this.handlebars.registerPartial('fileHeader', '{{#if fileHeader}}\n{{{fileHeader}}}\n{{/if}}');
3944
}
4045
}

src/generator/TemplateGenerator.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { Uri } from 'vscode';
22
import FileGenerator from './FileGenerator';
33
import GeneratedFile from './GeneratedFile';
4-
import GenerateFromTemplate from './util/GenerateFromTemplate';
4+
import HandlebarsTemplateRenderer from './HandlebarsTemplateRenderer';
55

66
export default class TemplateGenerator extends FileGenerator {
7+
protected renderer: HandlebarsTemplateRenderer | undefined;
8+
79
public constructor(
810
protected fileName: string,
911
protected templateName: string,
@@ -16,8 +18,20 @@ export default class TemplateGenerator extends FileGenerator {
1618
return this.data;
1719
}
1820

21+
protected getTemplateRenderer(): HandlebarsTemplateRenderer {
22+
if (!this.renderer) {
23+
this.renderer = new HandlebarsTemplateRenderer();
24+
}
25+
26+
return this.renderer;
27+
}
28+
29+
protected getTemplateContent(): Promise<string> {
30+
return this.getTemplateRenderer().render(this.templateName, this.getTemplateData());
31+
}
32+
1933
public async generate(workspaceUri: Uri): Promise<GeneratedFile> {
20-
const content = await GenerateFromTemplate.generate(this.templateName, this.getTemplateData());
34+
const content = await this.getTemplateContent();
2135

2236
const path = Uri.joinPath(workspaceUri, this.fileName);
2337
return new GeneratedFile(path, content);

src/generator/observer/ObserverEventsGenerator.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import GeneratedFile from 'generator/GeneratedFile';
22
import FileGenerator from 'generator/FileGenerator';
3-
import GenerateFromTemplate from 'generator/util/GenerateFromTemplate';
43
import { Uri } from 'vscode';
54
import { ObserverWizardData } from 'wizard/ObserverWizard';
65
import indentString from 'indent-string';
76
import PhpNamespace from 'common/PhpNamespace';
87
import FindOrCreateEventsXml from 'generator/util/FindOrCreateEventsXml';
98
import Magento from 'util/Magento';
10-
import FileHeader from 'common/xml/FileHeader';
9+
import HandlebarsTemplateRenderer from 'generator/HandlebarsTemplateRenderer';
1110

12-
export default class ObserverDiGenerator extends FileGenerator {
11+
export default class ObserverEventsGenerator extends FileGenerator {
1312
public constructor(protected data: ObserverWizardData) {
1413
super();
1514
}
@@ -27,7 +26,9 @@ export default class ObserverDiGenerator extends FileGenerator {
2726
);
2827
const insertPosition = this.getInsertPosition(eventsXml);
2928

30-
const observerXml = await GenerateFromTemplate.generate('xml/observer', {
29+
const renderer = new HandlebarsTemplateRenderer();
30+
31+
const observerXml = await renderer.render('xml/observer', {
3132
name: this.data.observerName,
3233
className: observerNamespace.append(this.data.className).toString(),
3334
eventName: this.data.eventName,

src/generator/plugin/PluginDiGenerator.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import GeneratedFile from 'generator/GeneratedFile';
22
import FileGenerator from 'generator/FileGenerator';
33
import FindOrCreateDiXml from 'generator/util/FindOrCreateDiXml';
4-
import GenerateFromTemplate from 'generator/util/GenerateFromTemplate';
54
import { PhpClass } from 'parser/php/PhpClass';
65
import { PhpMethod } from 'parser/php/PhpMethod';
76
import { Uri } from 'vscode';
87
import { PluginContextWizardData } from 'wizard/PluginContextWizard';
98
import indentString from 'indent-string';
109
import { PhpInterface } from 'parser/php/PhpInterface';
1110
import Magento from 'util/Magento';
11+
import HandlebarsTemplateRenderer from 'generator/HandlebarsTemplateRenderer';
1212

1313
export default class PluginDiGenerator extends FileGenerator {
1414
public constructor(
@@ -31,7 +31,9 @@ export default class PluginDiGenerator extends FileGenerator {
3131
const diXml = await FindOrCreateDiXml.execute(workspaceUri, vendor, module, this.data.scope);
3232
const insertPosition = this.getInsertPosition(diXml);
3333

34-
const pluginXml = await GenerateFromTemplate.generate('xml/plugin', {
34+
const renderer = new HandlebarsTemplateRenderer();
35+
36+
const pluginXml = await renderer.render('xml/plugin', {
3537
pluginName: this.data.name,
3638
pluginType: pluginType.toString(),
3739
sortOrder: this.data.sortOrder,

src/generator/preference/PreferenceDiGenerator.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import GeneratedFile from 'generator/GeneratedFile';
22
import FindOrCreateDiXml from 'generator/util/FindOrCreateDiXml';
3-
import GenerateFromTemplate from 'generator/util/GenerateFromTemplate';
43
import { Uri } from 'vscode';
54
import { PreferenceWizardData } from 'wizard/PreferenceWizard';
65
import indentString from 'indent-string';
76
import Magento from 'util/Magento';
87
import FileGenerator from 'generator/FileGenerator';
8+
import HandlebarsTemplateRenderer from 'generator/HandlebarsTemplateRenderer';
99

1010
export default class PreferenceDiGenerator extends FileGenerator {
1111
public constructor(protected data: PreferenceWizardData) {
@@ -23,7 +23,9 @@ export default class PreferenceDiGenerator extends FileGenerator {
2323
const diXml = await FindOrCreateDiXml.execute(workspaceUri, vendor, module, this.data.area);
2424
const insertPosition = this.getInsertPosition(diXml);
2525

26-
const pluginXml = await GenerateFromTemplate.generate('xml/preference', {
26+
const renderer = new HandlebarsTemplateRenderer();
27+
28+
const pluginXml = await renderer.render('xml/preference', {
2729
forClass: this.data.parentClass,
2830
typeClass: typeNamespace,
2931
});

src/generator/util/FindOrCreateDiXml.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Uri } from 'vscode';
22
import FileSystem from 'util/FileSystem';
3-
import GenerateFromTemplate from './GenerateFromTemplate';
43
import FileHeader from 'common/xml/FileHeader';
54
import { MagentoScope } from 'types';
65
import Magento from 'util/Magento';
6+
import HandlebarsTemplateRenderer from '../HandlebarsTemplateRenderer';
77

88
export default class FindOrCreateDiXml {
99
public static async execute(
@@ -21,7 +21,9 @@ export default class FindOrCreateDiXml {
2121

2222
const fileHeader = FileHeader.getHeader(module);
2323

24-
return await GenerateFromTemplate.generate('xml/blank-di', {
24+
const renderer = new HandlebarsTemplateRenderer();
25+
26+
return await renderer.render('xml/blank-di', {
2527
fileHeader,
2628
});
2729
}

src/generator/util/FindOrCreateEventsXml.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Uri } from 'vscode';
22
import FileSystem from 'util/FileSystem';
3-
import GenerateFromTemplate from './GenerateFromTemplate';
43
import { MagentoScope } from 'types';
54
import FileHeader from 'common/xml/FileHeader';
5+
import HandlebarsTemplateRenderer from '../HandlebarsTemplateRenderer';
66

77
export default class FindOrCreateEventsXml {
88
public static async execute(
@@ -27,9 +27,11 @@ export default class FindOrCreateEventsXml {
2727
return await FileSystem.readFile(eventsFile);
2828
}
2929

30+
const renderer = new HandlebarsTemplateRenderer();
31+
3032
const fileHeader = FileHeader.getHeader(`${vendor}_${module}`);
3133

32-
return await GenerateFromTemplate.generate('xml/blank-events', {
34+
return await renderer.render('xml/blank-events', {
3335
fileHeader,
3436
});
3537
}

0 commit comments

Comments
 (0)