Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>clang biomeNew to Visual Studio Code? Get it now.
clang biome

clang biome

noname

| (0) | Free
clang biome
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Clang Biome

A lint and format extension for C written against Renesas RL78 / CC-RL conventions. It began as a port of the desktop application rl78-biome — the same 10 lint rules and the same 20 formatter rules, moved out of a Tauri window and onto VSCode's own diagnostic and formatting surfaces. The lint rules are still that port verbatim; several formatter rule bodies have since been changed deliberately, and the resulting behaviour is described under Formatting behaviour below.

Parsing is done with tree-sitter, so the rules act on a syntax tree rather than on regular expressions. Where the tree cannot be trusted — an RL78 SFR bit access such as P1.0 = 1; is not valid C and parses as an error node — the affected region is marked protected and left byte for byte as it was written.

Status

Pre-release. Not yet verified inside a VSCode extension host. Every rule and both surfaces are exercised by npm run probe, a plain-Node harness that runs the built dist/ bundle, but nobody has yet pressed F5 and confirmed the behaviour in a real editor window. Treat the settings below as implemented-and-unit-proven, not as field-tested.

What it does

Lint runs automatically. Editing a document schedules an analysis 500 ms after you stop typing; switching editors, changing a clangBiome.* setting, and activation each trigger one too. Results appear in the Problems panel. There is no command to run it manually yet.

Format is a whole-document formatter, so Shift+Alt+F and format-on-save both reach it. Range formatting is deliberately not offered: indent, align-comment, align-declarations and align-array-elements all reason about the whole document, and a selected fragment parsed on its own becomes error nodes that the RL78 guard would then refuse to touch.

The formatter declines to act, returning no edits at all, when the document is excluded, larger than 200 KB, empty or whitespace-only, or fails to parse. That size ceiling is lower than the 500 KB the linter uses, because formatting costs roughly 3.4 microseconds per byte and format-on-save is enabled by default: at 200 KB a save already pauses the editor for about three quarters of a second, and the pause is what the user feels, not the missing reformat. The reason is written to the Clang Biome output channel — a document that silently does not change is otherwise indistinguishable from one that had nothing to fix.

Lint rules

constant-upper-snake, func-name-uppercase-start, global-var-uppercase-start, if-else-requires-else, no-assign-in-condition, no-magic-number, require-comment-empty-block, switch-requires-default, switch-sequence-break — all default to warning.

var-prefix defaults to off, matching the source it was ported from.

Each rule is one setting taking off, warning or error; severity and enablement are not split across two keys.

Formatter rules

Twenty rules, each individually switchable: brace-style, break-if-conditions, collapse-blank-lines, indent, align-declarations, control-keyword-spacing, condition-paren-spacing, function-call-spacing, space-after-keyword, space-around-operator, pointer-asterisk-style, unary-tightness, array-subscript-tightness, space-after-comma, space-after-semicolon, hex-literal-case, align-array-elements, align-comment, trim-trailing-space, final-newline.

Indentation is tabs by default — one tab per level, and format.indent.width is then not consulted at all. Set format.indent.style to space to indent with that many spaces per level instead. A line the RL78 guard protects, such as one containing P1.0, keeps its original leading whitespace under either style, so an SFR line can look out of step with its neighbours; that is the guard working, not an indent bug.

The editor's own tabSize and insertSpaces are not consulted. Indentation has one owner here, and two settings surfaces competing over one output is worse than an inconsistency you can see.

Four rules carry an option of their own: format.indent.style (default tab) and format.indent.width (1–16, default 4), format.braceStyle (kr, allman, linux, default linux), format.alignComment.column (1–500, default 100) and format.breakIfConditions.minConditions (1–32, default 2).

Three rules are off by default: align-declarations and align-array-elements, as in rl78-biome, plus collapse-blank-lines, which rl78-biome runs but this extension does not — a run of blank lines you left between two functions is yours to keep.

Formatting behaviour

The points below are fixed behaviour, not settings — there is no key to turn any of them off.

  • A declaration's leading type, storage-class or qualifier keyword is separated from the next token by exactly one space: extern int x; becomes extern int x;, and a tab after a return type (void<TAB>aaa()) becomes void aaa(). The payload of a #define is never touched.
  • A parenthesized condition of exactly one token loses its interior padding — while( 1 ) becomes while(1), and if(flag) / switch(mode) stay tight. A condition of two tokens or more keeps the padding, so if( a == 1 ) is left as written.
  • else and else if start on a new line after the closing } (Stroustrup), in every brace style. Where the opening { goes is still format.braceStyle's decision.
  • break-if-conditions splits a condition of minConditions clauses or more across lines, indents each continuation one level deeper than the if, and no longer forces the body's { onto a line of its own — where that brace goes is format.braceStyle's decision like any other.
  • Under the default linux brace style a function definition's { goes on its own line while a control statement's { stays at the end of its line. kr puts both at the end of the line; allman puts both on their own line.
  • align-comment pads a trailing comment out to column 100 on the first pass and then leaves the line alone. Formatting an already-formatted document is a no-op, including for a comment trailing a preprocessor directive such as #define MAX 10 /* max */, which earlier grew by a few bytes on every save.

Notable settings

clangBiome.lint.excludeFiles defaults to ["iodefine.h"]. Removing that entry makes the Renesas SFR definition header report a wall of naming and magic-number diagnostics, because SFR-name exclusion is still a stub in this version.

An invalid value never disables the extension. Each setting falls back on its own, and the reason is written to the output channel; one mistyped value does not drag the rest of the configuration back to defaults with it.

Building

npm install
npm run compile     # webpack -> dist/extension.js, plus the tree-sitter wasm
npm run probe       # plain-Node evidence harness over the built dist/

The two .wasm files are read from disk as byte arrays and handed to Language.load. Loading them by URL — which is what rl78-biome did from its WebView — does not work in a target: 'node' extension bundle.

Not implemented yet

A clangBiome.lintWorkspace command, a toggle command with a keybinding, and .vsix packaging. Range formatting is not planned.

License

MIT

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft