From 216b39c04b5e064494b805e58b436ffcf8ee18b1 Mon Sep 17 00:00:00 2001 From: msdlisper <1170167213@qq.com> Date: Sat, 28 Oct 2023 21:40:16 +0800 Subject: [PATCH 1/9] fix: bug with useContext/useSyncExternalStore (#609) --- .../use_exhaustive_dependencies.rs | 3 -- .../useExhaustiveDependencies/valid.js | 13 +++++-- .../useExhaustiveDependencies/valid.js.snap | 14 ++++++-- .../rules/use-exhaustive-dependencies.md | 35 +++++++++---------- 4 files changed, 39 insertions(+), 26 deletions(-) diff --git a/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs b/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs index bf6f368ffb96..f7de9dc08021 100644 --- a/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs +++ b/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs @@ -207,9 +207,6 @@ impl Default for ReactExtensiveDependenciesOptions { StableReactHookConfiguration::new("useReducer", Some(1)), StableReactHookConfiguration::new("useTransition", Some(1)), StableReactHookConfiguration::new("useRef", None), - StableReactHookConfiguration::new("useContext", None), - StableReactHookConfiguration::new("useId", None), - StableReactHookConfiguration::new("useSyncExternalStore", None), ]); Self { diff --git a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js index 5c84dd763152..9574877a4de8 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js +++ b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js @@ -1,7 +1,7 @@ /* should not generate diagnostics */ import React from "react"; -import { useEffect } from "react"; +import { useEffect, useSyncExternalStore } from "react"; import doSomething from 'a'; // No captures @@ -62,7 +62,7 @@ function MyComponent4() { console.log(id); console.log(externalStore); - }, [name, state, memoizedCallback, memoizedValue, isPending]); + }, [name, state, memoizedCallback, memoizedValue, isPending, externalStore, id, theme]); } // all hooks with dependencies @@ -167,3 +167,12 @@ function MyComponent16() { console.log(a); }, [a]); } + +// https://github.com/biomejs/biome/issues/609 +function MyComponent17() { + const data = useSyncExternalStore(subscribe, getSnapshot); + + useEffect(() => { + console.log(data); + }, [data]); +} diff --git a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js.snap b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js.snap index 5171784a7ea9..3a31d3b0c001 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js.snap @@ -1,5 +1,6 @@ --- source: crates/biome_js_analyze/tests/spec_tests.rs +assertion_line: 83 expression: valid.js --- # Input @@ -7,7 +8,7 @@ expression: valid.js /* should not generate diagnostics */ import React from "react"; -import { useEffect } from "react"; +import { useEffect, useSyncExternalStore } from "react"; import doSomething from 'a'; // No captures @@ -68,7 +69,7 @@ function MyComponent4() { console.log(id); console.log(externalStore); - }, [name, state, memoizedCallback, memoizedValue, isPending]); + }, [name, state, memoizedCallback, memoizedValue, isPending, externalStore, id, theme]); } // all hooks with dependencies @@ -174,6 +175,15 @@ function MyComponent16() { }, [a]); } +// https://github.com/biomejs/biome/issues/609 +function MyComponent17() { + const data = useSyncExternalStore(subscribe, getSnapshot); + + useEffect(() => { + console.log(data); + }, [data]); +} + ``` diff --git a/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md b/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md index 0e30387ccba4..7d85f57acf40 100644 --- a/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md +++ b/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md @@ -23,14 +23,11 @@ The rule will inspect the following **known** hooks: - `useMemo` - `useImperativeHandle` - `useState` -- `useContext` - `useReducer` - `useRef` - `useDebugValue` - `useDeferredValue` - `useTransition` -- `useId` -- `useSyncExternalStore` If you want to add more hooks to the rule, check the [#options](options). @@ -52,23 +49,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook does not specify all of its dependencies.
-  
+
     3 │ function component() {
     4 │     let a = 1;
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │         console.log(a);
     7 │     });
-  
+
    This dependency is not specified in the hook dependency list.
-  
+
     4 │     let a = 1;
     5 │     useEffect(() => {
   > 6 │         console.log(a);
                        ^
     7 │     });
     8 │ }
-  
+
 
