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

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