Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions crates/oxc_formatter/examples/sort_imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
use std::{fs, path::Path};

use oxc_allocator::Allocator;
use oxc_formatter::{FormatOptions, Formatter, SortImportsOptions, SortOrder, get_parse_options};
use oxc_formatter::{
FormatOptions, Formatter, SortImportsOptions, SortOrder, default_groups,
default_internal_patterns, get_parse_options,
};
use oxc_parser::Parser;
use oxc_span::SourceType;
use pico_args::Arguments;
Expand All @@ -28,8 +31,8 @@ fn main() -> Result<(), String> {
sort_side_effects,
ignore_case,
newlines_between,
internal_pattern: None,
groups: None,
internal_pattern: default_internal_patterns(),
groups: default_groups(),
};

// Read source file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,7 @@ fn to_path_kind(source: &str, options: &SortImportsOptions) -> ImportPathKind {
}

// Check if source matches any internal pattern
if match &options.internal_pattern {
Some(patterns) => patterns.iter().any(|p| source.starts_with(p.as_str())),
None => ["~/", "@/"].iter().any(|p| source.starts_with(*p)),
} {
if options.internal_pattern.iter().any(|p| source.starts_with(p.as_str())) {
return ImportPathKind::Internal;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,3 @@
/// Default groups configuration.
pub fn default_groups() -> Vec<Vec<GroupName>> {
use ImportModifier as M;
use ImportSelector as S;

vec![
vec![GroupName::with_modifier(S::Import, M::Type)],
vec![
GroupName::with_modifier(S::Builtin, M::Value),
GroupName::with_modifier(S::External, M::Value),
],
vec![GroupName::with_modifier(S::Internal, M::Type)],
vec![GroupName::with_modifier(S::Internal, M::Value)],
vec![
GroupName::with_modifier(S::Parent, M::Type),
GroupName::with_modifier(S::Sibling, M::Type),
GroupName::with_modifier(S::Index, M::Type),
],
vec![
GroupName::with_modifier(S::Parent, M::Value),
GroupName::with_modifier(S::Sibling, M::Value),
GroupName::with_modifier(S::Index, M::Value),
],
vec![GroupName::new(S::Unknown)],
]
}

/// Parse groups from string-based configuration.
/// If parsing fails (= undefined), it falls back to `Unknown` selector.
pub fn parse_groups_from_strings(string_groups: &Vec<Vec<String>>) -> Vec<Vec<GroupName>> {
Expand Down
8 changes: 2 additions & 6 deletions crates/oxc_formatter/src/ir_transform/sort_imports/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use oxc_allocator::{Allocator, Vec as ArenaVec};
use crate::{
formatter::format_element::{FormatElement, LineMode, document::Document},
ir_transform::sort_imports::{
group_config::{GroupName, default_groups, parse_groups_from_strings},
group_config::{GroupName, parse_groups_from_strings},
partitioned_chunk::PartitionedChunk,
source_line::SourceLine,
},
Expand All @@ -27,11 +27,7 @@ pub struct SortImportsTransform {
impl SortImportsTransform {
pub fn new(options: options::SortImportsOptions) -> Self {
// Parse string based groups into our internal representation for performance
let groups = if let Some(groups) = &options.groups {
parse_groups_from_strings(groups)
} else {
default_groups()
};
let groups = parse_groups_from_strings(&options.groups);
Self { options, groups }
}

Expand Down
31 changes: 25 additions & 6 deletions crates/oxc_formatter/src/ir_transform/sort_imports/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,11 @@ pub struct SortImportsOptions {
/// NOTE: Cannot be used together with `partition_by_newline: true`.
pub newlines_between: bool,
/// Prefixes for internal imports.
/// If `None`, uses the default internal patterns.
pub internal_pattern: Option<Vec<String>>,
/// Defaults to `["~/", "@/"]`.
pub internal_pattern: Vec<String>,
/// Groups configuration for organizing imports.
/// Each inner `Vec` represents a group, and multiple group names in the same `Vec` are treated as one.
/// If `None`, uses the default groups.
pub groups: Option<Vec<Vec<String>>>,
pub groups: Vec<Vec<String>>,
}

impl Default for SortImportsOptions {
Expand All @@ -42,12 +41,14 @@ impl Default for SortImportsOptions {
order: SortOrder::default(),
ignore_case: true,
newlines_between: true,
internal_pattern: None,
groups: None,
internal_pattern: default_internal_patterns(),
groups: default_groups(),
}
}
}

// ---

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub enum SortOrder {
/// Sort in ascending order (A-Z).
Expand Down Expand Up @@ -88,3 +89,21 @@ impl fmt::Display for SortOrder {
f.write_str(s)
}
}

/// Returns default prefixes for identifying internal imports: `["~/", "@/"]`.
pub fn default_internal_patterns() -> Vec<String> {
["~/", "@/"].iter().map(|s| (*s).to_string()).collect()
}

/// Returns default groups configuration for organizing imports.
pub fn default_groups() -> Vec<Vec<String>> {
vec![
vec!["type-import".to_string()],
vec!["value-builtin".to_string(), "value-external".to_string()],
vec!["type-internal".to_string()],
vec!["value-internal".to_string()],
vec!["type-parent".to_string(), "type-sibling".to_string(), "type-index".to_string()],
vec!["value-parent".to_string(), "value-sibling".to_string(), "value-index".to_string()],
vec!["unknown".to_string()],
]
}
19 changes: 10 additions & 9 deletions crates/oxc_formatter/src/service/oxfmtrc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
ArrowParentheses, AttributePosition, BracketSameLine, BracketSpacing,
EmbeddedLanguageFormatting, Expand, FormatOptions, IndentStyle, IndentWidth, LineEnding,
LineWidth, QuoteProperties, QuoteStyle, Semicolons, SortImportsOptions, SortOrder,
TrailingCommas,
TrailingCommas, default_groups, default_internal_patterns,
};

/// Configuration options for the formatter.
Expand Down Expand Up @@ -375,14 +375,16 @@ impl Oxfmtrc {
partition_by_newline: sort_imports_config.partition_by_newline,
partition_by_comment: sort_imports_config.partition_by_comment,
sort_side_effects: sort_imports_config.sort_side_effects,
order: sort_imports_config.order.map_or(SortOrder::Asc, |o| match o {
order: sort_imports_config.order.map_or(SortOrder::default(), |o| match o {
SortOrderConfig::Asc => SortOrder::Asc,
SortOrderConfig::Desc => SortOrder::Desc,
}),
ignore_case: sort_imports_config.ignore_case,
newlines_between: sort_imports_config.newlines_between,
internal_pattern: sort_imports_config.internal_pattern,
groups: sort_imports_config.groups,
internal_pattern: sort_imports_config
.internal_pattern
.unwrap_or_else(default_internal_patterns),
groups: sort_imports_config.groups.unwrap_or_else(default_groups),
});
}

Expand Down Expand Up @@ -563,10 +565,9 @@ mod tests {
)
.unwrap();
let sort_imports = config.into_format_options().unwrap().experimental_sort_imports.unwrap();
let groups = sort_imports.groups.as_ref().unwrap();
assert_eq!(groups.len(), 5);
assert_eq!(groups[0], vec!["builtin".to_string()]);
assert_eq!(groups[1], vec!["external".to_string(), "internal".to_string()]);
assert_eq!(groups[4], vec!["index".to_string()]);
assert_eq!(sort_imports.groups.len(), 5);
assert_eq!(sort_imports.groups[0], vec!["builtin".to_string()]);
assert_eq!(sort_imports.groups[1], vec!["external".to_string(), "internal".to_string()]);
assert_eq!(sort_imports.groups[4], vec!["index".to_string()]);
}
}
10 changes: 7 additions & 3 deletions napi/playground/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ use oxc::{
use oxc_formatter::{
ArrowParentheses, AttributePosition, BracketSameLine, BracketSpacing, Expand, FormatOptions,
Formatter, IndentStyle, IndentWidth, LineEnding, LineWidth, QuoteProperties, QuoteStyle,
Semicolons, SortImportsOptions, SortOrder, TrailingCommas, get_parse_options,
Semicolons, SortImportsOptions, SortOrder, TrailingCommas, default_groups,
default_internal_patterns, get_parse_options,
};
use oxc_linter::{
ConfigStore, ConfigStoreBuilder, ContextSubHost, ExternalPluginStore, LintOptions, Linter,
Expand Down Expand Up @@ -510,8 +511,11 @@ impl Oxc {
order,
ignore_case: sort_imports_config.ignore_case.unwrap_or(true),
newlines_between: sort_imports_config.newlines_between.unwrap_or(true),
internal_pattern: sort_imports_config.internal_pattern.clone(),
groups: sort_imports_config.groups.clone(),
internal_pattern: sort_imports_config
.internal_pattern
.clone()
.unwrap_or_else(default_internal_patterns),
groups: sort_imports_config.groups.clone().unwrap_or_else(default_groups),
});
}

Expand Down
Loading