Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(js-api): support applying lint fixes #1956

Merged
merged 9 commits into from
Mar 19, 2024

Conversation

mnahkies
Copy link
Contributor

@mnahkies mnahkies commented Mar 2, 2024

Summary

I've recently switched to using biome programmatically to format code before writing it to disk it in a code generation project

I was experimenting with the idea of having it additionally lint the files, but noticed there was no way to apply lint fixes without resorting to using private API's currently.

This aims to allow applying the fixes, following a similar API to that of formatContent

Note
I've not tried to implement a "fix range" option - as far as I can see that isn't something that is directly supported by the underlying analyzer.

It might be possible to implement using code_actions and filtering for those with a suggestion constrained by span? Probably more work than I have time to attempt at the moment though.

Test Plan

Unit tests demonstrate that the change is backwards compatible, and works.

Copy link

netlify bot commented Mar 2, 2024

Deploy Preview for biomejs ready!

Name Link
🔨 Latest commit 871665f
🔍 Latest deploy log https://app.netlify.com/sites/biomejs/deploys/65f94b9ad00dc60008a6da1c
😎 Deploy Preview https://deploy-preview-1956--biomejs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 95 (🔴 down 5 from production)
Accessibility: 97 (no change from production)
Best Practices: 100 (no change from production)
SEO: 93 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify site configuration.

@mnahkies mnahkies changed the title feat: support applying lint fixes when using js-api feat(js-api): support applying lint fixes Mar 2, 2024
path,
categories: ["Syntax", "Lint"],
max_diagnostics: Number.MAX_SAFE_INTEGER,
});

const hasErrors = diagnostics.some(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm unsure about this part - it would be great to get some guidance from someone more familiar with the biome code base here

Copy link
Member

Choose a reason for hiding this comment

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

Fixing a file, actually, works backwords: first you fix the file, then you pull the diagnostics.

Why? Because when fixing a file, you actually end reducing the diagnostics by applying the fixes. This means we need to pull the diagnostics after we fixed the file, to show the users any remaining diagnostics.

That's what we do in the CLI:

if let Some(fix_mode) = ctx.execution.as_fix_file_mode() {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That makes perfect sense, I'll go ahead and make that change.

I'm surprised we don't need to do the same in formatContent above? Though a quick test I see that I get back an [] for diagnostics - does the formatter simply not emit warning / information diagnostics on unformatted files?

Copy link
Member

@ematipico ematipico Mar 9, 2024

Choose a reason for hiding this comment

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

Formatting has different expectations and requirements.

Usually, formatters can't format broken syntax, that's why we need to check for parsing errors before running the formatter.

Same goes for broken syntax in Biome, broken blocks are kept verbatim, only blocks that are synaptically correct.

Given the previous statement, it's safe to assume that formatters don't emit new syntax/parse diagnostics, because there weren't any before. If they do, that's a bug in the formatter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess I naively would've expected that pulling diagnostics prior to formatting the file would've come back with the details of where it wasn't formatted correctly, and that after these issues would be gone (leaving only issues that couldn't be fixed from syntax errors, etc) - though I didn't consider that we'd just skip formatting in the presence of syntax errors, presumably to avoid making the errors worse.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(fixed in 139c3dc)

path,
categories: ["Syntax", "Lint"],
max_diagnostics: Number.MAX_SAFE_INTEGER,
});

const hasErrors = diagnostics.some(
Copy link
Member

Choose a reason for hiding this comment

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

Fixing a file, actually, works backwords: first you fix the file, then you pull the diagnostics.

Why? Because when fixing a file, you actually end reducing the diagnostics by applying the fixes. This means we need to pull the diagnostics after we fixed the file, to show the users any remaining diagnostics.

That's what we do in the CLI:

if let Some(fix_mode) = ctx.execution.as_fix_file_mode() {

Comment on lines 32 to 76
it("should fix lint issues and return new content if fileFileMode is SafeAndUnsafeFixes", () => {
const result = biome.lintContent('let a = "foo " + Date.now() + " bar"', {
filePath: "example.js",
fixFileMode: "SafeAndUnsafeFixes",
});

expect(result.content).toMatchSnapshot("fixed content");
});
Copy link
Member

Choose a reason for hiding this comment

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

We should add another test. A content that contains code that triggers a safe and unsafe fix, and then attempt to fix only the safe fixes.

Then, should assert that:

  • we fixed only the safe fix
  • there's still a diagnostic about the the rule that triggered the unsafe fix

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 6793ae0

@ematipico
Copy link
Member

Requested some changes because the logic of fixing a file should work the other way around:

  1. fix a file
  2. pull diagnostics

@mnahkies mnahkies force-pushed the mn/feat/support-applying-lint-js-api branch from 7ed1421 to 6793ae0 Compare March 9, 2024 08:06
const result = biome.lintContent(inputCode, {
filePath: "example.js",
});
expect(result.diagnostics).toMatchObject([
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've changed the assertions on diagnostics to just check the category instead of using snapshots - I felt this was more maintainable, but happy to change back if you disagree

@mnahkies mnahkies requested a review from ematipico March 9, 2024 08:09
@mnahkies mnahkies force-pushed the mn/feat/support-applying-lint-js-api branch from 6793ae0 to 139c3dc Compare March 12, 2024 07:20
Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

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

Looks good! Just a small nit to appress, if you could. Feel free to add a changelog entry


return { content: code };
})
: { content };
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason why we create a new object, instead of just returning content?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair point, object removed in 4a68be0

Changelog updated in 871665f

@github-actions github-actions bot added A-Website Area: website A-Changelog Area: changelog labels Mar 19, 2024
@ematipico ematipico merged commit 58974c9 into biomejs:main Mar 19, 2024
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Changelog Area: changelog A-Website Area: website
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants