diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 71da543a6..1a7c329ba 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,7 +47,9 @@ jobs: exit 1 fi cargo xtask install --root "$RUNNER_TEMP/install" + cargo install --path . --locked --features all-languages --root "$RUNNER_TEMP/full" python3 scripts/release.py pack --version "$version" --target "$TARGET" --install "$RUNNER_TEMP/install" --output dist + python3 scripts/release.py pack --version "$version" --target "$TARGET" --install "$RUNNER_TEMP/full" --edition full --output dist - name: Verify extracted archives without Bun or checkout assets env: TARGET: ${{ matrix.target }} @@ -57,6 +59,7 @@ jobs: tar -xzf "dist/diffr-$version-$TARGET.tar.gz" -C "$RUNNER_TEMP/extracted/bin" python3 xtask/tests/smoke_install.py "$RUNNER_TEMP/extracted" python3 scripts/smoke_cli_archive.py "dist/diffr-cli-$version-$TARGET.tar.gz" "$version" + python3 scripts/smoke_cli_archive.py "dist/diffr-cli-full-$version-$TARGET.tar.gz" "$version" - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: ${{ matrix.target }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b5937e739..6b3d3b94a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -131,6 +131,7 @@ jobs: bun-version: 1.3.10 - uses: dtolnay/rust-toolchain@1.85.0 - run: cargo build --locked + - run: cargo test --locked --features all-languages --bin diffr --test cli - working-directory: diffr-ts run: | bun install --frozen-lockfile diff --git a/Cargo.toml b/Cargo.toml index a8f37b0b0..b39a52880 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,24 +94,24 @@ tree-sitter-fortran = { version = "0.6.0", optional = true } tree-sitter-fsharp = { version = "0.3.0", optional = true } tree-sitter-gleam = "1.0.0" tree-sitter-go = "0.25.0" -tree-sitter-haskell = "0.23.1" +tree-sitter-haskell = { version = "0.23.1", optional = true } tree-sitter-hcl = "1.1.0" tree-sitter-html = "0.23.2" tree-sitter-java-orchard = "0.5.9" tree-sitter-javascript = "0.25.0" tree-sitter-json = "0.24.8" -tree-sitter-julia = "0.23.1" +tree-sitter-julia = { version = "0.23.1", optional = true } tree-sitter-lua = "0.5" tree-sitter-make = "1.1.1" tree-sitter-newick = "1.1.0" tree-sitter-nix = "0.3.0" tree-sitter-objc = "3.0.2" -tree-sitter-ocaml = "0.25.0" +tree-sitter-ocaml = { version = "0.25.0", optional = true } tree-sitter-pascal = "0.10.0" tree-sitter-php = "0.24.0" tree-sitter-proto = "0.4.0" tree-sitter-python = "0.25.0" -tree-sitter-qmljs = "0.3.0" +tree-sitter-qmljs = { version = "0.3.0", optional = true } tree-sitter-r = "1.2.0" tree-sitter-racket = "0.24.7" tree-sitter-ruby = "0.23.1" @@ -119,13 +119,13 @@ tree-sitter-rust-orchard = "0.16.6" tree-sitter-scala = "0.26.2" tree-sitter-scheme = "0.24.7" tree-sitter-sequel = "0.3.11" -tree-sitter-sfapex = "2.4.0" +tree-sitter-sfapex = { version = "2.4.0", optional = true } tree-sitter-solidity = "1.2.13" tree-sitter-swift = "0.7.1" tree-sitter-toml-ng = "0.7.0" tree-sitter-typescript = "0.23.2" tree-sitter-verilog = { version = "1.0.3", optional = true } -tree-sitter-vhdl = "1.4.0" +tree-sitter-vhdl = { version = "1.4.0", optional = true } tree-sitter-xml = "0.7.0" tree-sitter-yaml = "0.7.0" tree-sitter-zig = "1.1.2" @@ -235,8 +235,14 @@ name = "wasm" required-features = ["wasm-plugin-tests"] [features] -all-languages = ["lang-fortran", "lang-fsharp", "lang-verilog"] +all-languages = ["lang-fortran", "lang-fsharp", "lang-verilog", "lang-ocaml", "lang-julia", "lang-haskell", "lang-vhdl", "lang-apex", "lang-qml"] lang-fortran = ["dep:tree-sitter-fortran"] lang-fsharp = ["dep:tree-sitter-fsharp"] lang-verilog = ["dep:tree-sitter-verilog"] +lang-ocaml = ["dep:tree-sitter-ocaml"] +lang-julia = ["dep:tree-sitter-julia"] +lang-haskell = ["dep:tree-sitter-haskell"] +lang-vhdl = ["dep:tree-sitter-vhdl"] +lang-apex = ["dep:tree-sitter-sfapex"] +lang-qml = ["dep:tree-sitter-qmljs"] wasm-plugin-tests = [] diff --git a/diffr-ts/README.md b/diffr-ts/README.md index 7256802e6..33a05da7d 100644 --- a/diffr-ts/README.md +++ b/diffr-ts/README.md @@ -16,6 +16,10 @@ Supports macOS arm64, macOS x64, Linux arm64, and Linux x64. `--check` verifies network access. Downloads warn on network failure unless `--required`; invalid hashes or archives always fail. +`--full` fetches the full edition, which adds the parsers lean builds omit (Apex, +Fortran, F#, Haskell, Julia, OCaml, QML, Verilog, VHDL). It requires full-edition +pins, which start with the next release. + ## Wire changes Keep these files in sync: @@ -30,8 +34,8 @@ Keep these files in sync: ## Release After tagging the matching Rust release and building with `cargo build --locked`, -run from `diffr-ts`. New pins select the CLI-only release archives; older pins -continue to use the full archives: +run from `diffr-ts`. New pins select the lean and full CLI-only release archives; +older pins continue to use the combined archives: ```sh bun install --frozen-lockfile diff --git a/diffr-ts/bin/fetch.mjs b/diffr-ts/bin/fetch.mjs index 6ce74518f..ac9391326 100755 --- a/diffr-ts/bin/fetch.mjs +++ b/diffr-ts/bin/fetch.mjs @@ -19,6 +19,7 @@ try { async function main() { const { values } = parseArgs({ options: { into: { type: "string" }, + full: { type: "boolean", default: false }, check: { type: "boolean" }, required: { type: "boolean" }, pins: { type: "string", default: join(root, "pins.json") }, @@ -30,7 +31,9 @@ async function main() { if (pins.version !== version) throw new Error(`pins.json is for ${pins.version}, package is ${version}; run \`npm run pin\``); const target = targets[`${process.platform}-${process.arch}`]; if (!target) throw new Error(`no diffr release for ${process.platform}-${process.arch}`); - const expected = pins.sha256?.[target]; + const pin = values.full ? pins.full : pins; + if (!pin) throw new Error(`pins.json has no full edition for ${version}`); + const expected = pin.sha256?.[target]; if (typeof expected !== "string" || !/^[a-f0-9]{64}$/.test(expected)) { throw new Error(`pins.json has no valid sha256 for ${target}`); } @@ -41,7 +44,8 @@ async function main() { try { const stamp = JSON.parse(readFileSync(stampPath, "utf8")); const stat = lstatSync(binary); - installed = stat.isFile() && (stat.mode & 0o111) !== 0 && stamp.version === version && stamp.target === target; + installed = stat.isFile() && (stat.mode & 0o111) !== 0 && stamp.version === version && stamp.target === target + && Boolean(stamp.full) === values.full; } catch { /* Missing or damaged installations are fetched again. */ } if (installed) { console.log(`diffr ${version} (${target}) already at ${binary}`); @@ -49,8 +53,8 @@ async function main() { } if (values.check) throw new Error(`${binary} is missing or not diffr ${version} (${target})`); - const artifact = pins.artifact ?? "diffr"; - if (!["diffr", "diffr-cli"].includes(artifact)) throw new Error(`unknown pinned artifact: ${artifact}`); + const artifact = values.full ? "diffr-cli-full" : pins.artifact ?? "diffr"; + if (!["diffr", "diffr-cli", "diffr-cli-full"].includes(artifact)) throw new Error(`unknown pinned artifact: ${artifact}`); const asset = `${artifact}-${version}-${target}.tar.gz`; const url = `https://github.com/devdotfast/diffr/releases/download/${version}/${asset}`; let bytes; @@ -78,7 +82,7 @@ async function main() { } chmodSync(extracted, 0o755); const stamp = join(staging, "stamp.json"); - writeFileSync(stamp, `${JSON.stringify({ version, target }, null, 2)}\n`); + writeFileSync(stamp, `${JSON.stringify({ version, target, ...(values.full && { full: true }) }, null, 2)}\n`); renameSync(extracted, binary); renameSync(stamp, stampPath); } finally { diff --git a/diffr-ts/scripts/pin.mjs b/diffr-ts/scripts/pin.mjs index b858ec44c..5e240b3cd 100755 --- a/diffr-ts/scripts/pin.mjs +++ b/diffr-ts/scripts/pin.mjs @@ -8,17 +8,20 @@ const here = dirname(fileURLToPath(import.meta.url)); const root = join(here, ".."); const version = JSON.parse(readFileSync(join(root, "package.json"), "utf8")).version; const targets = ["aarch64-apple-darwin", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", "aarch64-unknown-linux-gnu"]; -const artifact = "diffr-cli"; -const sha256 = {}; -for (const target of targets) { - const url = `https://github.com/devdotfast/diffr/releases/download/${version}/${artifact}-${version}-${target}.tar.gz`; - const response = await fetch(url, { redirect: "follow", signal: AbortSignal.timeout(120_000) }); - if (!response.ok) { - console.error(`pin: GET ${url} failed with ${response.status} ${response.statusText}`); - process.exit(1); +async function hashes(artifact) { + const sha256 = {}; + for (const target of targets) { + const url = `https://github.com/devdotfast/diffr/releases/download/${version}/${artifact}-${version}-${target}.tar.gz`; + const response = await fetch(url, { redirect: "follow", signal: AbortSignal.timeout(120_000) }); + if (!response.ok) { + console.error(`pin: GET ${url} failed with ${response.status} ${response.statusText}`); + process.exit(1); + } + sha256[target] = createHash("sha256").update(Buffer.from(await response.arrayBuffer())).digest("hex"); + console.log(`${artifact} ${target} ${sha256[target]}`); } - sha256[target] = createHash("sha256").update(Buffer.from(await response.arrayBuffer())).digest("hex"); - console.log(`${target} ${sha256[target]}`); + return sha256; } -writeFileSync(join(root, "pins.json"), `${JSON.stringify({ version, artifact, sha256 }, null, 2)}\n`); +const pins = { version, artifact: "diffr-cli", sha256: await hashes("diffr-cli"), full: { sha256: await hashes("diffr-cli-full") } }; +writeFileSync(join(root, "pins.json"), `${JSON.stringify(pins, null, 2)}\n`); console.log(`wrote pins.json for ${version}`); diff --git a/diffr-ts/src/fetch.test.ts b/diffr-ts/src/fetch.test.ts index 282902a9c..1cf4f9ab6 100644 --- a/diffr-ts/src/fetch.test.ts +++ b/diffr-ts/src/fetch.test.ts @@ -152,3 +152,17 @@ test("unknown pinned artifacts fail before downloading", () => { expect(f.run().err).toContain("unknown pinned artifact"); expect(existsSync(join(f.dir, "requested"))).toBe(false); }); + +test("--full downloads the full archive, fails without full pins, and refetches when switching", () => { + const f = fixture("diffr", "diffr-cli"); + expect(f.run(["--full"]).err).toContain("no full edition"); + expect(existsSync(join(f.dir, "requested"))).toBe(false); + const pins = JSON.parse(readFileSync(f.pins, "utf8")); + writeFileSync(f.pins, JSON.stringify({ ...pins, full: { sha256: pins.sha256 } })); + expect(f.run(["--full"]).code).toBe(0); + expect(readFileSync(join(f.dir, "requested"), "utf8")).toBe( + `https://github.com/devdotfast/diffr/releases/download/${version}/diffr-cli-full-${version}-${target}.tar.gz`, + ); + expect(f.run(["--full", "--check"]).code).toBe(0); + expect(f.run(["--check"]).code).toBe(1); +}); diff --git a/diffr-ts/src/version.test.ts b/diffr-ts/src/version.test.ts index e87e32561..da34cdd1f 100644 --- a/diffr-ts/src/version.test.ts +++ b/diffr-ts/src/version.test.ts @@ -17,8 +17,10 @@ test("release pins match the package version and cover all supported targets", ( const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8")); const pins = JSON.parse(readFileSync(join(root, "pins.json"), "utf8")); expect(pins.version).toBe(pkg.version); - expect(Object.keys(pins.sha256).sort()).toEqual([ - "aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", - ]); - for (const hash of Object.values(pins.sha256)) expect(hash).toMatch(/^[a-f0-9]{64}$/); + for (const { sha256 } of pins.full ? [pins, pins.full] : [pins]) { + expect(Object.keys(sha256).sort()).toEqual([ + "aarch64-apple-darwin", "aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu", + ]); + for (const hash of Object.values(sha256)) expect(hash).toMatch(/^[a-f0-9]{64}$/); + } }); diff --git a/sample_files/ocaml_interface_1.mli b/sample_files/ocaml_interface_1.mli new file mode 100644 index 000000000..3e647cea8 --- /dev/null +++ b/sample_files/ocaml_interface_1.mli @@ -0,0 +1,3 @@ +(** Public interface *) +type result = { value : int } +val compute : int -> result diff --git a/sample_files/ocaml_interface_2.mli b/sample_files/ocaml_interface_2.mli new file mode 100644 index 000000000..b0da7420d --- /dev/null +++ b/sample_files/ocaml_interface_2.mli @@ -0,0 +1,3 @@ +(** Public interface *) +type result = { value : int; label : string } +val compute : int -> string -> result diff --git a/scripts/release.py b/scripts/release.py index ecc44e4c8..27f6751a8 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -14,11 +14,11 @@ def archive_name(version, target, artifact="diffr"): return f"{artifact}-{version}-{target}.tar.gz" -def pack(version, target, install, output): +def pack(version, target, install, output, edition="lean"): actual = subprocess.check_output([install / "bin/diffr", "--version"], text=True).strip() if actual != f"diffr {version}": raise ValueError(f"Release version mismatch: {actual}") - for artifact in ("diffr", "diffr-cli"): + for artifact in ("diffr-cli-full",) if edition == "full" else ("diffr", "diffr-cli"): with tarfile.open(output / archive_name(version, target, artifact), "w:gz") as archive: binaries = ("diffr", "diffr-tui") if artifact == "diffr" else ("diffr",) for name in binaries: @@ -30,7 +30,7 @@ def pack(version, target, install, output): def formula(version, output): checksums = {} for target in TARGETS: - for artifact in ("diffr", "diffr-cli"): + for artifact in ("diffr", "diffr-cli", "diffr-cli-full"): name = archive_name(version, target, artifact) checksums[name] = hashlib.sha256((output / name).read_bytes()).hexdigest() (output / "SHA256SUMS").write_text("".join( @@ -89,6 +89,7 @@ def install parser.add_argument("--output", type=Path, required=True) parser.add_argument("--target", choices=TARGETS) parser.add_argument("--install", type=Path) + parser.add_argument("--edition", choices=("lean", "full"), default="lean") args = parser.parse_args() if not re.fullmatch(r"\d+\.\d+\.\d+", args.version): parser.error("version must be a stable X.Y.Z release") @@ -96,6 +97,6 @@ def install if args.command == "pack": if not args.target or not args.install: parser.error("pack requires --target and --install") - pack(args.version, args.target, args.install.resolve(), args.output) + pack(args.version, args.target, args.install.resolve(), args.output, args.edition) else: formula(args.version, args.output) diff --git a/src/parse/guess_language.rs b/src/parse/guess_language.rs index c36ca5fc6..f68550d6e 100644 --- a/src/parse/guess_language.rs +++ b/src/parse/guess_language.rs @@ -20,6 +20,7 @@ use strum::{EnumIter, IntoEnumIterator}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)] pub(crate) enum Language { Ada, + #[cfg(feature = "lang-apex")] Apex, Asm, Bash, @@ -44,6 +45,7 @@ pub(crate) enum Language { Fortran, Gleam, Go, + #[cfg(feature = "lang-haskell")] Haskell, Hcl, Html, @@ -52,6 +54,7 @@ pub(crate) enum Language { JavaScript, JavascriptJsx, Json, + #[cfg(feature = "lang-julia")] Julia, Kotlin, LaTeX, @@ -60,13 +63,16 @@ pub(crate) enum Language { Newick, Nix, ObjC, + #[cfg(feature = "lang-ocaml")] OCaml, + #[cfg(feature = "lang-ocaml")] OCamlInterface, Pascal, Perl, Php, Proto, Python, + #[cfg(feature = "lang-qml")] Qml, R, Racket, @@ -83,6 +89,7 @@ pub(crate) enum Language { TypeScriptTsx, #[cfg(feature = "lang-verilog")] Verilog, + #[cfg(feature = "lang-vhdl")] Vhdl, Xml, Yaml, @@ -124,6 +131,7 @@ pub(crate) fn language_override_from_name(name: &str) -> Option &'static str { match language { Ada => "Ada", + #[cfg(feature = "lang-apex")] Apex => "Apex", Asm => "Assembly", Bash => "Bash", @@ -148,6 +156,7 @@ pub(crate) fn language_name(language: Language) -> &'static str { Fortran => "Fortran", Gleam => "Gleam", Go => "Go", + #[cfg(feature = "lang-haskell")] Haskell => "Haskell", Hcl => "HCL", Html => "HTML", @@ -156,6 +165,7 @@ pub(crate) fn language_name(language: Language) -> &'static str { JavaScript => "JavaScript", JavascriptJsx => "JavaScript JSX", Json => "JSON", + #[cfg(feature = "lang-julia")] Julia => "Julia", Kotlin => "Kotlin", LaTeX => "LaTeX", @@ -164,13 +174,16 @@ pub(crate) fn language_name(language: Language) -> &'static str { Newick => "Newick", Nix => "Nix", ObjC => "Objective-C", + #[cfg(feature = "lang-ocaml")] OCaml => "OCaml", + #[cfg(feature = "lang-ocaml")] OCamlInterface => "OCaml Interface", Pascal => "Pascal", Perl => "Perl", Php => "PHP", Proto => "Proto", Python => "Python", + #[cfg(feature = "lang-qml")] Qml => "QML", R => "R", Racket => "Racket", @@ -187,6 +200,7 @@ pub(crate) fn language_name(language: Language) -> &'static str { TypeScriptTsx => "TypeScript TSX", #[cfg(feature = "lang-verilog")] Verilog => "Verilog", + #[cfg(feature = "lang-vhdl")] Vhdl => "VHDL", Xml => "XML", Yaml => "YAML", @@ -251,6 +265,7 @@ pub(crate) fn language_globs(language: Language) -> Vec { "zshenv", "zshrc", ], + #[cfg(feature = "lang-apex")] Apex => &["*.apexc", "*.trigger"], C => &["*.c"], Clojure => &[ @@ -301,6 +316,7 @@ pub(crate) fn language_globs(language: Language) -> Vec { Fortran => &["*.f", "*.for", "*.f90", "*.F", "*.FOR", "*.F90"], Gleam => &["*.gleam"], Go => &["*.go"], + #[cfg(feature = "lang-haskell")] Haskell => &["*.hs"], Hcl => &["*.hcl", "*.nomad", "*.tf", "*.tfvars", "*.workflow"], Html => &["*.html", "*.htm", "*.xhtml"], @@ -338,6 +354,7 @@ pub(crate) fn language_globs(language: Language) -> Vec { "flake.lock", ], JavascriptJsx => &["*.jsx"], + #[cfg(feature = "lang-julia")] Julia => &["*.jl"], Kotlin => &["*.kt", "*.ktm", "*.kts"], LaTeX => &["*.aux", "*.cls", "*.sty", "*.tex"], @@ -366,7 +383,9 @@ pub(crate) fn language_globs(language: Language) -> Vec { Newick => &["*.nhx", "*.nwk", "*.nh"], Nix => &["*.nix"], ObjC => &["*.m"], + #[cfg(feature = "lang-ocaml")] OCaml => &["*.ml"], + #[cfg(feature = "lang-ocaml")] OCamlInterface => &["*.mli"], Pascal => &["*.pas", "*.dfm", "*.dpr", "*.lpr", "*.pascal"], Perl => &["*.pm", "*.pl"], @@ -375,6 +394,7 @@ pub(crate) fn language_globs(language: Language) -> Vec { ], Proto => &["*.proto"], Python => &["*.py", "*.py3", "*.pyi", "*.bzl", "TARGETS", "BUCK", "DEPS"], + #[cfg(feature = "lang-qml")] Qml => &["*.qml"], R => &["*.R", "*.r", "*.rd", "*.rsx", ".Rprofile", "expr-dist"], Racket => &["*.rkt"], @@ -406,6 +426,7 @@ pub(crate) fn language_globs(language: Language) -> Vec { TypeScriptTsx => &["*.tsx"], #[cfg(feature = "lang-verilog")] Verilog => &["*.v", "*.sv", "*.vh"], + #[cfg(feature = "lang-vhdl")] Vhdl => &["*.vhdl", "*.vhd"], Xml => &[ "*.ant", @@ -560,6 +581,7 @@ fn from_emacs_mode_header(src: &str) -> Option { "fortran" => Fortran, "gleam" => Gleam, "go" => Go, + #[cfg(feature = "lang-haskell")] "haskell" => Haskell, "hcl" => Hcl, "html" => Html, @@ -581,10 +603,12 @@ fn from_emacs_mode_header(src: &str) -> Option { "sql" => Sql, "swift" => Swift, "toml" => Toml, + #[cfg(feature = "lang-ocaml")] "tuareg" => OCaml, "typescript" => TypeScript, #[cfg(feature = "lang-verilog")] "verilog" => Verilog, + #[cfg(feature = "lang-vhdl")] "vhdl" => Vhdl, "yaml" => Yaml, "zig" => Zig, @@ -613,9 +637,11 @@ fn from_shebang(src: &str) -> Option { "elixir" => return Some(Elixir), "escript" => return Some(Erlang), "fish" => return Some(Fish), + #[cfg(feature = "lang-haskell")] "runghc" | "runhaskell" | "runhugs" => return Some(Haskell), "chakra" | "d8" | "gjs" | "js" | "node" | "nodejs" | "qjs" | "rhino" | "v8" | "v8-shell" => return Some(JavaScript), + #[cfg(feature = "lang-ocaml")] "ocaml" | "ocamlrun" | "ocamlscript" => return Some(OCaml), "perl" => return Some(Perl), "python" | "python2" | "python3" => return Some(Python), @@ -725,6 +751,7 @@ mod tests { } #[test] + #[cfg(feature = "lang-ocaml")] fn test_guess_by_emacs_mode_shorthand() { let path = Path::new("foo"); assert_eq!(guess(path, "(* -*- tuareg -*- *)", &[]), Some(OCaml)); diff --git a/src/parse/tree_sitter_parser.rs b/src/parse/tree_sitter_parser.rs index 1aef0c877..6f4cdef9e 100644 --- a/src/parse/tree_sitter_parser.rs +++ b/src/parse/tree_sitter_parser.rs @@ -92,6 +92,7 @@ extern "C" { } // TODO: begin/end and object/end. +#[cfg(feature = "lang-ocaml")] const OCAML_ATOM_NODES: [&str; 6] = [ "character", "string", @@ -138,6 +139,7 @@ fn build_config(language: guess::Language) -> TreeSitterConfig { sub_languages: vec![], } } + #[cfg(feature = "lang-apex")] Apex => { let language_fn = tree_sitter_sfapex::apex::LANGUAGE; let language = tree_sitter::Language::new(language_fn); @@ -517,6 +519,7 @@ fn build_config(language: guess::Language) -> TreeSitterConfig { sub_languages: vec![], } } + #[cfg(feature = "lang-haskell")] Haskell => { let language_fn = tree_sitter_haskell::LANGUAGE; let language = tree_sitter::Language::new(language_fn); @@ -689,6 +692,7 @@ fn build_config(language: guess::Language) -> TreeSitterConfig { sub_languages: vec![], } } + #[cfg(feature = "lang-julia")] Julia => { let language_fn = tree_sitter_julia::LANGUAGE; let language = tree_sitter::Language::new(language_fn); @@ -843,6 +847,7 @@ fn build_config(language: guess::Language) -> TreeSitterConfig { sub_languages: vec![], } } + #[cfg(feature = "lang-ocaml")] OCaml => { let language_fn = tree_sitter_ocaml::LANGUAGE_OCAML; let language = tree_sitter::Language::new(language_fn); @@ -856,6 +861,7 @@ fn build_config(language: guess::Language) -> TreeSitterConfig { sub_languages: vec![], } } + #[cfg(feature = "lang-ocaml")] OCamlInterface => { let language_fn = tree_sitter_ocaml::LANGUAGE_OCAML_INTERFACE; let language = tree_sitter::Language::new(language_fn); @@ -961,6 +967,7 @@ fn build_config(language: guess::Language) -> TreeSitterConfig { sub_languages: vec![], } } + #[cfg(feature = "lang-qml")] Qml => { let language_fn = tree_sitter_qmljs::LANGUAGE; let language = tree_sitter::Language::new(language_fn); @@ -1265,6 +1272,7 @@ fn build_config(language: guess::Language) -> TreeSitterConfig { sub_languages: vec![], } } + #[cfg(feature = "lang-vhdl")] Vhdl => { let language_fn = tree_sitter_vhdl::LANGUAGE; let language = tree_sitter::Language::new(language_fn); diff --git a/tests/cli.rs b/tests/cli.rs index 7eff6f7ac..b1670166a 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -40,6 +40,18 @@ fn optional_languages_follow_build_features() { std::fs::write(&config, "[plugins]\norder = []\n").unwrap(); for (name, fixture, extension, enabled) in [ + ("Apex", "apex", "trigger", cfg!(feature = "lang-apex")), + ("Haskell", "haskell", "hs", cfg!(feature = "lang-haskell")), + ("Julia", "julia", "jl", cfg!(feature = "lang-julia")), + ("OCaml", "ocaml", "ml", cfg!(feature = "lang-ocaml")), + ( + "OCaml Interface", + "ocaml_interface", + "mli", + cfg!(feature = "lang-ocaml"), + ), + ("QML", "qml", "qml", cfg!(feature = "lang-qml")), + ("VHDL", "vhdl", "vhd", cfg!(feature = "lang-vhdl")), ("Fortran", "fortran", "f90", cfg!(feature = "lang-fortran")), ("Verilog", "verilog", "sv", cfg!(feature = "lang-verilog")), ("F#", "f_sharp", "fs", cfg!(feature = "lang-fsharp")),