Repository navigation
Conversation
…ansform check GritQL metavariables cannot bind implements clauses, so decorator+class matching was impossible for implements-classes. Match the @pipe decorator and require the file to reference PipeTransform instead — covers export, extends, and implements-other class shapes. The rule now actually fires on real Angular code (it previously never matched exported classes).
Decorator+class snippets never matched exported classes because GritQL treats the export modifier as part of the statement; add export class variants. Align semantics with @angular-eslint: @Injectable and @pipe only support ngOnDestroy; @component and @directive support all hooks (directives do receive view hooks). Detect hooks as bare identifiers so any signature shape matches (: void, async, parameters).
Only flag classes decorated with @component. Plain TS classes ending in Component (e.g. React or shared code in a monorepo) are no longer flagged. Uses export-aware decorator+class patterns including extends variants.
Only flag classes decorated with @directive, using export-aware decorator+class patterns including extends variants.
Only flag classes decorated with @Injectable. NestJS services and plain TS classes ending in Service are no longer flagged. Uses export-aware decorator+class patterns including extends variants.
Only flag constructor parameter properties inside @Component/@Directive/ @Injectable/@pipe classes. Plain TS classes using parameter properties for values (and NestJS constructor DI) are no longer flagged.
Since Angular 19 standalone is the default and the v20 style guide recommends omitting the property, so flagging its absence produced an error on every idiomatic modern component, directive, and pipe.
GritQL cannot compare list order, so the rule could only detect the presence of NgModule metadata arrays and fired on every NgModule — including sorted and empty arrays — while its message claimed the array was unsorted. The upstream @angular-eslint rule was likewise deprecated and removed. Tracked as skipped in rules-to-migrate.json.
…param) shapes
The CLI generates ngOnInit(): void {} — the exact form the rule missed.
Add return-type variants for every hook and parameterized variants for
ngOnChanges, the only hook that takes an argument.
Implement the input/output pairing the doc always described: capture the output base name via regex and require a matching @input() in the file. Unpaired *Change outputs (Material-style events) are no longer flagged.
Biome has no linter.rules.plugins key — configs generated by init/merge were rejected with 'unknown key' and severity per rule can only be set inside each .grit via register_diagnostic. init now writes plugins: ['./node_modules/biome-plugin-angular'] (plugin entries are paths relative to the config, verified against the packed tarball, and extends of the preset resolves them from the project root). The strict preset is removed since severity differentiation is impossible; remove cleans up the invalid key written by earlier versions.
…endency The rules CLI command reads rules-to-migrate.json but the file was excluded from the npm tarball (verified crash on the installed package), and all README rule-doc links 404'd on npmjs.com without docs/. Declare @biomejs/biome >=2.4.8 <3 as a peer dependency instead of only a dev dependency, and drop the reference to a schema file that never existed.
The runner returned an empty diagnostics array when biome crashed or produced unparseable output, letting every 'valid' test pass vacuously. Throw instead, and reject non-plugin diagnostics (parse/config errors) so a broken fixture can never masquerade as a passing test.
Packs the plugin as npm would publish it, installs it into a fresh project, and lints through every documented onboarding path: direct plugins entry, cli init, and extends of the preset. This is the only test that exercises biome-manifest.jsonc resolution and the package files whitelist — all other tests load .grit files directly.
CI never ran the integration suite — the only tests exercising the real biome binary. Add it to the test matrix plus a non-blocking job against @biomejs/biome@latest as an early warning for upstream changes. The release workflow published on tag push with plain npm publish and the archived actions/create-release, while package.json configured semantic-release that nothing ever invoked — so CHANGELOG.md stayed empty and versions never bumped. Release now runs semantic-release on push to main after the full test suite.
The ts-morph pattern-matcher had drifted from the GritQL rules in both directions, certifying behavior the plugin does not have. Relabel it as the reference-semantics spec (integration tests on the real binary are the authority), delete the sort-ngmodule matcher, align prefer-standalone (only standalone: false), contextual-lifecycle (upstream semantics), and pipe-prefix (prefix must be followed by an uppercase letter).
…tions README now shows the only valid configs (plugins path or extends of the preset), documents that severities are fixed in the .grit files, drops the removed strict preset and sort-ngmodule rule, and replaces the 'heuristic/non-functional' caveats with the real remaining limitations (implements clauses and readonly properties, both pinned by it.fails tests). CLAUDE.md gets the verified GritQL pattern-writing rules. Track the three suffix rules in rules-to-migrate.json.
The implements-clause branches (over half the rule) never matched — GritQL cannot bind an implements clause — so any class with an implements clause was invisible, including the partial-implements case the rule exists for. Match each lifecycle method instead and require the corresponding interface to be referenced in the file. Diagnostics now name the exact missing interface. Also matches : void and parameterized ngOnChanges signatures.
…ures Every violation test now asserts on the diagnostic message, not just the count. New fixtures: attribute and multi-selector components, alias options objects, transform inputs, readonly outputs and queries, getter host bindings, setter inputs, and partial-implements lifecycle classes. Known engine gaps (multi-selector false positive, per-file interface check) are pinned with it.fails sentinels that flip when Biome lifts the limitation.
Every doc now shows the only valid Biome config, states the fixed severity from its .grit, and documents the real matching semantics: flipped prefer-standalone, functional contextual-lifecycle and use-pipe-transform-interface, decorator gating, per-file checks, and the implements/readonly engine limitations. Removed the fictional configurable-prefix claims and an unverifiable schematic reference.
All 109 integration tests pass unchanged on 2.5.5. Migrate the repo config (rules.recommended -> preset). Test-runner configs keep the deprecated rules.recommended form, the only shape valid on both the 2.4.8 peer-dependency floor and current releases. 2.5.0+ also unlocks fixable GritQL diagnostics and per-plugin file scoping for future use.
Snippet patterns only matched the exact shape they spelled out: a decorated class with an implements clause, a readonly member, or a method with an override modifier was invisible. On a CLI-generated Angular app every component implements OnInit, so the suffix rules, contextual-lifecycle and prefer-inject-function missed most real code. Rules now match through Biome's native AST nodes (JsClassDeclaration, JsExport, JsPropertyClassMember, JsMethodClassMember...), which expose decorators, implements clauses, modifiers and members as fields. Effects: - implements, extends, generics and export default classes are matched - readonly properties are matched - use-lifecycle-interface and use-pipe-transform-interface check the implements clause of each class instead of the whole file - prefer-inject-function flags every constructor parameter of a decorated class, like @angular-eslint/prefer-inject, not only parameter properties - no-input-rename / no-output-rename / no-output-on-prefix cover the input(), model(), output() and outputFromObservable() functions - component-selector accepts comma-separated selector lists - every message starts with "[rule-name]" so the suppression name (lint/plugin/rule-name) is discoverable; metavariables are not interpolated in messages The it.fails sentinels for these engine limitations now pass and were flipped to regular tests. The test runner enables unsafeParameterDecoratorsEnabled, which Angular constructors need.
Biome 2.5 plugins can rewrite code. The empty hook is deleted with a safe fix (biome lint --write) when the class does not implement the matching interface. When it does, deleting the method alone fails compilation with TS2420, so that case only reports and asks to remove both. Biome pairs rewrites with diagnostics by order of appearance in the file, so a single pattern cannot mix fixable and non-fixable branches: the rule is split in two files with the same stem, which Biome loads under one plugin name (one suppression name for users). The rule also moved to the native method node, so hooks with modifiers (protected override, async) and comment-only bodies are matched.
Port of @angular-eslint/directive-selector with the Angular CLI defaults: camelCase attribute selector with the app prefix. Comma-separated lists are accepted when every entry is valid.
Port of @angular-eslint/no-output-native. Covers @output() on every property shape (readonly included) and the output()/outputFromObservable() functions.
Port of @angular-eslint/no-conflicting-lifecycle: ngDoCheck and ngOnChanges must not be declared on the same class.
Port of @angular-eslint/no-lifecycle-call. Explicit hook calls are flagged; super.ngXxx() chaining is allowed.
Port of @angular-eslint/no-async-lifecycle-method. The async keyword is detected on the method text so every modifier combination is covered.
Port of @angular-eslint/no-pipe-impure: flags @pipe({ pure: false }).
Port of @angular-eslint/no-attribute-decorator, pointing to inject(new HostAttributeToken()) (Angular 17.4+).
Two default Biome settings break real Angular projects: - parameter decorators (@Inject, @optional, @Attribute...) are a parse error unless javascript.parser.unsafeParameterDecoratorsEnabled is on, and Biome skips the whole file - the recommended style/useImportType safe fix rewrites tokens that are only used as constructor parameter types to import type, after which the Angular build fails with NG2003 (no suitable injection token) The preset now sets both, scopes the plugin to **/*.ts minus spec files, and the CLI writes/merges/removes an extends entry pointing at it instead of a bare plugins path. The consumer smoke test covers the CLI round trip, parameter decorators, the absence of import type rewrites, the safe fix through the packed package, and the spec exclusion.
Native AST node patterns and plugin rewrites both need Biome 2.5.0, so the peer range moves from >=2.4.8 to >=2.5.0. Development and schemas move to 2.5.12. A CI job runs the integration suite against 2.5.0 so the peer range stays honest; the latest-Biome job remains as an early warning.
…rn rules README: preset rationale (parameter decorators, useImportType), the [rule-name] message prefix and where a biome-ignore comment must sit for a decorated class, the fix policy and the official schematics for the larger migrations, Angular 17-22, the seven new rules, and the Biome caveat on per-file rewrites. CONTRIBUTING and CLAUDE.md: native AST node patterns are the way to match classes and members; verified engine rules (full-match regex, static messages, unreliable pattern definitions, rewrite ordering, same-stem split for conditional fixes).
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment Thanks for integrating Codecov - We've got you covered ☂️ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Superseded by a new pull request from the same branch.