-
Notifications
You must be signed in to change notification settings - Fork 7
Developer Guide
This guide covers build setup, architecture, branch workflow, and local integration testing for contributors to the CQL VS Code extension and language server.
The project is split into two sub-projects that communicate over stdio:
vscode-cql (TypeScript VS Code extension)
│ JSON-RPC / stdio (LSP)
▼
cql-language-server (fat JAR, Kotlin/JVM)
| File | Role |
|---|---|
src/extension.ts |
Extension entry point; activates LSP client and registers commands |
src/cql-service/javaServiceInstaller.ts |
Downloads the language server JAR from Maven Central |
The extension spawns the language server JAR as a child process and communicates with it via JSON-RPC over stdio using the Language Server Protocol (LSP).
| Class | Role |
|---|---|
CqlLanguageServer |
LSP server root; wires document and workspace services |
CqlTextDocumentService |
Handles hover, diagnostics, formatting, go-to-definition, symbols, references |
CqlWorkspaceService |
Dispatches workspace/executeCommand (Execute CQL, View ELM, Call Graph) |
CqlCompilationManager |
Compiles CQL on each request (no caching) |
Plugin discovery uses ServiceLoader; the debug plugin (plugin/debug/) registers
CqlLanguageServerPluginFactory via @AutoService.
- Java 11 or later
- Maven 3.8 or later
- Node.js 20 or later
cd cql-language-server
# Run all tests
mvn test
# Build fat JAR (skip tests)
mvn package -DskipTests
# Build and install to local Maven repo
mvn install -DskipTestsNote:
mvn testdoes NOT update the running JAR used by the extension. You must runmvn packageormvn installand then restart the extension to pick up changes.
cd vscode-cql
npm install
npm run compile- Open
vscode-cql/as a workspace in VS Code. - Press F5 to launch the Extension Development Host with the extension loaded.
- Open a CQL file in the dev host to trigger language server activation.
By default the extension downloads the JAR version specified in package.json. To test
against a locally built JAR:
-
Build and install the language server:
cd cql-language-server mvn install -DskipTests -
Update the version in
vscode-cql/package.jsonto match the built JAR:"javaDependencies": { "cql-language-server": { "version": "<your-local-version>" } }
-
Press F5 in
vscode-cql/to launch with the new JAR.
After launching the dev host:
- Open a
.cqlfile — diagnostics and hover should work. - Trigger Execute CQL, View ELM, and View Call Graph via the Command Palette.
- Confirm go-to-definition (F12) and document symbols (Ctrl+Shift+O) resolve correctly.
Versioning is critical to both the VSCode extension and CQL Language Server. Deployment systems for both projects have well defined rules on verisoning. Publishing will fail if the versioning rules are not followed.
The VScode extension is published to the VSCode Marketplace.
Note (2026-03-29): There are plans to support publishing to Open VSX Registry.
VSCode Marketplace expects projects to use semver. Convention dictates that even minor versions are for release versions and odd minor versions are for pre-release versions. Prerelease version suffixes, e.g. -alpha, -prerelease, etc, are not supported
Development should be done on Prerelease versions. Once the pre-release has based UAT'd a release version can be published to the VS Code Marketplace.
Prior to promoting a Prerelease version to a Release version, ensure that the next Prerelease is published.
"VS Code will automatically update extensions to the highest version available, so even if a user opted-into a pre-release version and there is an extension release with a higher version, the user will be updated to the released version. So, we recommend that extensions use major.EVEN_NUMBER.patch for release versions and major.ODD_NUMBER.patch for pre-release versions. For example: 0.2.for release and 0.3. for pre-release." "If extension authors do not want their pre-release users to be updated to the release version, we recommend always incrementing and publishing a new pre-release version before publishing a release version to make sure that the pre-release version is always higher. Note that while pre-release users will be updated to a release version if it is higher, they still remain eligible to automatically update to future pre-releases with higher version numbers than the release version." VSCode Publishing Extensions - Prerelease notes
The CQL Language Server, which is a FAT jar, is published to Maven Central.
CQL-LS uses semver for release, and also supports -SNAPSHOT versions. Snapshots are pre-release versions of the next release.
This project uses trunk-based branching. master is the trunk — the single
long-lived branch. All work happens on short-lived branches that merge back to master
via pull requests. There is no develop, release, or hotfix tier.
-
Always branch from
master. Never commit directly tomaster. -
Branch naming:
-
feature/<name>for new features -
bugfix/<name>for bug fixes -
hotfix/<name>for hotfixes -
task/<name>for code-sprecific changes, e.g. documentation, github CI/CD, version changes, etc.
-
-
Keep PRs small and focused on a single concern. When a feature is large, split it into multiple focused PRs rather than one large PR — reviews are faster and easier to revert.
-
Check your current branch before starting work:
git branch --show-current
-
When one feature depends on another that has not yet merged, stack branches:
git checkout feature/first-feature git checkout -b feature/second-feature
Rebase the stacked branch onto
masterafter the base PR merges.
Since there is no long-lived release branches, when faced with having to create a Hotfix for an existing release a developer will have to pull the tagged release and use that as the base for the hotfix.
Since tags are technically "immutable" (unchanging) pointers to a specific commit, you can't just "edit" a tag. Instead, you branch off the tag, fix the code, and create a new tag.
-
Identify the Point of Failure First, find the tag associated with the buggy release (e.g., v1.0.0).
-
Create a Branch from the Tag You need a workspace to apply your fix. Create a new branch starting exactly where the old release was.
git checkout -b hotfix/fix-login-error v1.0.0
-
Apply and Commit the Fix Fix the bug, test it, and commit the changes to this temporary branch.
git add . git commit -m "fix: resolve login authentication timeout"
-
Tag the New Release Now, create a new semantic version tag (e.g., v1.0.1). This signals to your CI/CD pipeline that a new, stable version is ready for production.
git tag -a v1.0.1 -m "Hotfix for login timeout" git push origin v1.0.1 -
Don't Forget the Trunk! This is the most important step in trunk-based development. You must ensure the fix also exists in the main branch so the bug doesn't reappear in the next major release.
- If the fix is small: Cherry-pick the commit into main.
- If it's complex: Merge the hotfix branch back into main.
Developers may encounter different situtations leading up to an offical release cycle. This example is for those common scenario, but its left to the developers to handle each release appropiately as circumstances dictate.
The typical release cycle is:
- developers following trunk-based branching against
master -
masterhas aPrereleaseversion, with the patch version being updated on each publishedPrerelease
-
Prep
Releaseversion:- Create new
task/release-vX.X.0branch off ofmaster - Update
package.json- version to the nextRelease, i.e.evenminor, version. Expected patch version is0. - Update
CHANGELOG.md- add a new section at the top with a summary of changes (see existing entries for format) - Push changes to origin
- Create PR the version change
- After passing CI Build = ready for publishing to the VS Code Marketplace
- Merge into
master - Create a
taggedversion in github
- Create new
-
Prep next
Prereleaseversion:- Create new
task/prerelease-vX.X.0branch - Update
package.json- version to the nextPrerelease, i.e.oddminor, version. Expected patch version is0. - Update
CHANGELOG.md- add a new section at the top with a summary of changes (see existing entries for format) - Push changes to origin
- Create PR the version change
- After passing CI Build = ready for publishing to the VS Code Marketplace
- Merge into
master - Create a
taggedversion in github
- Create new
-
Publish the next
Prereleaseversion to the VS Code Marketplace- Pull master, and confirm the version is the same as the
Prereleaseversion fromStep 2 - Run
vsce login cqframeworkto authenticate - Run
vsce publish --prerelease - Wait for publishing to complete. Following publishing process at the Manage Publishers & Extensions page.
- Pull master, and confirm the version is the same as the
-
Publish the
Releaseversion to the VS Code Marketplace- Checkout the
taggedversion fromStep 1
git checkout <tag_name>
- Run
vsce login cqframeworkto authenticate - Run
vsce publish --prerelease
- Checkout the
Note: Once a
semverhas been published to the marketplace it cannont be reused. Publishing thePrereleaseversionX.<ODD>.0is needed to keep VSCode from overwriting a user's pre-release version. This is a limitation of VSCode and how extensions are handled.
The Prerelease version is meant to be the "working" version of the master branch. During development, updates should be made to the Prerelease version of the master branch. Once Prerelease changes are stable bump versions, as detailed above, to publish an offical release and the next Prerelease starter version.
The Prelease working version can be created immediately after the previous offical release, or the developers can wait until there are changes ready for merging to master.
- Update
package.json- version toX.X.1, keep the same major and minor version of thePrereleaseversion only change the patch - Push changes to origin
- Create PR the version change
- After passing CI Build = ready for publishing to the VS Code Marketplace
- Merge into
master - Development can now continue on the new
masterbranch using thePrereleasepatchedversion.
Only the verison is changed, there is no publish step. These changes are only for development.
Language Server is kotlin-based and uses snapshot-based release flow:
-
masteralways carries aSNAPSHOTversion (e.g.,1.2.0-SNAPSHOT). - When the team decides to release, a build is cut from
masterand published at the release version (e.g.,1.2.0) — to Maven Central forcql-language-server -
masteris immediately bumped to the next minor SNAPSHOT (1.3.0-SNAPSHOT) inpom.xml/package.jsonrespectively. - There are no release branches — releases are point-in-time cuts from the trunk.
- Releases are unscheduled and at the discretion of the primary development team.
dev-sandbox is an ephemeral integration branch — outside the trunk-based flow — used
to combine multiple in-flight feature branches for shared experimentation before any of
them are merged.
# In cql-language-server
cd cql-language-server
git checkout master && git pull origin master
git checkout -b dev-sandbox
# In vscode-cql
cd ../vscode-cql
git checkout master && git pull origin master
git checkout -b dev-sandboxgit checkout dev-sandbox
git merge feature/<name>Repeat for each feature branch you want to test together.
When you are done testing or want a clean slate:
git checkout dev-sandbox
git reset --hard masterdev-sandbox can be pushed to origin to share an in-progress integration environment
with other developers. Force-push is expected when resetting back to master:
git push --force origin dev-sandbox