Rust Rules
This guide shows how to write a native Rust rule, build it as a shared library, and run it with Golar on both .ts and .vue files.
You will build a rust/unsafe-calls rule that reports any call where the called value has type any, then run it on the example files.
Install Dependencies
Section titled “Install Dependencies”This example uses Vue so the same rule runs on a plain TypeScript file and an embedded-language file.
npm i -D golar @golar/vue vuepnpm add -D golar @golar/vue vueyarn add -D golar @golar/vue vueMake sure Rust and Cargo are installed before continuing.
Create Example Files
Section titled “Create Example Files”Create index.ts:
export declare const fn: any
fn()Create index.vue:
<script lang="ts" setup> import { fn } from './index.ts'</script>
<template> {{ fn() }}</template>Create the Addon Crate
Section titled “Create the Addon Crate”Create rust-addon/Cargo.toml:
[package]name = "my_golar_rule"version = "0.1.0"edition = "2024"
[lib]crate-type = ["cdylib"]Add dependencies:
cargo add golarcargo add --build napi-buildCreate rust-addon/build.rs:
fn main() { napi_build::setup();}Create rust-addon/src/lib.rs:
use golar::*;
fn run<'a>(ctx: &RuleContext<'a>) { walk(ctx.source_file.as_node(), &mut |node: Node<'_>| { if let Some(call) = node.cast::<CallExpression>() { check_call(ctx, call); }
false });}
fn check_call<'a>(ctx: &RuleContext<'a>, node: CallExpression<'a>) {
let Some(typ) = node .expression() .and_then(|expression| ctx.program.get_type_at_location(&expression)) else { return; };
if let Some(t) = typ.cast::<IntrinsicType>() && t.intrinsic_name() == "any" { ctx.report_node(node.as_node(), "Unsafe any call."); }}
inventory::submit! { Rule { name: "rust/unsafe-calls", run, }}This rule does the same work as the JavaScript example: walk the AST, get the type of each called expression, and report an error when that type is any.
The rule name in inventory::submit! must match the name you register in golar.config.ts.
Register the Rule
Section titled “Register the Rule”Create golar.config.ts:
import path from 'node:path'import process from 'node:process'
import { defineConfig, defineNativeRule } from 'golar/unstable'import '@golar/vue'
const addonFilename = process.platform === 'win32' ? 'my_golar_rule.dll' : process.platform === 'darwin' ? 'libmy_golar_rule.dylib' : 'libmy_golar_rule.so'const addonPath = path.join( import.meta.dirname, 'rust-addon', 'target', 'debug', addonFilename,)
export default defineConfig({ lint: { use: [ { files: ['index.ts', 'index.vue'], rules: [ defineNativeRule({ addonPath, name: 'rust/unsafe-calls', }), ], }, ], },})Build the Addon
Section titled “Build the Addon”cargo build --manifest-path rust-addon/Cargo.tomlThat produces the shared library that defineNativeRule(...) loads.
Run the Rule
Section titled “Run the Rule”Run Golar in the default mode:
npx golarpnpm golaryarn golarYou should see rust/unsafe-calls errors for both index.ts and index.vue.