New Code Generator - borkdominik/bigER GitHub Wiki
This page describes how the tool can be extended to include a new code generator.
Implementing the Generator
Generators are implemented on the server-side in Java or Xtend. The generators are located within the org.big.erd.generator
package.
As a first step, a new code generator must implement the IErGenerator
interface and its method. The code below, demonstrates how the interface is implemented for the SqlGenerator
:
class SqlGenerator implements IErGenerator {
override void generate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
val model = resource.contents.get(0) as Model
validate(resource, model) // optional additional validation
val fileName = (model.name ?: 'output') + ".sql"
fsa.generateFile(fileName, generate(model))
}
def String generate(Model model) {
// map model to generated code...
}
}
By passing an instance of Resource
the generator has access to the whole Model
and files can be created by using the provided IFileSystemAccess2
.
Execution of the Generator
The next step is to provide a command, such that the generator can be executed. This is accomplished in the ErCommandService
class (located in the org.big.erd.ide.commands
package), which stores commands and their corresponding generators in a hash map for look-up. The code below demonstrates how a new command can be added to the service.
static final String GENERATE_PREFIX = "erdiagram.generate"
static final String GENERATE_SQL_COMMAND = GENERATE_PREFIX + ".sql"
static final String GENERATE_EXAMPLE_COMMAND = GENERATE_PREFIX + ".example"
override initialize() {
generators = new HashMap
generators.put(GENERATE_SQL_COMMAND, new SqlGenerator)
// add the command and corresponding generator to the map
generators.put(GENERATE_EXAMPLE_COMMAND, new ExampleGenerator)
// initialize the command
return #[
GENERATE_SQL_COMMAND, GENERATE_EXAMPLE_COMMAND
]
}
The execute()
method can handle execution of the commands by using the initialized hash map to retrieve a corresponding generator for the command that is getting passed.
Command Proxy for Extension
The final step is to add a proxy for the new command to the client, such that the generator can be executed from VS Code.
Start by adding a command contribution point in the package.json
of the extension. Additionally, you can add the command to a menu such as editor/context
or explorer/context
, such that it can be executed from the context menu, when right-clicking .erd
files.
"commands": [
{
"command": "erdiagram.generate.sql.proxy",
"title": "Generate SQL",
"category": "bigER"
},
// other commands...
]
Next, provide a handler for the command and register the command with its handler in the extension. The handler is responsible for executing the command on the server and handling its response (see generateSqlHandler
for an example).
// File: generate.ts
export const sqlServerCommand = "erdiagram.generate.sql";
export const generateSqlHandler = async () => {
sendToServer(sqlServerCommand);
};
Registration of the commands is done in the registerCommands()
method of the extension (see erdiagram-lsp-extension.ts
)
// File: erdiagram-lsp-extension.ts
override registerCommands() {
this.context.subscriptions.push(
vscode.commands.registerCommand("erdiagram.generate.sql.proxy", generateSqlHandler)
);
}
Add to Webview
Finally, the command has to be made available for the webview. For this, simply add a new option to the existing GenerateButton
in the toolbar (see button.ts
).
export class GenerateButton implements ToolButtonDropdown {
constructor(
public readonly id = "btn_dropdown_generate",
public readonly label = "Generate",
public readonly icon = "file-code",
public readonly options = new Map<string, string>([
["sql", "Generic SQL"],
["postgres", "PostgreSQL"],
["oracle", "Oracle SQL"],
["mysql", "MySQL"],
["mssql", "MS SQL"],
["db2", "Db2"],
// Add new option here
])
) {}
}
After re-building all the packages the new option should appear in the dropdown of the toolbar.