```jsx @@ -84,23 +81,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook specifies more dependencies than necessary.
-  
+
     3 │ function component() {
     4 │     let b = 1;
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │     }, [b]);
     7 │ }
-  
+
    This dependency can be removed from the list.
-  
+
     4 │     let b = 1;
     5 │     useEffect(() => {
   > 6 │     }, [b]);
            ^
     7 │ }
     8 │ 
-  
+
 
```jsx @@ -118,23 +115,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook specifies more dependencies than necessary.
-  
+
     3 │ function component() {
     4 │     const [name, setName] = useState();
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │         console.log(name);
     7 │         setName("");
-  
+
    This dependency can be removed from the list.
-  
+
      6 │         console.log(name);
      7 │         setName("");
    > 8 │     }, [name, setName]);
                   ^^^^^^^
      9 │ }
     10 │ 
-  
+
 
```jsx @@ -152,23 +149,23 @@ function component() {
correctness/useExhaustiveDependencies.js:6:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook does not specify all of its dependencies.
-  
+
     4 │     let a = 1;
     5 │     const b = a + 1;
   > 6 │     useEffect(() => {
        ^^^^^^^^^
     7 │         console.log(b);
     8 │     });
-  
+
    This dependency is not specified in the hook dependency list.
-  
+
     5 │     const b = a + 1;
     6 │     useEffect(() => {
   > 7 │         console.log(b);
                        ^
     8 │     });
     9 │ }
-  
+
 
## Valid From 106c23f3bf2e703444cb5294bf7a2b7c3f3a676b Mon Sep 17 00:00:00 2001 From: msdlisper <1170167213@qq.com> Date: Sat, 28 Oct 2023 22:21:35 +0800 Subject: [PATCH 2/9] docs: update docs (#609) --- .../use_exhaustive_dependencies.rs | 9 ------ .../rules/use-exhaustive-dependencies.md | 32 +++++++++---------- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs b/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs index f7de9dc08021..adb8c4b85d6a 100644 --- a/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs +++ b/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs @@ -36,14 +36,11 @@ declare_rule! { /// - `useMemo` /// - `useImperativeHandle` /// - `useState` - /// - `useContext` /// - `useReducer` /// - `useRef` /// - `useDebugValue` /// - `useDeferredValue` /// - `useTransition` - /// - `useId` - /// - `useSyncExternalStore` /// /// If you want to add more hooks to the rule, check the [#options](options). /// @@ -180,7 +177,6 @@ impl Default for ReactExtensiveDependenciesOptions { ("useMemo".to_string(), (0, 1).into()), ("useImperativeHandle".to_string(), (1, 2).into()), ("useState".to_string(), ReactHookConfiguration::default()), - ("useContext".to_string(), ReactHookConfiguration::default()), ("useReducer".to_string(), ReactHookConfiguration::default()), ("useRef".to_string(), ReactHookConfiguration::default()), ( @@ -195,11 +191,6 @@ impl Default for ReactExtensiveDependenciesOptions { "useTransition".to_string(), ReactHookConfiguration::default(), ), - ("useId".to_string(), ReactHookConfiguration::default()), - ( - "useSyncExternalStore".to_string(), - ReactHookConfiguration::default(), - ), ]); let stable_config = FxHashSet::from_iter([ diff --git a/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md b/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md index 7d85f57acf40..8df5e9fb8f87 100644 --- a/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md +++ b/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md @@ -49,23 +49,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook does not specify all of its dependencies.
-
+  
     3 │ function component() {
     4 │     let a = 1;
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │         console.log(a);
     7 │     });
-
+  
    This dependency is not specified in the hook dependency list.
-
+  
     4 │     let a = 1;
     5 │     useEffect(() => {
   > 6 │         console.log(a);
                        ^
     7 │     });
     8 │ }
-
+  
 
```jsx @@ -81,23 +81,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook specifies more dependencies than necessary.
-
+  
     3 │ function component() {
     4 │     let b = 1;
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │     }, [b]);
     7 │ }
-
+  
    This dependency can be removed from the list.
-
+  
     4 │     let b = 1;
     5 │     useEffect(() => {
   > 6 │     }, [b]);
            ^
     7 │ }
     8 │ 
-
+  
 
