tree-sitter-salesforce
v0.2.0
Published
Tree-sitter grammars for Salesforce languages: Apex, SOQL, and more
Maintainers
Readme
tree-sitter-salesforce
Tree-sitter grammars for Salesforce languages — Apex, SOQL, SOSL, Formula Language, and Anonymous Apex.
Providing fast, incremental, error-tolerant parsing for Salesforce development tools.
Features
- 🚀 Production-quality Apex parser — Salesforce API v67 (Summer '25), covering
classes, interfaces, enums, triggers, DML, annotations, generics, and modern syntax
(
?.,??, switch/when, multi-SObject type patterns). - 🔍 SOQL parser — Full query syntax including
TYPEOF,GROUP BY ROLLUP/CUBE, date functions (CALENDAR_MONTH,FISCAL_YEAR), scalar functions (FORMAT,convertCurrency,toLabel,GROUPING),convertTimezone(), time literals, dynamic formula filtering (FORMULA(...)),ALL ROWSclause, bind variables,USING SCOPE / LOOKUP ... BIND, and all security clauses (WITH USER_MODE / SYSTEM_MODE / DATA CATEGORY / RecordVisibilityContext). - 🔎 SOSL parser — Full-text search language:
FIND {term} / 'term', field scopes, per-objectWHERE/ORDER BY/LIMIT/ projections (toLabel(),convertCurrency(),FORMAT()), and modernWITHclauses (USER_MODE,SYSTEM_MODE,METADATA,NETWORK IN,SNIPPET (TARGET_LENGTH=n)). - 📐 Formula Language parser — Declarative formula expressions for Validation Rules,
Formula Fields, and Flow criteria: 50+ built-in functions, field-path references, and
global context variables (
$User,$Organization,$CustomMetadata,$Setup). - 📝 Anonymous Apex parser — Parses top-level executable scripts (Developer Console
"Execute Anonymous",
sf apex run) without a class wrapper. - 📋 Salesforce Debug Log parser (
sflog) — Structured parser for execution logs (.log), timestamped execution events, SOQL/DML metrics,USER_DEBUGmessages, and cumulative governor limit tables. - 🔗 Language injection — SOQL and SOSL are highlighted correctly inside Apex code
(both static
[SELECT …]/[FIND …]literals and dynamicDatabase.*method strings). - 📦 Multi-language bindings — Python (≥ 0.22 native capsule API), Node.js, and WebAssembly bindings for browser and VS Code Web.
- 📚 Educational — Every grammar rule carries inline comments explaining why it exists, designed for contributors and parser authors.
Quick Start
Python
pip install tree-sitter-salesforceimport tree_sitter_salesforce as tss
from tree_sitter import Parser
parser = Parser()
# ── Apex (.cls / .trigger) ──────────────────────────────────────────────────
parser.language = tss.apex()
tree = parser.parse(b"""
public with sharing class AccountService {
public List<Account> getAccounts() {
return [SELECT Id, Name FROM Account];
}
}
""")
print(tree.root_node.sexp())
# ── Anonymous Apex (Developer Console / sf apex run) ────────────────────────
parser.language = tss.apex_anon()
tree = parser.parse(b"insert new Account(Name = 'Test');\nSystem.debug('done');")
print(tree.root_node.sexp())
# ── SOQL ────────────────────────────────────────────────────────────────────
parser.language = tss.soql()
tree = parser.parse(b"SELECT Id, Name FROM Account WHERE IsDeleted = false LIMIT 10")
print(tree.root_node.sexp())
# ── SOSL ────────────────────────────────────────────────────────────────────
parser.language = tss.sosl()
tree = parser.parse(b"FIND 'Acme*' IN ALL FIELDS RETURNING Account(Name), Contact(Email)")
print(tree.root_node.sexp())
# ── Formula Language ─────────────────────────────────────────────────────────
parser.language = tss.formula()
tree = parser.parse(b"IF(ISBLANK(Email__c), 'Required', Email__c & ' (' & $User.Name & ')')")
print(tree.root_node.sexp())
# ── Salesforce Debug Log (sflog) ─────────────────────────────────────────────
parser.language = tss.sflog()
tree = parser.parse(b"14:32:01.052 (52301000)|USER_DEBUG|[5]|DEBUG|Processing 10 accounts")
print(tree.root_node.sexp())Node.js
npm install tree-sitter tree-sitter-salesforceStandard Import:
const Parser = require('tree-sitter');
const { apex, apexAnon, soql, sosl, formula, sflog } = require('tree-sitter-salesforce');
const parser = new Parser();
parser.setLanguage(apex);
const tree = parser.parse(`public class AccountService { }`);
console.log(tree.rootNode.toString());Granular Subpath Exports:
// Direct submodule imports in CommonJS or ESM:
const apex = require('tree-sitter-salesforce/apex');
const soql = require('tree-sitter-salesforce/soql');
const sosl = require('tree-sitter-salesforce/sosl');
const formula = require('tree-sitter-salesforce/formula');
const sflog = require('tree-sitter-salesforce/sflog');
const apexAnon = require('tree-sitter-salesforce/apex-anon');
// In TypeScript / ESM:
// import apex from 'tree-sitter-salesforce/apex';
// import sflog from 'tree-sitter-salesforce/sflog';WebAssembly (Browser / VSCode Web) & Interactive Playground
Test syntax trees live directly in your browser using our zero-install interactive playground:
npm install web-tree-sitter tree-sitter-salesforceconst Parser = require('web-tree-sitter');
const { apexWasm, soqlWasm, soslWasm, formulaWasm, sflogWasm, apexAnonWasm } = require('tree-sitter-salesforce/bindings/web');
async function main() {
await Parser.init();
const parser = new Parser();
// Load compiled WASM grammar
const Apex = await Parser.Language.load(apexWasm);
parser.setLanguage(Apex);
const tree = parser.parse('public class AccountService { }');
console.log(tree.rootNode.toString());
}
main();Parser Status
| Parser | Grammar | Tests | Highlights | Injection | Tags |
|---|---|---|---|---|---|
| Apex | ✅ | ✅ | ✅ | ✅ SOQL + SOSL | ✅ |
| Apex (Anonymous) | ✅ | ✅ | ✅ (shared) | ✅ SOQL + SOSL | — |
| SOQL | ✅ | ✅ | ✅ | — | — |
| SOSL | ✅ | ✅ | ✅ | — | — |
| Formula Language | ✅ | ✅ | ✅ | — | — |
| Debug Log (sflog) | ✅ | ✅ | ✅ | — | — |
Salesforce API Version
Targets API v67 (Summer '25). See SALESFORCE_API.md.
Dynamic Query Support
| Scenario | SOQL | SOSL |
|---|---|---|
| Inline [SELECT …] / [FIND …] | ✅ Full parsing | ✅ Full parsing |
| Database.query('SELECT …') | ✅ String injection | — |
| Database.queryWithBinds(…) | ✅ String injection | — |
| Database.countQuery(…) | ✅ String injection | — |
| Database.getQueryLocator(…) | ✅ String injection | — |
| Concatenated query strings | ⚠️ Structural recognition | — |
Roadmap
| Feature | Status |
|---|---|
| Apex type-flow analysis queries (locals.scm for all grammars) | 🔲 Future |
| VS Code extension | 🔲 Future |
Documentation
- How Tree-Sitter Works
- Grammar DSL Cheatsheet
- Understanding Apex
- Understanding Anonymous Apex
- Understanding SOQL
- Understanding SOSL
- Understanding Formula Language
- Getting Started Tutorial
- Adding a New Language
- Testing Guide
- WebAssembly Playground Guide
- Release Process
- Architecture
Contributing
See CONTRIBUTING.md.
License
MIT — see LICENSE for details.
