JXForge for VS Code
Support for .jxml files, the markup of JXForge (native screens for JXParallel):
- Highlighting.
.jxml is XML, so the language includes VS Code's own XML grammar and adds scopes for
${a.b} (read binding), @{a.b} (two-way binding) and #handler / #handler(args) in the on* attributes
(onAction, onChange, onHover, ...). A colour such as background="#336699" is not taken for a handler.
- Completion, hover documentation and validation without settings. The extension bundles
jxml.xsd, the
schema JXForge generates from its tag table (95 tags), and registers it for **/*.jxml with the
XML extension from Red Hat.
Unknown tags and attributes, wrong values and misplaced children are underlined; tags and attributes complete
with their documentation. A file that names its own schema with xsi:noNamespaceSchemaLocation still uses that one.
- Snippets.
jxml (a screen: root Column with controller and the schema line), button (with a handler),
textfield (two-way binding), for, if and dialog.
- Go to Definition (F12 or Ctrl+Click) into the controller, by text search in the workspace:
#save goes to
save(), the first segment of ${customer.name} or @{customer.name} goes to getCustomer(), isCustomer(),
customer() or the field, and controller="com.acme.Foo" goes to the class. See Limits.
- A file icon for
.jxml (light and dark), and the language configuration of XML (comments, brackets, auto-closing,
folding, <!-- #region --> markers).
Install
From the Extensions view (Ctrl+Shift+X), search for JXForge (JXML) and choose Install, or run
code --install-extension bacuriim.jxforge-vscode.
To install a .vsix you built yourself (below) instead:
- Open the Extensions view (Ctrl+Shift+X).
- Choose the ... menu at the top of the view, then Install from VSIX....
- Pick
jxforge-vscode-0.1.0.vsix.
or, from a terminal: code --install-extension jxforge-vscode-0.1.0.vsix.
The extension is packaged with redhat.vscode-xml as an extension pack, so VS Code installs the XML extension
with it when it can reach the Marketplace. It is not a hard dependency (extensionDependencies): a hard
dependency stops the extension from activating, and with it the highlighting, snippets and Go to Definition, whenever
the XML extension is missing or disabled (offline installs, Open VSX-only editors that do not list it). Without
it, .jxml files are still highlighted and the extension offers to install it when a .jxml file is opened.
Build
Needs Node.js 22 or later (the packaging tool, @vscode/vsce, requires it). From this folder:
npm install
npm test # compile, grammar tests, grammar snapshot, unit tests
npm run package # writes jxforge-vscode-<version>.vsix here
npm test runs tsc, then
vscode-tmgrammar-test on test/grammar/*.jxml (scope
assertions) and vscode-tmgrammar-snap on test/snap/*.jxml (every token of a whole screen against a committed
.snap; after a deliberate grammar change run npx vscode-tmgrammar-snap -g test/grammars/xml.tmLanguage.json -g syntaxes/jxml.tmLanguage.json -u "test/snap/*.jxml" and review the diff), then mocha on the compiled unit tests
(out/test). test/grammars/xml.tmLanguage.json is a copy of VS Code's XML grammar (MIT, from microsoft/vscode),
there only so the tests can resolve text.xml.
Regenerating the schema
schemas/jxml.xsd is generated by com.jxparallel.forge.JxmlXsd and committed, so building the extension needs no
JDK. After a change to the tag table (JxmlSchema), regenerate it from the repository root with JDK 17:
mvn -o -q -pl jxparallel-forge -am package -DskipTests
cd jxforge-vscode
npm run xsd
The script runs JxmlXsd from the jars in jxparallel-forge/target and jxparallel-core/target (JAVA_HOME if set).
The schema checks tag names, attribute names, attribute values and which children a tag takes.
How the schema reaches the XML extension
The XML extension documents two extension points: contributes.xmlLanguageParticipants in package.json (which
makes the language server handle a language id, used here for jxml), and a TypeScript API that other extensions
call, addXMLFileAssociations (documented in src/api/xmlExtensionApi.ts of
redhat-developer/vscode-xml). It has no package.json
contribution point for a schema, so src/extension.ts calls the API when a .jxml file is opened.
The extension is activated by onLanguage:jxml.
Limits
- Go to Definition is a text search, not a Java analysis. It reads
controller="..." on the root element, looks for
a/b/Controller.java (and the files of enclosing classes for a nested class) anywhere in the workspace, outside
node_modules, target, build and out, and looks for a declaration line of the method. It resolves the first
segment of a binding only (customer in ${customer.name}; the rest needs types), does not follow inherited
methods, and does nothing for loop variables (${o.name} inside a <For var="o">). If two files match, the
first one VS Code returns is used.
- The schema checks the shape of a file, not what the controller has: a handler or a binding that does not exist
in the controller is not underlined.
- The automated tests run headless (grammar tests, unit tests); the schema registration and Go to Definition run only
inside the editor and were checked by hand in VS Code.