Skip to content

Commit

Permalink
Merge branch 'main' into fix/css-moz-document
Browse files Browse the repository at this point in the history
  • Loading branch information
eryue0220 authored Oct 20, 2024
2 parents fb65633 + 1b348f4 commit b0eb8d5
Show file tree
Hide file tree
Showing 32 changed files with 512 additions and 54 deletions.
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,54 @@ our [guidelines for writing a good changelog entry](https://github.com/biomejs/b
#### New features

- Add [noUselessUndefined](https://biomejs.dev/linter/rules/no-useless-undefined/). Contributed by @unvalley

- [useFilenamingConvention](https://biomejs.dev/linter/rules/use-filenaming-convention) accepts a new option `match` ([#4105](https://github.com/biomejs/biome/issues/4105)).

You can now validate filenames with a regular expression.
For instance, you can allow filenames to start with `%`:

```json
{
"linter": {
"rules": {
"style": {
"useFilenamingConvention": {
"level": "warn",
"options": {
"match": "%?(.+?)[.](.+)",
"filenameCases": ["camelCase"]
}
}
}
}
}
}
```

If the regular expression captures strings, the first capture is considered to be the name of the file, and the second one to be the extensions (dot-separated values).
The name of the file and the extensions are checked against `filenameCases`.
Given the previous configuration, the filename `%index.d.ts` is valid because the first capture `index` is in `camelCase` and the second capture `d.ts` include dot-separated values in `lowercase`.
On the other hand, `%Index.d.ts` is not valid because the first capture `Index` is in `PascalCase`.

Note that specifying `match` disallows any exceptions that are handled by the rule by default.
For example, the previous configuration doesn't allow filenames to be prefixed with underscores,
a period or a plus sign.
You need to include them in the regular expression if you still want to allow these exceptions.

Contributed by @Conaclos

- [useFilenamingConvention](https://biomejs.dev/linter/rules/use-filenaming-convention) and [useNamingConvention](https://biomejs.dev/linter/rules/use-naming-convention) `match` options now accept case-insensitive and case-sensitive groups.

By default, the regular expression in `match` is case-sensitive.
You can now make it case-insensitive by using a case-insensitive group `(?i:)`.
For example, the regular expression `(?i:a)` matches `a` and `A`.

Contributed by @Conaclos

### Parser

#### New features

- Add support for parsing the defer attribute in import statements ([#4215](https://github.com/biomejs/biome/issues/4215)).

```js
Expand Down
2 changes: 1 addition & 1 deletion crates/biome_cli/src/execute/migrate/eslint_typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use biome_deserialize_macros::Deserializable;
use biome_js_analyze::{
lint::nursery::use_consistent_member_accessibility,
lint::style::{use_consistent_array_type, use_naming_convention},
utils::regex::RestrictedRegex,
utils::restricted_regex::RestrictedRegex,
};

use super::eslint_eslint;
Expand Down
1 change: 1 addition & 0 deletions crates/biome_cli/src/execute/migrate/eslint_unicorn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl From<FilenameCaseOptions> for use_filenaming_convention::FilenamingConventi
use_filenaming_convention::FilenamingConventionOptions {
strict_case: true,
require_ascii: true,
matching: None,
filename_cases: filename_cases.unwrap_or_else(|| {
use_filenaming_convention::FilenameCases::from_iter([val.case.into()])
}),
Expand Down
1 change: 1 addition & 0 deletions crates/biome_formatter/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ macro_rules! format {
#[macro_export]
macro_rules! best_fitting {
($least_expanded:expr, $($tail:expr),+ $(,)?) => {{
#[allow(clippy::macro_metavars_in_unsafe)]
unsafe {
$crate::BestFitting::from_arguments_unchecked($crate::format_args!($least_expanded, $($tail),+))
}
Expand Down
23 changes: 20 additions & 3 deletions crates/biome_grit_formatter/src/grit/auxiliary/like.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
use crate::prelude::*;
use biome_grit_syntax::GritLike;
use biome_rowan::AstNode;
use biome_formatter::write;
use biome_grit_syntax::{GritLike, GritLikeFields};
#[derive(Debug, Clone, Default)]
pub(crate) struct FormatGritLike;
impl FormatNodeRule<GritLike> for FormatGritLike {
fn fmt_fields(&self, node: &GritLike, f: &mut GritFormatter) -> FormatResult<()> {
format_verbatim_node(node.syntax()).fmt(f)
let GritLikeFields {
like_token,
l_curly_token,
example,
threshold,
r_curly_token,
} = node.as_fields();

write!(
f,
[
like_token.format(),
l_curly_token.format(),
example.format(),
threshold.format(),
r_curly_token.format()
]
)
}
}
11 changes: 6 additions & 5 deletions crates/biome_grit_formatter/src/grit/lists/predicate_list.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use crate::prelude::*;
use biome_grit_syntax::GritPredicateList;

#[derive(Debug, Clone, Default)]
pub(crate) struct FormatGritPredicateList;
impl FormatRule<GritPredicateList> for FormatGritPredicateList {
type Context = GritFormatContext;
fn fmt(&self, node: &GritPredicateList, f: &mut GritFormatter) -> FormatResult<()> {
let mut join = f.join_nodes_with_hardline();
let separator = soft_line_break_or_space();
let mut joiner = f.join_with(&separator);

for predicate in node {
let predicate = predicate?;
join.entry(predicate.syntax(), &format_or_verbatim(predicate.format()));
for formatted in node.format_separated(",") {
joiner.entry(&group(&indent(&formatted)));
}

join.finish()
joiner.finish()
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::prelude::*;
use biome_grit_syntax::GritPredicateAccumulate;
use biome_rowan::AstNode;
use biome_formatter::write;
use biome_grit_syntax::{GritPredicateAccumulate, GritPredicateAccumulateFields};

#[derive(Debug, Clone, Default)]
pub(crate) struct FormatGritPredicateAccumulate;
impl FormatNodeRule<GritPredicateAccumulate> for FormatGritPredicateAccumulate {
Expand All @@ -9,6 +10,21 @@ impl FormatNodeRule<GritPredicateAccumulate> for FormatGritPredicateAccumulate {
node: &GritPredicateAccumulate,
f: &mut GritFormatter,
) -> FormatResult<()> {
format_verbatim_node(node.syntax()).fmt(f)
let GritPredicateAccumulateFields {
left,
add_assign_token,
right,
} = node.as_fields();

write!(
f,
[
left.format(),
space(),
add_assign_token.format(),
space(),
right.format()
]
)
}
}
21 changes: 18 additions & 3 deletions crates/biome_grit_formatter/src/grit/predicates/predicate_match.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
use crate::prelude::*;
use biome_grit_syntax::GritPredicateMatch;
use biome_rowan::AstNode;
use biome_formatter::write;
use biome_grit_syntax::{GritPredicateMatch, GritPredicateMatchFields};
#[derive(Debug, Clone, Default)]
pub(crate) struct FormatGritPredicateMatch;
impl FormatNodeRule<GritPredicateMatch> for FormatGritPredicateMatch {
fn fmt_fields(&self, node: &GritPredicateMatch, f: &mut GritFormatter) -> FormatResult<()> {
format_verbatim_node(node.syntax()).fmt(f)
let GritPredicateMatchFields {
left,
match_token,
right,
} = node.as_fields();

write!(
f,
[
left.format(),
space(),
match_token.format(),
space(),
right.format()
]
)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
use crate::prelude::*;
use biome_grit_syntax::GritPredicateRewrite;
use biome_rowan::AstNode;
use biome_formatter::write;
use biome_grit_syntax::{GritPredicateRewrite, GritPredicateRewriteFields};

#[derive(Debug, Clone, Default)]
pub(crate) struct FormatGritPredicateRewrite;
impl FormatNodeRule<GritPredicateRewrite> for FormatGritPredicateRewrite {
fn fmt_fields(&self, node: &GritPredicateRewrite, f: &mut GritFormatter) -> FormatResult<()> {
format_verbatim_node(node.syntax()).fmt(f)
let GritPredicateRewriteFields {
annotation,
left,
fat_arrow_token,
right,
} = node.as_fields();

write!(
f,
[
annotation.format(),
space(),
left.format(),
space(),
fat_arrow_token.format(),
space(),
right.format()
]
)
}
}
1 change: 1 addition & 0 deletions crates/biome_grit_formatter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod cst;
mod generated;
mod grit;
mod prelude;
pub(crate) mod separated;

use biome_formatter::{
comments::Comments,
Expand Down
10 changes: 5 additions & 5 deletions crates/biome_grit_formatter/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
#[allow(unused_imports)]
pub(crate) use crate::{
AsFormat, FormatNodeRule, FormattedIterExt as _, GritFormatContext, GritFormatter, IntoFormat,
AsFormat, FormatNodeRule, FormattedIterExt as _, FormattedIterExt, GritFormatContext,
GritFormatter, IntoFormat,
};
pub(crate) use biome_formatter::prelude::*;
#[allow(unused_imports)]
pub(crate) use biome_rowan::{
AstNode as _, AstNodeList as _, AstNodeSlotMap as _, AstSeparatedList as _,
};
pub(crate) use biome_rowan::{AstNode as _, AstSeparatedList};

pub(crate) use crate::separated::FormatAstSeparatedListExtension;
63 changes: 63 additions & 0 deletions crates/biome_grit_formatter/src/separated.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use biome_formatter::{
separated::{FormatSeparatedElementRule, FormatSeparatedIter},
FormatRefWithRule,
};

use crate::prelude::*;
use biome_grit_syntax::{GritLanguage, GritSyntaxToken};
use biome_rowan::{AstNode, AstSeparatedListElementsIterator};
use std::marker::PhantomData;

use crate::{cst::FormatGritSyntaxToken, AsFormat, GritFormatContext};

#[derive(Clone)]
pub(crate) struct GritFormatSeparatedElementRule<N>
where
N: AstNode<Language = GritLanguage>,
{
node: PhantomData<N>,
}

impl<N> FormatSeparatedElementRule<N> for GritFormatSeparatedElementRule<N>
where
N: AstNode<Language = GritLanguage> + AsFormat<GritFormatContext> + 'static,
{
type Context = GritFormatContext;
type FormatNode<'a> = N::Format<'a>;
type FormatSeparator<'a> = FormatRefWithRule<'a, GritSyntaxToken, FormatGritSyntaxToken>;

fn format_node<'a>(&self, node: &'a N) -> Self::FormatNode<'a> {
node.format()
}

fn format_separator<'a>(&self, separator: &'a GritSyntaxToken) -> Self::FormatSeparator<'a> {
separator.format()
}
}

type GritFormatSeparatedIter<Node> = FormatSeparatedIter<
AstSeparatedListElementsIterator<GritLanguage, Node>,
Node,
GritFormatSeparatedElementRule<Node>,
>;

/// AST Separated list formatting extension methods
pub(crate) trait FormatAstSeparatedListExtension:
AstSeparatedList<Language = GritLanguage>
{
/// Prints a separated list of nodes
///
/// Trailing separators will be reused from the original list or
/// created by calling the `separator_factory` function.
/// The last trailing separator in the list will only be printed
/// if the outer group breaks.
fn format_separated(&self, separator: &'static str) -> GritFormatSeparatedIter<Self::Node> {
GritFormatSeparatedIter::new(
self.elements(),
separator,
GritFormatSeparatedElementRule { node: PhantomData },
)
}
}

impl<T> FormatAstSeparatedListExtension for T where T: AstSeparatedList<Language = GritLanguage> {}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`function $functionName($_) {$_}` as $f where{ $functionName<:r"test.*",$f=>.,$new_file_name=`$functionName.test.js`,$new_files+=file(name = $new_file_name, body = $f)}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
source: crates/biome_formatter_test/src/snapshot_builder.rs
info: grit/patterns/create_new_files.grit
---
# Input

```grit
`function $functionName($_) {$_}` as $f where{ $functionName<:r"test.*",$f=>.,$new_file_name=`$functionName.test.js`,$new_files+=file(name = $new_file_name, body = $f)}
```


=============================

# Outputs

## Output 1

-----
Indent style: Tab
Indent width: 2
Line ending: LF
Line width: 80
Attribute Position: Auto
-----

```grit
`function $functionName($_) {$_}` as $f where {
$functionName <: r"test.*",
$f => .,
$new_file_name = `$functionName.test.js`,
$new_files += file(name = $new_file_name, body = $f)
}
```



## Unimplemented nodes/tokens

"`function $functionName($_) {$_}` as $f " => 0..40
"\t$functionNam" => 48..61
" r\"test.*" => 65..74
"\t$" => 77..79
" " => 83..84
"\t$new_file_nam" => 87..101
" `$functionName.test.js" => 104..127
"\t$new_file" => 130..140
" file(name = $new_file_name, body = $f" => 144..182
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl Rule for NoFlatMapIdentity {
AnyJsExpression::JsArrowFunctionExpression(arg) => {
let parameter: String = match arg.parameters().ok()? {
biome_js_syntax::AnyJsArrowFunctionParameters::AnyJsBinding(p) => {
p.text().trim_matches(&['(', ')']).to_owned()
p.text().trim_matches(['(', ')']).to_owned()
}
biome_js_syntax::AnyJsArrowFunctionParameters::JsParameters(p) => {
if p.items().len() == 1 {
Expand Down Expand Up @@ -110,8 +110,7 @@ impl Rule for NoFlatMapIdentity {
}
AnyJsExpression::JsFunctionExpression(arg) => {
let function_parameter = arg.parameters().ok()?.text();
let function_parameter =
function_parameter.trim_matches(&['(', ')']).to_owned();
let function_parameter = function_parameter.trim_matches(['(', ')']).to_owned();

let mut statement = arg.body().ok()?.statements().into_iter();
if let Some(AnyJsStatement::JsReturnStatement(body)) = statement.next() {
Expand Down
Loading

0 comments on commit b0eb8d5

Please sign in to comment.