Rule reference
v0.19.0Every rule the drenv language server applies, by feature. All of it is derived from the DragonRuby version your project runs — new engine, new intelligence, automatically.
The x.y.z+ tag on each rule is the drenv release it arrived in.
Completions
Sources are tried in order; the first that matches the receiver wins. Completions are generous — they may come from partial knowledge.
A constant receiver parsed from the installed engine's Ruby source — Geometry. and Easing. — completes with the method's signature and doc.
The full tree derived from the engine's docs and runtime source: args, args.inputs (+ keyboard, mouse, controller_one–four), args.outputs, args.audio, args.events, args.grid, args.layout, args.geometry, args.gtk. args.state / args.cvars / args.pixel_arrays appear as args. members but hold runtime/user-defined data, so they expose no static sub-members.
[1, 2]. → Array, "s". → String, {}. → Hash, 5. → Numeric, :s. → Symbol. Names come from a curated mruby baseline plus DragonRuby's own core-class extensions parsed from the engine (e.g. Array#map_2d).
Constructor-style class methods documented in the engine — Array.filter_map, Array.new — complete on the bare class.
A local typed by its assignment completes its class: enemies = [] → Array; @anim = Animation.new → the workspace class's methods (inherited through the superclass chain and included modules); @ivar assignments that all agree on one type; and a method receiver typed by its unique @return (camera.ui. → the ui method's return class). Inference stops after one hop.
h = { hp: 100 } → h. completes hp — DragonRuby patches Hash so h.hp reads h[:hp]. Keys list before the Hash methods; string keys are skipped (not dot-accessible).
include M mixes M's instance methods into the class — reachable on instances and as bare calls on self; extend M adds them as the class's singleton methods. Ancestry follows the superclass chain and includes recursively, unioned across every file that reopens the class.
A bare call (no receiver) completes only what Ruby could reach there: locals in scope, methods on self (the enclosing class, its superclass chain, and included modules) or defined at top level, and constants — not every method name in the workspace. A def's YARD doc rides the completion when the name is unambiguous.
Docs on hover
Resolution is ordered from most specific to least; the first match returns.
Geometry.distance and the args.* members show the exact markdown docs.dragonruby.org serves, matched to your installed engine version.
A method on a literal or typed core receiver ([1,2].each) shows the engine's Array#each doc.
@ivar / @@cvar show the class they belong to, and borrow the doc of a same-named attr_* in that class.
A parameter or local resolves to its method ("parameter of Class#method"); a parameter also shows its @param type and description from the method's doc block.
A bare constant resolves the way Ruby does — enclosing namespaces first, then top-level. Layout inside module Main sees Main::Layout / ::Layout, never an unrelated Conjuration::UI::Layout that merely shares the name.
Hovering a definition pins its qualified name and doc. A reopened name collapses to one entry; a genuinely ambiguous call lists candidates instead of guessing.
Comment blocks render as markdown: @param / @return / @yield / @yieldparam / @yieldreturn / @raise as typed sections, @note & @deprecated as callouts, @see and type references as links resolved namespace-relatively, @example as a fenced ruby block, unknown tags italicised, and RDoc +code+ as inline code.
Signature help
For engine methods with a parsed signature.
As you type arguments, the current parameter is highlighted — positional or keyword. Works on DragonRuby's paren-less call style, tracked from the syntax tree rather than counting commas.
Completions and hovers show the full signature, e.g. distance(point_one, point_two).
Diagnostics
Warnings fire only when the server owns the full surface — the receiver is an engine module and the arguments are statically known (a literal, or a one-hop literal variable). Performance hints are Information, never warnings. A squiggle means something is actually wrong.
tree-sitter error and missing nodes.
An unknown method on a fully-owned receiver (Geometry, Easing) — names the engine version. Array etc. have core methods beyond the documented set, so they get completions but never validity warnings.
Argument count outside the method's required..max range, quoting the signature. A trailing **opts splat and a collapsed trailing options-hash are handled.
A keyword the method doesn't accept — lists the accepted keywords. Label (anchor_x:) and hash-rocket (:anchor_x =>) forms both normalise.
A keyword parameter with no default that wasn't passed (suppressed when a **opts splat forwards keywords).
A hash-literal argument missing the geometric attributes the engine's own method body reads off that parameter (e.g. Geometry.distance reads .x/.y on both points). Extends to one-hop literal-hash variables; never to inferred or dispatched types.
Mutating a collection (delete/push/<</…) inside its own .each block. Collect changes and apply them after the loop.
outputs.<layer> << [ … ] renders an Array primitive; a Hash is faster.
Appending to outputs.<layer> once per loop iteration — build an Array and concatenate once.
A method that calls itself — deep recursion risks exhausting mruby's stack at 60fps.
A block-form .map standing as a non-final statement whose result is thrown away — .each expresses the intent.
Performance hints are softened from Information to Hint for methods provably invoked but never reachable from a tick (not hot per-frame). Methods on the tick call graph, or with no known callers, keep Information. Each links the engine's Troubleshoot Performance guide.
drenv.toml
Language service for the dependency manifest, from the CLI's schema.
Unknown keys, wrong value types, and malformed TOML surface as diagnostics (with best-effort positions), reusing the same schema drenv add / bundle enforce.
Section names ([package], [dependencies]) and keys (root, entrypoint, include, and dependency source specs) complete in context.
Principles behind the rules
- Engine-derived. Methods, docs, signatures, shapes, and guide links come from the installed engine — never a curated list, with one documented exception (the plain-mruby core baseline, since the engine ships only patches against it).
- Complete generously, warn conservatively. Completions may come from partial knowledge; a diagnostic requires owning the full surface and statically-known arguments.
- Inference stops at one hop. A receiver is typed from a single assignment or a single @return; that result is never re-fed to type a further hop.
- Dormant when irrelevant. Outside a DragonRuby project the server advertises no capabilities, so it's safe to enable for Ruby globally.