```jsx @@ -115,23 +115,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook specifies more dependencies than necessary.
-
+  
     3 │ function component() {
     4 │     const [name, setName] = useState();
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │         console.log(name);
     7 │         setName("");
-
+  
    This dependency can be removed from the list.
-
+  
      6 │         console.log(name);
      7 │         setName("");
    > 8 │     }, [name, setName]);
                   ^^^^^^^
      9 │ }
     10 │ 
-
+  
 
```jsx @@ -149,23 +149,23 @@ function component() {
correctness/useExhaustiveDependencies.js:6:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook does not specify all of its dependencies.
-
+  
     4 │     let a = 1;
     5 │     const b = a + 1;
   > 6 │     useEffect(() => {
        ^^^^^^^^^
     7 │         console.log(b);
     8 │     });
-
+  
    This dependency is not specified in the hook dependency list.
-
+  
     5 │     const b = a + 1;
     6 │     useEffect(() => {
   > 7 │         console.log(b);
                        ^
     8 │     });
     9 │ }
-
+  
 
## Valid From 73c758157f1f06359c2cfbc1a4eb5a7b90936935 Mon Sep 17 00:00:00 2001 From: msdlisper <1170167213@qq.com> Date: Fri, 3 Nov 2023 23:22:45 +0800 Subject: [PATCH 3/9] fix: ignore optional chaining (#607) --- CHANGELOG.md | 5 +++-- .../use_exhaustive_dependencies.rs | 21 +++++++++++++++---- .../useExhaustiveDependencies/valid.js | 11 +++++++++- .../useExhaustiveDependencies/valid.js.snap | 11 +++++++++- .../src/content/docs/internals/changelog.mdx | 5 +++-- 5 files changed, 43 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63d59129e43d..7af346f5631d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,8 +83,9 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom - Fix [#591](https://github.com/biomejs/biome/issues/591) which made [noRedeclare](https://biomejs.dev/linter/rules/no-redeclare) report type parameters with identical names but in different method signatures. Contributed by @Conaclos - Support more a11y roles and fix some methods for a11y lint rules Contributed @nissy-dev -- Fix `useExhaustiveDependencies`, by removing `useContext`, `useId` and `useSyncExternalStore` from the known hooks. Contributed by @msdlisper -- +- Fix [#609](https://github.com/biomejs/biome/issues/609) `useExhaustiveDependencies`, by removing `useContext`, `useId` and `useSyncExternalStore` from the known hooks. Contributed by @msdlisper +- Fix [#607](https://github.com/biomejs/biome/issues/609) `useExhaustiveDependencies`, ignore optional chaining, Contributed by @msdlisper + ### Parser #### Enhancements diff --git a/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs b/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs index 74aab65428da..33076e071561 100644 --- a/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs +++ b/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs @@ -533,8 +533,15 @@ impl Rule for UseExhaustiveDependencies { let mut suggested_fix = None; let mut is_captured_covered = false; for (dependency_text, dependency_range) in deps.iter() { - let capture_deeper_than_dependency = capture_text.starts_with(dependency_text); - let dependency_deeper_than_capture = dependency_text.starts_with(capture_text); + // capture_text and dependency_text should filter the "?" inside + // in order to ignore optional chaining + let filter_capture_text = capture_text.replace("?", ""); + let filter_dependency_text = dependency_text.replace("?", ""); + let capture_deeper_than_dependency = + filter_capture_text.starts_with(&filter_dependency_text); + let dependency_deeper_than_capture = filter_dependency_text + .replace("?", "") + .starts_with(&filter_capture_text); match ( capture_deeper_than_dependency, dependency_deeper_than_capture, @@ -586,8 +593,14 @@ impl Rule for UseExhaustiveDependencies { for (dependency_text, dep_range) in deps { let mut covers_any_capture = false; for (capture_text, _, _) in captures.iter() { - let capture_deeper_dependency = capture_text.starts_with(&dependency_text); - let dependency_deeper_capture = dependency_text.starts_with(capture_text); + // capture_text and dependency_text should filter the "?" inside + // in order to ignore optional chaining + let filter_capture_text = capture_text.replace("?", ""); + let filter_dependency_text = dependency_text.replace("?", ""); + let capture_deeper_dependency = + filter_capture_text.starts_with(&filter_dependency_text); + let dependency_deeper_capture = + filter_dependency_text.starts_with(&filter_capture_text); if capture_deeper_dependency || dependency_deeper_capture { covers_any_capture = true; break; diff --git a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js index 9574877a4de8..54fa4bc3f38e 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js +++ b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js @@ -1,7 +1,7 @@ /* should not generate diagnostics */ import React from "react"; -import { useEffect, useSyncExternalStore } from "react"; +import { useEffect, useSyncExternalStore, useMemo } from "react"; import doSomething from 'a'; // No captures @@ -176,3 +176,12 @@ function MyComponent17() { console.log(data); }, [data]); } + +// https://github.com/biomejs/biome/issues/607 +function MyComponent18() { + const obj = Math.random() > 0.5 ? { a: 1, b: 2 } : undefined; + + return useMemo(() => { + return obj?.a === 1 && obj.b === 2; + }, [obj?.a, obj?.b]); +} diff --git a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js.snap b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js.snap index 3a31d3b0c001..3fbe85a93e71 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js.snap @@ -8,7 +8,7 @@ expression: valid.js /* should not generate diagnostics */ import React from "react"; -import { useEffect, useSyncExternalStore } from "react"; +import { useEffect, useSyncExternalStore, useMemo } from "react"; import doSomething from 'a'; // No captures @@ -184,6 +184,15 @@ function MyComponent17() { }, [data]); } +// https://github.com/biomejs/biome/issues/607 +function MyComponent18() { + const obj = Math.random() > 0.5 ? { a: 1, b: 2 } : undefined; + + return useMemo(() => { + return obj?.a === 1 && obj.b === 2; + }, [obj?.a, obj?.b]); +} + ``` diff --git a/website/src/content/docs/internals/changelog.mdx b/website/src/content/docs/internals/changelog.mdx index 5d6508ff0207..dae7243e1360 100644 --- a/website/src/content/docs/internals/changelog.mdx +++ b/website/src/content/docs/internals/changelog.mdx @@ -89,8 +89,9 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom - Fix [#591](https://github.com/biomejs/biome/issues/591) which made [noRedeclare](https://biomejs.dev/linter/rules/no-redeclare) report type parameters with identical names but in different method signatures. Contributed by @Conaclos - Support more a11y roles and fix some methods for a11y lint rules Contributed @nissy-dev -- Fix `useExhaustiveDependencies`, by removing `useContext`, `useId` and `useSyncExternalStore` from the known hooks. Contributed by @msdlisper -- +- Fix [#609](https://github.com/biomejs/biome/issues/609) `useExhaustiveDependencies`, by removing `useContext`, `useId` and `useSyncExternalStore` from the known hooks. Contributed by @msdlisper +- Fix [#607](https://github.com/biomejs/biome/issues/609) `useExhaustiveDependencies`, ignore optional chaining, Contributed by @msdlisper + ### Parser #### Enhancements From 1bcbff66f7bc645df14d0fbed45cfae97610598e Mon Sep 17 00:00:00 2001 From: msdlisper <1170167213@qq.com> Date: Fri, 3 Nov 2023 23:33:04 +0800 Subject: [PATCH 4/9] refactor: remove useless code --- .../correctness/use_exhaustive_dependencies.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs b/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs index 33076e071561..939248a0f586 100644 --- a/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs +++ b/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs @@ -539,9 +539,8 @@ impl Rule for UseExhaustiveDependencies { let filter_dependency_text = dependency_text.replace("?", ""); let capture_deeper_than_dependency = filter_capture_text.starts_with(&filter_dependency_text); - let dependency_deeper_than_capture = filter_dependency_text - .replace("?", "") - .starts_with(&filter_capture_text); + let dependency_deeper_than_capture = + filter_dependency_text.starts_with(&filter_capture_text); match ( capture_deeper_than_dependency, dependency_deeper_than_capture, From fbc594b475592871b3172d1f347550d445066183 Mon Sep 17 00:00:00 2001 From: msdlisper <1170167213@qq.com> Date: Fri, 3 Nov 2023 23:53:54 +0800 Subject: [PATCH 5/9] refactor: modify according to clippy's prompts --- .../correctness/use_exhaustive_dependencies.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs b/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs index 939248a0f586..17fc201b5ddf 100644 --- a/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs +++ b/crates/biome_js_analyze/src/semantic_analyzers/correctness/use_exhaustive_dependencies.rs @@ -535,8 +535,8 @@ impl Rule for UseExhaustiveDependencies { for (dependency_text, dependency_range) in deps.iter() { // capture_text and dependency_text should filter the "?" inside // in order to ignore optional chaining - let filter_capture_text = capture_text.replace("?", ""); - let filter_dependency_text = dependency_text.replace("?", ""); + let filter_capture_text = capture_text.replace('?', ""); + let filter_dependency_text = dependency_text.replace('?', ""); let capture_deeper_than_dependency = filter_capture_text.starts_with(&filter_dependency_text); let dependency_deeper_than_capture = @@ -594,8 +594,8 @@ impl Rule for UseExhaustiveDependencies { for (capture_text, _, _) in captures.iter() { // capture_text and dependency_text should filter the "?" inside // in order to ignore optional chaining - let filter_capture_text = capture_text.replace("?", ""); - let filter_dependency_text = dependency_text.replace("?", ""); + let filter_capture_text = capture_text.replace('?', ""); + let filter_dependency_text = dependency_text.replace('?', ""); let capture_deeper_dependency = filter_capture_text.starts_with(&filter_dependency_text); let dependency_deeper_capture = From 230339c37fd995886e8ffde94f959d4a65908c30 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 3 Nov 2023 17:35:12 +0000 Subject: [PATCH 6/9] docs(website): reworked the editor plugins section (#665) Co-authored-by: Superchupu <53496941+SuperchupuDev@users.noreply.github.com> --- .../content/docs/guides/getting-started.mdx | 25 +------- .../docs/guides/integrate-in-editor.mdx | 59 +++++++++++++++++-- 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/website/src/content/docs/guides/getting-started.mdx b/website/src/content/docs/guides/getting-started.mdx index 3a1e072bfd3c..0ee0add16c75 100644 --- a/website/src/content/docs/guides/getting-started.mdx +++ b/website/src/content/docs/guides/getting-started.mdx @@ -87,30 +87,9 @@ The command `check` is command meant to run multiple tools at once. Currently, i - lint files - organize imports -## Editor Setup +## Install an editor plugin -We recommend installing our editor integration to get the most out of Biome. -The Biome editor integration allows you to: - -* Format files on save or when issuing the Format command. -* Lint files and apply code fixes - -### VS Code - -Install our official [Biome VS Code extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome) from the Visual Studio Marketplace. - -To make Biome the default formatter open a supported file (JavaScript or TypeScript) and: - -* open the *Command Palette* (View or Ctrl/++P) -* select *Format Document With...* -* select *Configure Default Formatter* -* select *Biome*. - -### Other Editors - -We would love to support more editors, but we don't have the capacity to implement and maintain multiple editor integrations at the moment. -Because Biome uses the language server protocol (LSP), it should be relatively easy to get Biome working with any editor with an LSP client. -If you're interested in building an integration for Biome, please, reach out, and we would be more than happy to support you. +We recommend installing an editor plugin to get the most out of Biome. Check out the [editor page](/guides/integrate-in-editor) to know which editors support Biome. ## CI Setup diff --git a/website/src/content/docs/guides/integrate-in-editor.mdx b/website/src/content/docs/guides/integrate-in-editor.mdx index a0d77f91d4bb..3cba7e338678 100644 --- a/website/src/content/docs/guides/integrate-in-editor.mdx +++ b/website/src/content/docs/guides/integrate-in-editor.mdx @@ -3,10 +3,61 @@ title: Integrate Biome in your editor description: Learn how you can integrate Biome with editors and IDEs --- -## LSP first-class support +## First-party plugins + +These are plugins that are maintained by the Biome team and part of the [Biome organization](https://github.com/biomejs). + +### VS Code + +The Biome editor integration allows you to: + +* Format files on save or when issuing the Format command. +* Lint files and apply code fixes + +Install our official [Biome VS Code extension](https://marketplace.visualstudio.com/items?itemName=biomejs.biome) from the Visual Studio Marketplace. + +To make Biome the default formatter open a [supported file](/internals/language-support/) and: + +* open the *Command Palette* (View or Ctrl/++P) +* select *Format Document With...* +* select *Configure Default Formatter* +* select *Biome*. + +### IntelliJ + +To install the Biome IntelliJ plugin, head over to [official plugin page](https://plugins.jetbrains.com/plugin/22761-biome) or follow these steps: + +**From JetBrains IDEs:** + +1. Open IntelliJ IDEA. +2. Go to **Settings/Preferences**. +3. Select **Plugins** from the left-hand menu. +4. Click on the **Marketplace** tab. +5. Search for "Biome" and click **Install**. +6. Restart the IDE to activate the plugin. + +**From disk:** + +1. Download the plugin .zip from releases tab. +2. Press `⌘Сmd,` to open the IDE settings and then select Plugins. +3. On the Plugins page, click The Settings button and then click Install Plugin from Disk…. + +## Third-party plugins + +These are plugin maintained by other communities, that you install in your editor: +- [`neovim`](https://neovim.io/): you'll have to install [`nvim-lspconfig`](https://github.com/neovim/nvim-lspconfig/), and follow the [instructions](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#biome); +- [`helix`](https://helix-editor.com/): follow the instruction of [this manual](https://github.com/biomejs/biome/blob/main/editors/helix/manual.md) + +:::note +Is there a plugin for an editor that isn't listed here? Please file a PR and we will be happy to add it to the list +::: + +## Write your own plugin Biome has [LSP](https://microsoft.github.io/language-server-protocol/) first-class support. If your editor does implement LSP, then the integration of Biome should be seamless. +### Use the LSP proxy + Biome has a command called `lsp-proxy`. When executed, Biome will spawn two processes: - a [daemon](/internals/architecture#daemon) that does execute the requested operations; - a server that functions as a proxy between the requests of the client - the editor - and the server - the daemon; @@ -15,7 +66,7 @@ If your editor is able to interact with a server and send [JSON-RPC](https://www You can check how the [`neo-vim biome plugin`](https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/server_configurations/biome.lua) does it. -## Use `stdin` +### Use `stdin` If your editor doesn't support LSP, you use directly the binary `biome` and call it using [standard input](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin)). @@ -26,7 +77,7 @@ The following commands can be called via standard input: Biome will return the new output (or the original output if changes haven't occurred) to [standard output](https://en.wikipedia.org/wiki/Standard_streams#Standard_output_(stdout)) and the diagnostics to [standard error](https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)). -When you used `stdin`, you must pass the `--stdin-file-path` option. The file `path` **doesn't need to exist** in your file system, it can be any name. **What's important** is to provide the correct file extension, so Biome knows **how to treat** your file. +When you use `stdin`, you must pass the `--stdin-file-path` option. The file `path` **doesn't need to exist** in your file system, it can be any name. **What's important** is to provide the correct file extension, so Biome knows **how to treat** your file. It's the editor's responsibility to locate the resolve the path of the binary and then call it when it's needed. The binaries are shipped to npm based on the architectures and OS that we support: @@ -62,7 +113,7 @@ If you decide to use the daemon, you're also responsible to restart/kill the pro Operations via the daemon are significantly slower than the CLI itself, so it's advised to run operations only on single files. ::: -## Daemon logs +### Daemon logs The Biome daemon saves logs in your file system. Logs are store in a folder called `biome-logs`. You can fine this folder in the temporary directory of your operating system. From f52b7ba376b12cba61caac6a005110475d04e2ed Mon Sep 17 00:00:00 2001 From: Nicolas Hedger <649677+nhedger@users.noreply.github.com> Date: Sat, 4 Nov 2023 00:36:26 +0100 Subject: [PATCH 7/9] ci(pull_request): free disk space on ubuntu-latest (#667) --- .github/workflows/pull_request.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 47a6f8bdc93d..ec14ec161aa5 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -74,6 +74,11 @@ jobs: - os: windows-latest - os: ubuntu-latest steps: + - name: Free Disk Space (Ubuntu) + if: matrix.os == 'ubuntu-latest' + uses: jlumbroso/free-disk-space@main + with: + android: true - name: Checkout PR branch uses: actions/checkout@v4 - name: Install toolchain From dfd6494551351de0adbbf049e2314b715e81f68a Mon Sep 17 00:00:00 2001 From: msdlisper <1170167213@qq.com> Date: Sat, 28 Oct 2023 21:40:16 +0800 Subject: [PATCH 8/9] fix: bug with useContext/useSyncExternalStore (#609) --- .../rules/use-exhaustive-dependencies.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md b/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md index 8df5e9fb8f87..7d85f57acf40 100644 --- a/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md +++ b/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md @@ -49,23 +49,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook does not specify all of its dependencies.
-  
+
     3 │ function component() {
     4 │     let a = 1;
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │         console.log(a);
     7 │     });
-  
+
    This dependency is not specified in the hook dependency list.
-  
+
     4 │     let a = 1;
     5 │     useEffect(() => {
   > 6 │         console.log(a);
                        ^
     7 │     });
     8 │ }
-  
+
 
```jsx @@ -81,23 +81,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook specifies more dependencies than necessary.
-  
+
     3 │ function component() {
     4 │     let b = 1;
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │     }, [b]);
     7 │ }
-  
+
    This dependency can be removed from the list.
-  
+
     4 │     let b = 1;
     5 │     useEffect(() => {
   > 6 │     }, [b]);
            ^
     7 │ }
     8 │ 
-  
+
 
```jsx @@ -115,23 +115,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook specifies more dependencies than necessary.
-  
+
     3 │ function component() {
     4 │     const [name, setName] = useState();
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │         console.log(name);
     7 │         setName("");
-  
+
    This dependency can be removed from the list.
-  
+
      6 │         console.log(name);
      7 │         setName("");
    > 8 │     }, [name, setName]);
                   ^^^^^^^
      9 │ }
     10 │ 
-  
+
 
```jsx @@ -149,23 +149,23 @@ function component() {
correctness/useExhaustiveDependencies.js:6:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook does not specify all of its dependencies.
-  
+
     4 │     let a = 1;
     5 │     const b = a + 1;
   > 6 │     useEffect(() => {
        ^^^^^^^^^
     7 │         console.log(b);
     8 │     });
-  
+
    This dependency is not specified in the hook dependency list.
-  
+
     5 │     const b = a + 1;
     6 │     useEffect(() => {
   > 7 │         console.log(b);
                        ^
     8 │     });
     9 │ }
-  
+
 
## Valid From 687e4ace3f08bf7311d27b9777b79e76de5f2395 Mon Sep 17 00:00:00 2001 From: msdlisper <1170167213@qq.com> Date: Sat, 28 Oct 2023 22:21:35 +0800 Subject: [PATCH 9/9] docs: update docs (#609) --- .../rules/use-exhaustive-dependencies.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md b/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md index 7d85f57acf40..8df5e9fb8f87 100644 --- a/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md +++ b/website/src/content/docs/linter/rules/use-exhaustive-dependencies.md @@ -49,23 +49,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook does not specify all of its dependencies.
-
+  
     3 │ function component() {
     4 │     let a = 1;
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │         console.log(a);
     7 │     });
-
+  
    This dependency is not specified in the hook dependency list.
-
+  
     4 │     let a = 1;
     5 │     useEffect(() => {
   > 6 │         console.log(a);
                        ^
     7 │     });
     8 │ }
-
+  
 
```jsx @@ -81,23 +81,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook specifies more dependencies than necessary.
-
+  
     3 │ function component() {
     4 │     let b = 1;
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │     }, [b]);
     7 │ }
