-
Notifications
You must be signed in to change notification settings - Fork 59
How to Create Your Own Dialect
A good example of a dialect is the IDMS dialect
A dialect extension has 2 parts:
-
jar
file with dialect logic - VS Code Extension that contains the
jar
file within the.vsix
extension file (see IDMS Dialect Support VS Code Extension)
The VS Code Extension logic is quite straightforward: the extension just registers itself in the COBOL LS Support VS Code Extension using a path to a jar
file (idms path example), a path to snippets, and other information about a dialect (idms dialect extension example)
The main dialect logic is situated in the jar
file
If you have your own COBOL dialect, there are probably some instructions that cannot be parsed by the regular COBOL parser, which need to be parsed and substituted with spaces by your dialect logic. There might also be a new type of copybook that must be properly resolved and injected into the COBOL program.
To create a new module with dialect logic you need to add a dependency for the common
module because for now, the only way to create a new dialect is to implement the CobolDialect
interface.
<dependency>
<groupId>org.eclipse.lsp.cobol</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
This library will be included in the final engine build, so it can have a provided
scope.
The core interface that needs to be implemented for a new dialect is the CobolDialect
interface. The final .jar
file with a dialect implementation will be picked up by the engine using URLClassLoader
, so the .jar
file and CobolDialect
implementation class must follow the naming convention to be picked up.
CobolDialect
has the following methods that need to be implemented/overridden:
-
getName
- returns the name of the dialect -
extend
- extends extended source with dialect's copybooks if needed. Use theCopybookService
to resolve copybooks -
processText
- process extended source and returns list of created nodes with list of errors (if any) -
getProcessors
- returns a list of processors that will be applied to theAST
on the defined processing stage -
runBefore
- returns a list of dialects. The current dialect will be processed before this list of dialects -
getKeywords
- returns a map with keyword/description pairs -
getSettingsSections
- returns a list of settings that will be requested from a VS Code side and placed into the dialect processing context before processing -
getWatchingFolderSettings
- returns a list of settings sections that hold dialect folders
Take a look into Idm dialect implementation for more details
For the fastest picking up a new dialect logic implemented in the separate .jar
file, this file and a class with the CobolDialect
implementation must follow the naming convention.
- the
.jar
file must have thedialect-
prefix. For example:dialect-idms.jar
- the
CobolDialect
interface implementation class must have theDialect
suffix. For example:IdmsDialect
- the
CobolDialect
implementation class must have a constructor with the following signature:
It is needed to pass to the dialect
CopybookService
and MessageService
services
public final class SomeDialect implements CobolDialect {
public SomeDialect(CopybookService copybookService, MessageService messageService) {
...
}
...
}
For more information see the DialectDiscoveryFolderService
class, which implements a picking-up dialect logic
CopybookService
is a service that provides copybook-resolving logic and is needed to get the content of the requested copybook with taking into account copybook processing settings and dialect folders
-
invalidateCache
- removes all cached copybooks -
resolve
- returns a copybook content with a URI of the copybook, or blank structure if the copybook was not resolved -
store
- stores a copybook in the cache, mostly used for testing purposes, because theresolve
copybook method already has this logic and after resolving the copybook you can be sure that this copybook was stored in the cache
MessageService
is used to retrieve a message for the error or warning using a string key
-
getMessage
returns a message for a given key
Dialect processing context is a context that holds all needed objects for dialect processing. There is a copybook config, document URI, etc.
Also, the context has an ExtendedSource
object that is used to extend or modify COBOL text
When dialects extend COBOL text with dialect copybooks we need to track all changes to be able to answer the question "where this token come from?". The ExtendedSource
object serves to keep the COBOL text consistent and to track changes and extensions of the COBOL text.
It has the following methods:
-
replace
- replaces in the document defined range with the given copybook document. For example, when you are resolving a copybook you probably want to replace a copybook statement with a copybook content -
extend
- the same asreplace
but with adjusting copybook statement range -
insert
- inserts a copybook document after the given line -
extendedText
- generates extended text based on extends, inserts, and replacements of the original COBOL text
and others
DialectOutcome
is a result of CobolDialect::processText
wrapped to the ResultWithErrors
object. It contains a list of created nodes by current dialect
and a modified DialectProcessingContext
. And ResultWithErrors
contains a list of generated errors (if any).
Now when you have a properly generated .jar
file with CobolDialect
implementation inside, you need to wrap it to the VS Code Extension and implement simple logic to register your dialect to the main COBOL LS Extension.
A good example is Idms Dialect Support Extension
Here is a folder for a .jar
file with your dialect logic.
And simple Idms Dialect Extension logic:
- import COBOL LS api:
import { getV1Api } from "@code4z/cobol-dialect-api";
- use returned API to register a new dialect:
const extensionId = context.extension.id;
const extensionUri = context.extensionUri;
const snippets = vscode.Uri.joinPath(extensionUri, "snippets.json");
const jar = vscode.Uri.joinPath(
extensionUri,
"server",
"jar",
"dialect-idms.jar",
);
const v1Api = await getV1Api(extensionId);
if (v1Api instanceof Error) {
vscode.window.showErrorMessage(v1Api.toString());
return;
}
const unregister = await v1Api.registerDialect({
name: "IDMS",
description: "IDMS dialect support",
snippets,
jar,
});
if (unregister instanceof Error) {
vscode.window.showErrorMessage(unregister.toString());
return;
}
unregisterDialect = unregister;
}
COBOL Language Support, part of Code4z