organizeImports
Podsumowanie
Dział zatytułowany „Podsumowanie”- Reguła dostępna od:
v1.0.0
- Kategoria diagnostyczna:
assist/source/organizeImports
- Ta akcja jest zalecana.
- Domyślna ważność tej reguły to information.
Jak włączyć w edytorze
Dział zatytułowany „Jak włączyć w edytorze”{ "editor.codeActionsOnSave": { "source.organizeImports.biome": "explicit", "source.fixAll.biome": "explicit" }}
{ "code_actions_on_format": { "source.organizeImports.biome": true, "source.fixAll.biome": true }}
source.organizeImports.biome
Jak skonfigurować
Dział zatytułowany „Jak skonfigurować”{ "assist": { "actions": { "source": { "organizeImports": "on" } } }}
Dostarcza akcję kodu do sortowania importów i eksportów w pliku przy użyciu wbudowanego lub niestandardowego porządku.
Importy i eksporty są najpierw rozdzielane na fragmenty, a następnie sortowane. Importy lub eksporty fragmentu są następnie grupowane zgodnie z grupami zdefiniowanymi przez użytkownika. W obrębie grupy importy są sortowane przy użyciu wbudowanego porządku, który zależy od rodzaju importu/eksportu, czy import/eksport ma atrybuty i źródła, z którego jest importowany. source jest również często nazywany specifier w ekosystemie JavaScript.
import A from "@my/lib" with { "attribute1": "value" };^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ kind source attributes
export * from "@my/lib" with { "attribute1": "value" };^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^ kind source attributes
Fragment importów i fragment eksportów
Dział zatytułowany „Fragment importów i fragment eksportów”Fragment to sekwencja sąsiadujących importów lub eksportów. Fragment zawiera tylko importy lub eksporty, nie oba jednocześnie. Poniższy przykład zawiera dwa fragmenty. Pierwszy fragment składa się z trzech importów, a drugi fragment składa się z trzech eksportów.
// fragment 1import A from "a";import * as B from "b";import { C } from "c";// fragment 2export * from "d";export * as F from "e";export { F } from "f";
Fragmenty kończą się również zaraz po napotkaniu instrukcji lub importu efektu ubocznego (zwanego również bare import). Każdy import efektu ubocznego tworzy niezależny fragment. Poniższy przykład zawiera sześć fragmentów:
// fragment 1import A from "a";import * as B from "b";// fragment 2import "x";// fragment 3import "y";// fragment 4import { C } from "c";// fragment 5export * from "d";function f() {}// fragment 6export * as E from "e";export { F } from "f";
- Pierwszy fragment zawiera dwa pierwsze
import
i kończy się pojawieniem się pierwszego importu efektu ubocznegoimport "x"
. - Drugi fragment zawiera tylko import efektu ubocznego
import "x"
. - Trzeci fragment zawiera tylko import efektu ubocznego
import "y"
. - Czwarty fragment zawiera pojedynczy
import
; Pierwszyexport
go kończy. - Piąty fragment zawiera pierwszy
export
; Deklaracja funkcji go kończy. - Szósty fragment zawiera ostatnie dwa
export
.
Fragmenty są również ograniczone przez odłączone komentarze. Odłączony komentarz to komentarz po którym następuje pusta linia. Komentarze nie poprzedzone pustą linią to dołączone komentarze. Należy zauważyć, że same puste linie nie są brane pod uwagę przy dzieleniu importów i eksportów na fragmenty. Poniższy przykład zawiera odłączony komentarz, który dzieli importy na dwa fragmenty:
// Dołączony komentarz 1import A from "a";
// Dołączony komentarz 2import * as B from "b";// Odłączony komentarz
import { C } from "c";
Linia import { C } from "c"
tworzy drugi fragment.
Pusta linia między pierwszymi dwoma importami jest ignorowana, więc tworzą one pojedynczy fragment.
Sortownik zapewnia, że fragmenty są oddzielone od siebie pustymi liniami. Tylko importy efektu ubocznego sąsiadujące z fragmentem importów nie są oddzielone pustą linią. Poniższy kod…
import A from "a";import * as B from "b";import "x";import { C } from "c";export * from "d";// Odłączony komentarz
export * as F from "e";// Dołączony komentarzexport { F } from "f";
jest sortowany jako:
import A from "a";import * as B from "b";import "x";import { C } from "c";
export * from "d";
// Odłączony komentarz
export * as F from "e";// Dołączony komentarzexport { F } from "f";
Należy również zauważyć, że puste linie wewnątrz fragmentu są ignorowane i zachowywane. Mogą być usunięte przez jawne zdefiniowanie grup, jak pokazano w następnej sekcji.
Sortowanie importów i eksportów
Dział zatytułowany „Sortowanie importów i eksportów”Po utworzeniu fragmentów, importy i eksporty każdego fragmentu są sortowane. Importy i eksporty są sortowane według ich źródła. Źródła są uporządkowane według “odległości”. Źródła “dalsze” od bieżącego modułu są umieszczane na górze, źródła “bliższe” użytkownikowi są umieszczane na dole. Prowadzi to do następującego porządku:
- URL-e takie jak
https://example.org
. - Pakiety z protokołem takim jak
node:path
,bun:test
,jsr:@my?lib
, lubnpm:lib
. - Pakiety takie jak
mylib
lub@my/lib
. - Aliasy: źródła zaczynające się od
@/
,#
,~
,$
, lub%
. Zwykle są to Node.js subpath imports lub TypeScript path aliases. - Ścieżki bezwzględne i względne.
Dwa importy/eksporty z tą samą kategorią źródła są sortowane przy użyciu natural sort order dostosowanego do URL-i, pakietów i ścieżek.
W szczególności, porządek zapewnia, że A < a < B < b
.
Porządek uwzględnia również liczby, np. a9 < a10
.
Na przykład, następujący kod…
import sibling from "./file.js";import internal from "#alias";import fs from "fs";import { test } from "node:test";import path from "node:path";m```jsimport data from "https://example.org";import scopedLibUsingJsr from "jsr:@scoped/lib";import path from "node:path";import { test } from "node:test";import scopedLib from "@scoped/lib";import fs from "fs";import lib from "lib";import internal from "#alias";import parent from "../parent.js";import sibling from "./file.js";
Jeśli dwa importy lub eksporty mają to samo źródło i są w tym samym fragmencie, są one uporządkowane według ich rodzaju następująco:
- Import/eksport typu namespace
- Import typu default
- Import/eksport typu named
- Import/eksport namespace
- Kombinowany import default i namespace
- Import default
- Kombinowany import default i named
- Import/eksport named
Importy i eksporty z atrybutami są zawsze umieszczane na początku. Na przykład, następujący kod…
import * as namespaceImport from "same-source";import type * as namespaceTypeImport from "same-source";import type { namedTypeImport } from "same-source";import defaultNamespaceCombined, * as namespaceCombined from "same-source";import defaultNamedCombined, { namedCombined } from "same-source";import defaultImport from "same-source";import type defaultTypeImport from "same-source";import { importWithAttribute } from "same-source" with { "attribute": "value" } ;
jest sortowany następująco:
import { importWithAttribute } from "same-source" with { "attribute": "value" } ;import type * as namespaceTypeImport from "same-source";import type defaultTypeImport from "same-source";import type { namedTypeImport } from "same-source";import * as namespaceImport from "same-source";import defaultNamespaceCombined, * as namespaceCombined from "same-source";import defaultImport from "same-source";import defaultNamedCombined, { namedCombined } from "same-source";
Ten domyślny porządek nie może być zmieniony. Jednak użytkownicy mogą nadal dostosować sposób sortowania importów i eksportów używając koncepcji grup, jak wyjaśniono w następnej sekcji.
Grupy importów i eksportów
Dział zatytułowany „Grupy importów i eksportów”Importy lub eksporty fragmentu są dzielone na grupy przed sortowaniem przy użyciu wbudowanego porządku opisanego w poprzedniej sekcji.
Domyślnie każdy fragment składa się z pojedynczej grupy.
Te domyślne grupy i ich porządek mogą nie odpowiadać Twoim preferencjom.
Sortownik dostarcza opcję groups
, która pozwala dostosować sposób dzielenia fragmentów na grupy.
Opcja groups
to lista dopasowań grup.
Dopasowanie grupy to:
- Wstępnie zdefiniowane dopasowanie grupy, lub
- Wzorzec glob, lub
- Dopasowanie obiektu, lub
- Lista wzorców glob, wstępnie zdefiniowanych dopasowań grup i dopasowań obiektów.
Wstępnie zdefiniowane dopasowania grup to ciągi znaków w CONSTANT_CASE
poprzedzone i zakończone przez :
.
Sortownik dostarcza kilka wstępnie zdefiniowanych dopasowań grup:
:ALIAS:
: źródła zaczynające się od#
,@/
,~
,$
, lub%
.:BUN:
: źródła zaczynające się od protokołubun:
lub odpowiadające wbudowanemu modułowi Bun takiemu jakbun
.:NODE:
: źródła zaczynające się od protokołunode:
lub odpowiadające wbudowanemu modułowi Node.js takiemu jakfs
lubpath
.:PACKAGE:
: pakiety scoped i bare.:PACKAGE_WITH_PROTOCOL:
: pakiety scoped i bare z protokołem.:PATH:
: ścieżki bezwzględne i względne.:URL:
: źródła zaczynające się odhttps://
ihttp://
.
Weźmy przykład.
W domyślnej konfiguracji, moduły Node.js bez protokołu node:
są oddzielone od tych z protokołem.
Aby pogrupować je razem, możesz użyć wstępnie zdefiniowanej grupy :NODE:
.
Przy danej konfiguracji…
{ "assist": { "actions": { "source": { "organizeImports": { "level": "on", "options": { "groups": [ ":URL:", ":NODE:" ] } } } } }}{ "assist": { "actions": { "source": { "organizeImports": { "level": "on", "options": { "groups": [ ":URL:", ":NODE:" ] } } } } }}
…i następujący kod…
import sibling from "./file.js";import internal from "#alias";import fs from "fs";import { test } from "node:test";import path from "node:path";import parent from "../parent.js";import scopedLibUsingJsr from "jsr:@scoped/lib";import data from "https://example.org";import lib from "lib";import scopedLib from "@scoped/lib";
…kończymy z następującym posortowanym wynikiem, gdzie importy node:path
i modułu Node.js fs
są pogrupowane razem:
import data from "https://example.org";import fs from "fs";import path from "node:path";import { test } from "node:test";import scopedLibUsingJsr from "jsr:@scoped/lib";import scopedLib from "@scoped/lib";import lib from "lib";import internal from "#alias";import parent from "../parent.js";import sibling from "./file.js";
Należy zauważyć, że wszystkie importy, które nie pasują do dopasowania grupy, są zawsze umieszczane na końcu.
Dopasowania grup mogą być również wzorcami glob i listami wzorców glob.
Wzorce glob wybierają importy i eksporty ze źródłem, które pasuje do wzorca.
W następnym przykładzie tworzymy dwie grupy: jedną, która zbiera importy/eksporty ze źródłem zaczynającym się od @my/lib
z wyjątkiem @my/lib/special
i drugą, która zbiera importy/eksporty zaczynające się od @/
.
{ "options": { "groups": [ ["@my/lib", "@my/lib/**", "!@my/lib/special", "!@my/lib/special/**"], "@/**" ] }}
Stosując tę konfigurację do następującego kodu…
import lib from "@my/lib";import aliased from "@/alias";import path from "@my/lib/special";import test from "@my/lib/path";
…otrzymujemy następujący posortowany wynik.
Importy ze źródłami @my/lib
i @my/lib/path
tworzą pierwszą grupę.
Pasują odpowiednio do wzorców glob @my/lib
i @my/lib/**
.
Import ze źródłem @my/lib/special
nie jest umieszczany w tej pierwszej grupie, ponieważ jest odrzucany przez wyjątek !@my/lib/special
.
Import ze źródłem @/alias
jest umieszczany w drugiej grupie, ponieważ pasuje do wzorca glob @/**
.
W końcu, inne importy są umieszczane na końcu.
import lib from "@my/lib";import test from "@my/lib/path";import aliased from "@/alias";import path from "@my/lib/special";
Należy zauważyć, że @my/lib
pasuje do @my/lib
, ale nie do @my/lib/**
.
Odwrotnie, @my/lib/subpath
pasuje do @my/lib/**
, ale nie do @my/lib
.
Więc musisz określić oba wzorce glob, jeśli chcesz zaakceptować wszystkie importy/eksporty, które zaczynają się od @my/lib
.
Prefiks !
wskazuje wyjątek.
Możesz tworzyć wyjątki wyjątków, następując po wyjątku zwykłym wzorcem glob.
Na przykład ["@my/lib", "@my/lib/**", "!@my/lib/special", "!@my/lib/special/**", "@my/lib/special/*/accepted/**"]
pozwala zaakceptować wszystkie źródła pasujące do @my/lib/special/*/accepted/**
.
Należy zauważyć, że wstępnie zdefiniowane grupy mogą być również negowane. !:NODE:
pasuje do wszystkich źródeł, które nie pasują do :NODE:
.
Aby uzyskać więcej szczegółów na temat obsługiwanych wzorców glob, zobacz dedykowaną sekcję.
W końcu, dopasowania grup mogą być dopasowaniami obiektów. Dopasowanie obiektu pozwala dopasować importy i eksporty tylko typu.
Przy danej konfiguracji:
{ "options": { "groups": [ { "type": false, "source": ["@my/lib", "@my/lib/**"] }, ["@my/lib", "@my/lib/**"] ] }}
Następujący kod:
import type { T } from "@my/lib";import { V } from "@my/lib";
is sorted as follows:
import { V } from "@my/lib";import type { T } from "@my/lib";
Dopasowanie obiektu { "type": false, "source": ["@my/lib", "@my/lib/**"] }
pasuje do importów i eksportów bez słowa kluczowego type
ze źródłem, które pasuje do jednego ze wzorców glob z listy ["@my/lib", "@my/lib/**"]
.
Sortownik pozwala na oddzielenie dwóch grup pustą linią przy użyciu wstępnie zdefiniowanego ciągu :BLANK_LINE:
.
Przy danej konfiguracji…
{ "options": { "groups": [ [":BUN:", ":NODE:"], ":BLANK_LINE:", ["@my/lib", "@my/lib/**", "!@my/lib/special", "!@my/lib/special/**"], "@/**" ] }}
…następujący kod…
import test from "bun:test";import path from "node:path";import lib from "@my/lib";import libPath from "@my/lib/path";import libSpecial from "@my/lib/special";import aliased from "@/alias";
…jest sortowany jako:
import path from "node:path";
import lib from "@my/lib";import test from "@my/lib/path";import aliased from "@/alias";import path from "@my/lib/special";
Grupy są dopasowywane w kolejności.
Oznacza to, że jedno dopasowanie grupy może zasłaniać następujące grupy.
Na przykład, w następnej konfiguracji, dopasowanie grupy :URL:
nigdy nie jest dopasowywane, ponieważ wszystkie importy i eksporty pasują do pierwszego dopasowania **
.
{ "options": { "groups": [ "**", ":URL:" ] }}
Obsługa komentarzy
Dział zatytułowany „Obsługa komentarzy”Podczas sortowania importów i eksportów, dołączone komentarze są przenoszone z ich importem lub eksportem, a odłączone komentarze (komentarze po których następuje pusta linia) pozostają na swoim miejscu.
Jednak jest wyjątek od tej reguły. Jeśli komentarz pojawia się na górze pliku, jest uważany za odłączony, nawet jeśli nie następuje po nim pusta linia. To zapewnia, że noty copyright i komentarze nagłówka pliku pozostają na górze pliku.
Na przykład, następujący kod…
// Nota copyright i komentarz nagłówka plikuimport F from "f";// Dołączony komentarz dla `e`import E from "e";// Dołączony komentarz dla `d`import D from "d";// Odłączony komentarz (nowy fragment)
// Dołączony komentarz dla `b`import B from "b";// Dołączony komentarz dla `a`import A from "a";
…jest sortowany następująco. Pusta linia jest automatycznie dodawana po komentarzu nagłówka, aby zapewnić, że dołączony komentarz nie łączy się z komentarzem nagłówka.
// Nota copyright i komentarz nagłówka pliku
// Dołączony komentarz dla `d`import D from "d";// Dołączony komentarz dla `e`import E from "e";import F from "f";
// Odłączony komentarz (nowy fragment)
// Dołączony komentarz dla `a`import A from "a";// Dołączony komentarz dla `b`import B from "b";
Łączenie importów i eksportów
Dział zatytułowany „Łączenie importów i eksportów”Organizator również łączy importy i eksporty, które mogą być połączone.
Na przykład, następujący kod:
import type { T1 } from "package";import type { T2 } from "package";import * as ns from "package";import D1 from "package";import D2 from "package";import { A } from "package";import { B } from "package";
jest łączony następująco:
import type { T1, T2 } from "package";import D1, * as ns from "package";import D2, { A, B } from "package";
Sortowanie named importów, named eksportów i atrybutów
Dział zatytułowany „Sortowanie named importów, named eksportów i atrybutów”Sortownik również sortuje named importy, named eksporty, a także atrybuty. Używa naturalnego porządku sortowania do porównywania liczb.
Następujący kod…
import { a, b, A, B, c10, c9 } from "a";
export { a, b, A, B, c10, c9 } from "a";
import special from "special" with { "type": "ty", "metadata": "data" };
…is sorted as follows:
import { A, a, B, b, c9, c10 } from "a";
export { A, a, B, b, c9, c10 } from "a";
import special from "special" with { "metadata": "data", "type": "ty" };
Obsługiwane wzorce glob
Dział zatytułowany „Obsługiwane wzorce glob”Musisz zrozumieć strukturę źródła, aby zrozumieć, które źródło pasuje do wzorca glob.
Źródło jest podzielone na segmenty źródła.
Każdy segment źródła jest ograniczony separatorem /
lub początkiem/końcem źródła.
Na przykład src/file.js
składa się z dwóch segmentów źródła: src
i file.js
.
- gwiazdka
*
która pasuje do zera lub więcej znaków wewnątrz segmentu źródła
file.js
pasuje do *.js
.
Odwrotnie, src/file.js
nie pasuje do *.js
- globstar
**
która pasuje do zera lub więcej segmentów źródła**
musi być ograniczona separatorami/
lub początkiem/końcem wzorca glob. Na przykład,**a
nie jest prawidłowym wzorcem glob. Również,**
nie może być następowana przez kolejny globstar. Na przykład,**/**
nie jest prawidłowym wzorcem glob.
file.js
i src/file.js
pasują do **
i **/*.js
Odwrotnie, README.txt
nie pasuje do **/*.js
ponieważ źródło kończy się na .txt
.
- Użyj
\*
aby wyescapować*
\*
pasuje do dosłownego znaku *
w źródle.
-
?
,[
,]
,{
, i}
muszą być wyescapowane używając\
. Te znaki są zarezerwowane do możliwego przyszłego użycia. -
Użyj
!
jako pierwszego znaku aby zanegować wzorzec glob
file.js
pasuje do !*.test.js
.
src/file.js
pasuje do !*.js
ponieważ źródło zawiera kilka segmentów.
Typowe konfiguracje
Dział zatytułowany „Typowe konfiguracje”Ta sekcja dostarcza kilka przykładów typowych konfiguracji.
Umieszczanie import type
i export type
na początku fragmentów
Dział zatytułowany „Umieszczanie import type i export type na początku fragmentów”{ "options": { "groups": [ { "type": true } ] }}
Należy zauważyć, że możesz chcieć użyć reguły lint useImportType
i jej style
aby wymusić użycie import type
zamiast import { type }
.
Umieszczanie import type
i export type
na końcu fragmentów
Dział zatytułowany „Umieszczanie import type i export type na końcu fragmentów”{ "options": { "groups": [ { "type": false } ] }}
Zmiana sortowania identyfikatorów importów na sortowanie leksykograficzne
Dział zatytułowany „Zmiana sortowania identyfikatorów importów na sortowanie leksykograficzne”To dotyczy tylko named importów/eksportów, a nie samego źródła.
{ "assist": { "actions": { "source": { "organizeImports": { "options": { "identifierOrder": "lexicographic" } } } } }}
import { var1, var2, var21, var11, var12, var22 } from 'my-package'
code-block.js:1:1 assist/source/organizeImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ The imports and exports are not sorted.
> 1 │ import { var1, var2, var21, var11, var12, var22 } from ‘my-package’
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 │
ℹ Safe fix: Organize Imports (Biome)
1 │ - import·{·var1,·var2,·var21,·var11,·var12,·var22·}·from·‘my-package’
1 │ + import·{·var1,·var2,·var11,·var12,·var21,·var22·}·from·‘my-package’
2 2 │
Zmiana sortowania identyfikatorów importów na sortowanie logiczne
Dział zatytułowany „Zmiana sortowania identyfikatorów importów na sortowanie logiczne”To jest domyślne zachowanie w przypadku, gdy nie nadpiszesz. To dotyczy tylko named importów/eksportów, a nie samego źródła.
{ "assist": { "actions": { "source": { "organizeImports": { "options": { "identifierOrder": "natural" } } } } }}
import { var1, var2, var21, var11, var12, var22 } from 'my-package'
code-block.js:1:1 assist/source/organizeImports FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ The imports and exports are not sorted.
> 1 │ import { var1, var2, var21, var11, var12, var22 } from ‘my-package’
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2 │
ℹ Safe fix: Organize Imports (Biome)
1 │ - import·{·var1,·var2,·var21,·var11,·var12,·var22·}·from·‘my-package’
1 │ + import·{·var1,·var2,·var11,·var12,·var21,·var22·}·from·‘my-package’
2 2 │
Copyright (c) 2023-present Biome Developers and Contributors.