-
+  
    This dependency can be removed from the list.
-
+  
     4 │     let b = 1;
     5 │     useEffect(() => {
   > 6 │     }, [b]);
            ^
     7 │ }
     8 │ 
-
+  
 
```jsx @@ -115,23 +115,23 @@ function component() {
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook specifies more dependencies than necessary.
-
+  
     3 │ function component() {
     4 │     const [name, setName] = useState();
   > 5 │     useEffect(() => {
        ^^^^^^^^^
     6 │         console.log(name);
     7 │         setName("");
-
+  
    This dependency can be removed from the list.
-
+  
      6 │         console.log(name);
      7 │         setName("");
    > 8 │     }, [name, setName]);
                   ^^^^^^^
      9 │ }
     10 │ 
-
+  
 
```jsx @@ -149,23 +149,23 @@ function component() {
correctness/useExhaustiveDependencies.js:6:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
    This hook does not specify all of its dependencies.
-
+  
     4 │     let a = 1;
     5 │     const b = a + 1;
   > 6 │     useEffect(() => {
        ^^^^^^^^^
     7 │         console.log(b);
     8 │     });
-
+  
    This dependency is not specified in the hook dependency list.
-
+  
     5 │     const b = a + 1;
     6 │     useEffect(() => {
   > 7 │         console.log(b);
                        ^
     8 │     });
     9 │ }
-
+  
 
## Valid