Skip to content

Conversation

@pchorus
Copy link

@pchorus pchorus commented Oct 26, 2025

This PR adds support for Angular ESLint rules according to angular-eslint/angular-eslint.

It also implements first recommended rule prefer-standalone.

@pchorus pchorus requested a review from camc314 as a code owner October 26, 2025 20:31
@graphite-app
Copy link
Contributor

graphite-app bot commented Oct 26, 2025

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

@github-actions github-actions bot added A-linter Area - Linter A-cli Area - CLI labels Oct 26, 2025
@camc314
Copy link
Contributor

camc314 commented Oct 26, 2025

I think this would be better as an external plugin? Does the angular eslint plugin not work with oxlint?

if !bool_value.value {
ctx.diagnostic_with_suggestion(
prefer_standalone_diagnostic(prop.span()),
|fixer| fixer.replace(prop.span(), ""),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The auto-fix produces invalid JavaScript syntax. When removing standalone: false, from the middle of an object, it leaves a leading comma on the next property. The test expectations show this bug:

@Component({
    ,  // <- Invalid syntax!
    template: '<div></div>'
})

Fix: The fixer needs to handle comma removal properly. Replace with logic that removes the property along with its trailing comma, or if it's the last property, remove it along with the preceding comma.

Suggested change
|fixer| fixer.replace(prop.span(), ""),
|fixer| {
// Get the text of the entire file
let source = fixer.source_text();
let span = prop.span();
// Find the next non-whitespace character after the property
let mut end = span.end;
while end < source.len() && (source.as_bytes()[end] as char).is_whitespace() {
end += 1;
}
// If the next character is a comma, include it in the removal
if end < source.len() && source.as_bytes()[end] as char == ',' {
end += 1;
fixer.replace(oxc_span::Span::new(span.start, end), "")
} else {
// Otherwise, look for a preceding comma
let mut start = span.start;
while start > 0 && (source.as_bytes()[start - 1] as char).is_whitespace() {
start -= 1;
}
// If there's a comma before the property, remove it too
if start > 0 && source.as_bytes()[start - 1] as char == ',' {
start -= 1;
fixer.replace(oxc_span::Span::new(start, span.end), "")
} else {
fixer.replace(span, "")
}
}
},

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Comment on lines +98 to +101
const ANGULAR_TEST_PATH: &str =
"https://raw.githubusercontent.com/angular-eslint/angular-eslint/tree/main/packages/eslint-plugin/tests/rules";
const ANGULAR_RULES_PATH: &str =
"https://raw.githubusercontent.com/angular-eslint/angular-eslint/tree/main/packages/eslint-plugin/src/rules";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The URLs contain /tree/main/ which is incorrect for raw.githubusercontent.com. This path segment is only used in the GitHub web interface, not for raw content access. These URLs will return 404 errors when the rule generator tries to fetch documentation.

Fix: Remove /tree from the URLs:

const ANGULAR_TEST_PATH: &str =
    "https://raw.githubusercontent.com/angular-eslint/angular-eslint/main/packages/eslint-plugin/tests/rules";
const ANGULAR_RULES_PATH: &str =
    "https://raw.githubusercontent.com/angular-eslint/angular-eslint/main/packages/eslint-plugin/src/rules";
Suggested change
const ANGULAR_TEST_PATH: &str =
"https://raw.githubusercontent.com/angular-eslint/angular-eslint/tree/main/packages/eslint-plugin/tests/rules";
const ANGULAR_RULES_PATH: &str =
"https://raw.githubusercontent.com/angular-eslint/angular-eslint/tree/main/packages/eslint-plugin/src/rules";
const ANGULAR_TEST_PATH: &str =
"https://raw.githubusercontent.com/angular-eslint/angular-eslint/main/packages/eslint-plugin/tests/rules";
const ANGULAR_RULES_PATH: &str =
"https://raw.githubusercontent.com/angular-eslint/angular-eslint/main/packages/eslint-plugin/src/rules";

Spotted by Graphite Agent

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@pchorus
Copy link
Author

pchorus commented Oct 26, 2025

@TheAlexLichter Here is the PR as discussed.

@pchorus pchorus changed the title 10 24 feat linter angular prefer standalone feat(linter): add plugin for angular and implement rule prefer standalone Oct 26, 2025
@github-actions github-actions bot added the C-enhancement Category - New feature or request label Oct 26, 2025
@pchorus pchorus mentioned this pull request Oct 27, 2025
@pchorus pchorus force-pushed the 10-24-feat_linter_angular_prefer_standalone branch from 5e90396 to 03d3d4d Compare October 27, 2025 20:32
@pchorus
Copy link
Author

pchorus commented Oct 27, 2025

I think this would be better as an external plugin? Does the angular eslint plugin not work with oxlint?

I will check.

@pchorus
Copy link
Author

pchorus commented Oct 27, 2025

I think this would be better as an external plugin? Does the angular eslint plugin not work with oxlint?

I tried to use oxlint with the angular-eslint package containing the eslint plugin in some of my Angular projects.
I created the .oxlintrc.json containing

{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "plugins": [],
  "jsPlugins": ["angular-eslint"],
...
}

When running oxlint I get the following error:

WARNING: JS plugins are experimental and not subject to semver.
Breaking changes are possible while JS plugins support is under development.
Failed to parse configuration file.

  × Failed to load JS plugin: angular-eslint
  │   TypeError: Cannot read properties of undefined (reading 'name')
  │     at loadPluginImpl (file:///xxxxxx/xxxxxx/development/and-action/node_modules/oxlint/dist/plugins.js:820:31)
  │     at async loadPlugin (file:///xxxxxx/xxxxxx/development/and-action/node_modules/oxlint/dist/plugins.js:810:13)

@camc314 What do you mean by "external plugin"? Do you refer to the current ESLint plugin?

@Sysix
Copy link
Member

Sysix commented Oct 28, 2025

@pchorus it should be @angular/eslint-plugin, but we there are some resolving name problems, which will be fixed with: #15010

@camc314
Copy link
Contributor

camc314 commented Oct 29, 2025

yeah, by external, i mean not built into oxlint e.g. JS plugin

Let see in the next release (later today) if it's working as expected, and go from there

@pchorus
Copy link
Author

pchorus commented Oct 29, 2025

@camc314 Sounds good. As soon as the new version is released I will give it a try.

Anyways, that means that rules for Angular are still written in JS. So my understanding is that migrating them to Rust would make all of them faster as well.

Are there any plans to include more JS-based rules into Rust?
Do you plan to allow external plugins written in Rust?

I would try to help with some stuff since most projects I work on are Angular projects and I would be happy to use Oxlint instead of ESLint.

@pchorus
Copy link
Author

pchorus commented Oct 30, 2025

yeah, by external, i mean not built into oxlint e.g. JS plugin

Let see in the next release (later today) if it's working as expected, and go from there

@camc314 Now it seems to work as expected with @angular-eslint/eslint-plugin. 👍🏻
I still have the question from my comment above on what do you think about migrating Angular rules to Rust somehow.

@camc314
Copy link
Contributor

camc314 commented Oct 30, 2025

@camc314 Now it seems to work as expected with @angular-eslint/eslint-plugin. 👍🏻

awesome, i'm glad it's working

Anyways, that means that rules for Angular are still written in JS. So my understanding is that migrating them to Rust would make all of them faster as well.

Yes, migrating the angular rules to rust would likley improve performance.

Are there any plans to include more JS-based rules into Rust?

Not at this time, once custom JS plugins and type aware linting is more stable, we may re-evaluate. The main reasoning for this is just the high maintence burden of supporting more plugins when the JS version is probably fast enough for most people's use cases. That said, if demand for a particular plugin is incredibly high, we may re-evaluate that decision.

Do you plan to allow external plugins written in Rust?

This is a more complex topic, we're hoping that custom JS plugins with raw transfer will be fast enough such that we don't need to build out a rust based plugin system.

@camc314
Copy link
Contributor

camc314 commented Oct 30, 2025

Thanks for working on this, and for using oxlint, but i'm going to close this for now.

@camc314 camc314 closed this Oct 30, 2025
@pchorus
Copy link
Author

pchorus commented Oct 30, 2025

@camc314 Thank you for sharing some insights about your plans and your point of view.
That sounds absolutely reasonable to me.

Thanks for working on this, and for using oxlint, but i'm going to close this for now.

Sure, thanks for your support.
I will check if I can possibly contribute to other oxlint regarding topics that actually help pushing it forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area - CLI A-linter Area - Linter C-enhancement Category - New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants