claude-video-effects
51 video effects for Claude Code: drop in a talking-head clip, type /effects orbit. Face tracking, behind-your-head layers. By @vibha.in.progress
翻译准备中
Salesforce Apex language support for Zed
翻译准备中
插件Shell · PythonGitHub @Damecek自行安装运营者未确认
试用过了吗? 点一下就好,无需登录。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
安装型项目无需部署域名也可验证。个人仓库可通过 GitHub 登录验证,组织仓库可使用上方的仓库验证文件。
正在加载完整 README。 以下为已保存的摘录。
Salesforce DX language support for the Zed editor. Apex is backed by aer (default) or Salesforce's Java-based Apex Language Server (apex-jorje-lsp.jar, opt-in). LWC HTML/JavaScript support is backed by Salesforce's @salesforce/lwc-language-server, and Visualforce uses a dedicated Tree-sitter grammar plus Salesforce's official Visualforce language server.
Build a Zed extension that enables Salesforce DX development with a practical MVP:查看完整 README ↗Salesforce DX language support for the Zed editor. Apex is backed by aer (default) or Salesforce's Java-based Apex Language Server (apex-jorje-lsp.jar, opt-in). LWC HTML/JavaScript support is backed by Salesforce's @salesforce/lwc-language-server, and Visualforce uses a dedicated Tree-sitter grammar plus Salesforce's official Visualforce language server.
Build a Zed extension that enables Salesforce DX development with a practical MVP:
.page/.component).This repository is in MVP bootstrap implementation: core language support and Apex LSP startup wiring are in place, with validation/operational hardening still in progress.
Primary references for this architecture:
config.toml, language servers):
https://zed.dev/docs/extensions/languagespackages/salesforcedx-vscode-apex/src/languageServer.tsThe extension supports two Apex language server backends, selectable via lsp.apex-language-server.settings.backend:
aer (default) — aer is a fast, modern, native Apex language server distributed as a single binary. No JVM required. Source paths are auto-discovered from sfdx-project.json packageDirectories.jorje — Salesforce's official Java-based apex-jorje-lsp.jar (downloaded and cached on first launch). Requires a Java 11+ runtime on the system.To opt into jorje, set:
{
"lsp": {
"apex-language-server": {
"settings": { "backend": "jorje" }
}
}
}
Lightning Web Components are served by Salesforce's public npm package
@salesforce/lwc-language-server.
The extension installs pinned version 4.12.13 on first launch and then reuses
Zed's extension-local node_modules cache on subsequent launches.
The extension registers one LWC language server entry for Zed's built-in HTML
and JavaScript languages with protocol ids html and javascript. Zed
extension manifests currently register language servers by language name rather
than by path glob, so the manifest has to be broad. The extension-side launcher
therefore checks the worktree before starting the process and refuses to launch
the LWC server unless one of these entry points matches:
lwc.config.json exists at the worktree root and at least one modules[].dir
directory exists.sfdx-project.json exists at the worktree root and contains at
least one packageDirectories[].path.*/lwc/*, such as force-app/main/default/lwc/hello or
src/lwc/modules/content.This keeps ordinary HTML/JavaScript projects from starting Salesforce's LWC server until Zed supports path-scoped language server activation.
The extension launches Salesforce's server through
scripts/lwc-language-server-wrapper.js instead of running the upstream
bin/lwc-language-server.js directly. The wrapper exists because upstream
@salesforce/[email protected] performs VS Code/SFDX workspace setup
during startup. By default, the wrapper patches those setup hooks before the
server starts so opening a project in Zed does not create or rewrite project
files.
Default LWC behavior suppresses IDE-scoped workspace files:
.vscode/settings.jsoncore.code-workspaceWhen the LWC server is allowed to start, the wrapper still allows upstream-generated files that can improve LWC development and code intelligence:
.sfdx/indexes/lwc/custom-components.json.sfdx/typings/lwc/*jsconfig.json / tsconfig.json files.forceignore updates for those generated JavaScript/TypeScript helper filesThis behavior is intentionally not user-configurable yet. The extension keeps a single code path until someone has a concrete use case for exposing a setting. The current rule is:
Specifically, the wrapper always patches upstream settings/workspace writes so
.vscode/settings.json and core.code-workspace are not created by Zed.
The wrapper does not patch upstream component indexing or typing generation for accepted LWC worktrees. That means upstream may create and maintain:
.sfdx/indexes/lwc/custom-components.json, a cache of discovered custom LWC
components that can help component intelligence across server restarts.sfdx/typings/lwc/*.d.ts, generated typings for Salesforce metadata such as
static resources, content assets, message channels, and custom labelsjsconfig.json / tsconfig.json files and related
.forceignore updates used by upstream JavaScript/TypeScript project supportIf npm installation is blocked by network or capability settings, Zed surfaces
the install failure in the language server startup error. Users with restricted
extension capabilities need to allow npm installation for
@salesforce/lwc-language-server.
Zed recognizes .page and .component files as the dedicated Visualforce
language. Parsing and syntax highlighting use
Damecek/tree-sitter-visualforce
pinned at commit b1f026749107d549e72b8cef841cfd3ae9cf8240 (release v0.1.1).
The grammar handles Visualforce markup and {!...} expressions structurally;
language queries provide highlighting, indentation, folding, bracket behavior,
and embedded JavaScript/CSS injections for script/style blocks and matching
inline attributes.
Salesforce's internal Visualforce language-server packages are not published on
npm, so this extension does not attempt an npm install or a runtime source build.
Instead, the extension uses Salesforce's official Visualforce VSIX from
release v67.4.0:
https://github.com/forcedotcom/salesforcedx-vscode/releases/download/v67.4.0/salesforcedx-vscode-visualforce-67.4.0.vsix6232bb3dc3bdfe2c491601b9c96c488fb52941c2ff62bcc125230e4dceacbb0cextension/dist/visualforceServer.js37f6808e5e4bd360f7c7f219fd2d71cc8d7ce22688b271c1a4ae5020bd85bb3fOn the first Visualforce language-server start, Zed extracts the pinned VSIX
into the extension-local versioned cache at
lsp/visualforce-language-server/v67.4.0/. The launcher hashes the extracted
JavaScript before every execution. A valid cache is reused; a missing or invalid
bundle gets one clean download/extraction attempt after removing only that
Visualforce version directory. A replacement with the wrong hash fails with an
expected/actual integrity error. The command is Zed's Node.js runtime followed
by a bundled protocol shim, the verified visualforceServer.js path, and
--stdio, with the worktree shell environment. The shim keeps the real document
id visualforce for apex:* completion and mirrors document changes to an
internal html shadow document because v67.4.0 gates embedded CSS/JavaScript
validation on that id. Shadow diagnostics are mapped back to the real document;
missing Zed workspace/configuration entries are normalized from null to an
empty settings object so the upstream CSS linter does not crash;
the dedicated Visualforce grammar and activation remain unchanged.
Initialization enables embedded CSS and JavaScript support.
The standalone smoke test independently verifies both the downloaded VSIX and
the extracted server hashes. It then initializes the real server, opens
scripts/fixtures/visualforce/CompletionProbe.page, requests completion, shuts
down, and checks clean process termination. The verified run returned 246
completion items, including 93 unique apex:* labels. Run it twice to exercise
cold and warm caches, followed by its deterministic checksum-negative mode:
rtk python3 scripts/test-visualforce-lsp-smoke.py
rtk python3 scripts/test-visualforce-lsp-smoke.py
rtk python3 scripts/test-visualforce-lsp-smoke.py --expect-corrupt-bundle-failure
rtk python3 scripts/test-visualforce-lsp-diagnostics.py
The test cache defaults to the ignored .cache/visualforce-language-server/
directory. --cache-dir, --vsix-url, and --node (or the corresponding
VISUALFORCE_LSP_CACHE_DIR, VISUALFORCE_LSP_VSIX_URL, and
VISUALFORCE_LSP_NODE environment variables) make offline and repeated runs
controllable.
The Zed-facing integration test verifies the manifest wiring, both file suffixes,
the exact grammar revision, runtime/smoke artifact identity, page/component
parsing, and every shipped query. Repository Python checks support Python 3.10+
and use the pinned tomli backport only on Python versions before 3.11:
rtk python3 -m pip install -r requirements-dev.txt
rtk python3 scripts/test-python-baseline.py
rtk python3 scripts/test-visualforce-lsp-framing.py
rtk python3 scripts/test-visualforce-integration.py
visualforce-language-server is registered only for Visualforce; it is not
attached globally to HTML.
The Apex language declaration sets prettier_parser_name = "apex", so Zed's
built-in Prettier picks up the right parser. Users still need to enable
Prettier and provide prettier-plugin-apex.
Recommended .zed/settings.json for an SFDX project:
{
"languages": {
"Apex": {
"format_on_save": "on",
"formatter": "prettier",
"prettier": {
"allowed": true,
"parser": "apex",
"plugins": ["prettier-plugin-apex"]
}
}
}
}
If the project has its own package.json / .prettierrc, Zed will use the
project-local Prettier and config (so the plugins and options keys above
are ignored, but allowed and parser still apply). Anonymous Apex blocks
should use "parser": "apex-anonymous".
Alternative — invoke Prettier as an external formatter (no bundled Prettier
needed, calls npx):
{
"languages": {
"Apex": {
"format_on_save": "on",
"formatter": {
"external": {
"command": "npx",
"arguments": [
"prettier",
"--plugin=prettier-plugin-apex",
"--parser", "apex",
"--stdin-filepath", "{buffer_path}"
]
}
}
}
}
}
The legacy reference for the jorje backend comes from Salesforce's VS Code extension. From languageServer.ts, Salesforce VS Code extension starts the language server as:
<java_home>/bin/java).apex-jorje-lsp.jar.apex.jorje.lsp.ApexLanguageServerLauncher.That means when the jorje backend is selected, this project treats apex-jorje-lsp.jar as the authoritative LSP server binary payload, launched as a Java process.
From requirements.ts + Salesforce Java setup docs:
JAVA_HOME / JDK_HOME).Planned structure (high-level):
.
├─ extension.toml
├─ Cargo.toml
├─ src/
│ └─ lib.rs
├─ languages/
│ └─ apex/
│ ├─ config.toml
│ ├─ highlights.scm
│ ├─ brackets.scm (optional early)
│ ├─ textobjects.scm (optional, later)
│ └─ injections.scm (optional, later)
└─ (no `grammars/` dir required; Tree-sitter grammars are fetched from Git repos declared in `extension.toml`)
Implement languages/apex/config.toml with:
name = "Apex"grammar = "apex" (Tree-sitter grammar name registered in extension.toml, see below)path_suffixes = ["cls", "trigger", "apex"]line_comments = ["// "]This gives Apex file association + comment behavior and is required before deeper LSP integration.
This extension uses the tree-sitter-sfapex grammar repository, pinned to a specific Git revision for deterministic builds:
https://github.com/aheber/tree-sitter-sfapex60cc57049ed6dd4e28e528024a0230ee8fb8a64dZed loads Tree-sitter grammars that are registered in extension.toml. Apex is one registered language in a broader Salesforce DX extension.
# extension.toml
[grammars.apex]
repository = "https://github.com/aheber/tree-sitter-sfapex"
rev = "60cc57049ed6dd4e28e528024a0230ee8fb8a64d"
tree-sitter-sfapex is a multi-grammar repository (it includes apex, soql, sosl, and sflog via tree-sitter.json).
If we decide to support these file types in Zed later, register them explicitly too:
# extension.toml
[grammars.soql]
repository = "https://github.com/aheber/tree-sitter-sfapex"
rev = "60cc57049ed6dd4e28e528024a0230ee8fb8a64d"
[grammars.sosl]
repository = "https://github.com/aheber/tree-sitter-sfapex"
rev = "60cc57049ed6dd4e28e528024a0230ee8fb8a64d"
[grammars.sflog]
repository = "https://github.com/aheber/tree-sitter-sfapex"
rev = "60cc57049ed6dd4e28e528024a0230ee8fb8a64d"
Upstream file type mapping (from tree-sitter.json) is:
apex: .cls, .triggersoql: .soqlsosl: .soslsflog: .sflogFor the Zed MVP we also associate .apex (Anonymous Apex) with the apex grammar via path_suffixes, even though it is not listed upstream.
For local grammar development (iterating on queries/grammar), Zed also supports file:// repositories in extension.toml.
MVP highlighting should come from Tree-sitter queries (highlights.scm) for deterministic baseline:
@comment, @comment.doc@keyword@string@number@function, @type, etc. where grammar supports itWhy Tree-sitter first:
Then optionally enable/validate semantic tokens in your Zed settings to augment highlighting.
off / combined / full)off: only Tree-sitter query highlighting is used. This is the most deterministic mode and the safest troubleshooting baseline.combined: Tree-sitter baseline + semantic token overlays when available. This is usually the best mode for Apex.full: semantic token rendering is prioritized. This can look better when server token coverage is strong, but may reduce fallback consistency if token classes are incomplete.Note: semantic token mode is an editor/user setting. The extension cannot force this value globally for users.
Optional toggle in .zed/settings.json while evaluating Apex color behavior:
{
"languages": {
"Apex": {
"semantic_tokens": "combined"
}
}
}
We prefer to reuse as much as possible from tree-sitter-sfapex (grammar + queries), and only patch where Zed-specific needs require it.
tree-sitter-sfapex ships Tree-sitter query files that we can treat as the baseline source-of-truth (and they are easy to diff/update because we pin the commit):
apex/queries/highlights.scmsoql/queries/highlights.scmsosl/queries/highlights.scmIn Zed, queries live under languages/<language>/ (e.g. languages/apex/highlights.scm). For the MVP, the intended workflow is:
apex/queries/highlights.scm into languages/apex/highlights.scm (verbatim first).When we add soql/sosl/sflog as Zed languages, we should follow the same approach:
languages/soql/highlights.scm, languages/sosl/highlights.scm, etc.If the pinned rev changes, re-sync the query files from upstream in the same PR so highlighting stays consistent with the grammar version.
In extension.toml:
[language_servers.apex-language-server]).Apex.In Rust extension code (src/lib.rs):
language_server_command(...) -> zed::Command.aer default, jorje opt-in).aer: resolve the binary via lsp.apex-language-server.binary.path → lsp.apex-language-server.settings.aer_path → worktree.which("aer"), then launch with aer lsp [<source-root>]....jorje: launch a Java process similarly to Salesforce VS Code:
command: resolved Java executable pathargs: -cp <path-to-jar> apex.jorje.lsp.ApexLanguageServerLauncher-Xmx optional for memory control)When the jorje backend is selected, the extension runtime downloads and caches the jar on first use inside the extension work directory.
forcedotcom/salesforcedx-vscode<extension-workdir>/lsp/apex-language-server/apex-jorje-lsp.jarscripts/test-lsp-launch.sh) downloads the same jar into .cache/apex-language-server/ (gitignored) and verifies its SHA-256 before each runOnly relevant when backend is set to jorje. Required capability in extension logic:
lsp.apex-language-server.binary.path pointing to a java executable).lsp.apex-language-server.settings.java_home (resolved as <java_home>/bin/java).JDK_HOME, then JAVA_HOME.bin/java presentjava -version reports supported major (>=11)Heap behavior:
-Xmx2048m (no user config needed)lsp.apex-language-server.settings.java_max_heap_mblsp.apex-language-server.binary.arguments with explicit -Xmx... (takes precedence)Default Apex LSP JVM properties:
-Ddebug.internal.errors=true-Ddebug.completion.statistics=false-Dlwc.typegeneration.disabled=truelsp.apex-language-server.binary.arguments with explicit -D... for the same property name (takes precedence)Example .zed/settings.json (jorje backend):
{
"lsp": {
"apex-language-server": {
"settings": {
"backend": "jorje",
"java_home": "/Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home",
"java_max_heap_mb": 2048
}
}
}
}
Recommended docs for users on the jorje backend should include Java 21 guidance (consistent with Salesforce recommendations).
Example .zed/settings.json (aer backend, default — only needed if aer is not on PATH):
{
"lsp": {
"apex-language-server": {
"settings": {
"aer_path": "/usr/local/bin/aer"
}
}
}
}
By default, the aer backend reads sfdx-project.json packageDirectories and passes those package roots to aer lsp as positional source roots. Salesforce documents package directory paths as project-relative package roots, with source-format metadata below the package directory. Salesforce's generated project layout commonly places Apex and adjacent metadata under:
<package>/main/default/classes<package>/main/default/triggers<package>/main/default/objects<package>/main/default/externalServicesDo not narrow aer inputs to Apex leaf folders such as classes or triggers. aer builds schema information by scanning metadata in the directories it receives; passing only classes can hide custom objects, fields, external services, flows, and other metadata that Apex type checking and completions may need. Passing the package root keeps custom source subtrees such as <package>/second/default/classes or <package>/main/second/triggers available without the extension guessing the user's internal layout.
References:
packageDirectories[].path is relative to the project.force-app/main/default; this extension treats that as the generated convention, not the only source subtree.aer test examples pass source roots such as force-app/main/default and note that schema is built by scanning metadata in supplied directories.classes; Apex triggers are stored in triggers.For unusual workspaces, set lsp.apex-language-server.settings.aer_source_paths explicitly to source roots containing Apex and adjacent metadata.
Salesforce DX language tooling behavior depends on project shape (sfdx-project.json, packageDirectories, and Salesforce DX metadata layout). For MVP, we need to be explicit about what we do (and do not) support so startup is deterministic.
Zed starts language servers per worktree (a directory project or a single-file worktree). Practically, this means:
.cls file).sfdx-project.json at the worktree root.
For MVP, syntax highlighting still works; Apex LSP behavior depends on the workspace root supplied by Zed.Zed also has a Restricted/Trusted worktree model:
.zed/settings.json in the project is not applied, and language servers configured by that project settings file are not spawned.language_server_command (installed extension code). Project settings may still matter for per-project configuration, but only after the worktree is trusted.sfdx-project.json at the top level.rootPath.packageDirectories roots (commonly force-app/main/default/...).Concrete examples of layouts we expect to work best:
sfdx-project.jsonforce-app/main/default/classes/*.clsforce-app/main/default/triggers/*.triggerConcrete examples that are not a primary MVP target (may partially work, but not guaranteed):
src/classes without sfdx-project.json.apex scripts outside an SFDX project (highlighting should work; LSP start behavior depends on Apex server tolerance when no SFDX layout is present)If unsupported workspace is opened, extension should degrade gracefully:
sfdx-project.json is absent at worktree root.sfdx-project.json files and does not override the workspace root that Zed passes to the language server.sfdx-project.json parsingThe current MVP performs minimal runtime parsing of sfdx-project.json for the default aer backend.
Implemented surface:
packageDirectories: determine source package roots passed to aer lsp.Future surface:
.cls is outside any package directory)namespace: used only for user-facing messaging and (future) LSP UX parity behaviors; we do not assume org namespace access in MVP.sourceApiVersion: used for compatibility decisions that depend on API version (future). For MVP it is optional and can be logged for diagnostics.If this parsing is added later and parsing fails (invalid JSON), the extension should not start LSP and should log an actionable parse error.
What changed:
extension.toml, Cargo.toml, src/lib.rs).extension.toml pinned to tree-sitter-sfapex commit 60cc57049ed6dd4e28e528024a0230ee8fb8a64d.languages/apex/config.toml with file suffixes .cls, .trigger, and .apex.languages/apex/highlights.scm sourced from upstream pinned grammar revision..soql, .sosl, and .sflog (and .log) as part of broader Salesforce DX language support.src/lib.rs (Java resolution + managed jar download/cache).scripts/test-lsp-launch.shscripts/lsp_smoke.pyscripts/fixtures/sfdx-minimal/Why:
How to verify:
cargo check to validate Rust extension scaffold builds../scripts/tree-sitter-smoke.py to verify the pinned Tree-sitter grammar parses current Apex fixtures and that local highlight queries compile against them../scripts/test-lsp-launch.sh to verify Java resolution, download/cache the pinned Apex LSP jar (with SHA-256 check), and exercise Apex LSP completion against both a fixture SFDX workspace root and a nested SFDX workspace inside a monorepo-style root..cls / .trigger / .apex files.extension.toml, Rust entrypoint).languages/apex/config.toml) as part of Salesforce DX language coverage.highlights.scm with comments/code distinction and common token classes.off / combined / full).language_server_command.extension.toml, languages/apex/config.toml).highlights.scm etc.) where tooling is available../scripts/tree-sitter-smoke.py to clone/cache the pinned tree-sitter-sfapex revision and parse Salesforce syntax fixtures. The script includes passing Summer '26 Apex coverage and expected-failure fixtures for known upstream parser gaps.cargo check, cargo clippy if configured).Current known parser gap:
FORMULA('...') in a WHERE clause does not parse cleanly in tree-sitter-sfapex as of the pinned revision. Keep scripts/fixtures/known-gaps/*formula* as expected failures until the upstream grammar supports this construct, then move them into passing fixtures.scripts/test-lsp-launch.sh provides deterministic process-level validation:
.cache/apex-language-server/ if missing and validates its SHA-256 checksum.System.Run:
./scripts/test-lsp-launch.sh
This can be run by both humans and AI agents in CI/local.
Use fixture workspace with minimal SFDX structure:
sfdx-project.json.cls file.trigger filePlanned automated check:
Even if full GUI assertion is hard, log-based validation is practical for agents.
.soql / .sosl / .sflog files: basic highlighting works.forcedotcom/salesforcedx-vscodepackages/salesforcedx-vscode-apex/src/languageServer.tspackages/salesforcedx-vscode-apex/src/requirements.tspackages/salesforcedx-vscode-apex/src/languageUtils/apexLanguageConfiguration.tsaer (native binary, no JVM).apex-jorje-lsp.jar (selected via backend = "jorje"); requires Java 11+ (Java 21 recommended).language_server_command launcher; jorje backend additionally manages jar download/cache.highlights.scm), semantic tokens optional enhancement.This repository includes a tasks.json file with pre-configured Salesforce CLI (sf) task templates for common operations (deploy, retrieve, org management, etc.).
Zed extensions currently have no mechanism to register commands or bundle task templates (unlike VS Code's contributes.commands). As a workaround, you can manually copy the file into your project's Zed configuration directory:
cp tasks.json <your-sfdx-project>/.zed/tasks.json
The tasks will then appear in Zed's task picker (cmd/ctrl+shift+t). All tasks use $ZED_WORKTREE_ROOT as the working directory, so they work from any file within the project.