Skip to content

Commit

Permalink
feat(grit): implement CSS plugins (#4448)
Browse files Browse the repository at this point in the history
  • Loading branch information
arendjr authored Nov 2, 2024
1 parent ad8d7bd commit ce96c2a
Show file tree
Hide file tree
Showing 36 changed files with 610 additions and 111 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions crates/biome_analyze/src/analyzer_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ use std::{fmt::Debug, path::PathBuf};
/// Definition of an analyzer plugin.
pub trait AnalyzerPlugin: Debug {
fn evaluate(&self, root: AnyParse, path: PathBuf) -> Vec<RuleDiagnostic>;

fn supports_css(&self) -> bool;

fn supports_js(&self) -> bool;
}
1 change: 1 addition & 0 deletions crates/biome_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ biome_diagnostics = { workspace = true }
biome_flags = { workspace = true }
biome_formatter = { workspace = true }
biome_fs = { workspace = true }
biome_grit_patterns = { workspace = true }
biome_js_analyze = { workspace = true }
biome_js_formatter = { workspace = true }
biome_json_formatter = { workspace = true }
Expand Down
11 changes: 11 additions & 0 deletions crates/biome_cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use biome_configuration::{BiomeDiagnostic, PartialConfiguration};
use biome_console::{markup, Console, ConsoleExt};
use biome_diagnostics::PrintDiagnostic;
use biome_fs::{BiomePath, FileSystem};
use biome_grit_patterns::GritTargetLanguage;
use biome_service::configuration::{
load_configuration, load_editorconfig, LoadedConfiguration, PartialConfigurationExt,
};
Expand Down Expand Up @@ -440,6 +441,16 @@ pub enum BiomeCommand {
#[bpaf(long("stdin-file-path"), argument("PATH"), hide_usage)]
stdin_file_path: Option<String>,

/// The language to which the pattern applies.
///
/// Grit queries are specific to the grammar of the language they
/// target, so we currently do not support writing queries that apply
/// to multiple languages at once.
///
/// If none given, the default language is JavaScript.
#[bpaf(long("language"), short('l'))]
language: Option<GritTargetLanguage>,

/// The GritQL pattern to search for.
///
/// Note that the search command (currently) does not support rewrites.
Expand Down
8 changes: 6 additions & 2 deletions crates/biome_cli/src/commands/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use biome_configuration::{
use biome_console::Console;
use biome_deserialize::Merge;
use biome_fs::FileSystem;
use biome_grit_patterns::GritTargetLanguage;
use biome_service::configuration::LoadedConfiguration;
use biome_service::workspace::ParsePatternParams;
use biome_service::{DynRef, Workspace, WorkspaceError};
Expand All @@ -16,6 +17,7 @@ pub(crate) struct SearchCommandPayload {
pub(crate) files_configuration: Option<PartialFilesConfiguration>,
pub(crate) paths: Vec<OsString>,
pub(crate) pattern: String,
pub(crate) language: Option<GritTargetLanguage>,
pub(crate) stdin_file_path: Option<String>,
pub(crate) vcs_configuration: Option<PartialVcsConfiguration>,
}
Expand Down Expand Up @@ -59,17 +61,19 @@ impl CommandRunner for SearchCommandPayload {
fn get_execution(
&self,
cli_options: &CliOptions,
_console: &mut dyn Console,
console: &mut dyn Console,
workspace: &dyn Workspace,
) -> Result<Execution, CliDiagnostic> {
let pattern = workspace
.parse_pattern(ParsePatternParams {
pattern: self.pattern.clone(),
default_language: self.language.clone().unwrap_or_default(),
})?
.pattern_id;
Ok(Execution::new(TraversalMode::Search {
pattern,
stdin: self.get_stdin(_console)?,
language: self.language.clone(),
stdin: self.get_stdin(console)?,
})
.set_report(cli_options))
}
Expand Down
10 changes: 10 additions & 0 deletions crates/biome_cli/src/execute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use biome_console::{markup, ConsoleExt};
use biome_diagnostics::adapters::SerdeJsonError;
use biome_diagnostics::{category, Category};
use biome_fs::BiomePath;
use biome_grit_patterns::GritTargetLanguage;
use biome_service::workspace::{
FeatureName, FeaturesBuilder, FixFileMode, FormatFileParams, OpenFileParams, PatternId,
};
Expand Down Expand Up @@ -197,6 +198,15 @@ pub enum TraversalMode {
/// Note that the search command does not support rewrites.
pattern: PatternId,

/// The language to query for.
///
/// Grit queries are specific to the grammar of the language they
/// target, so we currently do not support writing queries that apply
/// to multiple languages at once.
///
/// If none given, the default language is JavaScript.
language: Option<GritTargetLanguage>,

/// An optional tuple.
/// 1. The virtual path to the file
/// 2. The content of the file
Expand Down
2 changes: 2 additions & 0 deletions crates/biome_cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ impl<'app> CliSession<'app> {
files_configuration,
paths,
pattern,
language,
stdin_file_path,
vcs_configuration,
} => run_command(
Expand All @@ -258,6 +259,7 @@ impl<'app> CliSession<'app> {
files_configuration,
paths,
pattern,
language,
stdin_file_path,
vcs_configuration,
},
Expand Down
1 change: 1 addition & 0 deletions crates/biome_cli/tests/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ mod migrate;
mod migrate_eslint;
mod migrate_prettier;
mod rage;
mod search;
mod version;
118 changes: 118 additions & 0 deletions crates/biome_cli/tests/commands/search.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use biome_console::BufferConsole;
use biome_fs::MemoryFileSystem;
use biome_service::DynRef;
use bpaf::Args;
use std::path::Path;

use crate::{
run_cli,
snap_test::{assert_cli_snapshot, SnapshotPayload},
};

// Feel free to add content at the end of this dummy file. It shouldn't affect
// existing tests.
const CSS_FILE_CONTENT: &str = r#"div {
color: green;
}"#;

// Feel free to add content at the end of this dummy file. It shouldn't affect
// existing tests.
const JS_FILE_CONTENT: &str = r#"const a = 'foo';"#;

#[test]
fn search_css_pattern() {
let mut fs = MemoryFileSystem::default();
let mut console = BufferConsole::default();

let file_path = Path::new("file.css");
fs.insert(file_path.into(), CSS_FILE_CONTENT.as_bytes());

let result = run_cli(
DynRef::Borrowed(&mut fs),
&mut console,
Args::from(
[
"search",
"--language=css",
"`color: green`",
file_path.as_os_str().to_str().unwrap(),
]
.as_slice(),
),
);

assert!(result.is_ok(), "run_cli returned {result:?}");

assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"search_css_pattern",
fs,
console,
result,
));
}

#[test]
fn search_css_pattern_shorthand() {
let mut fs = MemoryFileSystem::default();
let mut console = BufferConsole::default();

let file_path = Path::new("file.css");
fs.insert(file_path.into(), CSS_FILE_CONTENT.as_bytes());

let result = run_cli(
DynRef::Borrowed(&mut fs),
&mut console,
Args::from(
[
"search",
"-lcss",
"`color: green`",
file_path.as_os_str().to_str().unwrap(),
]
.as_slice(),
),
);

assert!(result.is_ok(), "run_cli returned {result:?}");

assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"search_css_pattern_shorthand",
fs,
console,
result,
));
}

#[test]
fn search_js_pattern() {
let mut fs = MemoryFileSystem::default();
let mut console = BufferConsole::default();

let file_path = Path::new("file.js");
fs.insert(file_path.into(), JS_FILE_CONTENT.as_bytes());

let result = run_cli(
DynRef::Borrowed(&mut fs),
&mut console,
Args::from(
[
"search",
"`\"foo\"`",
file_path.as_os_str().to_str().unwrap(),
]
.as_slice(),
),
);

assert!(result.is_ok(), "run_cli returned {result:?}");

assert_cli_snapshot(SnapshotPayload::new(
module_path!(),
"search_js_pattern",
fs,
console,
result,
));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: content
---
## `file.css`

```css
div {
color: green;
}
```

# Emitted Messages

```block
file.css:2:5 search ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2 │ color: green;
```

```block
Searched 1 file in <TIME>. Found 1 match.
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: content
---
## `file.css`

```css
div {
color: green;
}
```

# Emitted Messages

```block
file.css:2:5 search ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2 │ color: green;
```

```block
Searched 1 file in <TIME>. Found 1 match.
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
source: crates/biome_cli/tests/snap_test.rs
expression: content
---
## `file.js`

```js
const a = 'foo';
```

# Emitted Messages

```block
file.js:1:11 search ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1 │ const a = 'foo';
```

```block
Searched 1 file in <TIME>. Found 1 match.
```
10 changes: 6 additions & 4 deletions crates/biome_css_analyze/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ schemars = { workspace = true, optional = true }
serde = { workspace = true, features = ["derive"] }

[dev-dependencies]
biome_css_parser = { path = "../biome_css_parser" }
biome_test_utils = { path = "../biome_test_utils" }
insta = { workspace = true, features = ["glob"] }
tests_macros = { path = "../tests_macros" }
biome_css_parser = { path = "../biome_css_parser" }
biome_fs = { workspace = true }
biome_plugin_loader = { workspace = true }
biome_test_utils = { path = "../biome_test_utils" }
insta = { workspace = true, features = ["glob"] }
tests_macros = { path = "../tests_macros" }

[features]
schema = ["schemars"]
Expand Down
Loading

0 comments on commit ce96c2a

Please sign in to comment.