From ca94eb0cca378a6c311873bf3bcb17341e7dc806 Mon Sep 17 00:00:00 2001 From: Cookie <34422996+CookieDasora@users.noreply.github.com> Date: Fri, 12 Jan 2024 18:06:13 +0000 Subject: [PATCH 01/49] docs(pt-br): translated git hooks page (#1498) Co-authored-by: Victor <78874691+victor-teles@users.noreply.github.com> --- website/astro.config.ts | 3 + .../docs/pt-br/guides/integrate-in-vcs.mdx | 68 +++++ website/src/content/docs/pt-br/index.mdx | 211 ++++++++++++++-- .../content/docs/pt-br/recipes/git-hooks.mdx | 234 ++++++++++++++++++ 4 files changed, 489 insertions(+), 27 deletions(-) create mode 100644 website/src/content/docs/pt-br/guides/integrate-in-vcs.mdx create mode 100644 website/src/content/docs/pt-br/recipes/git-hooks.mdx diff --git a/website/astro.config.ts b/website/astro.config.ts index b1247651fdd6..ef4c14eefe4a 100644 --- a/website/astro.config.ts +++ b/website/astro.config.ts @@ -138,6 +138,9 @@ export default defineConfig({ { label: "Integrate Biome with your VCS", link: "/guides/integrate-in-vcs", + translations: { + "pt-BR": "Integrando o Biome com o seu VCS", + }, }, ], }, diff --git a/website/src/content/docs/pt-br/guides/integrate-in-vcs.mdx b/website/src/content/docs/pt-br/guides/integrate-in-vcs.mdx new file mode 100644 index 000000000000..4424bbd8305f --- /dev/null +++ b/website/src/content/docs/pt-br/guides/integrate-in-vcs.mdx @@ -0,0 +1,68 @@ +--- +title: Integrando o Biome com o seu VCS +description: Aprenda como o Biome funciona, incluindo suposições, configuração e mais. +--- + + +A integração com o VCS (Sistema de controle de versão) é projetada para aproveitar recursos **adicionais** que somente um VCS pode fornecer, permitindo customizar +sua experiência ainda mais. + +Essa integração é **opcional** e possui dois campos obrigatórios. O campo `vcs.enabled` e o campo `vcs.clientKind`, ambos no arquivo de configuração: + +```json title="biome.json" +{ + "vcs": { + "enabled": true, + "clientKind": "git" + } +} +``` + +Essa configuração não faz **nada por si só**. Você precisa adicionar novos recursos. + +### Ignorando arquivos + +Esse é um recurso que permite que o Biome leia os arquivos ignorados do VCS e ignora todos os arquivos e pastas especificados nele. Esse é um recurso opcional, e você precisa ativar o campo `vcs.useIgnoreFile`: + +```json title="biome.json" ins={5} +{ + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + } +} +``` + +### Processando apenas arquivos modificados + +Esse é um recurso que só está disponível via CLI e permite processar **apenas** os arquivos que foram **alterados** de uma revisão para outra. + +Primeiro, você tem que atualizar seu arquivo de configuração e dizer para o Biome qual é a branch padrão com o campo `vcs.defaultBranch`: + +```json title="biome.json" ins={6} +{ + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true, + "defaultBranch": "main" + } +} +``` + +Em seguida, adicione a opção `--changed` no seu comando para processar apenas os arquivos que o seu VCS marcar como "modificado". O Biome, com ajuda do VCS, vai determinar o arquivo alterado da branch `main` e sua revisão atual: + +```shell +biome format --changed +``` + +:::caution +O Biome não verifica o que foi alterado, isso significa que adicionar espaços e novas linhas em um arquivo vai marcar-lo como "modificado" +::: + +Alternativamente, você pode usar a opção `--since` para especificar uma branch. Essa opção **tem precedência** sobre a opção `vcs.defaultBranch`. Por exemplo, você pode querer verificar suas alterações em relação a branch `next`: + +```shell +biome format --changed --since=next +``` diff --git a/website/src/content/docs/pt-br/index.mdx b/website/src/content/docs/pt-br/index.mdx index c3b137b31011..fb4a31e57142 100644 --- a/website/src/content/docs/pt-br/index.mdx +++ b/website/src/content/docs/pt-br/index.mdx @@ -2,9 +2,11 @@ title: Biome head: - tag: title - content: Biome, toolchain of the web + content: Biome, conjunto de ferramentas da web template: splash description: Formate, verifique erros e muito mais em uma fração de segundo. +editUrl: false +next: false hero: title: Um conjunto de ferramentas para seu projeto web tagline: Formate, verifique erros e muito mais em uma fração de segundo. @@ -24,35 +26,190 @@ hero: --- import { Card, CardGrid } from "@astrojs/starlight/components"; +import Inputf from "@src/components/formatter/input.md"; +import Outputf from "@src/components/formatter/output.md"; +import ProgressBar from "../../../playground/components/Progress.tsx"; +import Community from "@src/components/Community.astro"; +import { Icon } from "@astrojs/starlight/components"; +import arrow from "../../../assets/svg/arrow-right.svg"; +import { Image } from "astro:assets"; +import "../../../styles/_performance.scss"; +import "../../../styles/_installation.scss"; +import "../../../styles/_community.scss"; import Netlify from "@src/components/Netlify.astro"; import Sponsors from "@src/components/Sponsors.astro"; +import LinterExample from "@src/components/linter/example.md"; - - - Construído com Rust e uma arquitetura inovadora inspirado pelo - rust-analyzer. - - - Nenhuma configuração é necessária para começar a usar! Caso precise, temos - diversas opções disponíveis! - - - Projetado para suportar codebases de qualquer tamanho. Focado no crescimento - do projeto, em vez de suas ferramentas. - - - Com uma integração interna eficiente, conseguimos reutilizar trabalhos - anteriores, e qualquer melhoria em uma ferramenta beneficia todas elas. - - - Esqueça aquelas mensagens de erro obscuras! Quando alguma coisa está errada, - nós falamos exatamente o que está errado e como consertar! - - - Suporte pronto para todas as funcionalidades de linguagem que você utiliza - atualmente. Suporte de primeira classe para TypeScript e JSX. - - + +
+
+ + +
+

Formata código como o Prettier e economiza tempo

+ + **Biome é um [formatador rápido](https://github.com/biomejs/biome/tree/main/benchmark#formatting)** para _JavaScript_, _TypeScript_, _JSX_, e _JSON_ que atinge **[97% de compatibilidade com o _Prettier_](https://console.algora.io/challenges/prettier)**, **economizando tempo para o desenvolvedor e para o CI**. + + O Biome pode até **formatar código malformado** enquanto você programa no seu [editor favorito](/pt-br/guides/integrate-in-editor/). + +
+
+ CÓDIGO + +
+
+ SAÍDA + +
+
+ PERFORMANCE +
+
+
+ + +
+
+
+
~35x
+
+ Mais rápido que o Prettier quando formata 171,217 linhas de código em 2,104 arquivos com um Intel Core i7 1270P. +
+
+
+
+
+ + + Teste o formatador do Biome no [playground](/playground/) ou diretamente no seu projeto: + + ```shell + npm i -D --save-exact @biomejs/biome + npx @biomejs/biome format --write ./src + ``` +
+ + +
+

Corrija problemas e aprenda boas práticas

+ + **O Biome é um [linter performático](https://github.com/biomejs/biome/tree/main/benchmark#linting)** para _JavaScript_, _TypeScript_, e _JSX_ que possui **[mais de 190 regras](https://biomejs.dev/pt-br/linter/rules/)** do ESLint, TypeScript ESLint, e [de outras fontes](https://github.com/biomejs/biome/discussions/3). + + **O Biome retorna diagnósticos detalhados e contextualizados** que ajuda a melhorar seu código e ajuda você a se tornar um programador melhor! + + + + Teste o linter do Biome no [playground](/playground/) ou diretamente no seu projeto: + + ```shell + npm i -D --save-exact @biomejs/biome + npx @biomejs/biome lint --apply ./src + ``` + +
+ + +
+

Tudo de uma vez

+ + Não só como você pode formatar e analisar erros no seu código separadamente, você pode fazer **tudo isso com um comando**! + + Cada ferramenta integra suavemente com as outras para criar um **conjunto de ferramentas coesivo** para projetos web. + + Rode todas as ferramentas com o comando `check` + + ```shell + npm i -D --save-exact @biomejs/biome + npx @biomejs/biome check --apply ./src + ``` + +
+ + + +
+ + + + Construído com Rust e uma arquitetura inovadora inspirado pelo rust-analyzer. + + + Nenhuma configuração é necessária para começar a usar! Caso precise, temos + diversas opções disponíveis! + + + Projetado para suportar codebases de qualquer tamanho. Focado no crescimento + do projeto, em vez de suas ferramentas. + + + Com uma integração interna eficiente, conseguimos reutilizar trabalhos + anteriores, e qualquer melhoria em uma ferramenta beneficia todas elas. + + + Esqueça aquelas mensagens de erro obscuras! Quando alguma coisa está errada, + nós falamos exatamente o que está errado e como consertar! + + + Suporte pronto para todas as funcionalidades de linguagem que você utiliza + atualmente. Suporte de primeira classe para TypeScript e JSX. + + +
+
+
+
+

Experimente o Biome

+
+ Instale o Biome utilizando o seu gerenciador de pacotes favorito e integre ele no seu editor. +
+ + Instale com um gerenciador de pacotes + arrow + + + Integre o Biome no seu editor + arrow + +
+ +
+ +
+
+ +
+
+

Comunidade

+
+
+ Desenvolvido pela nossa incrível comunidade +
+ +
+
+ +
+
diff --git a/website/src/content/docs/pt-br/recipes/git-hooks.mdx b/website/src/content/docs/pt-br/recipes/git-hooks.mdx new file mode 100644 index 000000000000..e9b6b98d7568 --- /dev/null +++ b/website/src/content/docs/pt-br/recipes/git-hooks.mdx @@ -0,0 +1,234 @@ +--- +title: Git Hooks +description: Usando o Biome com Git Hooks +--- + +O Git permite executar scripts durante a execução de comandos git utilizando o [Git Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). +Você pode, por exemplo, formatar e lintar arquivos em stage antes de efetuar o commit ou push. +Existem diversas ferramentas para simplificar o gerenciamento do Git Hooks. +Nas próximas seções iremos introduzir algumas delas e como elas podem ser utilizadas com o Biome. + + +## Lefthook + +[Lefthook](https://github.com/evilmartians/lefthook) é um hook manager rápido, multiplataforma e livre de dependências. +Ele pode ser [instalado via NPM](https://github.com/evilmartians/lefthook#install). + + +Crie um arquivo chamado `lefthook.yml` na raíz do seu repositório Git. +Alguns exemplos de configurações: + +- Formatar e verificar erros antes de efetuar o commit. + + ```yaml title="lefthook.yml" + pre-commit: + commands: + check: + glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}" + run: npx biome check --no-errors-on-unmatched --files-ignore-unknown=true {staged_files} + ``` + +- Formatar, verificar erros e aplicar correções seguras antes de efetuar o commit. + + ```yaml title="lefthook.yml" + pre-commit: + commands: + check: + glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}" + run: npx biome check --apply --no-errors-on-unmatched --files-ignore-unknown=true {staged_files} && git update-index --again + ``` + + `git update-index --again` adiciona novamente os arquivos em stage. + +- Formatar e verificar erros antes de fazer o push. + + ```yaml title="lefthook.yml" + pre-push: + commands: + check: + glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}" + run: npx biome check --no-errors-on-unmatched --files-ignore-unknown=true {pushed_files} + ``` + +Não é necessário utilizar tanto `glob` quanto `--files-ignore-unknown=true`. +Utilizando apenas `--files-ignore-unknown=true` permite que os arquivos suportados sejam lidados pelo Biome. +Se você deseja mais controle sobre os arquivos que são lidados, você deve usar `glob` + +`--no-errors-on-unmatched` silencia possíveis erros no caso de *nenhum arquivo ser processado*. + +Uma vez configurado, execute `lefthook install` para inicializar os hooks. + +Se o seu projeto possuí um `package.json`, +você pode configurar automaticamente os hooks do _Lefthook_ após a instalação do pacote usando `scripts.postinstall`: + + +```json title="package.json" +{ + "scripts": { + "postinstall": "lefthook install" + } +} +``` + + +## Husky + +[Husky](https://github.com/typicode/husky) é um hook manager amplamente utilizado no ecossistema JavaScript. +O Husky não esconde alterações unstaged e não é capaz de fornecer uma lista de arquivos em stage. +Por isso que ele é normalmente utilizado em conjunto com outra ferramenta como _lint-staged_ ou _git-format-staged_. + +Se o seu projeto contém um `package.json`, +você pode configurar automaticamente os hooks do _husky_ após a instalação do pacote usando `scripts.postinstall`: + +```json title="package.json" +{ + "scripts": { + "postinstall": "husky install" + } +} +``` + +### lint-staged + +[lint-staged](https://github.com/lint-staged/lint-staged) é uma das ferramentas mais utilizadas no ecossistema JavaScript. + +Adicione o seguinte no arquivo de configuração do husky: + +```shell title=".husky/pre-commit" +lint-staged +``` + +O arquivo de configuração do lint-staged está ligada diretamente no `package.json`. +Aqui alguns exemplos de comandos que podem ser úteis ao executar os Git hooks: + +```jsonc title="package.json" +{ + "lint-staged": { + // Executa o Biome em arquivos em stage que possui as seguintes extensões: js, ts, jsx, tsx, json e jsonc. + "**.{js|ts|cjs|mjs|d.cts|d.mts|jsx|tsx|json|jsonc}": [ + "biome check --files-ignore-unknown=true", // Formatar e verificar erros. + "biome check --apply --no-errors-on-unmatched", // Formatar, organizar importações, verificar erros e aplicar correções seguras. + "biome check --apply --organize-imports-enabled=false --no-errors-on-unmatched", // Formatar e aplicar correções seguras. + "biome check --apply-unsafe --no-errors-on-unmatched", // Formatar, organizar importações, verificar erros e aplicar correções seguras e não seguras. + "biome format --write --no-errors-on-unmatched", // Formatação + "biome lint --apply --no-errors-on-unmatched", // Verificar erros e aplicar correções seguras. + ], + // Você pode também passar todos os arquivos e ignorar extensões desconhecidas. + "*": [ + "biome check --no-errors-on-unmatched --files-ignore-unknown=true", // Formatar e verificar erros. + ] + } +} +``` + +Lembre-se de usar a opção do CLI `--no-errors-on-unmatched` no seu comando para silenciar possíveis erros no caso de *nenhum arquivo ser processado*. + + +### git-format-staged + +Em constrate a outras ferramentas como _lefthook_, _pre-commit_ e _lint-staged_, +[git-format-staged](https://github.com/hallettj/git-format-staged) não utiliza `git stash` internamente. +Isso evita intervenção manual quando acontece um conflito entre alterações unstaged e alterações em stage. +Veja a [comparação do _git-format-staged_ com outras ferramentas](https://github.com/hallettj/git-format-staged#comparisons-to-similar-utilities). + +Veja alguns exemplos de configuração: + +- Formatar e verificar erros antes de efetuar o commit + + ```shell title=".husky/pre-commit" + git-format-staged --formatter 'biome check --files-ignore-unknown=true --no-errors-on-unmatched \"{}\"' . + ``` + +- Formatar, verificar erros e aplicar correções seguras antes de efetuar o commit + + ```shell title=".husky/pre-commit" + git-format-staged --formatter 'biome check --apply --files-ignore-unknown=true --no-errors-on-unmatched \"{}\"' . + ``` + + +## pre-commit + +[pre-commit](https://pre-commit.com/) é um hook manager multilíngue. +O Biome fornece quatro [pre-commit](https://pre-commit.com/) hooks por meio do repositório [biomejs/pre-commit](https://github.com/biomejs/pre-commit). + +| hook `id` | Descrição | +| --------------- | -------------------------------------------------------------------------------------------------- | +| `biome-ci` | Formata, verifica se as importações estão organizadas e verifica erros | +| `biome-check` | Formata, organiza as importações, verifica erros e aplica correções seguras nos arquivos do commit | +| `biome-format` | Formata os arquivos do commit | +| `biome-lint` | Verifica erros e aplica correções seguras nos arquivos do commit | + +No exemplo a seguir, assumimos que você [instalou o pre-commit](https://pre-commit.com/index.html#install) e executou o comando `pre-commit install` no seu repositório. +Se você quiser usar o hook `biome-check`, adicione a seguinte configuração na raíz do seu projeto em um arquivo chamado `.pre-commit-config.yaml`: + +```yaml title=".pre-commit-config.yaml" +repos: +- repo: https://github.com/biomejs/pre-commit + rev: "0.1.0" # Use the sha / tag you want to point at + hooks: + - id: biome-check + additional_dependencies: ["@biomejs/biome@1.4.1"] +``` + +Isso vai rodar o comando `biome check --apply` quando você executar `git commit`. + +Observe que você deve especificar a versão do Biome para usar devido a opção `additional_dependencies`. +O [pre-commit](https://pre-commit.com/) instala separadamente as ferramentas e sabe qual instalar. + +Se o Biome já está instalado como um pacote `npm` no seu repositório local, +então pode ser um fardo atualizar tanto o `package.json` e o `.pre-commit-config.yaml` quando você atualiza o Biome. +Em vez de utilizar os hooks que o Biome fornece, você pode especificar o seu próprio [hook local](https://pre-commit.com/index.html#repository-local-hooks). + +Por exemplo, se você usa o `npm`, você pode escrever o seguinte hook em `.pre-commit-config.yaml`: + +```yaml title=".pre-commit-config.yaml" +repos: + - repo: local + hooks: + - id: local-biome-check + name: biome check + entry: npx biome check --apply --files-ignore-unknown=true --no-errors-on-unmatched + language: system + types: [text] + files: "\\.(jsx?|tsx?|c(js|ts)|m(js|ts)|d\\.(ts|cts|mts)|jsonc?)$" +``` + +A opção `files` é opcional, +porque o Biome é capaz de ignorar arquivos desconhecidos (usando a opção `--files-ignore-unknown=true`). + +## Shell script + +Você pode usar também um shell script customizado. +Vale ressaltar que você pode encontrar incompatibilidades entre plataformas. +Recomendammos o uso das ferramentas apresentadas anteriormente. + +Alguns exemplos: + +- Formatar e verificar erros antes do commit + + ```shell title=".git/hooks/pre-commit" + #!/bin/sh + set -eu + + git diff -z --staged --name-only --diff-filter=ACMR | \ + xargs -0 npx biome check --files-ignore-unknown=true --no-errors-on-unmatched $STAGED_FILES + ``` + +- Formatar, verificar erros e aplicar correções seguras antes do commit. + + ```shell title=".git/hooks/pre-commit" + #!/bin/sh + set -eu + + if ! git status --short | grep --quiet '^MM'; then + printf '%s\n' "ERROR: Some staged files have unstaged changes" >&2 + exit 1; + fi + + git diff -z --staged --name-only --diff-filter=ACMR | \ + xargs -0 npx biome check --files-ignore-unknown=true --no-errors-on-unmatched + + git update-index --again + ``` + + Note que fazemos o hook falhar caso os arquivos em stage tenha alterações unstaged. From 3bd7a9cad7dabf68fae7e3e50bfe7aba2d23dbad Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 12 Jan 2024 20:50:50 +0000 Subject: [PATCH 02/49] feat: HTML grammar (#1544) --- Cargo.lock | 15 + Cargo.toml | 17 +- crates/biome_html_factory/Cargo.toml | 18 + crates/biome_html_factory/src/generated.rs | 6 + .../src/generated/node_factory.rs | 205 +++ .../src/generated/syntax_factory.rs | 357 +++++ crates/biome_html_factory/src/lib.rs | 12 + crates/biome_html_factory/src/make.rs | 7 + crates/biome_html_syntax/Cargo.toml | 20 + crates/biome_html_syntax/src/file_source.rs | 68 + crates/biome_html_syntax/src/generated.rs | 9 + .../biome_html_syntax/src/generated/kind.rs | 95 ++ .../biome_html_syntax/src/generated/macros.rs | 77 + .../biome_html_syntax/src/generated/nodes.rs | 1313 +++++++++++++++++ .../src/generated/nodes_mut.rs | 205 +++ crates/biome_html_syntax/src/lib.rs | 107 ++ crates/biome_html_syntax/src/syntax_node.rs | 24 + xtask/codegen/html.ungram | 115 ++ xtask/codegen/src/ast.rs | 16 +- xtask/codegen/src/css_kinds_src.rs | 2 +- xtask/codegen/src/formatter.rs | 7 + xtask/codegen/src/generate_macros.rs | 2 +- xtask/codegen/src/generate_node_factory.rs | 4 +- xtask/codegen/src/generate_nodes.rs | 4 +- xtask/codegen/src/generate_nodes_mut.rs | 2 +- xtask/codegen/src/generate_syntax_factory.rs | 7 +- xtask/codegen/src/generate_syntax_kinds.rs | 16 +- xtask/codegen/src/html_kinds_src.rs | 38 + .../src/{kinds_src.rs => js_kinds_src.rs} | 13 +- xtask/codegen/src/json_kinds_src.rs | 2 +- xtask/codegen/src/kind_src.rs | 9 + xtask/codegen/src/lib.rs | 26 +- 32 files changed, 2785 insertions(+), 33 deletions(-) create mode 100644 crates/biome_html_factory/Cargo.toml create mode 100644 crates/biome_html_factory/src/generated.rs create mode 100644 crates/biome_html_factory/src/generated/node_factory.rs create mode 100644 crates/biome_html_factory/src/generated/syntax_factory.rs create mode 100644 crates/biome_html_factory/src/lib.rs create mode 100644 crates/biome_html_factory/src/make.rs create mode 100644 crates/biome_html_syntax/Cargo.toml create mode 100644 crates/biome_html_syntax/src/file_source.rs create mode 100644 crates/biome_html_syntax/src/generated.rs create mode 100644 crates/biome_html_syntax/src/generated/kind.rs create mode 100644 crates/biome_html_syntax/src/generated/macros.rs create mode 100644 crates/biome_html_syntax/src/generated/nodes.rs create mode 100644 crates/biome_html_syntax/src/generated/nodes_mut.rs create mode 100644 crates/biome_html_syntax/src/lib.rs create mode 100644 crates/biome_html_syntax/src/syntax_node.rs create mode 100644 xtask/codegen/html.ungram create mode 100644 xtask/codegen/src/html_kinds_src.rs rename xtask/codegen/src/{kinds_src.rs => js_kinds_src.rs} (98%) create mode 100644 xtask/codegen/src/kind_src.rs diff --git a/Cargo.lock b/Cargo.lock index 225cf53fb739..d0d2f43393c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -430,6 +430,21 @@ dependencies = [ "tracing", ] +[[package]] +name = "biome_html_factory" +version = "0.4.0" +dependencies = [ + "biome_html_syntax", + "biome_rowan", +] + +[[package]] +name = "biome_html_syntax" +version = "0.4.0" +dependencies = [ + "biome_rowan", +] + [[package]] name = "biome_js_analyze" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index bfaa699576d7..4ac687785395 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -87,6 +87,8 @@ biome_diagnostics_categories = { version = "0.4.0", path = "./crates/biome_diagn biome_diagnostics_macros = { version = "0.4.0", path = "./crates/biome_diagnostics_macros" } biome_formatter = { version = "0.4.0", path = "./crates/biome_formatter" } biome_fs = { version = "0.4.0", path = "./crates/biome_fs" } +biome_html_factory = { version = "0.4.0", path = "./crates/biome_html_factory" } +biome_html_syntax = { version = "0.4.0", path = "./crates/biome_html_syntax" } biome_js_analyze = { version = "0.4.0", path = "./crates/biome_js_analyze" } biome_js_factory = { version = "0.4.0", path = "./crates/biome_js_factory" } biome_js_formatter = { version = "0.4.0", path = "./crates/biome_js_formatter" } @@ -99,13 +101,14 @@ biome_json_factory = { version = "0.4.0", path = "./crates/biome_json_ biome_json_formatter = { version = "0.4.0", path = "./crates/biome_json_formatter" } biome_json_parser = { version = "0.4.0", path = "./crates/biome_json_parser" } biome_json_syntax = { version = "0.4.0", path = "./crates/biome_json_syntax" } -biome_markup = { version = "0.4.0", path = "./crates/biome_markup" } -biome_parser = { version = "0.4.0", path = "./crates/biome_parser" } -biome_rowan = { version = "0.4.0", path = "./crates/biome_rowan" } -biome_suppression = { version = "0.4.0", path = "./crates/biome_suppression" } -biome_text_edit = { version = "0.4.0", path = "./crates/biome_text_edit" } -biome_text_size = { version = "0.4.0", path = "./crates/biome_text_size" } -biome_unicode_table = { version = "0.4.0", path = "./crates/biome_unicode_table" } + +biome_markup = { version = "0.4.0", path = "./crates/biome_markup" } +biome_parser = { version = "0.4.0", path = "./crates/biome_parser" } +biome_rowan = { version = "0.4.0", path = "./crates/biome_rowan" } +biome_suppression = { version = "0.4.0", path = "./crates/biome_suppression" } +biome_text_edit = { version = "0.4.0", path = "./crates/biome_text_edit" } +biome_text_size = { version = "0.4.0", path = "./crates/biome_text_size" } +biome_unicode_table = { version = "0.4.0", path = "./crates/biome_unicode_table" } # not publish biome_cli = { path = "./crates/biome_cli" } biome_flags = { path = "./crates/biome_flags" } diff --git a/crates/biome_html_factory/Cargo.toml b/crates/biome_html_factory/Cargo.toml new file mode 100644 index 000000000000..55ad88a2caa5 --- /dev/null +++ b/crates/biome_html_factory/Cargo.toml @@ -0,0 +1,18 @@ +[package] +authors.workspace = true +description = "Utilities to create HTML AST for biome_html_parser" +documentation = "https://docs.rs/biome_html_factory" +edition.workspace = true +license.workspace = true +name = "biome_html_factory" +repository.workspace = true +version = "0.4.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +biome_html_syntax = { workspace = true } +biome_rowan = { workspace = true } + +[lints] +workspace = true diff --git a/crates/biome_html_factory/src/generated.rs b/crates/biome_html_factory/src/generated.rs new file mode 100644 index 000000000000..d943c24df8f8 --- /dev/null +++ b/crates/biome_html_factory/src/generated.rs @@ -0,0 +1,6 @@ +#[rustfmt::skip] +pub(super) mod syntax_factory; +#[rustfmt::skip] +pub mod node_factory; + +pub use syntax_factory::HtmlSyntaxFactory; diff --git a/crates/biome_html_factory/src/generated/node_factory.rs b/crates/biome_html_factory/src/generated/node_factory.rs new file mode 100644 index 000000000000..ebb5167507cf --- /dev/null +++ b/crates/biome_html_factory/src/generated/node_factory.rs @@ -0,0 +1,205 @@ +//! Generated file, do not edit by hand, see `xtask/codegen` + +#![allow(clippy::redundant_closure)] +#![allow(clippy::too_many_arguments)] +use biome_html_syntax::{ + HtmlSyntaxElement as SyntaxElement, HtmlSyntaxNode as SyntaxNode, + HtmlSyntaxToken as SyntaxToken, *, +}; +use biome_rowan::AstNode; +pub fn html_attribute(name: HtmlName) -> HtmlAttributeBuilder { + HtmlAttributeBuilder { + name, + initializer: None, + } +} +pub struct HtmlAttributeBuilder { + name: HtmlName, + initializer: Option, +} +impl HtmlAttributeBuilder { + pub fn with_initializer(mut self, initializer: HtmlAttributeInitializerClause) -> Self { + self.initializer = Some(initializer); + self + } + pub fn build(self) -> HtmlAttribute { + HtmlAttribute::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_ATTRIBUTE, + [ + Some(SyntaxElement::Node(self.name.into_syntax())), + self.initializer + .map(|token| SyntaxElement::Node(token.into_syntax())), + ], + )) + } +} +pub fn html_attribute_initializer_clause( + eq_token: SyntaxToken, + value: HtmlString, +) -> HtmlAttributeInitializerClause { + HtmlAttributeInitializerClause::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_ATTRIBUTE_INITIALIZER_CLAUSE, + [ + Some(SyntaxElement::Token(eq_token)), + Some(SyntaxElement::Node(value.into_syntax())), + ], + )) +} +pub fn html_closing_element( + l_angle_token: SyntaxToken, + slash_token: SyntaxToken, + name: HtmlName, + r_angle_token: SyntaxToken, +) -> HtmlClosingElement { + HtmlClosingElement::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_CLOSING_ELEMENT, + [ + Some(SyntaxElement::Token(l_angle_token)), + Some(SyntaxElement::Token(slash_token)), + Some(SyntaxElement::Node(name.into_syntax())), + Some(SyntaxElement::Token(r_angle_token)), + ], + )) +} +pub fn html_directive( + l_angle_token: SyntaxToken, + excl_token: SyntaxToken, + content: HtmlString, + r_angle_token: SyntaxToken, +) -> HtmlDirective { + HtmlDirective::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_DIRECTIVE, + [ + Some(SyntaxElement::Token(l_angle_token)), + Some(SyntaxElement::Token(excl_token)), + Some(SyntaxElement::Node(content.into_syntax())), + Some(SyntaxElement::Token(r_angle_token)), + ], + )) +} +pub fn html_element( + opening_element: HtmlOpeningElement, + children: HtmlElementList, + closing_element: HtmlClosingElement, +) -> HtmlElement { + HtmlElement::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_ELEMENT, + [ + Some(SyntaxElement::Node(opening_element.into_syntax())), + Some(SyntaxElement::Node(children.into_syntax())), + Some(SyntaxElement::Node(closing_element.into_syntax())), + ], + )) +} +pub fn html_name(value_token: SyntaxToken) -> HtmlName { + HtmlName::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_NAME, + [Some(SyntaxElement::Token(value_token))], + )) +} +pub fn html_opening_element( + l_angle_token: SyntaxToken, + name: HtmlName, + attributes: HtmlAttributeList, + r_angle_token: SyntaxToken, +) -> HtmlOpeningElement { + HtmlOpeningElement::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_OPENING_ELEMENT, + [ + Some(SyntaxElement::Token(l_angle_token)), + Some(SyntaxElement::Node(name.into_syntax())), + Some(SyntaxElement::Node(attributes.into_syntax())), + Some(SyntaxElement::Token(r_angle_token)), + ], + )) +} +pub fn html_root( + directive: HtmlDirective, + tags: HtmlElementList, + eof_token: SyntaxToken, +) -> HtmlRootBuilder { + HtmlRootBuilder { + directive, + tags, + eof_token, + bom_token: None, + } +} +pub struct HtmlRootBuilder { + directive: HtmlDirective, + tags: HtmlElementList, + eof_token: SyntaxToken, + bom_token: Option, +} +impl HtmlRootBuilder { + pub fn with_bom_token(mut self, bom_token: SyntaxToken) -> Self { + self.bom_token = Some(bom_token); + self + } + pub fn build(self) -> HtmlRoot { + HtmlRoot::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_ROOT, + [ + self.bom_token.map(|token| SyntaxElement::Token(token)), + Some(SyntaxElement::Node(self.directive.into_syntax())), + Some(SyntaxElement::Node(self.tags.into_syntax())), + Some(SyntaxElement::Token(self.eof_token)), + ], + )) + } +} +pub fn html_self_closing_element( + l_angle_token: SyntaxToken, + name: HtmlName, + attributes: HtmlAttributeList, + slash_token: SyntaxToken, + r_angle_token: SyntaxToken, +) -> HtmlSelfClosingElement { + HtmlSelfClosingElement::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_SELF_CLOSING_ELEMENT, + [ + Some(SyntaxElement::Token(l_angle_token)), + Some(SyntaxElement::Node(name.into_syntax())), + Some(SyntaxElement::Node(attributes.into_syntax())), + Some(SyntaxElement::Token(slash_token)), + Some(SyntaxElement::Token(r_angle_token)), + ], + )) +} +pub fn html_string(value_token: SyntaxToken) -> HtmlString { + HtmlString::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_STRING, + [Some(SyntaxElement::Token(value_token))], + )) +} +pub fn html_attribute_list(items: I) -> HtmlAttributeList +where + I: IntoIterator, + I::IntoIter: ExactSizeIterator, +{ + HtmlAttributeList::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_ATTRIBUTE_LIST, + items + .into_iter() + .map(|item| Some(item.into_syntax().into())), + )) +} +pub fn html_element_list(items: I) -> HtmlElementList +where + I: IntoIterator, + I::IntoIter: ExactSizeIterator, +{ + HtmlElementList::unwrap_cast(SyntaxNode::new_detached( + HtmlSyntaxKind::HTML_ELEMENT_LIST, + items + .into_iter() + .map(|item| Some(item.into_syntax().into())), + )) +} +pub fn html_bogus(slots: I) -> HtmlBogus +where + I: IntoIterator>, + I::IntoIter: ExactSizeIterator, +{ + HtmlBogus::unwrap_cast(SyntaxNode::new_detached(HtmlSyntaxKind::HTML_BOGUS, slots)) +} diff --git a/crates/biome_html_factory/src/generated/syntax_factory.rs b/crates/biome_html_factory/src/generated/syntax_factory.rs new file mode 100644 index 000000000000..beab1db6a5ba --- /dev/null +++ b/crates/biome_html_factory/src/generated/syntax_factory.rs @@ -0,0 +1,357 @@ +//! Generated file, do not edit by hand, see `xtask/codegen` + +use biome_html_syntax::{HtmlSyntaxKind, HtmlSyntaxKind::*, T, *}; +use biome_rowan::{ + AstNode, ParsedChildren, RawNodeSlots, RawSyntaxNode, SyntaxFactory, SyntaxKind, +}; +#[derive(Debug)] +pub struct HtmlSyntaxFactory; +impl SyntaxFactory for HtmlSyntaxFactory { + type Kind = HtmlSyntaxKind; + #[allow(unused_mut)] + fn make_syntax( + kind: Self::Kind, + children: ParsedChildren, + ) -> RawSyntaxNode { + match kind { + HTML_BOGUS => RawSyntaxNode::new(kind, children.into_iter().map(Some)), + HTML_ATTRIBUTE => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<2usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if HtmlName::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlAttributeInitializerClause::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + HTML_ATTRIBUTE.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(HTML_ATTRIBUTE, children) + } + HTML_ATTRIBUTE_INITIALIZER_CLAUSE => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<2usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [=] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlString::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + HTML_ATTRIBUTE_INITIALIZER_CLAUSE.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(HTML_ATTRIBUTE_INITIALIZER_CLAUSE, children) + } + HTML_CLOSING_ELEMENT => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<4usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [<] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [/] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlName::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [>] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + HTML_CLOSING_ELEMENT.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(HTML_CLOSING_ELEMENT, children) + } + HTML_DIRECTIVE => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<4usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [<] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T![!] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlString::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [>] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + HTML_DIRECTIVE.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(HTML_DIRECTIVE, children) + } + HTML_ELEMENT => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<3usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if HtmlOpeningElement::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlElementList::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlClosingElement::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + HTML_ELEMENT.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(HTML_ELEMENT, children) + } + HTML_NAME => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<1usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if element.kind() == HTML_IDENT { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + HTML_NAME.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(HTML_NAME, children) + } + HTML_OPENING_ELEMENT => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<4usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [<] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlName::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlAttributeList::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [>] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + HTML_OPENING_ELEMENT.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(HTML_OPENING_ELEMENT, children) + } + HTML_ROOT => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<4usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if element.kind() == T![UNICODE_BOM] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlDirective::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlElementList::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T![EOF] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + HTML_ROOT.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(HTML_ROOT, children) + } + HTML_SELF_CLOSING_ELEMENT => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<5usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [<] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlName::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if HtmlAttributeList::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [/] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if element.kind() == T ! [>] { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + HTML_SELF_CLOSING_ELEMENT.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(HTML_SELF_CLOSING_ELEMENT, children) + } + HTML_STRING => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<1usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if element.kind() == HTML_STRING_LITERAL { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + HTML_STRING.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(HTML_STRING, children) + } + HTML_ATTRIBUTE_LIST => { + Self::make_node_list_syntax(kind, children, HtmlAttribute::can_cast) + } + HTML_ELEMENT_LIST => { + Self::make_node_list_syntax(kind, children, AnyHtmlElement::can_cast) + } + _ => unreachable!("Is {:?} a token?", kind), + } + } +} diff --git a/crates/biome_html_factory/src/lib.rs b/crates/biome_html_factory/src/lib.rs new file mode 100644 index 000000000000..fc1459eab3d9 --- /dev/null +++ b/crates/biome_html_factory/src/lib.rs @@ -0,0 +1,12 @@ +use biome_html_syntax::HtmlLanguage; +use biome_rowan::TreeBuilder; + +mod generated; +pub use crate::generated::HtmlSyntaxFactory; +pub mod make; + +// Re-exported for tests +#[doc(hidden)] +pub use biome_html_syntax as syntax; + +pub type JsonSyntaxTreeBuilder = TreeBuilder<'static, HtmlLanguage, HtmlSyntaxFactory>; diff --git a/crates/biome_html_factory/src/make.rs b/crates/biome_html_factory/src/make.rs new file mode 100644 index 000000000000..df4cffff5316 --- /dev/null +++ b/crates/biome_html_factory/src/make.rs @@ -0,0 +1,7 @@ +use biome_html_syntax::{HtmlSyntaxKind, HtmlSyntaxToken}; + +pub use crate::generated::node_factory::*; + +pub fn ident(text: &str) -> HtmlSyntaxToken { + HtmlSyntaxToken::new_detached(HtmlSyntaxKind::IDENT, text, [], []) +} diff --git a/crates/biome_html_syntax/Cargo.toml b/crates/biome_html_syntax/Cargo.toml new file mode 100644 index 000000000000..75fc6aff005d --- /dev/null +++ b/crates/biome_html_syntax/Cargo.toml @@ -0,0 +1,20 @@ +[package] +authors.workspace = true +categories.workspace = true +description = "SyntaxKind and common rowan definitions for biome_html_parser" +edition.workspace = true +homepage.workspace = true +keywords.workspace = true +license.workspace = true +name = "biome_html_syntax" +repository.workspace = true +version = "0.4.0" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +biome_rowan = { workspace = true } + + +[lints] +workspace = true diff --git a/crates/biome_html_syntax/src/file_source.rs b/crates/biome_html_syntax/src/file_source.rs new file mode 100644 index 000000000000..fce0556f97c4 --- /dev/null +++ b/crates/biome_html_syntax/src/file_source.rs @@ -0,0 +1,68 @@ +use crate::HtmlLanguage; +use biome_rowan::{FileSource, FileSourceError}; +use std::path::Path; + +#[derive(Debug, Default, Clone)] +pub struct HtmlFileSource { + #[allow(unused)] + variant: HtmlVariant, +} + +#[derive(Debug, Default, Clone)] +enum HtmlVariant { + #[default] + Standard, + Astro, +} + +impl HtmlFileSource { + pub fn html() -> Self { + Self { + variant: HtmlVariant::Standard, + } + } + pub fn astro() -> Self { + Self { + variant: HtmlVariant::Astro, + } + } +} + +impl<'a> FileSource<'a, HtmlLanguage> for HtmlFileSource {} + +impl TryFrom<&Path> for HtmlFileSource { + type Error = FileSourceError; + + fn try_from(path: &Path) -> Result { + let file_name = path + .file_name() + .ok_or_else(|| FileSourceError::MissingFileName(path.into()))? + .to_str() + .ok_or_else(|| FileSourceError::MissingFileName(path.into()))?; + + let extension = path + .extension() + .ok_or_else(|| FileSourceError::MissingFileExtension(path.into()))? + .to_str() + .ok_or_else(|| FileSourceError::MissingFileExtension(path.into()))?; + + compute_source_type_from_path_or_extension(file_name, extension) + } +} + +/// It deduce the [HtmlFileSource] from the file name and its extension +fn compute_source_type_from_path_or_extension( + file_name: &str, + extension: &str, +) -> Result { + Ok(match extension { + "html" => HtmlFileSource::html(), + "astro" => HtmlFileSource::astro(), + _ => { + return Err(FileSourceError::UnknownExtension( + file_name.into(), + extension.into(), + )); + } + }) +} diff --git a/crates/biome_html_syntax/src/generated.rs b/crates/biome_html_syntax/src/generated.rs new file mode 100644 index 000000000000..e62bfed1de4e --- /dev/null +++ b/crates/biome_html_syntax/src/generated.rs @@ -0,0 +1,9 @@ +#[rustfmt::skip] +pub(super) mod nodes; +#[rustfmt::skip] +pub mod macros; +#[macro_use] +pub mod kind; + +pub use kind::*; +pub use nodes::*; diff --git a/crates/biome_html_syntax/src/generated/kind.rs b/crates/biome_html_syntax/src/generated/kind.rs new file mode 100644 index 000000000000..3e25d00222e1 --- /dev/null +++ b/crates/biome_html_syntax/src/generated/kind.rs @@ -0,0 +1,95 @@ +//! Generated file, do not edit by hand, see `xtask/codegen` + +#![allow(clippy::all)] +#![allow(bad_style, missing_docs, unreachable_pub)] +#[doc = r" The kind of syntax node, e.g. `IDENT`, `FUNCTION_KW`, or `FOR_STMT`."] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[repr(u16)] +pub enum HtmlSyntaxKind { + #[doc(hidden)] + TOMBSTONE, + #[doc = r" Marks the end of the file. May have trivia attached"] + EOF, + #[doc = r" Any Unicode BOM character that may be present at the start of"] + #[doc = r" a file."] + UNICODE_BOM, + L_ANGLE, + R_ANGLE, + SLASH, + EQ, + BANG, + NULL_KW, + TRUE_KW, + FALSE_KW, + HTML_STRING_LITERAL, + ERROR_TOKEN, + NEWLINE, + WHITESPACE, + IDENT, + COMMENT, + HTML_IDENT, + HTML_ROOT, + HTML_DIRECTIVE, + HTML_SELF_CLOSING_TAG, + HTML_ELEMENT, + HTML_OPENING_ELEMENT, + HTML_CLOSING_ELEMENT, + HTML_SELF_CLOSING_ELEMENT, + HTML_ATTRIBUTE, + HTML_ATTRIBUTE_INITIALIZER_CLAUSE, + HTML_STRING, + HTML_NAME, + HTML_ELEMENT_LIST, + HTML_ATTRIBUTE_LIST, + HTML_BOGUS, + #[doc(hidden)] + __LAST, +} +use self::HtmlSyntaxKind::*; +impl HtmlSyntaxKind { + pub const fn is_punct(self) -> bool { + match self { + L_ANGLE | R_ANGLE | SLASH | EQ | BANG => true, + _ => false, + } + } + pub const fn is_literal(self) -> bool { + match self { + HTML_STRING_LITERAL => true, + _ => false, + } + } + pub const fn is_list(self) -> bool { + match self { + HTML_ELEMENT_LIST | HTML_ATTRIBUTE_LIST => true, + _ => false, + } + } + pub fn from_keyword(ident: &str) -> Option { + let kw = match ident { + "null" => NULL_KW, + "true" => TRUE_KW, + "false" => FALSE_KW, + _ => return None, + }; + Some(kw) + } + pub const fn to_string(&self) -> Option<&'static str> { + let tok = match self { + L_ANGLE => "<", + R_ANGLE => ">", + SLASH => "/", + EQ => "=", + BANG => "!", + NULL_KW => "null", + TRUE_KW => "true", + FALSE_KW => "false", + HTML_STRING_LITERAL => "string literal", + _ => return None, + }; + Some(tok) + } +} +#[doc = r" Utility macro for creating a SyntaxKind through simple macro syntax"] +#[macro_export] +macro_rules ! T { [<] => { $ crate :: HtmlSyntaxKind :: L_ANGLE } ; [>] => { $ crate :: HtmlSyntaxKind :: R_ANGLE } ; [/] => { $ crate :: HtmlSyntaxKind :: SLASH } ; [=] => { $ crate :: HtmlSyntaxKind :: EQ } ; [!] => { $ crate :: HtmlSyntaxKind :: BANG } ; [null] => { $ crate :: HtmlSyntaxKind :: NULL_KW } ; [true] => { $ crate :: HtmlSyntaxKind :: TRUE_KW } ; [false] => { $ crate :: HtmlSyntaxKind :: FALSE_KW } ; [ident] => { $ crate :: HtmlSyntaxKind :: IDENT } ; [EOF] => { $ crate :: HtmlSyntaxKind :: EOF } ; [UNICODE_BOM] => { $ crate :: HtmlSyntaxKind :: UNICODE_BOM } ; [#] => { $ crate :: HtmlSyntaxKind :: HASH } ; } diff --git a/crates/biome_html_syntax/src/generated/macros.rs b/crates/biome_html_syntax/src/generated/macros.rs new file mode 100644 index 000000000000..a96b93b53a34 --- /dev/null +++ b/crates/biome_html_syntax/src/generated/macros.rs @@ -0,0 +1,77 @@ +//! Generated file, do not edit by hand, see `xtask/codegen` + +#[doc = r" Reconstruct an AstNode from a SyntaxNode"] +#[doc = r""] +#[doc = r" This macros performs a match over the [kind](biome_rowan::SyntaxNode::kind)"] +#[doc = r" of the provided [biome_rowan::SyntaxNode] and constructs the appropriate"] +#[doc = r" AstNode type for it, then execute the provided expression over it."] +#[doc = r""] +#[doc = r" # Examples"] +#[doc = r""] +#[doc = r" ```ignore"] +#[doc = r" map_syntax_node!(syntax_node, node => node.format())"] +#[doc = r" ```"] +#[macro_export] +macro_rules! map_syntax_node { + ($ node : expr , $ pattern : pat => $ body : expr) => { + match $node { + node => match $crate::HtmlSyntaxNode::kind(&node) { + $crate::HtmlSyntaxKind::HTML_ATTRIBUTE => { + let $pattern = unsafe { $crate::HtmlAttribute::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_ATTRIBUTE_INITIALIZER_CLAUSE => { + let $pattern = + unsafe { $crate::HtmlAttributeInitializerClause::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_CLOSING_ELEMENT => { + let $pattern = unsafe { $crate::HtmlClosingElement::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_DIRECTIVE => { + let $pattern = unsafe { $crate::HtmlDirective::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_ELEMENT => { + let $pattern = unsafe { $crate::HtmlElement::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_NAME => { + let $pattern = unsafe { $crate::HtmlName::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_OPENING_ELEMENT => { + let $pattern = unsafe { $crate::HtmlOpeningElement::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_ROOT => { + let $pattern = unsafe { $crate::HtmlRoot::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_SELF_CLOSING_ELEMENT => { + let $pattern = unsafe { $crate::HtmlSelfClosingElement::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_STRING => { + let $pattern = unsafe { $crate::HtmlString::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_BOGUS => { + let $pattern = unsafe { $crate::HtmlBogus::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_ATTRIBUTE_LIST => { + let $pattern = unsafe { $crate::HtmlAttributeList::new_unchecked(node) }; + $body + } + $crate::HtmlSyntaxKind::HTML_ELEMENT_LIST => { + let $pattern = unsafe { $crate::HtmlElementList::new_unchecked(node) }; + $body + } + _ => unreachable!(), + }, + } + }; +} +pub(crate) use map_syntax_node; diff --git a/crates/biome_html_syntax/src/generated/nodes.rs b/crates/biome_html_syntax/src/generated/nodes.rs new file mode 100644 index 000000000000..31da15ef7872 --- /dev/null +++ b/crates/biome_html_syntax/src/generated/nodes.rs @@ -0,0 +1,1313 @@ +//! Generated file, do not edit by hand, see `xtask/codegen` + +#![allow(clippy::enum_variant_names)] +#![allow(clippy::match_like_matches_macro)] +use crate::{ + macros::map_syntax_node, + HtmlLanguage as Language, HtmlSyntaxElement as SyntaxElement, + HtmlSyntaxElementChildren as SyntaxElementChildren, + HtmlSyntaxKind::{self as SyntaxKind, *}, + HtmlSyntaxList as SyntaxList, HtmlSyntaxNode as SyntaxNode, HtmlSyntaxToken as SyntaxToken, +}; +use biome_rowan::{support, AstNode, RawSyntaxKind, SyntaxKindSet, SyntaxResult}; +#[allow(unused)] +use biome_rowan::{ + AstNodeList, AstNodeListIterator, AstSeparatedList, AstSeparatedListNodesIterator, +}; +#[cfg(feature = "serde")] +use serde::ser::SerializeSeq; +#[cfg(feature = "serde")] +use serde::{Serialize, Serializer}; +use std::fmt::{Debug, Formatter}; +#[doc = r" Sentinel value indicating a missing element in a dynamic node, where"] +#[doc = r" the slots are not statically known."] +#[allow(dead_code)] +pub(crate) const SLOT_MAP_EMPTY_VALUE: u8 = u8::MAX; +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct HtmlAttribute { + pub(crate) syntax: SyntaxNode, +} +impl HtmlAttribute { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> HtmlAttributeFields { + HtmlAttributeFields { + name: self.name(), + initializer: self.initializer(), + } + } + pub fn name(&self) -> SyntaxResult { + support::required_node(&self.syntax, 0usize) + } + pub fn initializer(&self) -> Option { + support::node(&self.syntax, 1usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlAttribute { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlAttributeFields { + pub name: SyntaxResult, + pub initializer: Option, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct HtmlAttributeInitializerClause { + pub(crate) syntax: SyntaxNode, +} +impl HtmlAttributeInitializerClause { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> HtmlAttributeInitializerClauseFields { + HtmlAttributeInitializerClauseFields { + eq_token: self.eq_token(), + value: self.value(), + } + } + pub fn eq_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } + pub fn value(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlAttributeInitializerClause { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlAttributeInitializerClauseFields { + pub eq_token: SyntaxResult, + pub value: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct HtmlClosingElement { + pub(crate) syntax: SyntaxNode, +} +impl HtmlClosingElement { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> HtmlClosingElementFields { + HtmlClosingElementFields { + l_angle_token: self.l_angle_token(), + slash_token: self.slash_token(), + name: self.name(), + r_angle_token: self.r_angle_token(), + } + } + pub fn l_angle_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } + pub fn slash_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) + } + pub fn name(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) + } + pub fn r_angle_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlClosingElement { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlClosingElementFields { + pub l_angle_token: SyntaxResult, + pub slash_token: SyntaxResult, + pub name: SyntaxResult, + pub r_angle_token: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct HtmlDirective { + pub(crate) syntax: SyntaxNode, +} +impl HtmlDirective { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> HtmlDirectiveFields { + HtmlDirectiveFields { + l_angle_token: self.l_angle_token(), + excl_token: self.excl_token(), + content: self.content(), + r_angle_token: self.r_angle_token(), + } + } + pub fn l_angle_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } + pub fn excl_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 1usize) + } + pub fn content(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) + } + pub fn r_angle_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlDirective { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlDirectiveFields { + pub l_angle_token: SyntaxResult, + pub excl_token: SyntaxResult, + pub content: SyntaxResult, + pub r_angle_token: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct HtmlElement { + pub(crate) syntax: SyntaxNode, +} +impl HtmlElement { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> HtmlElementFields { + HtmlElementFields { + opening_element: self.opening_element(), + children: self.children(), + closing_element: self.closing_element(), + } + } + pub fn opening_element(&self) -> SyntaxResult { + support::required_node(&self.syntax, 0usize) + } + pub fn children(&self) -> HtmlElementList { + support::list(&self.syntax, 1usize) + } + pub fn closing_element(&self) -> SyntaxResult { + support::required_node(&self.syntax, 2usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlElement { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlElementFields { + pub opening_element: SyntaxResult, + pub children: HtmlElementList, + pub closing_element: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct HtmlName { + pub(crate) syntax: SyntaxNode, +} +impl HtmlName { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> HtmlNameFields { + HtmlNameFields { + value_token: self.value_token(), + } + } + pub fn value_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlName { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlNameFields { + pub value_token: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct HtmlOpeningElement { + pub(crate) syntax: SyntaxNode, +} +impl HtmlOpeningElement { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> HtmlOpeningElementFields { + HtmlOpeningElementFields { + l_angle_token: self.l_angle_token(), + name: self.name(), + attributes: self.attributes(), + r_angle_token: self.r_angle_token(), + } + } + pub fn l_angle_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } + pub fn name(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) + } + pub fn attributes(&self) -> HtmlAttributeList { + support::list(&self.syntax, 2usize) + } + pub fn r_angle_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlOpeningElement { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlOpeningElementFields { + pub l_angle_token: SyntaxResult, + pub name: SyntaxResult, + pub attributes: HtmlAttributeList, + pub r_angle_token: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct HtmlRoot { + pub(crate) syntax: SyntaxNode, +} +impl HtmlRoot { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> HtmlRootFields { + HtmlRootFields { + bom_token: self.bom_token(), + directive: self.directive(), + tags: self.tags(), + eof_token: self.eof_token(), + } + } + pub fn bom_token(&self) -> Option { + support::token(&self.syntax, 0usize) + } + pub fn directive(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) + } + pub fn tags(&self) -> HtmlElementList { + support::list(&self.syntax, 2usize) + } + pub fn eof_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlRoot { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlRootFields { + pub bom_token: Option, + pub directive: SyntaxResult, + pub tags: HtmlElementList, + pub eof_token: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct HtmlSelfClosingElement { + pub(crate) syntax: SyntaxNode, +} +impl HtmlSelfClosingElement { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> HtmlSelfClosingElementFields { + HtmlSelfClosingElementFields { + l_angle_token: self.l_angle_token(), + name: self.name(), + attributes: self.attributes(), + slash_token: self.slash_token(), + r_angle_token: self.r_angle_token(), + } + } + pub fn l_angle_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } + pub fn name(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) + } + pub fn attributes(&self) -> HtmlAttributeList { + support::list(&self.syntax, 2usize) + } + pub fn slash_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 3usize) + } + pub fn r_angle_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 4usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlSelfClosingElement { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlSelfClosingElementFields { + pub l_angle_token: SyntaxResult, + pub name: SyntaxResult, + pub attributes: HtmlAttributeList, + pub slash_token: SyntaxResult, + pub r_angle_token: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +pub struct HtmlString { + pub(crate) syntax: SyntaxNode, +} +impl HtmlString { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> HtmlStringFields { + HtmlStringFields { + value_token: self.value_token(), + } + } + pub fn value_token(&self) -> SyntaxResult { + support::required_token(&self.syntax, 0usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlString { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlStringFields { + pub value_token: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize))] +pub enum AnyHtmlElement { + HtmlElement(HtmlElement), + HtmlSelfClosingElement(HtmlSelfClosingElement), +} +impl AnyHtmlElement { + pub fn as_html_element(&self) -> Option<&HtmlElement> { + match &self { + AnyHtmlElement::HtmlElement(item) => Some(item), + _ => None, + } + } + pub fn as_html_self_closing_element(&self) -> Option<&HtmlSelfClosingElement> { + match &self { + AnyHtmlElement::HtmlSelfClosingElement(item) => Some(item), + _ => None, + } + } +} +impl AstNode for HtmlAttribute { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ATTRIBUTE as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_ATTRIBUTE + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlAttribute { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlAttribute") + .field("name", &support::DebugSyntaxResult(self.name())) + .field( + "initializer", + &support::DebugOptionalElement(self.initializer()), + ) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlAttribute) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlAttribute) -> SyntaxElement { + n.syntax.into() + } +} +impl AstNode for HtmlAttributeInitializerClause { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ATTRIBUTE_INITIALIZER_CLAUSE as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_ATTRIBUTE_INITIALIZER_CLAUSE + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlAttributeInitializerClause { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlAttributeInitializerClause") + .field("eq_token", &support::DebugSyntaxResult(self.eq_token())) + .field("value", &support::DebugSyntaxResult(self.value())) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlAttributeInitializerClause) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlAttributeInitializerClause) -> SyntaxElement { + n.syntax.into() + } +} +impl AstNode for HtmlClosingElement { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_CLOSING_ELEMENT as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_CLOSING_ELEMENT + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlClosingElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlClosingElement") + .field( + "l_angle_token", + &support::DebugSyntaxResult(self.l_angle_token()), + ) + .field( + "slash_token", + &support::DebugSyntaxResult(self.slash_token()), + ) + .field("name", &support::DebugSyntaxResult(self.name())) + .field( + "r_angle_token", + &support::DebugSyntaxResult(self.r_angle_token()), + ) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlClosingElement) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlClosingElement) -> SyntaxElement { + n.syntax.into() + } +} +impl AstNode for HtmlDirective { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_DIRECTIVE as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_DIRECTIVE + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlDirective { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlDirective") + .field( + "l_angle_token", + &support::DebugSyntaxResult(self.l_angle_token()), + ) + .field("excl_token", &support::DebugSyntaxResult(self.excl_token())) + .field("content", &support::DebugSyntaxResult(self.content())) + .field( + "r_angle_token", + &support::DebugSyntaxResult(self.r_angle_token()), + ) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlDirective) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlDirective) -> SyntaxElement { + n.syntax.into() + } +} +impl AstNode for HtmlElement { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ELEMENT as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_ELEMENT + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlElement") + .field( + "opening_element", + &support::DebugSyntaxResult(self.opening_element()), + ) + .field("children", &self.children()) + .field( + "closing_element", + &support::DebugSyntaxResult(self.closing_element()), + ) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlElement) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlElement) -> SyntaxElement { + n.syntax.into() + } +} +impl AstNode for HtmlName { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_NAME as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_NAME + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlName") + .field( + "value_token", + &support::DebugSyntaxResult(self.value_token()), + ) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlName) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlName) -> SyntaxElement { + n.syntax.into() + } +} +impl AstNode for HtmlOpeningElement { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_OPENING_ELEMENT as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_OPENING_ELEMENT + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlOpeningElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlOpeningElement") + .field( + "l_angle_token", + &support::DebugSyntaxResult(self.l_angle_token()), + ) + .field("name", &support::DebugSyntaxResult(self.name())) + .field("attributes", &self.attributes()) + .field( + "r_angle_token", + &support::DebugSyntaxResult(self.r_angle_token()), + ) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlOpeningElement) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlOpeningElement) -> SyntaxElement { + n.syntax.into() + } +} +impl AstNode for HtmlRoot { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ROOT as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_ROOT + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlRoot { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlRoot") + .field( + "bom_token", + &support::DebugOptionalElement(self.bom_token()), + ) + .field("directive", &support::DebugSyntaxResult(self.directive())) + .field("tags", &self.tags()) + .field("eof_token", &support::DebugSyntaxResult(self.eof_token())) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlRoot) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlRoot) -> SyntaxElement { + n.syntax.into() + } +} +impl AstNode for HtmlSelfClosingElement { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_SELF_CLOSING_ELEMENT as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_SELF_CLOSING_ELEMENT + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlSelfClosingElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlSelfClosingElement") + .field( + "l_angle_token", + &support::DebugSyntaxResult(self.l_angle_token()), + ) + .field("name", &support::DebugSyntaxResult(self.name())) + .field("attributes", &self.attributes()) + .field( + "slash_token", + &support::DebugSyntaxResult(self.slash_token()), + ) + .field( + "r_angle_token", + &support::DebugSyntaxResult(self.r_angle_token()), + ) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlSelfClosingElement) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlSelfClosingElement) -> SyntaxElement { + n.syntax.into() + } +} +impl AstNode for HtmlString { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_STRING as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_STRING + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlString { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlString") + .field( + "value_token", + &support::DebugSyntaxResult(self.value_token()), + ) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlString) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlString) -> SyntaxElement { + n.syntax.into() + } +} +impl From for AnyHtmlElement { + fn from(node: HtmlElement) -> AnyHtmlElement { + AnyHtmlElement::HtmlElement(node) + } +} +impl From for AnyHtmlElement { + fn from(node: HtmlSelfClosingElement) -> AnyHtmlElement { + AnyHtmlElement::HtmlSelfClosingElement(node) + } +} +impl AstNode for AnyHtmlElement { + type Language = Language; + const KIND_SET: SyntaxKindSet = + HtmlElement::KIND_SET.union(HtmlSelfClosingElement::KIND_SET); + fn can_cast(kind: SyntaxKind) -> bool { + matches!(kind, HTML_ELEMENT | HTML_SELF_CLOSING_ELEMENT) + } + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + HTML_ELEMENT => AnyHtmlElement::HtmlElement(HtmlElement { syntax }), + HTML_SELF_CLOSING_ELEMENT => { + AnyHtmlElement::HtmlSelfClosingElement(HtmlSelfClosingElement { syntax }) + } + _ => return None, + }; + Some(res) + } + fn syntax(&self) -> &SyntaxNode { + match self { + AnyHtmlElement::HtmlElement(it) => &it.syntax, + AnyHtmlElement::HtmlSelfClosingElement(it) => &it.syntax, + } + } + fn into_syntax(self) -> SyntaxNode { + match self { + AnyHtmlElement::HtmlElement(it) => it.syntax, + AnyHtmlElement::HtmlSelfClosingElement(it) => it.syntax, + } + } +} +impl std::fmt::Debug for AnyHtmlElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + AnyHtmlElement::HtmlElement(it) => std::fmt::Debug::fmt(it, f), + AnyHtmlElement::HtmlSelfClosingElement(it) => std::fmt::Debug::fmt(it, f), + } + } +} +impl From for SyntaxNode { + fn from(n: AnyHtmlElement) -> SyntaxNode { + match n { + AnyHtmlElement::HtmlElement(it) => it.into(), + AnyHtmlElement::HtmlSelfClosingElement(it) => it.into(), + } + } +} +impl From for SyntaxElement { + fn from(n: AnyHtmlElement) -> SyntaxElement { + let node: SyntaxNode = n.into(); + node.into() + } +} +impl std::fmt::Display for AnyHtmlElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for HtmlAttribute { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for HtmlAttributeInitializerClause { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for HtmlClosingElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for HtmlDirective { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for HtmlElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for HtmlName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for HtmlOpeningElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for HtmlRoot { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for HtmlSelfClosingElement { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +impl std::fmt::Display for HtmlString { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} +#[derive(Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct HtmlBogus { + syntax: SyntaxNode, +} +impl HtmlBogus { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn items(&self) -> SyntaxElementChildren { + support::elements(&self.syntax) + } +} +impl AstNode for HtmlBogus { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_BOGUS as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_BOGUS + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for HtmlBogus { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HtmlBogus") + .field("items", &DebugSyntaxElementChildren(self.items())) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: HtmlBogus) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: HtmlBogus) -> SyntaxElement { + n.syntax.into() + } +} +#[derive(Clone, Eq, PartialEq, Hash)] +pub struct HtmlAttributeList { + syntax_list: SyntaxList, +} +impl HtmlAttributeList { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { + syntax_list: syntax.into_list(), + } + } +} +impl AstNode for HtmlAttributeList { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ATTRIBUTE_LIST as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_ATTRIBUTE_LIST + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(HtmlAttributeList { + syntax_list: syntax.into_list(), + }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + self.syntax_list.node() + } + fn into_syntax(self) -> SyntaxNode { + self.syntax_list.into_node() + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlAttributeList { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.len()))?; + for e in self.iter() { + seq.serialize_element(&e)?; + } + seq.end() + } +} +impl AstNodeList for HtmlAttributeList { + type Language = Language; + type Node = HtmlAttribute; + fn syntax_list(&self) -> &SyntaxList { + &self.syntax_list + } + fn into_syntax_list(self) -> SyntaxList { + self.syntax_list + } +} +impl Debug for HtmlAttributeList { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str("HtmlAttributeList ")?; + f.debug_list().entries(self.iter()).finish() + } +} +impl IntoIterator for &HtmlAttributeList { + type Item = HtmlAttribute; + type IntoIter = AstNodeListIterator; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} +impl IntoIterator for HtmlAttributeList { + type Item = HtmlAttribute; + type IntoIter = AstNodeListIterator; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} +#[derive(Clone, Eq, PartialEq, Hash)] +pub struct HtmlElementList { + syntax_list: SyntaxList, +} +impl HtmlElementList { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { + syntax_list: syntax.into_list(), + } + } +} +impl AstNode for HtmlElementList { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(HTML_ELEMENT_LIST as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == HTML_ELEMENT_LIST + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(HtmlElementList { + syntax_list: syntax.into_list(), + }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + self.syntax_list.node() + } + fn into_syntax(self) -> SyntaxNode { + self.syntax_list.into_node() + } +} +#[cfg(feature = "serde")] +impl Serialize for HtmlElementList { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(Some(self.len()))?; + for e in self.iter() { + seq.serialize_element(&e)?; + } + seq.end() + } +} +impl AstNodeList for HtmlElementList { + type Language = Language; + type Node = AnyHtmlElement; + fn syntax_list(&self) -> &SyntaxList { + &self.syntax_list + } + fn into_syntax_list(self) -> SyntaxList { + self.syntax_list + } +} +impl Debug for HtmlElementList { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str("HtmlElementList ")?; + f.debug_list().entries(self.iter()).finish() + } +} +impl IntoIterator for &HtmlElementList { + type Item = AnyHtmlElement; + type IntoIter = AstNodeListIterator; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} +impl IntoIterator for HtmlElementList { + type Item = AnyHtmlElement; + type IntoIter = AstNodeListIterator; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} +#[derive(Clone)] +pub struct DebugSyntaxElementChildren(pub SyntaxElementChildren); +impl Debug for DebugSyntaxElementChildren { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_list() + .entries(self.clone().0.map(DebugSyntaxElement)) + .finish() + } +} +struct DebugSyntaxElement(SyntaxElement); +impl Debug for DebugSyntaxElement { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match &self.0 { + SyntaxElement::Node(node) => { + map_syntax_node ! (node . clone () , node => std :: fmt :: Debug :: fmt (& node , f)) + } + SyntaxElement::Token(token) => Debug::fmt(token, f), + } + } +} diff --git a/crates/biome_html_syntax/src/generated/nodes_mut.rs b/crates/biome_html_syntax/src/generated/nodes_mut.rs new file mode 100644 index 000000000000..21dfbdf5b624 --- /dev/null +++ b/crates/biome_html_syntax/src/generated/nodes_mut.rs @@ -0,0 +1,205 @@ +//! Generated file, do not edit by hand, see `xtask/codegen` + +use crate::{generated::nodes::*, HtmlSyntaxToken as SyntaxToken}; +use biome_rowan::AstNode; +use std::iter::once; +impl HtmlAttribute { + pub fn with_name(self, element: HtmlName) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_initializer(self, element: Option) -> Self { + Self::unwrap_cast(self.syntax.splice_slots( + 1usize..=1usize, + once(element.map(|element| element.into_syntax().into())), + )) + } +} +impl HtmlAttributeInitializerClause { + pub fn with_eq_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_value(self, element: HtmlString) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + ) + } +} +impl HtmlClosingElement { + pub fn with_l_angle_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_slash_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into()))), + ) + } + pub fn with_name(self, element: HtmlName) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_r_angle_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(3usize..=3usize, once(Some(element.into()))), + ) + } +} +impl HtmlDirective { + pub fn with_l_angle_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_excl_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into()))), + ) + } + pub fn with_content(self, element: HtmlString) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_r_angle_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(3usize..=3usize, once(Some(element.into()))), + ) + } +} +impl HtmlElement { + pub fn with_opening_element(self, element: HtmlOpeningElement) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_children(self, element: HtmlElementList) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_closing_element(self, element: HtmlClosingElement) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } +} +impl HtmlName { + pub fn with_value_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } +} +impl HtmlOpeningElement { + pub fn with_l_angle_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_name(self, element: HtmlName) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_attributes(self, element: HtmlAttributeList) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_r_angle_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(3usize..=3usize, once(Some(element.into()))), + ) + } +} +impl HtmlRoot { + pub fn with_bom_token(self, element: Option) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(element.map(|element| element.into()))), + ) + } + pub fn with_directive(self, element: HtmlDirective) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_tags(self, element: HtmlElementList) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_eof_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(3usize..=3usize, once(Some(element.into()))), + ) + } +} +impl HtmlSelfClosingElement { + pub fn with_l_angle_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } + pub fn with_name(self, element: HtmlName) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_attributes(self, element: HtmlAttributeList) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(2usize..=2usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_slash_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(3usize..=3usize, once(Some(element.into()))), + ) + } + pub fn with_r_angle_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(4usize..=4usize, once(Some(element.into()))), + ) + } +} +impl HtmlString { + pub fn with_value_token(self, element: SyntaxToken) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into()))), + ) + } +} diff --git a/crates/biome_html_syntax/src/lib.rs b/crates/biome_html_syntax/src/lib.rs new file mode 100644 index 000000000000..126deb0eb83c --- /dev/null +++ b/crates/biome_html_syntax/src/lib.rs @@ -0,0 +1,107 @@ +#[macro_use] +mod generated; +mod file_source; +mod syntax_node; + +pub use self::generated::*; +pub use biome_rowan::{TextLen, TextRange, TextSize, TokenAtOffset, TriviaPieceKind, WalkEvent}; +pub use file_source::HtmlFileSource; +pub use syntax_node::*; + +use biome_rowan::{RawSyntaxKind, TokenText}; + +impl From for HtmlSyntaxKind { + fn from(d: u16) -> HtmlSyntaxKind { + assert!(d <= (HtmlSyntaxKind::__LAST as u16)); + unsafe { std::mem::transmute::(d) } + } +} + +impl From for u16 { + fn from(k: HtmlSyntaxKind) -> u16 { + k as u16 + } +} + +impl HtmlSyntaxKind { + pub fn is_trivia(self) -> bool { + matches!(self, HtmlSyntaxKind::NEWLINE | HtmlSyntaxKind::WHITESPACE) + } + + pub fn is_comments(self) -> bool { + matches!(self, HtmlSyntaxKind::COMMENT) + } + + #[inline] + pub const fn is_keyword(self) -> bool { + matches!(self, T![null] | T![true] | T![false]) + } +} + +impl biome_rowan::SyntaxKind for HtmlSyntaxKind { + const TOMBSTONE: Self = HtmlSyntaxKind::TOMBSTONE; + const EOF: Self = HtmlSyntaxKind::EOF; + + fn is_bogus(&self) -> bool { + matches!(self, HtmlSyntaxKind::HTML_BOGUS) + } + + fn to_bogus(&self) -> Self { + HtmlSyntaxKind::HTML_BOGUS + } + + #[inline] + fn to_raw(&self) -> RawSyntaxKind { + RawSyntaxKind(*self as u16) + } + + #[inline] + fn from_raw(raw: RawSyntaxKind) -> Self { + Self::from(raw.0) + } + + fn is_root(&self) -> bool { + matches!(self, HtmlSyntaxKind::HTML_ROOT) + } + + fn is_list(&self) -> bool { + HtmlSyntaxKind::is_list(*self) + } + + fn to_string(&self) -> Option<&'static str> { + HtmlSyntaxKind::to_string(self) + } +} + +impl TryFrom for TriviaPieceKind { + type Error = (); + + fn try_from(value: HtmlSyntaxKind) -> Result { + if value.is_trivia() { + match value { + HtmlSyntaxKind::NEWLINE => Ok(TriviaPieceKind::Newline), + HtmlSyntaxKind::WHITESPACE => Ok(TriviaPieceKind::Whitespace), + _ => unreachable!("Not Trivia"), + } + } else if value.is_comments() { + match value { + HtmlSyntaxKind::COMMENT => Ok(TriviaPieceKind::SingleLineComment), + _ => unreachable!("Not Comment"), + } + } else { + Err(()) + } + } +} + +/// Text of `token`, excluding all trivia and removing quotes if `token` is a string literal. +pub fn inner_string_text(token: &HtmlSyntaxToken) -> TokenText { + let mut text = token.token_text_trimmed(); + if token.kind() == HtmlSyntaxKind::HTML_STRING_LITERAL { + // remove string delimiters + // SAFETY: string literal token have a delimiters at the start and the end of the string + let range = TextRange::new(1.into(), text.len() - TextSize::from(1)); + text = text.slice(range); + } + text +} diff --git a/crates/biome_html_syntax/src/syntax_node.rs b/crates/biome_html_syntax/src/syntax_node.rs new file mode 100644 index 000000000000..66e9992a635c --- /dev/null +++ b/crates/biome_html_syntax/src/syntax_node.rs @@ -0,0 +1,24 @@ +//! This module defines the Concrete Syntax Tree used by Biome. +//! +//! The tree is entirely lossless, whitespace, comments, and errors are preserved. +//! It also provides traversal methods including parent, children, and siblings of nodes. +//! +//! This is a simple wrapper around the `rowan` crate which does most of the heavy lifting and is language agnostic. + +use crate::{HtmlRoot, HtmlSyntaxKind}; +use biome_rowan::Language; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct HtmlLanguage; + +impl Language for HtmlLanguage { + type Kind = HtmlSyntaxKind; + type Root = HtmlRoot; +} + +pub type HtmlSyntaxNode = biome_rowan::SyntaxNode; +pub type HtmlSyntaxToken = biome_rowan::SyntaxToken; +pub type HtmlSyntaxElement = biome_rowan::SyntaxElement; +pub type HtmlSyntaxNodeChildren = biome_rowan::SyntaxNodeChildren; +pub type HtmlSyntaxElementChildren = biome_rowan::SyntaxElementChildren; +pub type HtmlSyntaxList = biome_rowan::SyntaxList; diff --git a/xtask/codegen/html.ungram b/xtask/codegen/html.ungram new file mode 100644 index 000000000000..175a35e6b70f --- /dev/null +++ b/xtask/codegen/html.ungram @@ -0,0 +1,115 @@ +// CSS Un-Grammar. +// +// This grammar specifies the structure of Rust's concrete syntax tree. +// It does not specify parsing rules (ambiguities, precedence, etc are out of scope). +// Tokens are processed -- contextual keywords are recognised, compound operators glued. +// +// Legend: +// +// // -- comment +// Name = -- non-terminal definition +// 'ident' -- token (terminal) +// A B -- sequence +// A | B -- alternation +// A* -- zero or more repetition +// (A (',' A)* ','?) -- repetition of node A separated by ',' and allowing a trailing comma +// (A (',' A)*) -- repetition of node A separated by ',' without a trailing comma +// A? -- zero or one repetition +// (A) -- same as A +// label:A -- suggested name for field of AST node + +// NOTES +// +// - SyntaxNode, SyntaxToken and SyntaxElement will be stripped from the codegen +// - Bogus nodes are special nodes used to keep track of broken code; they are +// not part of the grammar but they will appear inside the green tree + + +/////////////// +// BOGUS NODES +/////////////// +// SyntaxElement is a generic data structure that is meant to track nodes and tokens +// in cases where we care about both types +// +// As Bogus* node will need to yield both tokens and nodes without discrimination, +// and their children will need to yield nodes and tokens as well. +// For this reason, SyntaxElement = SyntaxElement +SyntaxElement = SyntaxElement + +HtmlBogus = SyntaxElement* + +HtmlRoot = + bom: 'UNICODE_BOM'? + directive: HtmlDirective + tags: HtmlElementList + eof: 'EOF' + +// +// ^^^^^^^^^^^^^^^ +// TODO: add better representation +HtmlDirective = + '<' + '!' + content: HtmlString + '>' + +// ================================== +// Elements (AKA tags) +// ================================== + +HtmlElementList = AnyHtmlElement* + +AnyHtmlElement = + HtmlSelfClosingElement + | HtmlElement + + +// +HtmlSelfClosingElement = + '<' + name: HtmlName + attributes: HtmlAttributeList + '/' + '>' + +HtmlElement = + opening_element: HtmlOpeningElement + children: HtmlElementList + closing_element: HtmlClosingElement + + +// +// ^^ ^ +HtmlOpeningElement = + '<' + name: HtmlName + attributes: HtmlAttributeList + '>' + +// +HtmlClosingElement = + '<' + '/' + name: HtmlName + '>' + +// ================================== +// Attributes +// ================================== + +HtmlAttributeList = HtmlAttribute* + +HtmlAttribute = + name: HtmlName + initializer: HtmlAttributeInitializerClause? + + +// +// ^^^^ +HtmlAttributeInitializerClause = + '=' + value: HtmlString + + +HtmlString = value: 'html_string_literal' +HtmlName = value: 'html_ident' diff --git a/xtask/codegen/src/ast.rs b/xtask/codegen/src/ast.rs index dce0e81e033c..6b1900ba2770 100644 --- a/xtask/codegen/src/ast.rs +++ b/xtask/codegen/src/ast.rs @@ -6,17 +6,18 @@ use std::str::FromStr; use std::vec; use super::{ - kinds_src::{AstSrc, Field}, + js_kinds_src::{AstSrc, Field}, to_lower_snake_case, Mode, }; use crate::css_kinds_src::CSS_KINDS_SRC; use crate::generate_node_factory::generate_node_factory; use crate::generate_nodes_mut::generate_nodes_mut; use crate::generate_syntax_factory::generate_syntax_factory; -use crate::json_kinds_src::JSON_KINDS_SRC; -use crate::kinds_src::{ +use crate::html_kinds_src::HTML_KINDS_SRC; +use crate::js_kinds_src::{ AstEnumSrc, AstListSeparatorConfiguration, AstListSrc, AstNodeSrc, TokenKind, JS_KINDS_SRC, }; +use crate::json_kinds_src::JSON_KINDS_SRC; use crate::termcolorful::{println_string_with_fg_color, Color}; use crate::ALL_LANGUAGE_KIND; use crate::{ @@ -26,6 +27,7 @@ use crate::{ use biome_ungrammar::{Grammar, Rule, Token}; use std::fmt::Write; use xtask::{project_root, Result}; + // these node won't generate any code pub const SYNTAX_ELEMENT_TYPE: &str = "SyntaxElement"; @@ -65,6 +67,7 @@ pub(crate) fn load_ast(language: LanguageKind) -> AstSrc { LanguageKind::Js => load_js_ast(), LanguageKind::Css => load_css_ast(), LanguageKind::Json => load_json_ast(), + LanguageKind::Html => load_html_ast(), } } @@ -82,6 +85,7 @@ pub(crate) fn generate_syntax(ast: AstSrc, mode: &Mode, language_kind: LanguageK LanguageKind::Js => JS_KINDS_SRC, LanguageKind::Css => CSS_KINDS_SRC, LanguageKind::Json => JSON_KINDS_SRC, + LanguageKind::Html => HTML_KINDS_SRC, }; let ast_nodes_file = syntax_generated_path.join("nodes.rs"); @@ -182,6 +186,12 @@ pub(crate) fn load_json_ast() -> AstSrc { make_ast(&grammar) } +pub(crate) fn load_html_ast() -> AstSrc { + let grammar_src = include_str!("../html.ungram"); + let grammar: Grammar = grammar_src.parse().unwrap(); + make_ast(&grammar) +} + pub(crate) fn append_css_property_value_implied_alternatives(variants: Vec) -> Vec { let mut cloned = variants.clone(); if !cloned.iter().any(|v| v == "CssWideKeyword") { diff --git a/xtask/codegen/src/css_kinds_src.rs b/xtask/codegen/src/css_kinds_src.rs index 7828ef07eaa9..973577f64568 100644 --- a/xtask/codegen/src/css_kinds_src.rs +++ b/xtask/codegen/src/css_kinds_src.rs @@ -1,4 +1,4 @@ -use crate::kinds_src::KindsSrc; +use crate::kind_src::KindsSrc; pub const CSS_KINDS_SRC: KindsSrc = KindsSrc { punct: &[ diff --git a/xtask/codegen/src/formatter.rs b/xtask/codegen/src/formatter.rs index 3b29c22795bc..b5adc3973df9 100644 --- a/xtask/codegen/src/formatter.rs +++ b/xtask/codegen/src/formatter.rs @@ -780,6 +780,11 @@ fn get_node_concept( } _ => NodeConcept::Auxiliary, }, + + LanguageKind::Html => match name { + _ if name.ends_with("Value") => NodeConcept::Value, + _ => NodeConcept::Auxiliary, + }, } } } @@ -841,6 +846,7 @@ impl LanguageKind { LanguageKind::Js => "JsFormatter", LanguageKind::Css => "CssFormatter", LanguageKind::Json => "JsonFormatter", + LanguageKind::Html => "HtmlFormatter", }; Ident::new(name, Span::call_site()) @@ -851,6 +857,7 @@ impl LanguageKind { LanguageKind::Js => "JsFormatContext", LanguageKind::Css => "CssFormatContext", LanguageKind::Json => "JsonFormatContext", + LanguageKind::Html => "HtmlFormatContext", }; Ident::new(name, Span::call_site()) diff --git a/xtask/codegen/src/generate_macros.rs b/xtask/codegen/src/generate_macros.rs index 199807b5e1cc..87a3668c74b5 100644 --- a/xtask/codegen/src/generate_macros.rs +++ b/xtask/codegen/src/generate_macros.rs @@ -1,4 +1,4 @@ -use super::kinds_src::AstSrc; +use super::js_kinds_src::AstSrc; use crate::{to_upper_snake_case, LanguageKind, Result}; use quote::{format_ident, quote}; diff --git a/xtask/codegen/src/generate_node_factory.rs b/xtask/codegen/src/generate_node_factory.rs index c8608520e478..e0a4a2a43cf1 100644 --- a/xtask/codegen/src/generate_node_factory.rs +++ b/xtask/codegen/src/generate_node_factory.rs @@ -1,6 +1,6 @@ -use super::kinds_src::AstSrc; +use super::js_kinds_src::AstSrc; use crate::to_lower_snake_case; -use crate::{kinds_src::Field, to_upper_snake_case, LanguageKind}; +use crate::{js_kinds_src::Field, to_upper_snake_case, LanguageKind}; use quote::{format_ident, quote}; use xtask::Result; diff --git a/xtask/codegen/src/generate_nodes.rs b/xtask/codegen/src/generate_nodes.rs index 0b12e5c2bf9b..e29589e888ef 100644 --- a/xtask/codegen/src/generate_nodes.rs +++ b/xtask/codegen/src/generate_nodes.rs @@ -1,6 +1,7 @@ use crate::css_kinds_src::CSS_KINDS_SRC; +use crate::html_kinds_src::HTML_KINDS_SRC; +use crate::js_kinds_src::{AstNodeSrc, AstSrc, Field, TokenKind, JS_KINDS_SRC}; use crate::json_kinds_src::JSON_KINDS_SRC; -use crate::kinds_src::{AstNodeSrc, AstSrc, Field, TokenKind, JS_KINDS_SRC}; use crate::{to_lower_snake_case, to_upper_snake_case, LanguageKind}; use proc_macro2::{Literal, TokenStream}; use quote::{format_ident, quote}; @@ -947,6 +948,7 @@ pub(crate) fn token_kind_to_code( LanguageKind::Js => JS_KINDS_SRC, LanguageKind::Css => CSS_KINDS_SRC, LanguageKind::Json => JSON_KINDS_SRC, + LanguageKind::Html => HTML_KINDS_SRC, }; if kind_source.literals.contains(&kind_variant_name.as_str()) || kind_source.tokens.contains(&kind_variant_name.as_str()) diff --git a/xtask/codegen/src/generate_nodes_mut.rs b/xtask/codegen/src/generate_nodes_mut.rs index c85937c95cfe..e096454bc366 100644 --- a/xtask/codegen/src/generate_nodes_mut.rs +++ b/xtask/codegen/src/generate_nodes_mut.rs @@ -1,4 +1,4 @@ -use crate::kinds_src::{AstSrc, Field}; +use crate::js_kinds_src::{AstSrc, Field}; use crate::LanguageKind; use quote::{format_ident, quote}; use xtask::Result; diff --git a/xtask/codegen/src/generate_syntax_factory.rs b/xtask/codegen/src/generate_syntax_factory.rs index 27e964c12e7c..008c21066154 100644 --- a/xtask/codegen/src/generate_syntax_factory.rs +++ b/xtask/codegen/src/generate_syntax_factory.rs @@ -1,4 +1,4 @@ -use super::kinds_src::AstSrc; +use super::js_kinds_src::AstSrc; use crate::generate_nodes::{get_field_predicate, group_fields_for_ordering, token_kind_to_code}; use crate::{to_upper_snake_case, LanguageKind}; use proc_macro2::TokenStream; @@ -22,6 +22,11 @@ pub fn generate_syntax_factory(ast: &AstSrc, language_kind: LanguageKind) -> Res quote! { JsonSyntaxKind }, quote! { JsonSyntaxFactory }, ), + LanguageKind::Html => ( + quote! { biome_html_syntax }, + quote! { HtmlSyntaxKind }, + quote! { HtmlSyntaxFactory }, + ), }; let normal_node_arms = ast.nodes.iter().map(|node| { let kind = format_ident!("{}", to_upper_snake_case(&node.name)); diff --git a/xtask/codegen/src/generate_syntax_kinds.rs b/xtask/codegen/src/generate_syntax_kinds.rs index dc61989e1417..9a956eb7392b 100644 --- a/xtask/codegen/src/generate_syntax_kinds.rs +++ b/xtask/codegen/src/generate_syntax_kinds.rs @@ -1,9 +1,8 @@ +use crate::kind_src::KindsSrc; use crate::{to_upper_snake_case, LanguageKind, Result}; use proc_macro2::{Literal, Punct, Spacing}; use quote::{format_ident, quote}; -use super::kinds_src::KindsSrc; - pub fn generate_syntax_kinds(grammar: KindsSrc, language_kind: LanguageKind) -> Result { let syntax_kind = language_kind.syntax_kind(); let punctuation_values = grammar.punct.iter().map(|(token, _name)| { @@ -123,6 +122,19 @@ pub fn generate_syntax_kinds(grammar: KindsSrc, language_kind: LanguageKind) -> } } } + LanguageKind::Html => { + quote! { + pub const fn to_string(&self) -> Option<&'static str> { + let tok = match self { + #(#punctuation => #punctuation_strings,)* + #(#full_keywords => #all_keyword_to_strings,)* + HTML_STRING_LITERAL => "string literal", + _ => return None, + }; + Some(tok) + } + } + } }; let ast = quote! { diff --git a/xtask/codegen/src/html_kinds_src.rs b/xtask/codegen/src/html_kinds_src.rs new file mode 100644 index 000000000000..e1bbc332a6e7 --- /dev/null +++ b/xtask/codegen/src/html_kinds_src.rs @@ -0,0 +1,38 @@ +use crate::kind_src::KindsSrc; + +pub const HTML_KINDS_SRC: KindsSrc = KindsSrc { + punct: &[ + ("<", "L_ANGLE"), + (">", "R_ANGLE"), + ("/", "SLASH"), + ("=", "EQ"), + ("!", "BANG"), + ], + keywords: &["null", "true", "false"], + literals: &["HTML_STRING_LITERAL"], + tokens: &[ + "ERROR_TOKEN", + "NEWLINE", + "WHITESPACE", + "IDENT", + "COMMENT", + "HTML_IDENT", + ], + nodes: &[ + "HTML_ROOT", + "HTML_DIRECTIVE", + "HTML_SELF_CLOSING_TAG", + "HTML_ELEMENT", + "HTML_OPENING_ELEMENT", + "HTML_CLOSING_ELEMENT", + "HTML_SELF_CLOSING_ELEMENT", + "HTML_ATTRIBUTE", + "HTML_ATTRIBUTE_INITIALIZER_CLAUSE", + "HTML_STRING", + "HTML_NAME", + "HTML_ELEMENT_LIST", + "HTML_ATTRIBUTE_LIST", + // Bogus nodes + "HTML_BOGUS", + ], +}; diff --git a/xtask/codegen/src/kinds_src.rs b/xtask/codegen/src/js_kinds_src.rs similarity index 98% rename from xtask/codegen/src/kinds_src.rs rename to xtask/codegen/src/js_kinds_src.rs index 62197be5a024..901c8279decd 100644 --- a/xtask/codegen/src/kinds_src.rs +++ b/xtask/codegen/src/js_kinds_src.rs @@ -2,21 +2,13 @@ //! Based on the rust analyzer parser and ast definitions use crate::css_kinds_src::CSS_KINDS_SRC; +use crate::html_kinds_src::HTML_KINDS_SRC; use crate::json_kinds_src::JSON_KINDS_SRC; +use crate::kind_src::{KindsSrc, LANGUAGE_PREFIXES}; use crate::LanguageKind; use quote::format_ident; use std::collections::BTreeMap; -const LANGUAGE_PREFIXES: [&str; 6] = ["js_", "ts_", "jsx_", "tsx_", "css_", "json_"]; - -pub struct KindsSrc<'a> { - pub punct: &'a [(&'a str, &'a str)], - pub keywords: &'a [&'a str], - pub literals: &'a [&'a str], - pub tokens: &'a [&'a str], - pub nodes: &'a [&'a str], -} - pub const JS_KINDS_SRC: KindsSrc = KindsSrc { punct: &[ (";", "SEMICOLON"), @@ -699,6 +691,7 @@ impl Field { LanguageKind::Js => JS_KINDS_SRC, LanguageKind::Css => CSS_KINDS_SRC, LanguageKind::Json => JSON_KINDS_SRC, + LanguageKind::Html => HTML_KINDS_SRC, }; // we need to replace "-" with "_" for the keywords diff --git a/xtask/codegen/src/json_kinds_src.rs b/xtask/codegen/src/json_kinds_src.rs index 99a9384f8d98..26fa02a5afd6 100644 --- a/xtask/codegen/src/json_kinds_src.rs +++ b/xtask/codegen/src/json_kinds_src.rs @@ -1,4 +1,4 @@ -use crate::kinds_src::KindsSrc; +use crate::kind_src::KindsSrc; pub const JSON_KINDS_SRC: KindsSrc = KindsSrc { punct: &[ diff --git a/xtask/codegen/src/kind_src.rs b/xtask/codegen/src/kind_src.rs new file mode 100644 index 000000000000..45e6227e2374 --- /dev/null +++ b/xtask/codegen/src/kind_src.rs @@ -0,0 +1,9 @@ +pub const LANGUAGE_PREFIXES: [&str; 7] = ["js_", "ts_", "jsx_", "tsx_", "css_", "json_", "html_"]; + +pub struct KindsSrc<'a> { + pub punct: &'a [(&'a str, &'a str)], + pub keywords: &'a [&'a str], + pub literals: &'a [&'a str], + pub tokens: &'a [&'a str], + pub nodes: &'a [&'a str], +} diff --git a/xtask/codegen/src/lib.rs b/xtask/codegen/src/lib.rs index c99dc29b78cf..d51f0aa0d6c5 100644 --- a/xtask/codegen/src/lib.rs +++ b/xtask/codegen/src/lib.rs @@ -11,8 +11,11 @@ mod generate_nodes; mod generate_nodes_mut; mod generate_syntax_factory; mod generate_syntax_kinds; +mod js_kinds_src; mod json_kinds_src; -mod kinds_src; + +mod html_kinds_src; +mod kind_src; mod parser_tests; pub mod promote_rule; mod termcolorful; @@ -41,6 +44,7 @@ pub enum LanguageKind { Js, Css, Json, + Html, } impl std::fmt::Display for LanguageKind { @@ -49,12 +53,17 @@ impl std::fmt::Display for LanguageKind { LanguageKind::Js => write!(f, "js"), LanguageKind::Css => write!(f, "css"), LanguageKind::Json => write!(f, "json"), + LanguageKind::Html => write!(f, "html"), } } } -pub const ALL_LANGUAGE_KIND: [LanguageKind; 3] = - [LanguageKind::Js, LanguageKind::Css, LanguageKind::Json]; +pub const ALL_LANGUAGE_KIND: [LanguageKind; 4] = [ + LanguageKind::Js, + LanguageKind::Css, + LanguageKind::Json, + LanguageKind::Html, +]; impl FromStr for LanguageKind { type Err = String; @@ -64,6 +73,7 @@ impl FromStr for LanguageKind { "js" => Ok(LanguageKind::Js), "css" => Ok(LanguageKind::Css), "json" => Ok(LanguageKind::Json), + "html" => Ok(LanguageKind::Html), _ => Err(format!( "Language {} not supported, please use: `js`, `css` or `json`", kind @@ -82,6 +92,7 @@ impl LanguageKind { LanguageKind::Js => quote! { JsSyntaxKind }, LanguageKind::Css => quote! { CssSyntaxKind }, LanguageKind::Json => quote! { JsonSyntaxKind }, + LanguageKind::Html => quote! { HtmlSyntaxKind }, } } @@ -90,6 +101,7 @@ impl LanguageKind { LanguageKind::Js => quote! { JsSyntaxNode }, LanguageKind::Css => quote! { CssSyntaxNode }, LanguageKind::Json => quote! { JsonSyntaxNode }, + LanguageKind::Html => quote! { HtmlSyntaxNode }, } } @@ -98,6 +110,7 @@ impl LanguageKind { LanguageKind::Js => quote! { JsSyntaxElement }, LanguageKind::Css => quote! { CssSyntaxElement }, LanguageKind::Json => quote! { JsonSyntaxElement }, + LanguageKind::Html => quote! { HtmlSyntaxElement }, } } @@ -106,6 +119,7 @@ impl LanguageKind { LanguageKind::Js => quote! { JsSyntaxToken }, LanguageKind::Css => quote! { CssSyntaxToken }, LanguageKind::Json => quote! { JsonSyntaxToken }, + LanguageKind::Html => quote! { HtmlSyntaxToken }, } } @@ -114,6 +128,7 @@ impl LanguageKind { LanguageKind::Js => quote! { JsSyntaxElementChildren }, LanguageKind::Css => quote! { CssSyntaxElementChildren }, LanguageKind::Json => quote! { JsonSyntaxElementChildren }, + LanguageKind::Html => quote! { HtmlSyntaxElementChildren }, } } @@ -122,6 +137,7 @@ impl LanguageKind { LanguageKind::Js => quote! { JsSyntaxList }, LanguageKind::Css => quote! { CssSyntaxList }, LanguageKind::Json => quote! { JsonSyntaxList }, + LanguageKind::Html => quote! { HtmlSyntaxList }, } } @@ -130,6 +146,7 @@ impl LanguageKind { LanguageKind::Js => quote! { JsLanguage }, LanguageKind::Css => quote! { CssLanguage }, LanguageKind::Json => quote! { JsonLanguage }, + LanguageKind::Html => quote! { HtmlLanguage }, } } @@ -138,6 +155,7 @@ impl LanguageKind { LanguageKind::Js => "biome_js_formatter", LanguageKind::Css => "biome_css_formatter", LanguageKind::Json => "biome_json_formatter", + LanguageKind::Html => "biome_html_formatter", } } @@ -146,6 +164,7 @@ impl LanguageKind { LanguageKind::Js => "biome_js_syntax", LanguageKind::Css => "biome_css_syntax", LanguageKind::Json => "biome_json_syntax", + LanguageKind::Html => "biome_html_syntax", } } @@ -154,6 +173,7 @@ impl LanguageKind { LanguageKind::Js => "biome_js_factory", LanguageKind::Css => "biome_css_factory", LanguageKind::Json => "biome_json_factory", + LanguageKind::Html => "biome_html_factory", } } } From a6caba8718d4f029c93bf7f108ac3086c20bdc7c Mon Sep 17 00:00:00 2001 From: Denis Bezrukov <6227442+denbezrukov@users.noreply.github.com> Date: Fri, 12 Jan 2024 23:26:10 +0200 Subject: [PATCH 03/49] Refactor CSS Parser to rename CssRule to CssQualifiedRule (#1546) --- .../src/generated/node_factory.rs | 21 +- .../src/generated/syntax_factory.rs | 49 ++- .../biome_css_formatter/src/css/any/rule.rs | 2 +- .../src/css/auxiliary/mod.rs | 2 +- .../auxiliary/{rule.rs => qualified_rule.rs} | 11 +- crates/biome_css_formatter/src/generated.rs | 36 +- crates/biome_css_parser/src/syntax/mod.rs | 14 +- .../src/syntax/parse_error.rs | 2 +- .../at_rule/at_rule_container_error.css.snap | 8 +- .../at_rule/at_rule_font_face_error.css.snap | 4 +- .../error/at_rule/at_rule_keyframes.css.snap | 12 +- .../at_rule/at_rule_keyframes_1.css.snap | 8 +- .../error/css_unfinished_block.css.snap | 4 +- .../property/property_generic_error.css.snap | 4 +- .../selector/attribute_selector.css.snap | 12 +- .../selector/class_selector_err.css.snap | 4 +- .../error/selector/id_selector_err.css.snap | 4 +- .../error/selector/invalid_selector.css.snap | 8 +- .../selector/missing_identifier.css.snap | 4 +- ..._class_function_compound_selector.css.snap | 28 +- ...s_function_compound_selector_list.css.snap | 32 +- .../pseudo_class_function_identifier.css.snap | 40 +- .../pseudo_class_function_nth.css.snap | 68 +-- ...s_function_relative_selector_list.css.snap | 32 +- .../pseudo_class_function_selector.css.snap | 20 +- ...eudo_class_function_selector_list.css.snap | 32 +- .../pseudo_class_function_value_list.css.snap | 24 +- .../pseudo_class_identifier.css.snap | 12 +- .../error/selector/pseudo_element.css.snap | 20 +- ...seudo_element_function_identifier.css.snap | 8 +- .../pseudo_element_function_selector.css.snap | 20 +- .../error/selector/traling_comma.css.snap | 4 +- .../at_rule_container_complex.css.snap | 8 +- .../ok/at_rule/at_rule_document.css.snap | 12 +- .../ok/at_rule/at_rule_layer.css.snap | 40 +- .../ok/at_rule/at_rule_media_complex.css.snap | 8 +- .../ok/at_rule/at_rule_scope.css.snap | 32 +- .../at_rule/at_rule_starting_style.css.snap | 8 +- .../ok/at_rule/at_rule_supports.css.snap | 92 ++-- .../css_test_suite/ok/class_selector.css.snap | 4 +- .../ok/declaration_list.css.snap | 44 +- .../css_test_suite/ok/dimension.css.snap | 8 +- .../css_test_suite/ok/function/calc.css.snap | 96 ++--- .../ok/function/linear-gradient.css.snap | 4 +- .../ok/function/unknow.css.snap | 4 +- .../css_test_suite/ok/function/url.css.snap | 4 +- .../css_test_suite/ok/function/var.css.snap | 4 +- .../ok/property/property_all.css.snap | 4 +- .../ok/property/property_border.css.snap | 4 +- .../ok/property/property_generic.css.snap | 4 +- .../ok/property/property_z-index.css.snap | 4 +- .../ok/selector/attribute.css.snap | 192 ++++----- .../css_test_suite/ok/selector/class.css.snap | 4 +- .../ok/selector/complex.css.snap | 48 +-- .../css_test_suite/ok/selector/id.css.snap | 4 +- .../pseudo_class_an_plus_b.css.snap | 396 +++++++++--------- .../pseudo_class/pseudo_class_any.css.snap | 44 +- .../pseudo_class/pseudo_class_basic.css.snap | 76 ++-- .../pseudo_class_current.css.snap | 8 +- .../pseudo_class/pseudo_class_dir.css.snap | 24 +- .../pseudo_class/pseudo_class_future.css.snap | 8 +- .../pseudo_class/pseudo_class_has.css.snap | 44 +- .../pseudo_class/pseudo_class_host.css.snap | 20 +- .../pseudo_class_host_context.css.snap | 12 +- .../pseudo_class/pseudo_class_ident.css.snap | 32 +- .../pseudo_class/pseudo_class_is.css.snap | 64 +-- .../pseudo_class/pseudo_class_lang.css.snap | 32 +- .../pseudo_class_matches.css.snap | 8 +- .../pseudo_class/pseudo_class_module.css.snap | 12 +- .../pseudo_class/pseudo_class_not.css.snap | 96 ++--- .../pseudo_class/pseudo_class_past.css.snap | 8 +- .../pseudo_class/pseudo_class_where.css.snap | 44 +- .../ok/selector/pseudo_element/basic.css.snap | 76 ++-- .../pseudo_element/cue-region.css.snap | 12 +- .../ok/selector/pseudo_element/cue.css.snap | 24 +- .../selector/pseudo_element/escaped.css.snap | 4 +- .../pseudo_element/highlight.css.snap | 12 +- .../ok/selector/pseudo_element/part.css.snap | 8 +- .../pseudo_element/presudo_complex.css.snap | 24 +- .../selector/pseudo_element/slotted.css.snap | 16 +- .../ok/selector/subselector.css.snap | 16 +- .../css_test_suite/ok/selector/type.css.snap | 16 +- .../ok/selector/universal.css.snap | 12 +- .../ok/values/url_value.css.snap | 4 +- crates/biome_css_syntax/src/generated/kind.rs | 2 +- .../biome_css_syntax/src/generated/macros.rs | 8 +- .../biome_css_syntax/src/generated/nodes.rs | 196 ++++----- .../src/generated/nodes_mut.rs | 28 +- crates/biome_unicode_table/src/tables.rs | 8 +- xtask/codegen/css.ungram | 4 +- xtask/codegen/src/css_kinds_src.rs | 2 +- 91 files changed, 1300 insertions(+), 1281 deletions(-) rename crates/biome_css_formatter/src/css/auxiliary/{rule.rs => qualified_rule.rs} (55%) diff --git a/crates/biome_css_factory/src/generated/node_factory.rs b/crates/biome_css_factory/src/generated/node_factory.rs index 4ec0a158057f..2bc2566c3cc6 100644 --- a/crates/biome_css_factory/src/generated/node_factory.rs +++ b/crates/biome_css_factory/src/generated/node_factory.rs @@ -1508,6 +1508,18 @@ pub fn css_pseudo_element_selector( ], )) } +pub fn css_qualified_rule( + prelude: CssSelectorList, + block: AnyCssDeclarationListBlock, +) -> CssQualifiedRule { + CssQualifiedRule::unwrap_cast(SyntaxNode::new_detached( + CssSyntaxKind::CSS_QUALIFIED_RULE, + [ + Some(SyntaxElement::Node(prelude.into_syntax())), + Some(SyntaxElement::Node(block.into_syntax())), + ], + )) +} pub fn css_query_feature_boolean(name: CssIdentifier) -> CssQueryFeatureBoolean { CssQueryFeatureBoolean::unwrap_cast(SyntaxNode::new_detached( CssSyntaxKind::CSS_QUERY_FEATURE_BOOLEAN, @@ -1662,15 +1674,6 @@ impl CssRootBuilder { )) } } -pub fn css_rule(prelude: CssSelectorList, block: AnyCssDeclarationListBlock) -> CssRule { - CssRule::unwrap_cast(SyntaxNode::new_detached( - CssSyntaxKind::CSS_RULE, - [ - Some(SyntaxElement::Node(prelude.into_syntax())), - Some(SyntaxElement::Node(block.into_syntax())), - ], - )) -} pub fn css_rule_list_block( l_curly_token: SyntaxToken, rules: CssRuleList, diff --git a/crates/biome_css_factory/src/generated/syntax_factory.rs b/crates/biome_css_factory/src/generated/syntax_factory.rs index bebd68d45115..f45a2c70f5c5 100644 --- a/crates/biome_css_factory/src/generated/syntax_factory.rs +++ b/crates/biome_css_factory/src/generated/syntax_factory.rs @@ -3060,6 +3060,32 @@ impl SyntaxFactory for CssSyntaxFactory { } slots.into_node(CSS_PSEUDO_ELEMENT_SELECTOR, children) } + CSS_QUALIFIED_RULE => { + let mut elements = (&children).into_iter(); + let mut slots: RawNodeSlots<2usize> = RawNodeSlots::default(); + let mut current_element = elements.next(); + if let Some(element) = ¤t_element { + if CssSelectorList::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if let Some(element) = ¤t_element { + if AnyCssDeclarationListBlock::can_cast(element.kind()) { + slots.mark_present(); + current_element = elements.next(); + } + } + slots.next_slot(); + if current_element.is_some() { + return RawSyntaxNode::new( + CSS_QUALIFIED_RULE.to_bogus(), + children.into_iter().map(Some), + ); + } + slots.into_node(CSS_QUALIFIED_RULE, children) + } CSS_QUERY_FEATURE_BOOLEAN => { let mut elements = (&children).into_iter(); let mut slots: RawNodeSlots<1usize> = RawNodeSlots::default(); @@ -3362,29 +3388,6 @@ impl SyntaxFactory for CssSyntaxFactory { } slots.into_node(CSS_ROOT, children) } - CSS_RULE => { - let mut elements = (&children).into_iter(); - let mut slots: RawNodeSlots<2usize> = RawNodeSlots::default(); - let mut current_element = elements.next(); - if let Some(element) = ¤t_element { - if CssSelectorList::can_cast(element.kind()) { - slots.mark_present(); - current_element = elements.next(); - } - } - slots.next_slot(); - if let Some(element) = ¤t_element { - if AnyCssDeclarationListBlock::can_cast(element.kind()) { - slots.mark_present(); - current_element = elements.next(); - } - } - slots.next_slot(); - if current_element.is_some() { - return RawSyntaxNode::new(CSS_RULE.to_bogus(), children.into_iter().map(Some)); - } - slots.into_node(CSS_RULE, children) - } CSS_RULE_LIST_BLOCK => { let mut elements = (&children).into_iter(); let mut slots: RawNodeSlots<3usize> = RawNodeSlots::default(); diff --git a/crates/biome_css_formatter/src/css/any/rule.rs b/crates/biome_css_formatter/src/css/any/rule.rs index 0be82e00fc37..0f058c2bad47 100644 --- a/crates/biome_css_formatter/src/css/any/rule.rs +++ b/crates/biome_css_formatter/src/css/any/rule.rs @@ -8,7 +8,7 @@ impl FormatRule for FormatAnyCssRule { type Context = CssFormatContext; fn fmt(&self, node: &AnyCssRule, f: &mut CssFormatter) -> FormatResult<()> { match node { - AnyCssRule::CssRule(node) => node.format().fmt(f), + AnyCssRule::CssQualifiedRule(node) => node.format().fmt(f), AnyCssRule::CssAtRule(node) => node.format().fmt(f), AnyCssRule::CssBogusRule(node) => node.format().fmt(f), } diff --git a/crates/biome_css_formatter/src/css/auxiliary/mod.rs b/crates/biome_css_formatter/src/css/auxiliary/mod.rs index 3b917003873f..09ea6fbd98fe 100644 --- a/crates/biome_css_formatter/src/css/auxiliary/mod.rs +++ b/crates/biome_css_formatter/src/css/auxiliary/mod.rs @@ -48,6 +48,7 @@ pub(crate) mod nth_offset; pub(crate) mod page_at_rule_block; pub(crate) mod parameter; pub(crate) mod parenthesized_expression; +pub(crate) mod qualified_rule; pub(crate) mod query_feature_boolean; pub(crate) mod query_feature_plain; pub(crate) mod query_feature_range; @@ -55,7 +56,6 @@ pub(crate) mod query_feature_range_comparison; pub(crate) mod query_feature_range_interval; pub(crate) mod query_feature_reverse_range; pub(crate) mod root; -pub(crate) mod rule; pub(crate) mod rule_list_block; pub(crate) mod scope_edge; pub(crate) mod scope_range_end; diff --git a/crates/biome_css_formatter/src/css/auxiliary/rule.rs b/crates/biome_css_formatter/src/css/auxiliary/qualified_rule.rs similarity index 55% rename from crates/biome_css_formatter/src/css/auxiliary/rule.rs rename to crates/biome_css_formatter/src/css/auxiliary/qualified_rule.rs index d13d03468c71..5bf62ecbca0f 100644 --- a/crates/biome_css_formatter/src/css/auxiliary/rule.rs +++ b/crates/biome_css_formatter/src/css/auxiliary/qualified_rule.rs @@ -1,11 +1,12 @@ use crate::prelude::*; -use biome_css_syntax::{CssRule, CssRuleFields}; +use biome_css_syntax::{CssQualifiedRule, CssQualifiedRuleFields}; use biome_formatter::write; + #[derive(Debug, Clone, Default)] -pub(crate) struct FormatCssRule; -impl FormatNodeRule for FormatCssRule { - fn fmt_fields(&self, node: &CssRule, f: &mut CssFormatter) -> FormatResult<()> { - let CssRuleFields { prelude, block } = node.as_fields(); +pub(crate) struct FormatCssQualifiedRule; +impl FormatNodeRule for FormatCssQualifiedRule { + fn fmt_fields(&self, node: &CssQualifiedRule, f: &mut CssFormatter) -> FormatResult<()> { + let CssQualifiedRuleFields { prelude, block } = node.as_fields(); write!( f, diff --git a/crates/biome_css_formatter/src/generated.rs b/crates/biome_css_formatter/src/generated.rs index 96fedf619d21..956a5e4b4b28 100644 --- a/crates/biome_css_formatter/src/generated.rs +++ b/crates/biome_css_formatter/src/generated.rs @@ -30,30 +30,44 @@ impl IntoFormat for biome_css_syntax::CssRoot { FormatOwnedWithRule::new(self, crate::css::auxiliary::root::FormatCssRoot::default()) } } -impl FormatRule for crate::css::auxiliary::rule::FormatCssRule { +impl FormatRule + for crate::css::auxiliary::qualified_rule::FormatCssQualifiedRule +{ type Context = CssFormatContext; #[inline(always)] - fn fmt(&self, node: &biome_css_syntax::CssRule, f: &mut CssFormatter) -> FormatResult<()> { - FormatNodeRule::::fmt(self, node, f) + fn fmt( + &self, + node: &biome_css_syntax::CssQualifiedRule, + f: &mut CssFormatter, + ) -> FormatResult<()> { + FormatNodeRule::::fmt(self, node, f) } } -impl AsFormat for biome_css_syntax::CssRule { +impl AsFormat for biome_css_syntax::CssQualifiedRule { type Format<'a> = FormatRefWithRule< 'a, - biome_css_syntax::CssRule, - crate::css::auxiliary::rule::FormatCssRule, + biome_css_syntax::CssQualifiedRule, + crate::css::auxiliary::qualified_rule::FormatCssQualifiedRule, >; fn format(&self) -> Self::Format<'_> { #![allow(clippy::default_constructed_unit_structs)] - FormatRefWithRule::new(self, crate::css::auxiliary::rule::FormatCssRule::default()) + FormatRefWithRule::new( + self, + crate::css::auxiliary::qualified_rule::FormatCssQualifiedRule::default(), + ) } } -impl IntoFormat for biome_css_syntax::CssRule { - type Format = - FormatOwnedWithRule; +impl IntoFormat for biome_css_syntax::CssQualifiedRule { + type Format = FormatOwnedWithRule< + biome_css_syntax::CssQualifiedRule, + crate::css::auxiliary::qualified_rule::FormatCssQualifiedRule, + >; fn into_format(self) -> Self::Format { #![allow(clippy::default_constructed_unit_structs)] - FormatOwnedWithRule::new(self, crate::css::auxiliary::rule::FormatCssRule::default()) + FormatOwnedWithRule::new( + self, + crate::css::auxiliary::qualified_rule::FormatCssQualifiedRule::default(), + ) } } impl FormatRule for crate::css::statements::at_rule::FormatCssAtRule { diff --git a/crates/biome_css_parser/src/syntax/mod.rs b/crates/biome_css_parser/src/syntax/mod.rs index 9ecc4e51630f..d058bc5e5805 100644 --- a/crates/biome_css_parser/src/syntax/mod.rs +++ b/crates/biome_css_parser/src/syntax/mod.rs @@ -70,7 +70,7 @@ impl ParseRecovery for RuleListParseRecovery { const RECOVERED_KIND: Self::Kind = CSS_BOGUS_RULE; fn is_at_recovered(&self, p: &mut Self::Parser<'_>) -> bool { - is_at_at_rule(p) || is_at_rule(p) + is_at_at_rule(p) || is_at_qualified_rule(p) } } @@ -82,8 +82,8 @@ impl ParseNodeList for RuleList { fn parse_element(&mut self, p: &mut Self::Parser<'_>) -> ParsedSyntax { if is_at_at_rule(p) { parse_at_rule(p) - } else if is_at_rule(p) { - parse_rule(p) + } else if is_at_qualified_rule(p) { + parse_qualified_rule(p) } else { Absent } @@ -103,13 +103,13 @@ impl ParseNodeList for RuleList { } #[inline] -pub(crate) fn is_at_rule(p: &mut CssParser) -> bool { +pub(crate) fn is_at_qualified_rule(p: &mut CssParser) -> bool { is_at_selector(p) } #[inline] -pub(crate) fn parse_rule(p: &mut CssParser) -> ParsedSyntax { - if !is_at_rule(p) { +pub(crate) fn parse_qualified_rule(p: &mut CssParser) -> ParsedSyntax { + if !is_at_qualified_rule(p) { return Absent; } @@ -118,7 +118,7 @@ pub(crate) fn parse_rule(p: &mut CssParser) -> ParsedSyntax { SelectorList::default().parse_list(p); let kind = if parse_or_recover_declaration_list_block(p).is_ok() { - CSS_RULE + CSS_QUALIFIED_RULE } else { CSS_BOGUS_RULE }; diff --git a/crates/biome_css_parser/src/syntax/parse_error.rs b/crates/biome_css_parser/src/syntax/parse_error.rs index 02ad7ae38244..31f101ac0d5b 100644 --- a/crates/biome_css_parser/src/syntax/parse_error.rs +++ b/crates/biome_css_parser/src/syntax/parse_error.rs @@ -73,7 +73,7 @@ pub(crate) fn expected_selector(p: &CssParser, range: TextRange) -> ParseDiagnos } pub(crate) fn expected_any_rule(p: &CssParser, range: TextRange) -> ParseDiagnostic { - expected_any(&["rule", "at rule"], range, p) + expected_any(&["qualified rule", "at rule"], range, p) } pub(crate) fn expected_any_declaration_or_at_rule( diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container_error.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container_error.css.snap index 43b39febb7e4..468cbaa4a03f 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container_error.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_container_error.css.snap @@ -220,7 +220,7 @@ CssRoot { ], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -263,7 +263,7 @@ CssRoot { ], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -612,7 +612,7 @@ CssRoot { 0: CONTAINER_KW@203..213 "container" [] [Whitespace(" ")] 1: CSS_BOGUS@213..221 0: INHERIT_KW@213..221 "inherit" [] [Whitespace(" ")] - 6: CSS_RULE@221..240 + 6: CSS_QUALIFIED_RULE@221..240 0: CSS_SELECTOR_LIST@221..237 0: CSS_COMPLEX_SELECTOR@221..227 0: CSS_COMPOUND_SELECTOR@221..226 @@ -640,7 +640,7 @@ CssRoot { 0: CONTAINER_KW@243..253 "container" [] [Whitespace(" ")] 1: CSS_CUSTOM_IDENTIFIER@253..257 0: IDENT@253..257 "not" [] [Whitespace(" ")] - 8: CSS_RULE@257..277 + 8: CSS_QUALIFIED_RULE@257..277 0: CSS_SELECTOR_LIST@257..273 0: CSS_COMPLEX_SELECTOR@257..263 0: CSS_COMPOUND_SELECTOR@257..262 diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_font_face_error.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_font_face_error.css.snap index f6fe937ab0d6..01ef8aa02fab 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_font_face_error.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_font_face_error.css.snap @@ -26,7 +26,7 @@ CssRoot { ], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -101,7 +101,7 @@ CssRoot { 0: AT@0..1 "@" [] [] 1: CSS_BOGUS_AT_RULE@1..11 0: FONT_FACE_KW@1..11 "font-face" [] [Whitespace(" ")] - 1: CSS_RULE@11..17 + 1: CSS_QUALIFIED_RULE@11..17 0: CSS_SELECTOR_LIST@11..15 0: CSS_COMPOUND_SELECTOR@11..15 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes.css.snap index b13a684cdaac..d88b7260906b 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes.css.snap @@ -501,7 +501,7 @@ CssRoot { }, }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1122,7 +1122,7 @@ CssRoot { 0: R_PAREN@446..447 ")" [] [] 1: SEMICOLON@447..448 ";" [] [] 2: R_CURLY@448..451 "}" [Newline("\n"), Whitespace("\t")] [] - 6: CSS_RULE@451..492 + 6: CSS_QUALIFIED_RULE@451..492 0: CSS_SELECTOR_LIST@451..457 0: CSS_COMPOUND_SELECTOR@451..457 0: (empty) @@ -1481,7 +1481,7 @@ at_rule_keyframes.css:42:2 parse ━━━━━━━━━━━━━━━ at_rule_keyframes.css:47:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - × Expected a rule, or an at rule but instead found '}'. + × Expected a qualified rule, or an at rule but instead found '}'. 45 │ transform: translateX(100%); 46 │ } @@ -1490,7 +1490,7 @@ at_rule_keyframes.css:47:1 parse ━━━━━━━━━━━━━━━ 48 │ 49 │ @keyframes slidein { - i Expected a rule, or an at rule here. + i Expected a qualified rule, or an at rule here. 45 │ transform: translateX(100%); 46 │ } @@ -1551,7 +1551,7 @@ at_rule_keyframes.css:56:2 parse ━━━━━━━━━━━━━━━ at_rule_keyframes.css:57:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - × Expected a rule, or an at rule but instead found '}'. + × Expected a qualified rule, or an at rule but instead found '}'. 55 │ transform: translateX(100%); 56 │ } @@ -1560,7 +1560,7 @@ at_rule_keyframes.css:57:1 parse ━━━━━━━━━━━━━━━ 58 │ 59 │ @keyframes slidein { - i Expected a rule, or an at rule here. + i Expected a qualified rule, or an at rule here. 55 │ transform: translateX(100%); 56 │ } diff --git a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes_1.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes_1.css.snap index 7aeebbba89ed..d8fe383dbd0b 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes_1.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/at_rule/at_rule_keyframes_1.css.snap @@ -138,7 +138,7 @@ CssRoot { }, }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -417,7 +417,7 @@ CssRoot { 0: CSS_KEYFRAMES_IDENT_SELECTOR@87..93 0: FROM_KW@87..93 "from" [Newline("\n"), Whitespace("\t")] [] 2: R_CURLY@93..96 "}" [Newline("\n"), Whitespace("\t")] [] - 2: CSS_RULE@96..120 + 2: CSS_QUALIFIED_RULE@96..120 0: CSS_SELECTOR_LIST@96..101 0: CSS_COMPOUND_SELECTOR@96..101 0: (empty) @@ -601,7 +601,7 @@ at_rule_keyframes_1.css:12:2 parse ━━━━━━━━━━━━━━━ at_rule_keyframes_1.css:16:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - × Expected a rule, or an at rule but instead found '}'. + × Expected a qualified rule, or an at rule but instead found '}'. 14 │ color: blue; 15 │ } @@ -610,7 +610,7 @@ at_rule_keyframes_1.css:16:1 parse ━━━━━━━━━━━━━━━ 17 │ 18 │ @keyframes name2 { - i Expected a rule, or an at rule here. + i Expected a qualified rule, or an at rule here. 14 │ color: blue; 15 │ } diff --git a/crates/biome_css_parser/tests/css_test_suite/error/css_unfinished_block.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/css_unfinished_block.css.snap index 7853e8f9acf8..9cc87e525f59 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/css_unfinished_block.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/css_unfinished_block.css.snap @@ -17,7 +17,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -49,7 +49,7 @@ CssRoot { 0: CSS_ROOT@0..10 0: (empty) 1: CSS_RULE_LIST@0..9 - 0: CSS_RULE@0..9 + 0: CSS_QUALIFIED_RULE@0..9 0: CSS_SELECTOR_LIST@0..8 0: CSS_COMPOUND_SELECTOR@0..8 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css.snap index f3a83237529e..bb419e7d6461 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/property/property_generic_error.css.snap @@ -20,7 +20,7 @@ div { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -94,7 +94,7 @@ CssRoot { 0: CSS_ROOT@0..66 0: (empty) 1: CSS_RULE_LIST@0..66 - 0: CSS_RULE@0..66 + 0: CSS_QUALIFIED_RULE@0..66 0: CSS_SELECTOR_LIST@0..4 0: CSS_COMPOUND_SELECTOR@0..4 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/attribute_selector.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/attribute_selector.css.snap index 6c1cdf0a306d..9378520ac75c 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/attribute_selector.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/attribute_selector.css.snap @@ -22,7 +22,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -48,7 +48,7 @@ CssRoot { r_curly_token: R_CURLY@10..11 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -86,7 +86,7 @@ CssRoot { r_curly_token: R_CURLY@30..31 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -162,7 +162,7 @@ CssRoot { 0: CSS_ROOT@0..66 0: (empty) 1: CSS_RULE_LIST@0..65 - 0: CSS_RULE@0..11 + 0: CSS_QUALIFIED_RULE@0..11 0: CSS_SELECTOR_LIST@0..9 0: CSS_COMPOUND_SELECTOR@0..9 0: (empty) @@ -177,7 +177,7 @@ CssRoot { 0: L_CURLY@9..10 "{" [] [] 1: CSS_DECLARATION_LIST@10..10 2: R_CURLY@10..11 "}" [] [] - 1: CSS_RULE@11..31 + 1: CSS_QUALIFIED_RULE@11..31 0: CSS_SELECTOR_LIST@11..29 0: CSS_COMPOUND_SELECTOR@11..29 0: (empty) @@ -200,7 +200,7 @@ CssRoot { 0: L_CURLY@29..30 "{" [] [] 1: CSS_DECLARATION_LIST@30..30 2: R_CURLY@30..31 "}" [] [] - 2: CSS_RULE@31..50 + 2: CSS_QUALIFIED_RULE@31..50 0: CSS_SELECTOR_LIST@31..48 0: CSS_COMPOUND_SELECTOR@31..48 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/class_selector_err.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/class_selector_err.css.snap index 5a9bdeb8b1dd..8ec8abbc5cd6 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/class_selector_err.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/class_selector_err.css.snap @@ -17,7 +17,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -53,7 +53,7 @@ CssRoot { 0: CSS_ROOT@0..12 0: (empty) 1: CSS_RULE_LIST@0..11 - 0: CSS_RULE@0..11 + 0: CSS_QUALIFIED_RULE@0..11 0: CSS_SELECTOR_LIST@0..9 0: CSS_COMPOUND_SELECTOR@0..9 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/id_selector_err.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/id_selector_err.css.snap index e365e757c700..0053d6e90b82 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/id_selector_err.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/id_selector_err.css.snap @@ -17,7 +17,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -53,7 +53,7 @@ CssRoot { 0: CSS_ROOT@0..12 0: (empty) 1: CSS_RULE_LIST@0..11 - 0: CSS_RULE@0..11 + 0: CSS_QUALIFIED_RULE@0..11 0: CSS_SELECTOR_LIST@0..9 0: CSS_COMPOUND_SELECTOR@0..9 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/invalid_selector.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/invalid_selector.css.snap index 8b0f4b7f8114..2f18c8b6976e 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/invalid_selector.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/invalid_selector.css.snap @@ -24,7 +24,7 @@ CssRoot { BANG@0..1 "!" [] [], ], }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -58,7 +58,7 @@ CssRoot { 1: CSS_RULE_LIST@0..15 0: CSS_BOGUS_RULE@0..1 0: BANG@0..1 "!" [] [] - 1: CSS_RULE@1..15 + 1: CSS_QUALIFIED_RULE@1..15 0: CSS_SELECTOR_LIST@1..11 0: CSS_COMPOUND_SELECTOR@1..11 0: (empty) @@ -81,14 +81,14 @@ CssRoot { ``` invalid_selector.css:1:1 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - × Expected a rule, or an at rule but instead found '!'. + × Expected a qualified rule, or an at rule but instead found '!'. > 1 │ !.selector { │ ^ 2 │ 3 │ } - i Expected a rule, or an at rule here. + i Expected a qualified rule, or an at rule here. > 1 │ !.selector { │ ^ diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/missing_identifier.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/missing_identifier.css.snap index 4896d634eed4..a03dac4b2f27 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/missing_identifier.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/missing_identifier.css.snap @@ -17,7 +17,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -58,7 +58,7 @@ CssRoot { 0: CSS_ROOT@0..9 0: (empty) 1: CSS_RULE_LIST@0..8 - 0: CSS_RULE@0..8 + 0: CSS_QUALIFIED_RULE@0..8 0: CSS_SELECTOR_LIST@0..6 0: CSS_COMPOUND_SELECTOR@0..2 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_compound_selector.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_compound_selector.css.snap index 20d6b1cbf159..d547698486cb 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_compound_selector.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_compound_selector.css.snap @@ -24,7 +24,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -48,7 +48,7 @@ CssRoot { r_curly_token: R_CURLY@8..9 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -73,7 +73,7 @@ CssRoot { r_curly_token: R_CURLY@19..20 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -117,7 +117,7 @@ CssRoot { r_curly_token: R_CURLY@42..43 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -160,7 +160,7 @@ CssRoot { r_curly_token: R_CURLY@64..65 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -204,7 +204,7 @@ CssRoot { r_curly_token: R_CURLY@86..87 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -247,7 +247,7 @@ CssRoot { r_curly_token: R_CURLY@107..108 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -327,7 +327,7 @@ CssRoot { 0: CSS_ROOT@0..134 0: (empty) 1: CSS_RULE_LIST@0..133 - 0: CSS_RULE@0..9 + 0: CSS_QUALIFIED_RULE@0..9 0: CSS_SELECTOR_LIST@0..7 0: CSS_COMPOUND_SELECTOR@0..7 0: (empty) @@ -342,7 +342,7 @@ CssRoot { 0: L_CURLY@7..8 "{" [] [] 1: CSS_DECLARATION_LIST@8..8 2: R_CURLY@8..9 "}" [] [] - 1: CSS_RULE@9..20 + 1: CSS_QUALIFIED_RULE@9..20 0: CSS_SELECTOR_LIST@9..18 0: CSS_COMPOUND_SELECTOR@9..18 0: (empty) @@ -358,7 +358,7 @@ CssRoot { 0: L_CURLY@18..19 "{" [] [] 1: CSS_DECLARATION_LIST@19..19 2: R_CURLY@19..20 "}" [] [] - 2: CSS_RULE@20..43 + 2: CSS_QUALIFIED_RULE@20..43 0: CSS_SELECTOR_LIST@20..41 0: CSS_COMPOUND_SELECTOR@20..41 0: (empty) @@ -386,7 +386,7 @@ CssRoot { 0: L_CURLY@41..42 "{" [] [] 1: CSS_DECLARATION_LIST@42..42 2: R_CURLY@42..43 "}" [] [] - 3: CSS_RULE@43..65 + 3: CSS_QUALIFIED_RULE@43..65 0: CSS_SELECTOR_LIST@43..63 0: CSS_COMPOUND_SELECTOR@43..63 0: (empty) @@ -413,7 +413,7 @@ CssRoot { 0: L_CURLY@63..64 "{" [] [] 1: CSS_DECLARATION_LIST@64..64 2: R_CURLY@64..65 "}" [] [] - 4: CSS_RULE@65..87 + 4: CSS_QUALIFIED_RULE@65..87 0: CSS_SELECTOR_LIST@65..85 0: CSS_COMPOUND_SELECTOR@65..85 0: (empty) @@ -441,7 +441,7 @@ CssRoot { 0: L_CURLY@85..86 "{" [] [] 1: CSS_DECLARATION_LIST@86..86 2: R_CURLY@86..87 "}" [] [] - 5: CSS_RULE@87..108 + 5: CSS_QUALIFIED_RULE@87..108 0: CSS_SELECTOR_LIST@87..106 0: CSS_COMPOUND_SELECTOR@87..106 0: (empty) @@ -468,7 +468,7 @@ CssRoot { 0: L_CURLY@106..107 "{" [] [] 1: CSS_DECLARATION_LIST@107..107 2: R_CURLY@107..108 "}" [] [] - 6: CSS_RULE@108..122 + 6: CSS_QUALIFIED_RULE@108..122 0: CSS_SELECTOR_LIST@108..120 0: CSS_COMPOUND_SELECTOR@108..120 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_compound_selector_list.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_compound_selector_list.css.snap index a9ed2955ac85..9a55638c1624 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_compound_selector_list.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_compound_selector_list.css.snap @@ -25,7 +25,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -50,7 +50,7 @@ CssRoot { r_curly_token: R_CURLY@8..9 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -76,7 +76,7 @@ CssRoot { r_curly_token: R_CURLY@19..20 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -108,7 +108,7 @@ CssRoot { r_curly_token: R_CURLY@38..39 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -139,7 +139,7 @@ CssRoot { r_curly_token: R_CURLY@56..57 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -185,7 +185,7 @@ CssRoot { r_curly_token: R_CURLY@78..79 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -232,7 +232,7 @@ CssRoot { r_curly_token: R_CURLY@101..102 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -277,7 +277,7 @@ CssRoot { r_curly_token: R_CURLY@122..123 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -361,7 +361,7 @@ CssRoot { 0: CSS_ROOT@0..149 0: (empty) 1: CSS_RULE_LIST@0..148 - 0: CSS_RULE@0..9 + 0: CSS_QUALIFIED_RULE@0..9 0: CSS_SELECTOR_LIST@0..7 0: CSS_COMPOUND_SELECTOR@0..7 0: (empty) @@ -377,7 +377,7 @@ CssRoot { 0: L_CURLY@7..8 "{" [] [] 1: CSS_DECLARATION_LIST@8..8 2: R_CURLY@8..9 "}" [] [] - 1: CSS_RULE@9..20 + 1: CSS_QUALIFIED_RULE@9..20 0: CSS_SELECTOR_LIST@9..18 0: CSS_COMPOUND_SELECTOR@9..18 0: (empty) @@ -394,7 +394,7 @@ CssRoot { 0: L_CURLY@18..19 "{" [] [] 1: CSS_DECLARATION_LIST@19..19 2: R_CURLY@19..20 "}" [] [] - 2: CSS_RULE@20..39 + 2: CSS_QUALIFIED_RULE@20..39 0: CSS_SELECTOR_LIST@20..37 0: CSS_COMPOUND_SELECTOR@20..37 0: (empty) @@ -414,7 +414,7 @@ CssRoot { 0: L_CURLY@37..38 "{" [] [] 1: CSS_DECLARATION_LIST@38..38 2: R_CURLY@38..39 "}" [] [] - 3: CSS_RULE@39..57 + 3: CSS_QUALIFIED_RULE@39..57 0: CSS_SELECTOR_LIST@39..55 0: CSS_COMPOUND_SELECTOR@39..55 0: (empty) @@ -433,7 +433,7 @@ CssRoot { 0: L_CURLY@55..56 "{" [] [] 1: CSS_DECLARATION_LIST@56..56 2: R_CURLY@56..57 "}" [] [] - 4: CSS_RULE@57..79 + 4: CSS_QUALIFIED_RULE@57..79 0: CSS_SELECTOR_LIST@57..77 0: CSS_COMPOUND_SELECTOR@57..77 0: (empty) @@ -462,7 +462,7 @@ CssRoot { 0: L_CURLY@77..78 "{" [] [] 1: CSS_DECLARATION_LIST@78..78 2: R_CURLY@78..79 "}" [] [] - 5: CSS_RULE@79..102 + 5: CSS_QUALIFIED_RULE@79..102 0: CSS_SELECTOR_LIST@79..100 0: CSS_COMPOUND_SELECTOR@79..100 0: (empty) @@ -492,7 +492,7 @@ CssRoot { 0: L_CURLY@100..101 "{" [] [] 1: CSS_DECLARATION_LIST@101..101 2: R_CURLY@101..102 "}" [] [] - 6: CSS_RULE@102..123 + 6: CSS_QUALIFIED_RULE@102..123 0: CSS_SELECTOR_LIST@102..121 0: CSS_COMPOUND_SELECTOR@102..121 0: (empty) @@ -520,7 +520,7 @@ CssRoot { 0: L_CURLY@121..122 "{" [] [] 1: CSS_DECLARATION_LIST@122..122 2: R_CURLY@122..123 "}" [] [] - 7: CSS_RULE@123..137 + 7: CSS_QUALIFIED_RULE@123..137 0: CSS_SELECTOR_LIST@123..135 0: CSS_COMPOUND_SELECTOR@123..135 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_identifier.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_identifier.css.snap index 47f5d92fab2e..69c6ed34982a 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_identifier.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_identifier.css.snap @@ -27,7 +27,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -51,7 +51,7 @@ CssRoot { r_curly_token: R_CURLY@7..8 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -76,7 +76,7 @@ CssRoot { r_curly_token: R_CURLY@17..18 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -103,7 +103,7 @@ CssRoot { r_curly_token: R_CURLY@29..30 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -132,7 +132,7 @@ CssRoot { r_curly_token: R_CURLY@45..46 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -163,7 +163,7 @@ CssRoot { r_curly_token: R_CURLY@63..64 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -193,7 +193,7 @@ CssRoot { r_curly_token: R_CURLY@80..81 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -226,7 +226,7 @@ CssRoot { r_curly_token: R_CURLY@99..100 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -260,7 +260,7 @@ CssRoot { r_curly_token: R_CURLY@119..120 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -291,7 +291,7 @@ CssRoot { r_curly_token: R_CURLY@142..143 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -361,7 +361,7 @@ CssRoot { 0: CSS_ROOT@0..182 0: (empty) 1: CSS_RULE_LIST@0..181 - 0: CSS_RULE@0..8 + 0: CSS_QUALIFIED_RULE@0..8 0: CSS_SELECTOR_LIST@0..6 0: CSS_COMPOUND_SELECTOR@0..6 0: (empty) @@ -376,7 +376,7 @@ CssRoot { 0: L_CURLY@6..7 "{" [] [] 1: CSS_DECLARATION_LIST@7..7 2: R_CURLY@7..8 "}" [] [] - 1: CSS_RULE@8..18 + 1: CSS_QUALIFIED_RULE@8..18 0: CSS_SELECTOR_LIST@8..16 0: CSS_COMPOUND_SELECTOR@8..16 0: (empty) @@ -392,7 +392,7 @@ CssRoot { 0: L_CURLY@16..17 "{" [] [] 1: CSS_DECLARATION_LIST@17..17 2: R_CURLY@17..18 "}" [] [] - 2: CSS_RULE@18..30 + 2: CSS_QUALIFIED_RULE@18..30 0: CSS_SELECTOR_LIST@18..28 0: CSS_COMPOUND_SELECTOR@18..28 0: (empty) @@ -409,7 +409,7 @@ CssRoot { 0: L_CURLY@28..29 "{" [] [] 1: CSS_DECLARATION_LIST@29..29 2: R_CURLY@29..30 "}" [] [] - 3: CSS_RULE@30..46 + 3: CSS_QUALIFIED_RULE@30..46 0: CSS_SELECTOR_LIST@30..44 0: CSS_COMPOUND_SELECTOR@30..44 0: (empty) @@ -426,7 +426,7 @@ CssRoot { 0: L_CURLY@44..45 "{" [] [] 1: CSS_DECLARATION_LIST@45..45 2: R_CURLY@45..46 "}" [] [] - 4: CSS_RULE@46..64 + 4: CSS_QUALIFIED_RULE@46..64 0: CSS_SELECTOR_LIST@46..62 0: CSS_COMPOUND_SELECTOR@46..62 0: (empty) @@ -445,7 +445,7 @@ CssRoot { 0: L_CURLY@62..63 "{" [] [] 1: CSS_DECLARATION_LIST@63..63 2: R_CURLY@63..64 "}" [] [] - 5: CSS_RULE@64..81 + 5: CSS_QUALIFIED_RULE@64..81 0: CSS_SELECTOR_LIST@64..79 0: CSS_COMPOUND_SELECTOR@64..79 0: (empty) @@ -463,7 +463,7 @@ CssRoot { 0: L_CURLY@79..80 "{" [] [] 1: CSS_DECLARATION_LIST@80..80 2: R_CURLY@80..81 "}" [] [] - 6: CSS_RULE@81..100 + 6: CSS_QUALIFIED_RULE@81..100 0: CSS_SELECTOR_LIST@81..98 0: CSS_COMPOUND_SELECTOR@81..98 0: (empty) @@ -483,7 +483,7 @@ CssRoot { 0: L_CURLY@98..99 "{" [] [] 1: CSS_DECLARATION_LIST@99..99 2: R_CURLY@99..100 "}" [] [] - 7: CSS_RULE@100..120 + 7: CSS_QUALIFIED_RULE@100..120 0: CSS_SELECTOR_LIST@100..118 0: CSS_COMPOUND_SELECTOR@100..118 0: (empty) @@ -504,7 +504,7 @@ CssRoot { 0: L_CURLY@118..119 "{" [] [] 1: CSS_DECLARATION_LIST@119..119 2: R_CURLY@119..120 "}" [] [] - 8: CSS_RULE@120..143 + 8: CSS_QUALIFIED_RULE@120..143 0: CSS_SELECTOR_LIST@120..141 0: CSS_COMPOUND_SELECTOR@120..141 0: (empty) @@ -523,7 +523,7 @@ CssRoot { 0: L_CURLY@141..142 "{" [] [] 1: CSS_DECLARATION_LIST@142..142 2: R_CURLY@142..143 "}" [] [] - 9: CSS_RULE@143..167 + 9: CSS_QUALIFIED_RULE@143..167 0: CSS_SELECTOR_LIST@143..165 0: CSS_COMPOUND_SELECTOR@143..165 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_nth.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_nth.css.snap index 794252ba6119..651b3e3c5ad5 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_nth.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_nth.css.snap @@ -33,7 +33,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -63,7 +63,7 @@ CssRoot { r_curly_token: R_CURLY@21..22 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -104,7 +104,7 @@ CssRoot { r_curly_token: R_CURLY@41..42 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -151,7 +151,7 @@ CssRoot { r_curly_token: R_CURLY@67..68 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -197,7 +197,7 @@ CssRoot { r_curly_token: R_CURLY@92..93 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -236,7 +236,7 @@ CssRoot { r_curly_token: R_CURLY@115..116 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -278,7 +278,7 @@ CssRoot { r_curly_token: R_CURLY@144..145 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -318,7 +318,7 @@ CssRoot { r_curly_token: R_CURLY@166..167 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -362,7 +362,7 @@ CssRoot { r_curly_token: R_CURLY@190..191 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -405,7 +405,7 @@ CssRoot { r_curly_token: R_CURLY@213..214 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -442,7 +442,7 @@ CssRoot { r_curly_token: R_CURLY@238..239 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -478,7 +478,7 @@ CssRoot { r_curly_token: R_CURLY@262..263 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -529,7 +529,7 @@ CssRoot { r_curly_token: R_CURLY@291..292 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -581,7 +581,7 @@ CssRoot { r_curly_token: R_CURLY@319..320 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -620,7 +620,7 @@ CssRoot { r_curly_token: R_CURLY@346..347 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -658,7 +658,7 @@ CssRoot { r_curly_token: R_CURLY@372..373 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -697,7 +697,7 @@ CssRoot { r_curly_token: R_CURLY@391..392 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -786,7 +786,7 @@ CssRoot { 0: CSS_ROOT@0..433 0: (empty) 1: CSS_RULE_LIST@0..433 - 0: CSS_RULE@0..22 + 0: CSS_QUALIFIED_RULE@0..22 0: CSS_SELECTOR_LIST@0..20 0: CSS_COMPOUND_SELECTOR@0..20 0: (empty) @@ -804,7 +804,7 @@ CssRoot { 0: L_CURLY@20..21 "{" [] [] 1: CSS_DECLARATION_LIST@21..21 2: R_CURLY@21..22 "}" [] [] - 1: CSS_RULE@22..42 + 1: CSS_QUALIFIED_RULE@22..42 0: CSS_SELECTOR_LIST@22..40 0: CSS_COMPOUND_SELECTOR@22..40 0: (empty) @@ -830,7 +830,7 @@ CssRoot { 0: L_CURLY@40..41 "{" [] [] 1: CSS_DECLARATION_LIST@41..41 2: R_CURLY@41..42 "}" [] [] - 2: CSS_RULE@42..68 + 2: CSS_QUALIFIED_RULE@42..68 0: CSS_SELECTOR_LIST@42..66 0: CSS_COMPOUND_SELECTOR@42..66 0: (empty) @@ -860,7 +860,7 @@ CssRoot { 0: L_CURLY@66..67 "{" [] [] 1: CSS_DECLARATION_LIST@67..67 2: R_CURLY@67..68 "}" [] [] - 3: CSS_RULE@68..93 + 3: CSS_QUALIFIED_RULE@68..93 0: CSS_SELECTOR_LIST@68..91 0: CSS_COMPOUND_SELECTOR@68..91 0: (empty) @@ -889,7 +889,7 @@ CssRoot { 0: L_CURLY@91..92 "{" [] [] 1: CSS_DECLARATION_LIST@92..92 2: R_CURLY@92..93 "}" [] [] - 4: CSS_RULE@93..116 + 4: CSS_QUALIFIED_RULE@93..116 0: CSS_SELECTOR_LIST@93..114 0: CSS_COMPOUND_SELECTOR@93..114 0: (empty) @@ -916,7 +916,7 @@ CssRoot { 0: L_CURLY@114..115 "{" [] [] 1: CSS_DECLARATION_LIST@115..115 2: R_CURLY@115..116 "}" [] [] - 5: CSS_RULE@116..145 + 5: CSS_QUALIFIED_RULE@116..145 0: CSS_SELECTOR_LIST@116..143 0: CSS_COMPOUND_SELECTOR@116..143 0: (empty) @@ -943,7 +943,7 @@ CssRoot { 0: L_CURLY@143..144 "{" [] [] 1: CSS_DECLARATION_LIST@144..144 2: R_CURLY@144..145 "}" [] [] - 6: CSS_RULE@145..167 + 6: CSS_QUALIFIED_RULE@145..167 0: CSS_SELECTOR_LIST@145..165 0: CSS_COMPOUND_SELECTOR@145..165 0: (empty) @@ -969,7 +969,7 @@ CssRoot { 0: L_CURLY@165..166 "{" [] [] 1: CSS_DECLARATION_LIST@166..166 2: R_CURLY@166..167 "}" [] [] - 7: CSS_RULE@167..191 + 7: CSS_QUALIFIED_RULE@167..191 0: CSS_SELECTOR_LIST@167..189 0: CSS_COMPOUND_SELECTOR@167..189 0: (empty) @@ -997,7 +997,7 @@ CssRoot { 0: L_CURLY@189..190 "{" [] [] 1: CSS_DECLARATION_LIST@190..190 2: R_CURLY@190..191 "}" [] [] - 8: CSS_RULE@191..214 + 8: CSS_QUALIFIED_RULE@191..214 0: CSS_SELECTOR_LIST@191..212 0: CSS_COMPOUND_SELECTOR@191..212 0: (empty) @@ -1024,7 +1024,7 @@ CssRoot { 0: L_CURLY@212..213 "{" [] [] 1: CSS_DECLARATION_LIST@213..213 2: R_CURLY@213..214 "}" [] [] - 9: CSS_RULE@214..239 + 9: CSS_QUALIFIED_RULE@214..239 0: CSS_SELECTOR_LIST@214..237 0: CSS_COMPOUND_SELECTOR@214..237 0: (empty) @@ -1047,7 +1047,7 @@ CssRoot { 0: L_CURLY@237..238 "{" [] [] 1: CSS_DECLARATION_LIST@238..238 2: R_CURLY@238..239 "}" [] [] - 10: CSS_RULE@239..263 + 10: CSS_QUALIFIED_RULE@239..263 0: CSS_SELECTOR_LIST@239..261 0: CSS_COMPOUND_SELECTOR@239..261 0: (empty) @@ -1069,7 +1069,7 @@ CssRoot { 0: L_CURLY@261..262 "{" [] [] 1: CSS_DECLARATION_LIST@262..262 2: R_CURLY@262..263 "}" [] [] - 11: CSS_RULE@263..292 + 11: CSS_QUALIFIED_RULE@263..292 0: CSS_SELECTOR_LIST@263..290 0: CSS_COMPOUND_SELECTOR@263..290 0: (empty) @@ -1102,7 +1102,7 @@ CssRoot { 0: L_CURLY@290..291 "{" [] [] 1: CSS_DECLARATION_LIST@291..291 2: R_CURLY@291..292 "}" [] [] - 12: CSS_RULE@292..320 + 12: CSS_QUALIFIED_RULE@292..320 0: CSS_SELECTOR_LIST@292..318 0: CSS_COMPOUND_SELECTOR@292..318 0: (empty) @@ -1134,7 +1134,7 @@ CssRoot { 0: L_CURLY@318..319 "{" [] [] 1: CSS_DECLARATION_LIST@319..319 2: R_CURLY@319..320 "}" [] [] - 13: CSS_RULE@320..347 + 13: CSS_QUALIFIED_RULE@320..347 0: CSS_SELECTOR_LIST@320..345 0: CSS_COMPOUND_SELECTOR@320..345 0: (empty) @@ -1159,7 +1159,7 @@ CssRoot { 0: L_CURLY@345..346 "{" [] [] 1: CSS_DECLARATION_LIST@346..346 2: R_CURLY@346..347 "}" [] [] - 14: CSS_RULE@347..373 + 14: CSS_QUALIFIED_RULE@347..373 0: CSS_SELECTOR_LIST@347..371 0: CSS_COMPOUND_SELECTOR@347..371 0: (empty) @@ -1183,7 +1183,7 @@ CssRoot { 0: L_CURLY@371..372 "{" [] [] 1: CSS_DECLARATION_LIST@372..372 2: R_CURLY@372..373 "}" [] [] - 15: CSS_RULE@373..392 + 15: CSS_QUALIFIED_RULE@373..392 0: CSS_SELECTOR_LIST@373..390 0: CSS_COMPOUND_SELECTOR@373..390 0: (empty) @@ -1207,7 +1207,7 @@ CssRoot { 0: L_CURLY@390..391 "{" [] [] 1: CSS_DECLARATION_LIST@391..391 2: R_CURLY@391..392 "}" [] [] - 16: CSS_RULE@392..415 + 16: CSS_QUALIFIED_RULE@392..415 0: CSS_SELECTOR_LIST@392..413 0: CSS_COMPOUND_SELECTOR@392..413 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_relative_selector_list.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_relative_selector_list.css.snap index 3d1e87a6b1ec..5b9b9244ee71 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_relative_selector_list.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_relative_selector_list.css.snap @@ -25,7 +25,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -50,7 +50,7 @@ CssRoot { r_curly_token: R_CURLY@7..8 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -76,7 +76,7 @@ CssRoot { r_curly_token: R_CURLY@17..18 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -108,7 +108,7 @@ CssRoot { r_curly_token: R_CURLY@35..36 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -139,7 +139,7 @@ CssRoot { r_curly_token: R_CURLY@52..53 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -173,7 +173,7 @@ CssRoot { r_curly_token: R_CURLY@77..78 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -238,7 +238,7 @@ CssRoot { r_curly_token: R_CURLY@107..108 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -294,7 +294,7 @@ CssRoot { r_curly_token: R_CURLY@127..128 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -384,7 +384,7 @@ CssRoot { 0: CSS_ROOT@0..152 0: (empty) 1: CSS_RULE_LIST@0..151 - 0: CSS_RULE@0..8 + 0: CSS_QUALIFIED_RULE@0..8 0: CSS_SELECTOR_LIST@0..6 0: CSS_COMPOUND_SELECTOR@0..6 0: (empty) @@ -400,7 +400,7 @@ CssRoot { 0: L_CURLY@6..7 "{" [] [] 1: CSS_DECLARATION_LIST@7..7 2: R_CURLY@7..8 "}" [] [] - 1: CSS_RULE@8..18 + 1: CSS_QUALIFIED_RULE@8..18 0: CSS_SELECTOR_LIST@8..16 0: CSS_COMPOUND_SELECTOR@8..16 0: (empty) @@ -417,7 +417,7 @@ CssRoot { 0: L_CURLY@16..17 "{" [] [] 1: CSS_DECLARATION_LIST@17..17 2: R_CURLY@17..18 "}" [] [] - 2: CSS_RULE@18..36 + 2: CSS_QUALIFIED_RULE@18..36 0: CSS_SELECTOR_LIST@18..34 0: CSS_COMPOUND_SELECTOR@18..34 0: (empty) @@ -437,7 +437,7 @@ CssRoot { 0: L_CURLY@34..35 "{" [] [] 1: CSS_DECLARATION_LIST@35..35 2: R_CURLY@35..36 "}" [] [] - 3: CSS_RULE@36..53 + 3: CSS_QUALIFIED_RULE@36..53 0: CSS_SELECTOR_LIST@36..51 0: CSS_COMPOUND_SELECTOR@36..51 0: (empty) @@ -456,7 +456,7 @@ CssRoot { 0: L_CURLY@51..52 "{" [] [] 1: CSS_DECLARATION_LIST@52..52 2: R_CURLY@52..53 "}" [] [] - 4: CSS_RULE@53..78 + 4: CSS_QUALIFIED_RULE@53..78 0: CSS_SELECTOR_LIST@53..76 0: CSS_COMPOUND_SELECTOR@53..76 0: (empty) @@ -478,7 +478,7 @@ CssRoot { 0: L_CURLY@76..77 "{" [] [] 1: CSS_DECLARATION_LIST@77..77 2: R_CURLY@77..78 "}" [] [] - 5: CSS_RULE@78..108 + 5: CSS_QUALIFIED_RULE@78..108 0: CSS_SELECTOR_LIST@78..106 0: CSS_COMPOUND_SELECTOR@78..106 0: (empty) @@ -520,7 +520,7 @@ CssRoot { 0: L_CURLY@106..107 "{" [] [] 1: CSS_DECLARATION_LIST@107..107 2: R_CURLY@107..108 "}" [] [] - 6: CSS_RULE@108..128 + 6: CSS_QUALIFIED_RULE@108..128 0: CSS_SELECTOR_LIST@108..126 0: CSS_COMPOUND_SELECTOR@108..126 0: (empty) @@ -556,7 +556,7 @@ CssRoot { 0: L_CURLY@126..127 "{" [] [] 1: CSS_DECLARATION_LIST@127..127 2: R_CURLY@127..128 "}" [] [] - 7: CSS_RULE@128..141 + 7: CSS_QUALIFIED_RULE@128..141 0: CSS_SELECTOR_LIST@128..139 0: CSS_COMPOUND_SELECTOR@128..139 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector.css.snap index f64526d0632b..667b25ceb658 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector.css.snap @@ -22,7 +22,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -46,7 +46,7 @@ CssRoot { r_curly_token: R_CURLY@10..11 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -71,7 +71,7 @@ CssRoot { r_curly_token: R_CURLY@23..24 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -115,7 +115,7 @@ CssRoot { r_curly_token: R_CURLY@48..49 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -158,7 +158,7 @@ CssRoot { r_curly_token: R_CURLY@72..73 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -268,7 +268,7 @@ CssRoot { 0: CSS_ROOT@0..117 0: (empty) 1: CSS_RULE_LIST@0..116 - 0: CSS_RULE@0..11 + 0: CSS_QUALIFIED_RULE@0..11 0: CSS_SELECTOR_LIST@0..9 0: CSS_COMPOUND_SELECTOR@0..9 0: (empty) @@ -283,7 +283,7 @@ CssRoot { 0: L_CURLY@9..10 "{" [] [] 1: CSS_DECLARATION_LIST@10..10 2: R_CURLY@10..11 "}" [] [] - 1: CSS_RULE@11..24 + 1: CSS_QUALIFIED_RULE@11..24 0: CSS_SELECTOR_LIST@11..22 0: CSS_COMPOUND_SELECTOR@11..22 0: (empty) @@ -299,7 +299,7 @@ CssRoot { 0: L_CURLY@22..23 "{" [] [] 1: CSS_DECLARATION_LIST@23..23 2: R_CURLY@23..24 "}" [] [] - 2: CSS_RULE@24..49 + 2: CSS_QUALIFIED_RULE@24..49 0: CSS_SELECTOR_LIST@24..47 0: CSS_COMPOUND_SELECTOR@24..47 0: (empty) @@ -327,7 +327,7 @@ CssRoot { 0: L_CURLY@47..48 "{" [] [] 1: CSS_DECLARATION_LIST@48..48 2: R_CURLY@48..49 "}" [] [] - 3: CSS_RULE@49..73 + 3: CSS_QUALIFIED_RULE@49..73 0: CSS_SELECTOR_LIST@49..71 0: CSS_COMPOUND_SELECTOR@49..71 0: (empty) @@ -354,7 +354,7 @@ CssRoot { 0: L_CURLY@71..72 "{" [] [] 1: CSS_DECLARATION_LIST@72..72 2: R_CURLY@72..73 "}" [] [] - 4: CSS_RULE@73..96 + 4: CSS_QUALIFIED_RULE@73..96 0: CSS_SELECTOR_LIST@73..94 0: CSS_COMPOUND_SELECTOR@73..94 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector_list.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector_list.css.snap index ae6e0063db30..a0bbe739cff8 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector_list.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_selector_list.css.snap @@ -25,7 +25,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -50,7 +50,7 @@ CssRoot { r_curly_token: R_CURLY@9..10 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -76,7 +76,7 @@ CssRoot { r_curly_token: R_CURLY@21..22 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -108,7 +108,7 @@ CssRoot { r_curly_token: R_CURLY@41..42 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -139,7 +139,7 @@ CssRoot { r_curly_token: R_CURLY@60..61 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -173,7 +173,7 @@ CssRoot { r_curly_token: R_CURLY@87..88 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -235,7 +235,7 @@ CssRoot { r_curly_token: R_CURLY@119..120 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -288,7 +288,7 @@ CssRoot { r_curly_token: R_CURLY@141..142 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -372,7 +372,7 @@ CssRoot { 0: CSS_ROOT@0..170 0: (empty) 1: CSS_RULE_LIST@0..169 - 0: CSS_RULE@0..10 + 0: CSS_QUALIFIED_RULE@0..10 0: CSS_SELECTOR_LIST@0..8 0: CSS_COMPOUND_SELECTOR@0..8 0: (empty) @@ -388,7 +388,7 @@ CssRoot { 0: L_CURLY@8..9 "{" [] [] 1: CSS_DECLARATION_LIST@9..9 2: R_CURLY@9..10 "}" [] [] - 1: CSS_RULE@10..22 + 1: CSS_QUALIFIED_RULE@10..22 0: CSS_SELECTOR_LIST@10..20 0: CSS_COMPOUND_SELECTOR@10..20 0: (empty) @@ -405,7 +405,7 @@ CssRoot { 0: L_CURLY@20..21 "{" [] [] 1: CSS_DECLARATION_LIST@21..21 2: R_CURLY@21..22 "}" [] [] - 2: CSS_RULE@22..42 + 2: CSS_QUALIFIED_RULE@22..42 0: CSS_SELECTOR_LIST@22..40 0: CSS_COMPOUND_SELECTOR@22..40 0: (empty) @@ -425,7 +425,7 @@ CssRoot { 0: L_CURLY@40..41 "{" [] [] 1: CSS_DECLARATION_LIST@41..41 2: R_CURLY@41..42 "}" [] [] - 3: CSS_RULE@42..61 + 3: CSS_QUALIFIED_RULE@42..61 0: CSS_SELECTOR_LIST@42..59 0: CSS_COMPOUND_SELECTOR@42..59 0: (empty) @@ -444,7 +444,7 @@ CssRoot { 0: L_CURLY@59..60 "{" [] [] 1: CSS_DECLARATION_LIST@60..60 2: R_CURLY@60..61 "}" [] [] - 4: CSS_RULE@61..88 + 4: CSS_QUALIFIED_RULE@61..88 0: CSS_SELECTOR_LIST@61..86 0: CSS_COMPOUND_SELECTOR@61..86 0: (empty) @@ -466,7 +466,7 @@ CssRoot { 0: L_CURLY@86..87 "{" [] [] 1: CSS_DECLARATION_LIST@87..87 2: R_CURLY@87..88 "}" [] [] - 5: CSS_RULE@88..120 + 5: CSS_QUALIFIED_RULE@88..120 0: CSS_SELECTOR_LIST@88..118 0: CSS_COMPOUND_SELECTOR@88..118 0: (empty) @@ -506,7 +506,7 @@ CssRoot { 0: L_CURLY@118..119 "{" [] [] 1: CSS_DECLARATION_LIST@119..119 2: R_CURLY@119..120 "}" [] [] - 6: CSS_RULE@120..142 + 6: CSS_QUALIFIED_RULE@120..142 0: CSS_SELECTOR_LIST@120..140 0: CSS_COMPOUND_SELECTOR@120..140 0: (empty) @@ -540,7 +540,7 @@ CssRoot { 0: L_CURLY@140..141 "{" [] [] 1: CSS_DECLARATION_LIST@141..141 2: R_CURLY@141..142 "}" [] [] - 7: CSS_RULE@142..157 + 7: CSS_QUALIFIED_RULE@142..157 0: CSS_SELECTOR_LIST@142..155 0: CSS_COMPOUND_SELECTOR@142..155 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_value_list.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_value_list.css.snap index 8e43de178115..39286568e2c2 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_value_list.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_function_value_list.css.snap @@ -23,7 +23,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -48,7 +48,7 @@ CssRoot { r_curly_token: R_CURLY@8..9 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -74,7 +74,7 @@ CssRoot { r_curly_token: R_CURLY@19..20 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -109,7 +109,7 @@ CssRoot { r_curly_token: R_CURLY@42..43 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -143,7 +143,7 @@ CssRoot { r_curly_token: R_CURLY@64..65 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -175,7 +175,7 @@ CssRoot { r_curly_token: R_CURLY@80..81 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -249,7 +249,7 @@ CssRoot { 0: CSS_ROOT@0..110 0: (empty) 1: CSS_RULE_LIST@0..109 - 0: CSS_RULE@0..9 + 0: CSS_QUALIFIED_RULE@0..9 0: CSS_SELECTOR_LIST@0..7 0: CSS_COMPOUND_SELECTOR@0..7 0: (empty) @@ -265,7 +265,7 @@ CssRoot { 0: L_CURLY@7..8 "{" [] [] 1: CSS_DECLARATION_LIST@8..8 2: R_CURLY@8..9 "}" [] [] - 1: CSS_RULE@9..20 + 1: CSS_QUALIFIED_RULE@9..20 0: CSS_SELECTOR_LIST@9..18 0: CSS_COMPOUND_SELECTOR@9..18 0: (empty) @@ -282,7 +282,7 @@ CssRoot { 0: L_CURLY@18..19 "{" [] [] 1: CSS_DECLARATION_LIST@19..19 2: R_CURLY@19..20 "}" [] [] - 2: CSS_RULE@20..43 + 2: CSS_QUALIFIED_RULE@20..43 0: CSS_SELECTOR_LIST@20..41 0: CSS_COMPOUND_SELECTOR@20..41 0: (empty) @@ -305,7 +305,7 @@ CssRoot { 0: L_CURLY@41..42 "{" [] [] 1: CSS_DECLARATION_LIST@42..42 2: R_CURLY@42..43 "}" [] [] - 3: CSS_RULE@43..65 + 3: CSS_QUALIFIED_RULE@43..65 0: CSS_SELECTOR_LIST@43..63 0: CSS_COMPOUND_SELECTOR@43..63 0: (empty) @@ -327,7 +327,7 @@ CssRoot { 0: L_CURLY@63..64 "{" [] [] 1: CSS_DECLARATION_LIST@64..64 2: R_CURLY@64..65 "}" [] [] - 4: CSS_RULE@65..81 + 4: CSS_QUALIFIED_RULE@65..81 0: CSS_SELECTOR_LIST@65..79 0: CSS_COMPOUND_SELECTOR@65..79 0: (empty) @@ -349,7 +349,7 @@ CssRoot { 0: L_CURLY@79..80 "{" [] [] 1: CSS_DECLARATION_LIST@80..80 2: R_CURLY@80..81 "}" [] [] - 5: CSS_RULE@81..96 + 5: CSS_QUALIFIED_RULE@81..96 0: CSS_SELECTOR_LIST@81..94 0: CSS_COMPOUND_SELECTOR@81..94 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_identifier.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_identifier.css.snap index 0f520610e9d7..23fc7fe7e023 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_identifier.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_class/pseudo_class_identifier.css.snap @@ -20,7 +20,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -40,7 +40,7 @@ CssRoot { r_curly_token: R_CURLY@3..4 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -66,7 +66,7 @@ CssRoot { r_curly_token: R_CURLY@14..15 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -120,7 +120,7 @@ CssRoot { 0: CSS_ROOT@0..29 0: (empty) 1: CSS_RULE_LIST@0..28 - 0: CSS_RULE@0..4 + 0: CSS_QUALIFIED_RULE@0..4 0: CSS_SELECTOR_LIST@0..2 0: CSS_COMPOUND_SELECTOR@0..2 0: (empty) @@ -132,7 +132,7 @@ CssRoot { 0: L_CURLY@2..3 "{" [] [] 1: CSS_DECLARATION_LIST@3..3 2: R_CURLY@3..4 "}" [] [] - 1: CSS_RULE@4..15 + 1: CSS_QUALIFIED_RULE@4..15 0: CSS_SELECTOR_LIST@4..13 0: CSS_COMPOUND_SELECTOR@4..13 0: (empty) @@ -148,7 +148,7 @@ CssRoot { 0: L_CURLY@13..14 "{" [] [] 1: CSS_DECLARATION_LIST@14..14 2: R_CURLY@14..15 "}" [] [] - 2: CSS_RULE@15..26 + 2: CSS_QUALIFIED_RULE@15..26 0: CSS_SELECTOR_LIST@15..24 0: CSS_COMPOUND_SELECTOR@15..24 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element.css.snap index 14a6c56bab58..ef80e69de48a 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element.css.snap @@ -25,7 +25,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -44,7 +44,7 @@ CssRoot { r_curly_token: R_CURLY@4..5 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -70,7 +70,7 @@ CssRoot { r_curly_token: R_CURLY@16..17 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -106,7 +106,7 @@ CssRoot { r_curly_token: R_CURLY@32..33 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -138,7 +138,7 @@ CssRoot { r_curly_token: R_CURLY@50..51 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -183,7 +183,7 @@ CssRoot { 0: CSS_ROOT@0..79 0: (empty) 1: CSS_RULE_LIST@0..78 - 0: CSS_RULE@0..5 + 0: CSS_QUALIFIED_RULE@0..5 0: CSS_SELECTOR_LIST@0..3 0: CSS_COMPOUND_SELECTOR@0..3 0: (empty) @@ -196,7 +196,7 @@ CssRoot { 0: L_CURLY@3..4 "{" [] [] 1: CSS_DECLARATION_LIST@4..4 2: R_CURLY@4..5 "}" [] [] - 1: CSS_RULE@5..17 + 1: CSS_QUALIFIED_RULE@5..17 0: CSS_SELECTOR_LIST@5..15 0: CSS_COMPOUND_SELECTOR@5..15 0: (empty) @@ -212,7 +212,7 @@ CssRoot { 0: L_CURLY@15..16 "{" [] [] 1: CSS_DECLARATION_LIST@16..16 2: R_CURLY@16..17 "}" [] [] - 2: CSS_RULE@17..33 + 2: CSS_QUALIFIED_RULE@17..33 0: CSS_SELECTOR_LIST@17..31 0: CSS_COMPOUND_SELECTOR@17..31 0: (empty) @@ -235,7 +235,7 @@ CssRoot { 0: L_CURLY@31..32 "{" [] [] 1: CSS_DECLARATION_LIST@32..32 2: R_CURLY@32..33 "}" [] [] - 3: CSS_RULE@33..51 + 3: CSS_QUALIFIED_RULE@33..51 0: CSS_SELECTOR_LIST@33..49 0: CSS_COMPOUND_SELECTOR@33..49 0: (empty) @@ -254,7 +254,7 @@ CssRoot { 0: L_CURLY@49..50 "{" [] [] 1: CSS_DECLARATION_LIST@50..50 2: R_CURLY@50..51 "}" [] [] - 4: CSS_RULE@51..78 + 4: CSS_QUALIFIED_RULE@51..78 0: CSS_SELECTOR_LIST@51..76 0: CSS_COMPOUND_SELECTOR@51..76 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element_function_identifier.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element_function_identifier.css.snap index 161e706f9170..e2021e0cd874 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element_function_identifier.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element_function_identifier.css.snap @@ -19,7 +19,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -53,7 +53,7 @@ CssRoot { r_curly_token: R_CURLY@24..25 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -109,7 +109,7 @@ CssRoot { 0: CSS_ROOT@0..55 0: (empty) 1: CSS_RULE_LIST@0..54 - 0: CSS_RULE@0..25 + 0: CSS_QUALIFIED_RULE@0..25 0: CSS_SELECTOR_LIST@0..23 0: CSS_COMPOUND_SELECTOR@0..23 0: (empty) @@ -130,7 +130,7 @@ CssRoot { 0: L_CURLY@23..24 "{" [] [] 1: CSS_DECLARATION_LIST@24..24 2: R_CURLY@24..25 "}" [] [] - 1: CSS_RULE@25..41 + 1: CSS_QUALIFIED_RULE@25..41 0: CSS_SELECTOR_LIST@25..39 0: CSS_COMPOUND_SELECTOR@25..39 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element_function_selector.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element_function_selector.css.snap index ade9c4a21d86..2c9961491368 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element_function_selector.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/pseudo_element_function_selector.css.snap @@ -21,7 +21,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -47,7 +47,7 @@ CssRoot { r_curly_token: R_CURLY@9..10 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -74,7 +74,7 @@ CssRoot { r_curly_token: R_CURLY@21..22 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -120,7 +120,7 @@ CssRoot { r_curly_token: R_CURLY@45..46 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -165,7 +165,7 @@ CssRoot { r_curly_token: R_CURLY@68..69 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -229,7 +229,7 @@ CssRoot { 0: CSS_ROOT@0..92 0: (empty) 1: CSS_RULE_LIST@0..91 - 0: CSS_RULE@0..10 + 0: CSS_QUALIFIED_RULE@0..10 0: CSS_SELECTOR_LIST@0..8 0: CSS_COMPOUND_SELECTOR@0..8 0: (empty) @@ -245,7 +245,7 @@ CssRoot { 0: L_CURLY@8..9 "{" [] [] 1: CSS_DECLARATION_LIST@9..9 2: R_CURLY@9..10 "}" [] [] - 1: CSS_RULE@10..22 + 1: CSS_QUALIFIED_RULE@10..22 0: CSS_SELECTOR_LIST@10..20 0: CSS_COMPOUND_SELECTOR@10..20 0: (empty) @@ -262,7 +262,7 @@ CssRoot { 0: L_CURLY@20..21 "{" [] [] 1: CSS_DECLARATION_LIST@21..21 2: R_CURLY@21..22 "}" [] [] - 2: CSS_RULE@22..46 + 2: CSS_QUALIFIED_RULE@22..46 0: CSS_SELECTOR_LIST@22..44 0: CSS_COMPOUND_SELECTOR@22..44 0: (empty) @@ -291,7 +291,7 @@ CssRoot { 0: L_CURLY@44..45 "{" [] [] 1: CSS_DECLARATION_LIST@45..45 2: R_CURLY@45..46 "}" [] [] - 3: CSS_RULE@46..69 + 3: CSS_QUALIFIED_RULE@46..69 0: CSS_SELECTOR_LIST@46..67 0: CSS_COMPOUND_SELECTOR@46..67 0: (empty) @@ -319,7 +319,7 @@ CssRoot { 0: L_CURLY@67..68 "{" [] [] 1: CSS_DECLARATION_LIST@68..68 2: R_CURLY@68..69 "}" [] [] - 4: CSS_RULE@69..91 + 4: CSS_QUALIFIED_RULE@69..91 0: CSS_SELECTOR_LIST@69..89 0: CSS_COMPOUND_SELECTOR@69..89 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/error/selector/traling_comma.css.snap b/crates/biome_css_parser/tests/css_test_suite/error/selector/traling_comma.css.snap index 18705283f977..ee4d80b5d469 100644 --- a/crates/biome_css_parser/tests/css_test_suite/error/selector/traling_comma.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/error/selector/traling_comma.css.snap @@ -19,7 +19,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -53,7 +53,7 @@ CssRoot { 0: CSS_ROOT@0..16 0: (empty) 1: CSS_RULE_LIST@0..15 - 0: CSS_RULE@0..15 + 0: CSS_QUALIFIED_RULE@0..15 0: CSS_SELECTOR_LIST@0..11 0: CSS_COMPOUND_SELECTOR@0..9 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container_complex.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container_complex.css.snap index 23dbc444747c..8238ab494e09 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container_complex.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_container_complex.css.snap @@ -1180,7 +1180,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@1237..1238 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1217,7 +1217,7 @@ CssRoot { r_curly_token: R_CURLY@1277..1280 "}" [Newline("\n"), Whitespace("\t")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2060,7 +2060,7 @@ CssRoot { 3: CSS_RULE_LIST_BLOCK@1237..1321 0: L_CURLY@1237..1238 "{" [] [] 1: CSS_RULE_LIST@1238..1319 - 0: CSS_RULE@1238..1280 + 0: CSS_QUALIFIED_RULE@1238..1280 0: CSS_SELECTOR_LIST@1238..1247 0: CSS_COMPOUND_SELECTOR@1238..1247 0: (empty) @@ -2084,7 +2084,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@1276..1277 ";" [] [] 2: R_CURLY@1277..1280 "}" [Newline("\n"), Whitespace("\t")] [] - 1: CSS_RULE@1280..1319 + 1: CSS_QUALIFIED_RULE@1280..1319 0: CSS_SELECTOR_LIST@1280..1286 0: CSS_COMPOUND_SELECTOR@1280..1286 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_document.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_document.css.snap index af30e77f5365..007855b5d171 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_document.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_document.css.snap @@ -58,7 +58,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@42..43 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -152,7 +152,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@216..217 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -325,7 +325,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@517..518 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -401,7 +401,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@42..70 0: L_CURLY@42..43 "{" [] [] 1: CSS_RULE_LIST@43..68 - 0: CSS_RULE@43..68 + 0: CSS_QUALIFIED_RULE@43..68 0: CSS_SELECTOR_LIST@43..48 0: CSS_COMPOUND_SELECTOR@43..48 0: (empty) @@ -468,7 +468,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@216..269 0: L_CURLY@216..217 "{" [] [] 1: CSS_RULE_LIST@217..267 - 0: CSS_RULE@217..267 + 0: CSS_QUALIFIED_RULE@217..267 0: CSS_SELECTOR_LIST@217..224 0: CSS_COMPOUND_SELECTOR@217..224 0: (empty) @@ -590,7 +590,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@517..560 0: L_CURLY@517..518 "{" [] [] 1: CSS_RULE_LIST@518..557 - 0: CSS_RULE@518..557 + 0: CSS_QUALIFIED_RULE@518..557 0: CSS_SELECTOR_LIST@518..529 0: CSS_COMPOUND_SELECTOR@518..529 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_layer.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_layer.css.snap index 0a5738f9ac47..af928bbccddc 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_layer.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_layer.css.snap @@ -384,7 +384,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@350..351 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -440,7 +440,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@403..404 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -492,7 +492,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@450..451 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -565,7 +565,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@499..500 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -643,7 +643,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@568..569 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -700,7 +700,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@618..619 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -766,7 +766,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@669..670 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -851,7 +851,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@844..845 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -896,7 +896,7 @@ CssRoot { }, }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -948,7 +948,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@933..934 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1340,7 +1340,7 @@ CssRoot { 1: CSS_RULE_LIST_BLOCK@350..384 0: L_CURLY@350..351 "{" [] [] 1: CSS_RULE_LIST@351..382 - 0: CSS_RULE@351..382 + 0: CSS_QUALIFIED_RULE@351..382 0: CSS_SELECTOR_LIST@351..360 0: CSS_COMPOUND_SELECTOR@351..360 0: (empty) @@ -1376,7 +1376,7 @@ CssRoot { 1: CSS_RULE_LIST_BLOCK@403..484 0: L_CURLY@403..404 "{" [] [] 1: CSS_RULE_LIST@404..482 - 0: CSS_RULE@404..434 + 0: CSS_QUALIFIED_RULE@404..434 0: CSS_SELECTOR_LIST@404..413 0: CSS_COMPOUND_SELECTOR@404..413 0: (empty) @@ -1412,7 +1412,7 @@ CssRoot { 1: CSS_RULE_LIST_BLOCK@450..482 0: L_CURLY@450..451 "{" [] [] 1: CSS_RULE_LIST@451..479 - 0: CSS_RULE@451..479 + 0: CSS_QUALIFIED_RULE@451..479 0: CSS_SELECTOR_LIST@451..461 0: CSS_COMPOUND_SELECTOR@451..456 0: (empty) @@ -1457,7 +1457,7 @@ CssRoot { 1: CSS_RULE_LIST_BLOCK@499..531 0: L_CURLY@499..500 "{" [] [] 1: CSS_RULE_LIST@500..529 - 0: CSS_RULE@500..529 + 0: CSS_QUALIFIED_RULE@500..529 0: CSS_SELECTOR_LIST@500..511 0: CSS_COMPOUND_SELECTOR@500..511 0: (empty) @@ -1510,7 +1510,7 @@ CssRoot { 1: CSS_RULE_LIST_BLOCK@568..602 0: L_CURLY@568..569 "{" [] [] 1: CSS_RULE_LIST@569..599 - 0: CSS_RULE@569..599 + 0: CSS_QUALIFIED_RULE@569..599 0: CSS_SELECTOR_LIST@569..574 0: CSS_COMPOUND_SELECTOR@569..574 0: (empty) @@ -1547,7 +1547,7 @@ CssRoot { 1: CSS_RULE_LIST_BLOCK@618..642 0: L_CURLY@618..619 "{" [] [] 1: CSS_RULE_LIST@619..639 - 0: CSS_RULE@619..639 + 0: CSS_QUALIFIED_RULE@619..639 0: CSS_SELECTOR_LIST@619..624 0: CSS_COMPOUND_SELECTOR@619..624 0: (empty) @@ -1587,7 +1587,7 @@ CssRoot { 1: CSS_RULE_LIST_BLOCK@669..790 0: L_CURLY@669..670 "{" [] [] 1: CSS_RULE_LIST@670..788 - 0: CSS_RULE@670..788 + 0: CSS_QUALIFIED_RULE@670..788 0: CSS_SELECTOR_LIST@670..763 0: CSS_COMPOUND_SELECTOR@670..763 0: (empty) @@ -1644,7 +1644,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@844..887 0: L_CURLY@844..845 "{" [] [] 1: CSS_RULE_LIST@845..884 - 0: CSS_RULE@845..884 + 0: CSS_QUALIFIED_RULE@845..884 0: CSS_SELECTOR_LIST@845..856 0: CSS_COMPOUND_SELECTOR@845..856 0: (empty) @@ -1672,7 +1672,7 @@ CssRoot { 1: SEMICOLON@879..880 ";" [] [] 2: R_CURLY@880..884 "}" [Newline("\n"), Whitespace("\t\t")] [] 2: R_CURLY@884..887 "}" [Newline("\n"), Whitespace("\t")] [] - 1: CSS_RULE@887..917 + 1: CSS_QUALIFIED_RULE@887..917 0: CSS_SELECTOR_LIST@887..896 0: CSS_COMPOUND_SELECTOR@887..896 0: (empty) @@ -1708,7 +1708,7 @@ CssRoot { 1: CSS_RULE_LIST_BLOCK@933..965 0: L_CURLY@933..934 "{" [] [] 1: CSS_RULE_LIST@934..962 - 0: CSS_RULE@934..962 + 0: CSS_QUALIFIED_RULE@934..962 0: CSS_SELECTOR_LIST@934..944 0: CSS_COMPOUND_SELECTOR@934..939 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_media_complex.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_media_complex.css.snap index 16b15d7028e3..09f283b06271 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_media_complex.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_media_complex.css.snap @@ -796,7 +796,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@767..768 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -833,7 +833,7 @@ CssRoot { r_curly_token: R_CURLY@812..816 "}" [Newline("\n"), Whitespace("\t\t")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1399,7 +1399,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@767..861 0: L_CURLY@767..768 "{" [] [] 1: CSS_RULE_LIST@768..859 - 0: CSS_RULE@768..816 + 0: CSS_QUALIFIED_RULE@768..816 0: CSS_SELECTOR_LIST@768..780 0: CSS_COMPOUND_SELECTOR@768..780 0: (empty) @@ -1423,7 +1423,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@811..812 ";" [] [] 2: R_CURLY@812..816 "}" [Newline("\n"), Whitespace("\t\t")] [] - 1: CSS_RULE@816..859 + 1: CSS_QUALIFIED_RULE@816..859 0: CSS_SELECTOR_LIST@816..823 0: CSS_COMPOUND_SELECTOR@816..823 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_scope.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_scope.css.snap index 5822e4151dfb..dc0dbdc1d0bd 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_scope.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_scope.css.snap @@ -79,7 +79,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@7..8 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -146,7 +146,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@112..113 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -225,7 +225,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@215..216 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -261,7 +261,7 @@ CssRoot { r_curly_token: R_CURLY@243..245 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -361,7 +361,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@319..320 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -397,7 +397,7 @@ CssRoot { r_curly_token: R_CURLY@347..349 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -479,7 +479,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@407..408 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -515,7 +515,7 @@ CssRoot { r_curly_token: R_CURLY@435..437 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -783,7 +783,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@7..87 0: L_CURLY@7..8 "{" [] [] 1: CSS_RULE_LIST@8..85 - 0: CSS_RULE@8..85 + 0: CSS_QUALIFIED_RULE@8..85 0: CSS_SELECTOR_LIST@8..59 0: CSS_COMPOUND_SELECTOR@8..59 0: (empty) @@ -827,7 +827,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@112..188 0: L_CURLY@112..113 "{" [] [] 1: CSS_RULE_LIST@113..186 - 0: CSS_RULE@113..186 + 0: CSS_QUALIFIED_RULE@113..186 0: CSS_SELECTOR_LIST@113..162 0: CSS_COMPOUND_SELECTOR@113..162 0: (empty) @@ -880,7 +880,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@215..276 0: L_CURLY@215..216 "{" [] [] 1: CSS_RULE_LIST@216..274 - 0: CSS_RULE@216..245 + 0: CSS_QUALIFIED_RULE@216..245 0: CSS_SELECTOR_LIST@216..221 0: CSS_COMPOUND_SELECTOR@216..221 0: (empty) @@ -904,7 +904,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@242..243 ";" [] [] 2: R_CURLY@243..245 "}" [Newline("\n")] [] - 1: CSS_RULE@245..274 + 1: CSS_QUALIFIED_RULE@245..274 0: CSS_SELECTOR_LIST@245..256 0: CSS_COMPOUND_SELECTOR@245..256 0: (empty) @@ -971,7 +971,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@319..380 0: L_CURLY@319..320 "{" [] [] 1: CSS_RULE_LIST@320..378 - 0: CSS_RULE@320..349 + 0: CSS_QUALIFIED_RULE@320..349 0: CSS_SELECTOR_LIST@320..325 0: CSS_COMPOUND_SELECTOR@320..325 0: (empty) @@ -995,7 +995,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@346..347 ";" [] [] 2: R_CURLY@347..349 "}" [Newline("\n")] [] - 1: CSS_RULE@349..378 + 1: CSS_QUALIFIED_RULE@349..378 0: CSS_SELECTOR_LIST@349..360 0: CSS_COMPOUND_SELECTOR@349..360 0: (empty) @@ -1050,7 +1050,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@407..468 0: L_CURLY@407..408 "{" [] [] 1: CSS_RULE_LIST@408..466 - 0: CSS_RULE@408..437 + 0: CSS_QUALIFIED_RULE@408..437 0: CSS_SELECTOR_LIST@408..413 0: CSS_COMPOUND_SELECTOR@408..413 0: (empty) @@ -1074,7 +1074,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@434..435 ";" [] [] 2: R_CURLY@435..437 "}" [Newline("\n")] [] - 1: CSS_RULE@437..466 + 1: CSS_QUALIFIED_RULE@437..466 0: CSS_SELECTOR_LIST@437..448 0: CSS_COMPOUND_SELECTOR@437..448 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_starting_style.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_starting_style.css.snap index 9bd15c775fad..ea1cfeb70273 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_starting_style.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_starting_style.css.snap @@ -38,7 +38,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@16..17 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -115,7 +115,7 @@ CssRoot { }, }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -180,7 +180,7 @@ CssRoot { 1: CSS_RULE_LIST_BLOCK@16..168 0: L_CURLY@16..17 "{" [] [] 1: CSS_RULE_LIST@17..166 - 0: CSS_RULE@17..59 + 0: CSS_QUALIFIED_RULE@17..59 0: CSS_SELECTOR_LIST@17..22 0: CSS_COMPOUND_SELECTOR@17..22 0: (empty) @@ -233,7 +233,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@127..128 ";" [] [] 2: R_CURLY@128..132 "}" [Newline("\n"), Whitespace("\t\t")] [] - 1: CSS_RULE@132..163 + 1: CSS_QUALIFIED_RULE@132..163 0: CSS_SELECTOR_LIST@132..140 0: CSS_COMPOUND_SELECTOR@132..140 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_supports.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_supports.css.snap index 1a35263127e8..97287eecbe23 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_supports.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/at_rule/at_rule_supports.css.snap @@ -206,7 +206,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@26..27 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -271,7 +271,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@84..85 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -340,7 +340,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@151..152 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1480,7 +1480,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@1485..1486 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -1566,7 +1566,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@1569..1570 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1673,7 +1673,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@1680..1681 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1740,7 +1740,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@1732..1733 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1803,7 +1803,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@1786..1787 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1870,7 +1870,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@1842..1843 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1953,7 +1953,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@1898..1899 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2040,7 +2040,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@1956..1957 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2127,7 +2127,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@2035..2036 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2290,7 +2290,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@2206..2207 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2397,7 +2397,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@2281..2282 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -2536,7 +2536,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@2367..2368 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2794,7 +2794,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@2610..2611 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2884,7 +2884,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@2690..2691 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2953,7 +2953,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@2744..2745 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3030,7 +3030,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@2817..2818 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -3119,7 +3119,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@2900..2901 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3182,7 +3182,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@2963..2964 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3234,7 +3234,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@3010..3011 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3301,7 +3301,7 @@ CssRoot { block: CssRuleListBlock { l_curly_token: L_CURLY@3074..3075 "{" [] [], rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3378,7 +3378,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@26..56 0: L_CURLY@26..27 "{" [] [] 1: CSS_RULE_LIST@27..54 - 0: CSS_RULE@27..54 + 0: CSS_QUALIFIED_RULE@27..54 0: CSS_SELECTOR_LIST@27..33 0: CSS_COMPOUND_SELECTOR@27..33 0: (empty) @@ -3421,7 +3421,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@84..191 0: L_CURLY@84..85 "{" [] [] 1: CSS_RULE_LIST@85..189 - 0: CSS_RULE@85..111 + 0: CSS_QUALIFIED_RULE@85..111 0: CSS_SELECTOR_LIST@85..92 0: CSS_COMPOUND_SELECTOR@85..92 0: (empty) @@ -3469,7 +3469,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@151..189 0: L_CURLY@151..152 "{" [] [] 1: CSS_RULE_LIST@152..186 - 0: CSS_RULE@152..186 + 0: CSS_QUALIFIED_RULE@152..186 0: CSS_SELECTOR_LIST@152..163 0: CSS_COMPOUND_SELECTOR@152..163 0: (empty) @@ -4239,7 +4239,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@1485..1532 0: L_CURLY@1485..1486 "{" [] [] 1: CSS_RULE_LIST@1486..1530 - 0: CSS_RULE@1486..1530 + 0: CSS_QUALIFIED_RULE@1486..1530 0: CSS_SELECTOR_LIST@1486..1507 0: CSS_COMPLEX_SELECTOR@1486..1507 0: CSS_COMPOUND_SELECTOR@1486..1501 @@ -4296,7 +4296,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@1569..1616 0: L_CURLY@1569..1570 "{" [] [] 1: CSS_RULE_LIST@1570..1614 - 0: CSS_RULE@1570..1614 + 0: CSS_QUALIFIED_RULE@1570..1614 0: CSS_SELECTOR_LIST@1570..1588 0: CSS_COMPOUND_SELECTOR@1570..1588 0: (empty) @@ -4366,7 +4366,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@1680..1707 0: L_CURLY@1680..1681 "{" [] [] 1: CSS_RULE_LIST@1681..1705 - 0: CSS_RULE@1681..1705 + 0: CSS_QUALIFIED_RULE@1681..1705 0: CSS_SELECTOR_LIST@1681..1685 0: CSS_COMPOUND_SELECTOR@1681..1685 0: (empty) @@ -4411,7 +4411,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@1732..1759 0: L_CURLY@1732..1733 "{" [] [] 1: CSS_RULE_LIST@1733..1757 - 0: CSS_RULE@1733..1757 + 0: CSS_QUALIFIED_RULE@1733..1757 0: CSS_SELECTOR_LIST@1733..1737 0: CSS_COMPOUND_SELECTOR@1733..1737 0: (empty) @@ -4453,7 +4453,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@1786..1813 0: L_CURLY@1786..1787 "{" [] [] 1: CSS_RULE_LIST@1787..1811 - 0: CSS_RULE@1787..1811 + 0: CSS_QUALIFIED_RULE@1787..1811 0: CSS_SELECTOR_LIST@1787..1791 0: CSS_COMPOUND_SELECTOR@1787..1791 0: (empty) @@ -4498,7 +4498,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@1842..1869 0: L_CURLY@1842..1843 "{" [] [] 1: CSS_RULE_LIST@1843..1867 - 0: CSS_RULE@1843..1867 + 0: CSS_QUALIFIED_RULE@1843..1867 0: CSS_SELECTOR_LIST@1843..1847 0: CSS_COMPOUND_SELECTOR@1843..1847 0: (empty) @@ -4551,7 +4551,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@1898..1925 0: L_CURLY@1898..1899 "{" [] [] 1: CSS_RULE_LIST@1899..1923 - 0: CSS_RULE@1899..1923 + 0: CSS_QUALIFIED_RULE@1899..1923 0: CSS_SELECTOR_LIST@1899..1903 0: CSS_COMPOUND_SELECTOR@1899..1903 0: (empty) @@ -4607,7 +4607,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@1956..1983 0: L_CURLY@1956..1957 "{" [] [] 1: CSS_RULE_LIST@1957..1981 - 0: CSS_RULE@1957..1981 + 0: CSS_QUALIFIED_RULE@1957..1981 0: CSS_SELECTOR_LIST@1957..1961 0: CSS_COMPOUND_SELECTOR@1957..1961 0: (empty) @@ -4663,7 +4663,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@2035..2062 0: L_CURLY@2035..2036 "{" [] [] 1: CSS_RULE_LIST@2036..2060 - 0: CSS_RULE@2036..2060 + 0: CSS_QUALIFIED_RULE@2036..2060 0: CSS_SELECTOR_LIST@2036..2040 0: CSS_COMPOUND_SELECTOR@2036..2040 0: (empty) @@ -4770,7 +4770,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@2206..2245 0: L_CURLY@2206..2207 "{" [] [] 1: CSS_RULE_LIST@2207..2243 - 0: CSS_RULE@2207..2243 + 0: CSS_QUALIFIED_RULE@2207..2243 0: CSS_SELECTOR_LIST@2207..2214 0: CSS_COMPOUND_SELECTOR@2207..2214 0: (empty) @@ -4842,7 +4842,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@2281..2322 0: L_CURLY@2281..2282 "{" [] [] 1: CSS_RULE_LIST@2282..2320 - 0: CSS_RULE@2282..2320 + 0: CSS_QUALIFIED_RULE@2282..2320 0: CSS_SELECTOR_LIST@2282..2302 0: CSS_COMPLEX_SELECTOR@2282..2291 0: CSS_COMPOUND_SELECTOR@2282..2287 @@ -4938,7 +4938,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@2367..2456 0: L_CURLY@2367..2368 "{" [] [] 1: CSS_RULE_LIST@2368..2454 - 0: CSS_RULE@2368..2454 + 0: CSS_QUALIFIED_RULE@2368..2454 0: CSS_SELECTOR_LIST@2368..2437 0: CSS_COMPOUND_SELECTOR@2368..2437 0: (empty) @@ -5111,7 +5111,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@2610..2657 0: L_CURLY@2610..2611 "{" [] [] 1: CSS_RULE_LIST@2611..2655 - 0: CSS_RULE@2611..2655 + 0: CSS_QUALIFIED_RULE@2611..2655 0: CSS_SELECTOR_LIST@2611..2629 0: CSS_COMPOUND_SELECTOR@2611..2629 0: (empty) @@ -5169,7 +5169,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@2690..2722 0: L_CURLY@2690..2691 "{" [] [] 1: CSS_RULE_LIST@2691..2720 - 0: CSS_RULE@2691..2720 + 0: CSS_QUALIFIED_RULE@2691..2720 0: CSS_SELECTOR_LIST@2691..2697 0: CSS_COMPOUND_SELECTOR@2691..2697 0: (empty) @@ -5214,7 +5214,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@2744..2771 0: L_CURLY@2744..2745 "{" [] [] 1: CSS_RULE_LIST@2745..2769 - 0: CSS_RULE@2745..2769 + 0: CSS_QUALIFIED_RULE@2745..2769 0: CSS_SELECTOR_LIST@2745..2749 0: CSS_COMPOUND_SELECTOR@2745..2749 0: (empty) @@ -5267,7 +5267,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@2817..2864 0: L_CURLY@2817..2818 "{" [] [] 1: CSS_RULE_LIST@2818..2862 - 0: CSS_RULE@2818..2862 + 0: CSS_QUALIFIED_RULE@2818..2862 0: CSS_SELECTOR_LIST@2818..2839 0: CSS_COMPLEX_SELECTOR@2818..2839 0: CSS_COMPOUND_SELECTOR@2818..2833 @@ -5325,7 +5325,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@2900..2927 0: L_CURLY@2900..2901 "{" [] [] 1: CSS_RULE_LIST@2901..2925 - 0: CSS_RULE@2901..2925 + 0: CSS_QUALIFIED_RULE@2901..2925 0: CSS_SELECTOR_LIST@2901..2905 0: CSS_COMPOUND_SELECTOR@2901..2905 0: (empty) @@ -5367,7 +5367,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@2963..2990 0: L_CURLY@2963..2964 "{" [] [] 1: CSS_RULE_LIST@2964..2988 - 0: CSS_RULE@2964..2988 + 0: CSS_QUALIFIED_RULE@2964..2988 0: CSS_SELECTOR_LIST@2964..2968 0: CSS_COMPOUND_SELECTOR@2964..2968 0: (empty) @@ -5402,7 +5402,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@3010..3037 0: L_CURLY@3010..3011 "{" [] [] 1: CSS_RULE_LIST@3011..3035 - 0: CSS_RULE@3011..3035 + 0: CSS_QUALIFIED_RULE@3011..3035 0: CSS_SELECTOR_LIST@3011..3015 0: CSS_COMPOUND_SELECTOR@3011..3015 0: (empty) @@ -5446,7 +5446,7 @@ CssRoot { 2: CSS_RULE_LIST_BLOCK@3074..3119 0: L_CURLY@3074..3075 "{" [] [] 1: CSS_RULE_LIST@3075..3117 - 0: CSS_RULE@3075..3117 + 0: CSS_QUALIFIED_RULE@3075..3117 0: CSS_SELECTOR_LIST@3075..3086 0: CSS_COMPOUND_SELECTOR@3075..3086 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/class_selector.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/class_selector.css.snap index 258cf13a8840..9d9783b0d205 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/class_selector.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/class_selector.css.snap @@ -17,7 +17,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -49,7 +49,7 @@ CssRoot { 0: CSS_ROOT@0..11 0: (empty) 1: CSS_RULE_LIST@0..10 - 0: CSS_RULE@0..10 + 0: CSS_QUALIFIED_RULE@0..10 0: CSS_SELECTOR_LIST@0..8 0: CSS_COMPOUND_SELECTOR@0..8 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/declaration_list.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/declaration_list.css.snap index ef1d903566cc..5cc7f1e83081 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/declaration_list.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/declaration_list.css.snap @@ -62,7 +62,7 @@ div { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -112,7 +112,7 @@ CssRoot { r_curly_token: R_CURLY@39..41 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -148,7 +148,7 @@ CssRoot { r_curly_token: R_CURLY@62..64 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -188,7 +188,7 @@ CssRoot { r_curly_token: R_CURLY@85..87 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -238,7 +238,7 @@ CssRoot { r_curly_token: R_CURLY@109..111 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -298,7 +298,7 @@ CssRoot { r_curly_token: R_CURLY@135..137 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -361,7 +361,7 @@ CssRoot { r_curly_token: R_CURLY@163..165 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -402,7 +402,7 @@ CssRoot { r_curly_token: R_CURLY@186..188 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -437,7 +437,7 @@ CssRoot { r_curly_token: R_CURLY@214..216 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -481,7 +481,7 @@ CssRoot { r_curly_token: R_CURLY@251..253 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -534,7 +534,7 @@ CssRoot { r_curly_token: R_CURLY@328..330 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -641,7 +641,7 @@ CssRoot { 0: CSS_ROOT@0..456 0: (empty) 1: CSS_RULE_LIST@0..455 - 0: CSS_RULE@0..41 + 0: CSS_QUALIFIED_RULE@0..41 0: CSS_SELECTOR_LIST@0..2 0: CSS_COMPOUND_SELECTOR@0..2 0: (empty) @@ -674,7 +674,7 @@ CssRoot { 1: (empty) 3: SEMICOLON@38..39 ";" [] [] 2: R_CURLY@39..41 "}" [Newline("\n")] [] - 1: CSS_RULE@41..64 + 1: CSS_QUALIFIED_RULE@41..64 0: CSS_SELECTOR_LIST@41..45 0: CSS_COMPOUND_SELECTOR@41..45 0: (empty) @@ -698,7 +698,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@61..62 ";" [] [] 2: R_CURLY@62..64 "}" [Newline("\n")] [] - 2: CSS_RULE@64..87 + 2: CSS_QUALIFIED_RULE@64..87 0: CSS_SELECTOR_LIST@64..68 0: CSS_COMPOUND_SELECTOR@64..68 0: (empty) @@ -725,7 +725,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@84..85 ";" [] [] 2: R_CURLY@85..87 "}" [Newline("\n")] [] - 3: CSS_RULE@87..111 + 3: CSS_QUALIFIED_RULE@87..111 0: CSS_SELECTOR_LIST@87..91 0: CSS_COMPOUND_SELECTOR@87..91 0: (empty) @@ -757,7 +757,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@108..109 ";" [] [] 2: R_CURLY@109..111 "}" [Newline("\n")] [] - 4: CSS_RULE@111..137 + 4: CSS_QUALIFIED_RULE@111..137 0: CSS_SELECTOR_LIST@111..115 0: CSS_COMPOUND_SELECTOR@111..115 0: (empty) @@ -795,7 +795,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@134..135 ";" [] [] 2: R_CURLY@135..137 "}" [Newline("\n")] [] - 5: CSS_RULE@137..165 + 5: CSS_QUALIFIED_RULE@137..165 0: CSS_SELECTOR_LIST@137..141 0: CSS_COMPOUND_SELECTOR@137..141 0: (empty) @@ -835,7 +835,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@162..163 ";" [] [] 2: R_CURLY@163..165 "}" [Newline("\n")] [] - 6: CSS_RULE@165..188 + 6: CSS_QUALIFIED_RULE@165..188 0: CSS_SELECTOR_LIST@165..169 0: CSS_COMPOUND_SELECTOR@165..169 0: (empty) @@ -862,7 +862,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@185..186 ";" [] [] 2: R_CURLY@186..188 "}" [Newline("\n")] [] - 7: CSS_RULE@188..216 + 7: CSS_QUALIFIED_RULE@188..216 0: CSS_SELECTOR_LIST@188..192 0: CSS_COMPOUND_SELECTOR@188..192 0: (empty) @@ -885,7 +885,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@213..214 ";" [] [] 2: R_CURLY@214..216 "}" [Newline("\n")] [] - 8: CSS_RULE@216..253 + 8: CSS_QUALIFIED_RULE@216..253 0: CSS_SELECTOR_LIST@216..222 0: CSS_COMPOUND_SELECTOR@216..222 0: (empty) @@ -914,7 +914,7 @@ CssRoot { 1: IMPORTANT_KW@241..250 "important" [] [] 1: SEMICOLON@250..251 ";" [] [] 2: R_CURLY@251..253 "}" [Newline("\n")] [] - 9: CSS_RULE@253..330 + 9: CSS_QUALIFIED_RULE@253..330 0: CSS_SELECTOR_LIST@253..259 0: CSS_COMPOUND_SELECTOR@253..259 0: (empty) @@ -948,7 +948,7 @@ CssRoot { 1: IMPORTANT_KW@318..327 "important" [] [] 1: SEMICOLON@327..328 ";" [] [] 2: R_CURLY@328..330 "}" [Newline("\n")] [] - 10: CSS_RULE@330..455 + 10: CSS_QUALIFIED_RULE@330..455 0: CSS_SELECTOR_LIST@330..336 0: CSS_COMPOUND_SELECTOR@330..336 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/dimension.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/dimension.css.snap index 469255dd0ca9..875939da4e60 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/dimension.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/dimension.css.snap @@ -96,7 +96,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1270,7 +1270,7 @@ CssRoot { r_curly_token: R_CURLY@915..917 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1335,7 +1335,7 @@ CssRoot { 0: CSS_ROOT@0..979 0: (empty) 1: CSS_RULE_LIST@0..979 - 0: CSS_RULE@0..917 + 0: CSS_QUALIFIED_RULE@0..917 0: CSS_SELECTOR_LIST@0..10 0: CSS_COMPOUND_SELECTOR@0..10 0: (empty) @@ -2141,7 +2141,7 @@ CssRoot { 1: (empty) 143: SEMICOLON@914..915 ";" [] [] 2: R_CURLY@915..917 "}" [Newline("\n")] [] - 1: CSS_RULE@917..979 + 1: CSS_QUALIFIED_RULE@917..979 0: CSS_SELECTOR_LIST@917..939 0: CSS_COMPOUND_SELECTOR@917..939 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/function/calc.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/function/calc.css.snap index 4cbacdc95ed9..149b3c638acb 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/function/calc.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/function/calc.css.snap @@ -164,7 +164,7 @@ div { width: calc(50% - ( ( 4% ) * 0.5 ) ); } CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -229,7 +229,7 @@ CssRoot { r_curly_token: R_CURLY@40..42 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1408,7 +1408,7 @@ CssRoot { r_curly_token: R_CURLY@846..848 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1826,7 +1826,7 @@ CssRoot { r_curly_token: R_CURLY@1103..1105 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1950,7 +1950,7 @@ CssRoot { r_curly_token: R_CURLY@1214..1216 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1969,7 +1969,7 @@ CssRoot { r_curly_token: R_CURLY@1223..1320 "}" [Newline("\n"), Whitespace(" "), Comments("/*height: -webkit-cal ..."), Newline("\n"), Whitespace(" "), Comments("/*width: -moz-calc((5 ..."), Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2030,7 +2030,7 @@ CssRoot { r_curly_token: R_CURLY@1350..1351 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2092,7 +2092,7 @@ CssRoot { r_curly_token: R_CURLY@1389..1390 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2172,7 +2172,7 @@ CssRoot { r_curly_token: R_CURLY@1435..1436 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2296,7 +2296,7 @@ CssRoot { r_curly_token: R_CURLY@1549..1551 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2395,7 +2395,7 @@ CssRoot { r_curly_token: R_CURLY@1706..1708 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2505,7 +2505,7 @@ CssRoot { r_curly_token: R_CURLY@1835..1837 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3428,7 +3428,7 @@ CssRoot { r_curly_token: R_CURLY@2475..2477 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3642,7 +3642,7 @@ CssRoot { r_curly_token: R_CURLY@2633..2635 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3706,7 +3706,7 @@ CssRoot { r_curly_token: R_CURLY@2671..2673 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3825,7 +3825,7 @@ CssRoot { r_curly_token: R_CURLY@2757..2759 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3944,7 +3944,7 @@ CssRoot { r_curly_token: R_CURLY@2843..2845 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -4067,7 +4067,7 @@ CssRoot { r_curly_token: R_CURLY@2927..2929 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -4190,7 +4190,7 @@ CssRoot { r_curly_token: R_CURLY@3011..3013 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -4263,7 +4263,7 @@ CssRoot { r_curly_token: R_CURLY@3059..3061 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -4340,7 +4340,7 @@ CssRoot { r_curly_token: R_CURLY@3108..3110 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -4392,7 +4392,7 @@ CssRoot { r_curly_token: R_CURLY@3140..3142 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -4454,7 +4454,7 @@ CssRoot { r_curly_token: R_CURLY@3174..3176 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -4533,7 +4533,7 @@ CssRoot { r_curly_token: R_CURLY@3232..3234 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -4847,7 +4847,7 @@ CssRoot { 0: CSS_ROOT@0..3559 0: (empty) 1: CSS_RULE_LIST@0..3559 - 0: CSS_RULE@0..42 + 0: CSS_QUALIFIED_RULE@0..42 0: CSS_SELECTOR_LIST@0..6 0: CSS_COMPOUND_SELECTOR@0..6 0: (empty) @@ -4888,7 +4888,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@39..40 ";" [] [] 2: R_CURLY@40..42 "}" [Newline("\n")] [] - 1: CSS_RULE@42..848 + 1: CSS_QUALIFIED_RULE@42..848 0: CSS_SELECTOR_LIST@42..48 0: CSS_COMPOUND_SELECTOR@42..48 0: (empty) @@ -5635,7 +5635,7 @@ CssRoot { 1: (empty) 45: SEMICOLON@845..846 ";" [] [] 2: R_CURLY@846..848 "}" [Newline("\n")] [] - 2: CSS_RULE@848..1105 + 2: CSS_QUALIFIED_RULE@848..1105 0: CSS_SELECTOR_LIST@848..855 0: CSS_COMPOUND_SELECTOR@848..855 0: (empty) @@ -5895,7 +5895,7 @@ CssRoot { 1: (empty) 11: SEMICOLON@1102..1103 ";" [] [] 2: R_CURLY@1103..1105 "}" [Newline("\n")] [] - 3: CSS_RULE@1105..1216 + 3: CSS_QUALIFIED_RULE@1105..1216 0: CSS_SELECTOR_LIST@1105..1113 0: CSS_COMPOUND_SELECTOR@1105..1113 0: (empty) @@ -5974,7 +5974,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@1213..1214 ";" [] [] 2: R_CURLY@1214..1216 "}" [Newline("\n")] [] - 4: CSS_RULE@1216..1320 + 4: CSS_QUALIFIED_RULE@1216..1320 0: CSS_SELECTOR_LIST@1216..1222 0: CSS_COMPOUND_SELECTOR@1216..1222 0: (empty) @@ -5987,7 +5987,7 @@ CssRoot { 0: L_CURLY@1222..1223 "{" [] [] 1: CSS_DECLARATION_LIST@1223..1223 2: R_CURLY@1223..1320 "}" [Newline("\n"), Whitespace(" "), Comments("/*height: -webkit-cal ..."), Newline("\n"), Whitespace(" "), Comments("/*width: -moz-calc((5 ..."), Newline("\n")] [] - 5: CSS_RULE@1320..1351 + 5: CSS_QUALIFIED_RULE@1320..1351 0: CSS_SELECTOR_LIST@1320..1325 0: CSS_COMPOUND_SELECTOR@1320..1325 0: (empty) @@ -6026,7 +6026,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@1348..1350 ";" [] [Whitespace(" ")] 2: R_CURLY@1350..1351 "}" [] [] - 6: CSS_RULE@1351..1390 + 6: CSS_QUALIFIED_RULE@1351..1390 0: CSS_SELECTOR_LIST@1351..1356 0: CSS_COMPOUND_SELECTOR@1351..1356 0: (empty) @@ -6066,7 +6066,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@1387..1389 ";" [] [Whitespace(" ")] 2: R_CURLY@1389..1390 "}" [] [] - 7: CSS_RULE@1390..1436 + 7: CSS_QUALIFIED_RULE@1390..1436 0: CSS_SELECTOR_LIST@1390..1395 0: CSS_COMPOUND_SELECTOR@1390..1395 0: (empty) @@ -6118,7 +6118,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@1433..1435 ";" [] [Whitespace(" ")] 2: R_CURLY@1435..1436 "}" [] [] - 8: CSS_RULE@1436..1551 + 8: CSS_QUALIFIED_RULE@1436..1551 0: CSS_SELECTOR_LIST@1436..1444 0: CSS_COMPOUND_SELECTOR@1436..1444 0: (empty) @@ -6197,7 +6197,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@1548..1549 ";" [] [] 2: R_CURLY@1549..1551 "}" [Newline("\n")] [] - 9: CSS_RULE@1551..1708 + 9: CSS_QUALIFIED_RULE@1551..1708 0: CSS_SELECTOR_LIST@1551..1559 0: CSS_COMPOUND_SELECTOR@1551..1559 0: (empty) @@ -6260,7 +6260,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@1705..1706 ";" [] [] 2: R_CURLY@1706..1708 "}" [Newline("\n")] [] - 10: CSS_RULE@1708..1837 + 10: CSS_QUALIFIED_RULE@1708..1837 0: CSS_SELECTOR_LIST@1708..1716 0: CSS_COMPOUND_SELECTOR@1708..1716 0: (empty) @@ -6330,7 +6330,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@1834..1835 ";" [] [] 2: R_CURLY@1835..1837 "}" [Newline("\n")] [] - 11: CSS_RULE@1837..2477 + 11: CSS_QUALIFIED_RULE@1837..2477 0: CSS_SELECTOR_LIST@1837..1845 0: CSS_COMPOUND_SELECTOR@1837..1845 0: (empty) @@ -6909,7 +6909,7 @@ CssRoot { 1: (empty) 35: SEMICOLON@2474..2475 ";" [] [] 2: R_CURLY@2475..2477 "}" [Newline("\n")] [] - 12: CSS_RULE@2477..2635 + 12: CSS_QUALIFIED_RULE@2477..2635 0: CSS_SELECTOR_LIST@2477..2488 0: CSS_COMPOUND_SELECTOR@2477..2488 0: (empty) @@ -7046,7 +7046,7 @@ CssRoot { 1: (empty) 5: SEMICOLON@2632..2633 ";" [] [] 2: R_CURLY@2633..2635 "}" [Newline("\n")] [] - 13: CSS_RULE@2635..2673 + 13: CSS_QUALIFIED_RULE@2635..2673 0: CSS_SELECTOR_LIST@2635..2642 0: CSS_COMPOUND_SELECTOR@2635..2642 0: (empty) @@ -7087,7 +7087,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@2670..2671 ";" [] [] 2: R_CURLY@2671..2673 "}" [Newline("\n")] [] - 14: CSS_RULE@2673..2759 + 14: CSS_QUALIFIED_RULE@2673..2759 0: CSS_SELECTOR_LIST@2673..2680 0: CSS_COMPOUND_SELECTOR@2673..2680 0: (empty) @@ -7162,7 +7162,7 @@ CssRoot { 1: (empty) 3: SEMICOLON@2756..2757 ";" [] [] 2: R_CURLY@2757..2759 "}" [Newline("\n")] [] - 15: CSS_RULE@2759..2845 + 15: CSS_QUALIFIED_RULE@2759..2845 0: CSS_SELECTOR_LIST@2759..2766 0: CSS_COMPOUND_SELECTOR@2759..2766 0: (empty) @@ -7237,7 +7237,7 @@ CssRoot { 1: (empty) 3: SEMICOLON@2842..2843 ";" [] [] 2: R_CURLY@2843..2845 "}" [Newline("\n")] [] - 16: CSS_RULE@2845..2929 + 16: CSS_QUALIFIED_RULE@2845..2929 0: CSS_SELECTOR_LIST@2845..2853 0: CSS_COMPOUND_SELECTOR@2845..2853 0: (empty) @@ -7314,7 +7314,7 @@ CssRoot { 1: (empty) 3: SEMICOLON@2926..2927 ";" [] [] 2: R_CURLY@2927..2929 "}" [Newline("\n")] [] - 17: CSS_RULE@2929..3013 + 17: CSS_QUALIFIED_RULE@2929..3013 0: CSS_SELECTOR_LIST@2929..2937 0: CSS_COMPOUND_SELECTOR@2929..2937 0: (empty) @@ -7391,7 +7391,7 @@ CssRoot { 1: (empty) 3: SEMICOLON@3010..3011 ";" [] [] 2: R_CURLY@3011..3013 "}" [Newline("\n")] [] - 18: CSS_RULE@3013..3061 + 18: CSS_QUALIFIED_RULE@3013..3061 0: CSS_SELECTOR_LIST@3013..3021 0: CSS_COMPOUND_SELECTOR@3013..3021 0: (empty) @@ -7437,7 +7437,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@3058..3059 ";" [] [] 2: R_CURLY@3059..3061 "}" [Newline("\n")] [] - 19: CSS_RULE@3061..3110 + 19: CSS_QUALIFIED_RULE@3061..3110 0: CSS_SELECTOR_LIST@3061..3070 0: CSS_COMPOUND_SELECTOR@3061..3070 0: (empty) @@ -7485,7 +7485,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@3107..3108 ";" [] [] 2: R_CURLY@3108..3110 "}" [Newline("\n")] [] - 20: CSS_RULE@3110..3142 + 20: CSS_QUALIFIED_RULE@3110..3142 0: CSS_SELECTOR_LIST@3110..3118 0: CSS_COMPOUND_SELECTOR@3110..3118 0: (empty) @@ -7518,7 +7518,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@3139..3140 ";" [] [] 2: R_CURLY@3140..3142 "}" [Newline("\n")] [] - 21: CSS_RULE@3142..3176 + 21: CSS_QUALIFIED_RULE@3142..3176 0: CSS_SELECTOR_LIST@3142..3149 0: CSS_COMPOUND_SELECTOR@3142..3149 0: (empty) @@ -7557,7 +7557,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@3173..3174 ";" [] [] 2: R_CURLY@3174..3176 "}" [Newline("\n")] [] - 22: CSS_RULE@3176..3234 + 22: CSS_QUALIFIED_RULE@3176..3234 0: CSS_SELECTOR_LIST@3176..3183 0: CSS_COMPOUND_SELECTOR@3176..3183 0: (empty) @@ -7607,7 +7607,7 @@ CssRoot { 1: (empty) 1: SEMICOLON@3231..3232 ";" [] [] 2: R_CURLY@3232..3234 "}" [Newline("\n")] [] - 23: CSS_RULE@3234..3559 + 23: CSS_QUALIFIED_RULE@3234..3559 0: CSS_SELECTOR_LIST@3234..3242 0: CSS_COMPOUND_SELECTOR@3234..3242 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/function/linear-gradient.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/function/linear-gradient.css.snap index 8e3f7befa0ac..c750ffadd5fe 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/function/linear-gradient.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/function/linear-gradient.css.snap @@ -30,7 +30,7 @@ a { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -768,7 +768,7 @@ CssRoot { 0: CSS_ROOT@0..748 0: (empty) 1: CSS_RULE_LIST@0..748 - 0: CSS_RULE@0..748 + 0: CSS_QUALIFIED_RULE@0..748 0: CSS_SELECTOR_LIST@0..2 0: CSS_COMPOUND_SELECTOR@0..2 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/function/unknow.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/function/unknow.css.snap index 696826d1bcaa..754f1ba3bc30 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/function/unknow.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/function/unknow.css.snap @@ -20,7 +20,7 @@ div { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -144,7 +144,7 @@ CssRoot { 0: CSS_ROOT@0..78 0: (empty) 1: CSS_RULE_LIST@0..78 - 0: CSS_RULE@0..78 + 0: CSS_QUALIFIED_RULE@0..78 0: CSS_SELECTOR_LIST@0..4 0: CSS_COMPOUND_SELECTOR@0..4 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/function/url.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/function/url.css.snap index 34ab2ca176b3..f42479f205fe 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/function/url.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/function/url.css.snap @@ -64,7 +64,7 @@ a { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -658,7 +658,7 @@ CssRoot { 0: CSS_ROOT@0..1251 0: (empty) 1: CSS_RULE_LIST@0..1251 - 0: CSS_RULE@0..1251 + 0: CSS_QUALIFIED_RULE@0..1251 0: CSS_SELECTOR_LIST@0..2 0: CSS_COMPOUND_SELECTOR@0..2 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/function/var.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/function/var.css.snap index c034c814283e..eefa483a66b8 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/function/var.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/function/var.css.snap @@ -20,7 +20,7 @@ div { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -152,7 +152,7 @@ CssRoot { 0: CSS_ROOT@0..77 0: (empty) 1: CSS_RULE_LIST@0..77 - 0: CSS_RULE@0..77 + 0: CSS_QUALIFIED_RULE@0..77 0: CSS_SELECTOR_LIST@0..4 0: CSS_COMPOUND_SELECTOR@0..4 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css.snap index c5a30e53c063..0a7660106719 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_all.css.snap @@ -32,7 +32,7 @@ div { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -273,7 +273,7 @@ CssRoot { 0: CSS_ROOT@0..335 0: (empty) 1: CSS_RULE_LIST@0..335 - 0: CSS_RULE@0..335 + 0: CSS_QUALIFIED_RULE@0..335 0: CSS_SELECTOR_LIST@0..4 0: CSS_COMPOUND_SELECTOR@0..4 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_border.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_border.css.snap index d58bf49ef9ec..7321d369b067 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_border.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_border.css.snap @@ -65,7 +65,7 @@ div { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -746,7 +746,7 @@ CssRoot { 0: CSS_ROOT@0..973 0: (empty) 1: CSS_RULE_LIST@0..972 - 0: CSS_RULE@0..972 + 0: CSS_QUALIFIED_RULE@0..972 0: CSS_SELECTOR_LIST@0..4 0: CSS_COMPOUND_SELECTOR@0..4 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css.snap index c66f68d2b1b4..bba5d8a83d60 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_generic.css.snap @@ -41,7 +41,7 @@ div { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -487,7 +487,7 @@ CssRoot { 0: CSS_ROOT@0..827 0: (empty) 1: CSS_RULE_LIST@0..827 - 0: CSS_RULE@0..827 + 0: CSS_QUALIFIED_RULE@0..827 0: CSS_SELECTOR_LIST@0..4 0: CSS_COMPOUND_SELECTOR@0..4 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css.snap index 36f5e072ec34..1dfb1603487c 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/property/property_z-index.css.snap @@ -43,7 +43,7 @@ div { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -362,7 +362,7 @@ CssRoot { 0: CSS_ROOT@0..528 0: (empty) 1: CSS_RULE_LIST@0..527 - 0: CSS_RULE@0..527 + 0: CSS_QUALIFIED_RULE@0..527 0: CSS_SELECTOR_LIST@0..4 0: CSS_COMPOUND_SELECTOR@0..4 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/attribute.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/attribute.css.snap index ae74f99c249f..74fb0e406864 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/attribute.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/attribute.css.snap @@ -64,7 +64,7 @@ a[href='te"s"t'] {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -90,7 +90,7 @@ CssRoot { r_curly_token: R_CURLY@9..10 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -124,7 +124,7 @@ CssRoot { r_curly_token: R_CURLY@24..25 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -158,7 +158,7 @@ CssRoot { r_curly_token: R_CURLY@41..42 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -192,7 +192,7 @@ CssRoot { r_curly_token: R_CURLY@62..63 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -226,7 +226,7 @@ CssRoot { r_curly_token: R_CURLY@91..92 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -260,7 +260,7 @@ CssRoot { r_curly_token: R_CURLY@110..111 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -294,7 +294,7 @@ CssRoot { r_curly_token: R_CURLY@126..127 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -328,7 +328,7 @@ CssRoot { r_curly_token: R_CURLY@141..142 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -362,7 +362,7 @@ CssRoot { r_curly_token: R_CURLY@159..160 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -396,7 +396,7 @@ CssRoot { r_curly_token: R_CURLY@180..181 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -430,7 +430,7 @@ CssRoot { r_curly_token: R_CURLY@207..208 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -464,7 +464,7 @@ CssRoot { r_curly_token: R_CURLY@234..235 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -498,7 +498,7 @@ CssRoot { r_curly_token: R_CURLY@254..255 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -532,7 +532,7 @@ CssRoot { r_curly_token: R_CURLY@274..275 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -558,7 +558,7 @@ CssRoot { r_curly_token: R_CURLY@283..284 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -584,7 +584,7 @@ CssRoot { r_curly_token: R_CURLY@294..295 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -610,7 +610,7 @@ CssRoot { r_curly_token: R_CURLY@309..310 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -649,7 +649,7 @@ CssRoot { r_curly_token: R_CURLY@332..333 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -688,7 +688,7 @@ CssRoot { r_curly_token: R_CURLY@363..364 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -722,7 +722,7 @@ CssRoot { r_curly_token: R_CURLY@392..393 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -756,7 +756,7 @@ CssRoot { r_curly_token: R_CURLY@427..428 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -790,7 +790,7 @@ CssRoot { r_curly_token: R_CURLY@468..469 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -816,7 +816,7 @@ CssRoot { r_curly_token: R_CURLY@484..485 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -850,7 +850,7 @@ CssRoot { r_curly_token: R_CURLY@504..505 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -888,7 +888,7 @@ CssRoot { r_curly_token: R_CURLY@525..526 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -920,7 +920,7 @@ CssRoot { r_curly_token: R_CURLY@540..541 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -952,7 +952,7 @@ CssRoot { r_curly_token: R_CURLY@558..559 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -986,7 +986,7 @@ CssRoot { r_curly_token: R_CURLY@575..576 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1031,7 +1031,7 @@ CssRoot { r_curly_token: R_CURLY@613..614 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1076,7 +1076,7 @@ CssRoot { r_curly_token: R_CURLY@654..655 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1115,7 +1115,7 @@ CssRoot { r_curly_token: R_CURLY@674..675 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1154,7 +1154,7 @@ CssRoot { r_curly_token: R_CURLY@694..695 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1180,7 +1180,7 @@ CssRoot { r_curly_token: R_CURLY@709..710 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1206,7 +1206,7 @@ CssRoot { r_curly_token: R_CURLY@726..727 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1232,7 +1232,7 @@ CssRoot { r_curly_token: R_CURLY@746..747 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1266,7 +1266,7 @@ CssRoot { r_curly_token: R_CURLY@758..759 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1300,7 +1300,7 @@ CssRoot { r_curly_token: R_CURLY@770..771 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1334,7 +1334,7 @@ CssRoot { r_curly_token: R_CURLY@782..783 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1368,7 +1368,7 @@ CssRoot { r_curly_token: R_CURLY@812..813 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1402,7 +1402,7 @@ CssRoot { r_curly_token: R_CURLY@826..827 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1441,7 +1441,7 @@ CssRoot { r_curly_token: R_CURLY@846..847 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1482,7 +1482,7 @@ CssRoot { r_curly_token: R_CURLY@868..869 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1523,7 +1523,7 @@ CssRoot { r_curly_token: R_CURLY@885..886 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1554,7 +1554,7 @@ CssRoot { r_curly_token: R_CURLY@896..897 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1585,7 +1585,7 @@ CssRoot { r_curly_token: R_CURLY@913..914 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1614,7 +1614,7 @@ CssRoot { r_curly_token: R_CURLY@923..924 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1643,7 +1643,7 @@ CssRoot { r_curly_token: R_CURLY@935..936 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1683,7 +1683,7 @@ CssRoot { 0: CSS_ROOT@0..953 0: (empty) 1: CSS_RULE_LIST@0..952 - 0: CSS_RULE@0..10 + 0: CSS_QUALIFIED_RULE@0..10 0: CSS_SELECTOR_LIST@0..8 0: CSS_COMPOUND_SELECTOR@0..8 0: (empty) @@ -1701,7 +1701,7 @@ CssRoot { 0: L_CURLY@8..9 "{" [] [] 1: CSS_DECLARATION_LIST@9..9 2: R_CURLY@9..10 "}" [] [] - 1: CSS_RULE@10..25 + 1: CSS_QUALIFIED_RULE@10..25 0: CSS_SELECTOR_LIST@10..23 0: CSS_COMPOUND_SELECTOR@10..23 0: (empty) @@ -1724,7 +1724,7 @@ CssRoot { 0: L_CURLY@23..24 "{" [] [] 1: CSS_DECLARATION_LIST@24..24 2: R_CURLY@24..25 "}" [] [] - 2: CSS_RULE@25..42 + 2: CSS_QUALIFIED_RULE@25..42 0: CSS_SELECTOR_LIST@25..40 0: CSS_COMPOUND_SELECTOR@25..40 0: (empty) @@ -1747,7 +1747,7 @@ CssRoot { 0: L_CURLY@40..41 "{" [] [] 1: CSS_DECLARATION_LIST@41..41 2: R_CURLY@41..42 "}" [] [] - 3: CSS_RULE@42..63 + 3: CSS_QUALIFIED_RULE@42..63 0: CSS_SELECTOR_LIST@42..61 0: CSS_COMPOUND_SELECTOR@42..61 0: (empty) @@ -1770,7 +1770,7 @@ CssRoot { 0: L_CURLY@61..62 "{" [] [] 1: CSS_DECLARATION_LIST@62..62 2: R_CURLY@62..63 "}" [] [] - 4: CSS_RULE@63..92 + 4: CSS_QUALIFIED_RULE@63..92 0: CSS_SELECTOR_LIST@63..90 0: CSS_COMPOUND_SELECTOR@63..90 0: (empty) @@ -1793,7 +1793,7 @@ CssRoot { 0: L_CURLY@90..91 "{" [] [] 1: CSS_DECLARATION_LIST@91..91 2: R_CURLY@91..92 "}" [] [] - 5: CSS_RULE@92..111 + 5: CSS_QUALIFIED_RULE@92..111 0: CSS_SELECTOR_LIST@92..109 0: CSS_COMPOUND_SELECTOR@92..109 0: (empty) @@ -1816,7 +1816,7 @@ CssRoot { 0: L_CURLY@109..110 "{" [] [] 1: CSS_DECLARATION_LIST@110..110 2: R_CURLY@110..111 "}" [] [] - 6: CSS_RULE@111..127 + 6: CSS_QUALIFIED_RULE@111..127 0: CSS_SELECTOR_LIST@111..125 0: CSS_COMPOUND_SELECTOR@111..125 0: (empty) @@ -1839,7 +1839,7 @@ CssRoot { 0: L_CURLY@125..126 "{" [] [] 1: CSS_DECLARATION_LIST@126..126 2: R_CURLY@126..127 "}" [] [] - 7: CSS_RULE@127..142 + 7: CSS_QUALIFIED_RULE@127..142 0: CSS_SELECTOR_LIST@127..140 0: CSS_COMPOUND_SELECTOR@127..140 0: (empty) @@ -1862,7 +1862,7 @@ CssRoot { 0: L_CURLY@140..141 "{" [] [] 1: CSS_DECLARATION_LIST@141..141 2: R_CURLY@141..142 "}" [] [] - 8: CSS_RULE@142..160 + 8: CSS_QUALIFIED_RULE@142..160 0: CSS_SELECTOR_LIST@142..158 0: CSS_COMPOUND_SELECTOR@142..158 0: (empty) @@ -1885,7 +1885,7 @@ CssRoot { 0: L_CURLY@158..159 "{" [] [] 1: CSS_DECLARATION_LIST@159..159 2: R_CURLY@159..160 "}" [] [] - 9: CSS_RULE@160..181 + 9: CSS_QUALIFIED_RULE@160..181 0: CSS_SELECTOR_LIST@160..179 0: CSS_COMPOUND_SELECTOR@160..179 0: (empty) @@ -1908,7 +1908,7 @@ CssRoot { 0: L_CURLY@179..180 "{" [] [] 1: CSS_DECLARATION_LIST@180..180 2: R_CURLY@180..181 "}" [] [] - 10: CSS_RULE@181..208 + 10: CSS_QUALIFIED_RULE@181..208 0: CSS_SELECTOR_LIST@181..206 0: CSS_COMPOUND_SELECTOR@181..206 0: (empty) @@ -1931,7 +1931,7 @@ CssRoot { 0: L_CURLY@206..207 "{" [] [] 1: CSS_DECLARATION_LIST@207..207 2: R_CURLY@207..208 "}" [] [] - 11: CSS_RULE@208..235 + 11: CSS_QUALIFIED_RULE@208..235 0: CSS_SELECTOR_LIST@208..233 0: CSS_COMPOUND_SELECTOR@208..233 0: (empty) @@ -1954,7 +1954,7 @@ CssRoot { 0: L_CURLY@233..234 "{" [] [] 1: CSS_DECLARATION_LIST@234..234 2: R_CURLY@234..235 "}" [] [] - 12: CSS_RULE@235..255 + 12: CSS_QUALIFIED_RULE@235..255 0: CSS_SELECTOR_LIST@235..253 0: CSS_COMPOUND_SELECTOR@235..253 0: (empty) @@ -1977,7 +1977,7 @@ CssRoot { 0: L_CURLY@253..254 "{" [] [] 1: CSS_DECLARATION_LIST@254..254 2: R_CURLY@254..255 "}" [] [] - 13: CSS_RULE@255..275 + 13: CSS_QUALIFIED_RULE@255..275 0: CSS_SELECTOR_LIST@255..273 0: CSS_COMPOUND_SELECTOR@255..273 0: (empty) @@ -2000,7 +2000,7 @@ CssRoot { 0: L_CURLY@273..274 "{" [] [] 1: CSS_DECLARATION_LIST@274..274 2: R_CURLY@274..275 "}" [] [] - 14: CSS_RULE@275..284 + 14: CSS_QUALIFIED_RULE@275..284 0: CSS_SELECTOR_LIST@275..282 0: CSS_COMPOUND_SELECTOR@275..282 0: (empty) @@ -2018,7 +2018,7 @@ CssRoot { 0: L_CURLY@282..283 "{" [] [] 1: CSS_DECLARATION_LIST@283..283 2: R_CURLY@283..284 "}" [] [] - 15: CSS_RULE@284..295 + 15: CSS_QUALIFIED_RULE@284..295 0: CSS_SELECTOR_LIST@284..293 0: CSS_COMPOUND_SELECTOR@284..293 0: (empty) @@ -2036,7 +2036,7 @@ CssRoot { 0: L_CURLY@293..294 "{" [] [] 1: CSS_DECLARATION_LIST@294..294 2: R_CURLY@294..295 "}" [] [] - 16: CSS_RULE@295..310 + 16: CSS_QUALIFIED_RULE@295..310 0: CSS_SELECTOR_LIST@295..308 0: CSS_COMPOUND_SELECTOR@295..308 0: (empty) @@ -2054,7 +2054,7 @@ CssRoot { 0: L_CURLY@308..309 "{" [] [] 1: CSS_DECLARATION_LIST@309..309 2: R_CURLY@309..310 "}" [] [] - 17: CSS_RULE@310..333 + 17: CSS_QUALIFIED_RULE@310..333 0: CSS_SELECTOR_LIST@310..331 0: CSS_COMPOUND_SELECTOR@310..331 0: (empty) @@ -2080,7 +2080,7 @@ CssRoot { 0: L_CURLY@331..332 "{" [] [] 1: CSS_DECLARATION_LIST@332..332 2: R_CURLY@332..333 "}" [] [] - 18: CSS_RULE@333..364 + 18: CSS_QUALIFIED_RULE@333..364 0: CSS_SELECTOR_LIST@333..362 0: CSS_COMPOUND_SELECTOR@333..362 0: (empty) @@ -2106,7 +2106,7 @@ CssRoot { 0: L_CURLY@362..363 "{" [] [] 1: CSS_DECLARATION_LIST@363..363 2: R_CURLY@363..364 "}" [] [] - 19: CSS_RULE@364..393 + 19: CSS_QUALIFIED_RULE@364..393 0: CSS_SELECTOR_LIST@364..391 0: CSS_COMPOUND_SELECTOR@364..391 0: (empty) @@ -2129,7 +2129,7 @@ CssRoot { 0: L_CURLY@391..392 "{" [] [] 1: CSS_DECLARATION_LIST@392..392 2: R_CURLY@392..393 "}" [] [] - 20: CSS_RULE@393..428 + 20: CSS_QUALIFIED_RULE@393..428 0: CSS_SELECTOR_LIST@393..426 0: CSS_COMPOUND_SELECTOR@393..426 0: (empty) @@ -2152,7 +2152,7 @@ CssRoot { 0: L_CURLY@426..427 "{" [] [] 1: CSS_DECLARATION_LIST@427..427 2: R_CURLY@427..428 "}" [] [] - 21: CSS_RULE@428..469 + 21: CSS_QUALIFIED_RULE@428..469 0: CSS_SELECTOR_LIST@428..467 0: CSS_COMPOUND_SELECTOR@428..467 0: (empty) @@ -2175,7 +2175,7 @@ CssRoot { 0: L_CURLY@467..468 "{" [] [] 1: CSS_DECLARATION_LIST@468..468 2: R_CURLY@468..469 "}" [] [] - 22: CSS_RULE@469..485 + 22: CSS_QUALIFIED_RULE@469..485 0: CSS_SELECTOR_LIST@469..483 0: CSS_COMPOUND_SELECTOR@469..483 0: (empty) @@ -2193,7 +2193,7 @@ CssRoot { 0: L_CURLY@483..484 "{" [] [] 1: CSS_DECLARATION_LIST@484..484 2: R_CURLY@484..485 "}" [] [] - 23: CSS_RULE@485..505 + 23: CSS_QUALIFIED_RULE@485..505 0: CSS_SELECTOR_LIST@485..503 0: CSS_COMPOUND_SELECTOR@485..503 0: (empty) @@ -2216,7 +2216,7 @@ CssRoot { 0: L_CURLY@503..504 "{" [] [] 1: CSS_DECLARATION_LIST@504..504 2: R_CURLY@504..505 "}" [] [] - 24: CSS_RULE@505..526 + 24: CSS_QUALIFIED_RULE@505..526 0: CSS_SELECTOR_LIST@505..524 0: CSS_COMPOUND_SELECTOR@505..524 0: (empty) @@ -2242,7 +2242,7 @@ CssRoot { 0: L_CURLY@524..525 "{" [] [] 1: CSS_DECLARATION_LIST@525..525 2: R_CURLY@525..526 "}" [] [] - 25: CSS_RULE@526..541 + 25: CSS_QUALIFIED_RULE@526..541 0: CSS_SELECTOR_LIST@526..539 0: CSS_COMPOUND_SELECTOR@526..539 0: (empty) @@ -2264,7 +2264,7 @@ CssRoot { 0: L_CURLY@539..540 "{" [] [] 1: CSS_DECLARATION_LIST@540..540 2: R_CURLY@540..541 "}" [] [] - 26: CSS_RULE@541..559 + 26: CSS_QUALIFIED_RULE@541..559 0: CSS_SELECTOR_LIST@541..557 0: CSS_COMPOUND_SELECTOR@541..557 0: (empty) @@ -2286,7 +2286,7 @@ CssRoot { 0: L_CURLY@557..558 "{" [] [] 1: CSS_DECLARATION_LIST@558..558 2: R_CURLY@558..559 "}" [] [] - 27: CSS_RULE@559..576 + 27: CSS_QUALIFIED_RULE@559..576 0: CSS_SELECTOR_LIST@559..574 0: CSS_COMPOUND_SELECTOR@559..574 0: (empty) @@ -2309,7 +2309,7 @@ CssRoot { 0: L_CURLY@574..575 "{" [] [] 1: CSS_DECLARATION_LIST@575..575 2: R_CURLY@575..576 "}" [] [] - 28: CSS_RULE@576..614 + 28: CSS_QUALIFIED_RULE@576..614 0: CSS_SELECTOR_LIST@576..612 0: CSS_COMPOUND_SELECTOR@576..612 0: (empty) @@ -2340,7 +2340,7 @@ CssRoot { 0: L_CURLY@612..613 "{" [] [] 1: CSS_DECLARATION_LIST@613..613 2: R_CURLY@613..614 "}" [] [] - 29: CSS_RULE@614..655 + 29: CSS_QUALIFIED_RULE@614..655 0: CSS_SELECTOR_LIST@614..653 0: CSS_COMPOUND_SELECTOR@614..653 0: (empty) @@ -2371,7 +2371,7 @@ CssRoot { 0: L_CURLY@653..654 "{" [] [] 1: CSS_DECLARATION_LIST@654..654 2: R_CURLY@654..655 "}" [] [] - 30: CSS_RULE@655..675 + 30: CSS_QUALIFIED_RULE@655..675 0: CSS_SELECTOR_LIST@655..673 0: CSS_COMPOUND_SELECTOR@655..673 0: (empty) @@ -2397,7 +2397,7 @@ CssRoot { 0: L_CURLY@673..674 "{" [] [] 1: CSS_DECLARATION_LIST@674..674 2: R_CURLY@674..675 "}" [] [] - 31: CSS_RULE@675..695 + 31: CSS_QUALIFIED_RULE@675..695 0: CSS_SELECTOR_LIST@675..693 0: CSS_COMPOUND_SELECTOR@675..693 0: (empty) @@ -2423,7 +2423,7 @@ CssRoot { 0: L_CURLY@693..694 "{" [] [] 1: CSS_DECLARATION_LIST@694..694 2: R_CURLY@694..695 "}" [] [] - 32: CSS_RULE@695..710 + 32: CSS_QUALIFIED_RULE@695..710 0: CSS_SELECTOR_LIST@695..708 0: CSS_COMPOUND_SELECTOR@695..708 0: (empty) @@ -2441,7 +2441,7 @@ CssRoot { 0: L_CURLY@708..709 "{" [] [] 1: CSS_DECLARATION_LIST@709..709 2: R_CURLY@709..710 "}" [] [] - 33: CSS_RULE@710..727 + 33: CSS_QUALIFIED_RULE@710..727 0: CSS_SELECTOR_LIST@710..725 0: CSS_COMPOUND_SELECTOR@710..725 0: (empty) @@ -2459,7 +2459,7 @@ CssRoot { 0: L_CURLY@725..726 "{" [] [] 1: CSS_DECLARATION_LIST@726..726 2: R_CURLY@726..727 "}" [] [] - 34: CSS_RULE@727..747 + 34: CSS_QUALIFIED_RULE@727..747 0: CSS_SELECTOR_LIST@727..745 0: CSS_COMPOUND_SELECTOR@727..745 0: (empty) @@ -2477,7 +2477,7 @@ CssRoot { 0: L_CURLY@745..746 "{" [] [] 1: CSS_DECLARATION_LIST@746..746 2: R_CURLY@746..747 "}" [] [] - 35: CSS_RULE@747..759 + 35: CSS_QUALIFIED_RULE@747..759 0: CSS_SELECTOR_LIST@747..757 0: CSS_COMPOUND_SELECTOR@747..757 0: (empty) @@ -2500,7 +2500,7 @@ CssRoot { 0: L_CURLY@757..758 "{" [] [] 1: CSS_DECLARATION_LIST@758..758 2: R_CURLY@758..759 "}" [] [] - 36: CSS_RULE@759..771 + 36: CSS_QUALIFIED_RULE@759..771 0: CSS_SELECTOR_LIST@759..769 0: CSS_COMPOUND_SELECTOR@759..769 0: (empty) @@ -2523,7 +2523,7 @@ CssRoot { 0: L_CURLY@769..770 "{" [] [] 1: CSS_DECLARATION_LIST@770..770 2: R_CURLY@770..771 "}" [] [] - 37: CSS_RULE@771..783 + 37: CSS_QUALIFIED_RULE@771..783 0: CSS_SELECTOR_LIST@771..781 0: CSS_COMPOUND_SELECTOR@771..781 0: (empty) @@ -2546,7 +2546,7 @@ CssRoot { 0: L_CURLY@781..782 "{" [] [] 1: CSS_DECLARATION_LIST@782..782 2: R_CURLY@782..783 "}" [] [] - 38: CSS_RULE@783..813 + 38: CSS_QUALIFIED_RULE@783..813 0: CSS_SELECTOR_LIST@783..811 0: CSS_COMPOUND_SELECTOR@783..811 0: (empty) @@ -2569,7 +2569,7 @@ CssRoot { 0: L_CURLY@811..812 "{" [] [] 1: CSS_DECLARATION_LIST@812..812 2: R_CURLY@812..813 "}" [] [] - 39: CSS_RULE@813..827 + 39: CSS_QUALIFIED_RULE@813..827 0: CSS_SELECTOR_LIST@813..824 0: CSS_COMPOUND_SELECTOR@813..824 0: (empty) @@ -2592,7 +2592,7 @@ CssRoot { 0: L_CURLY@824..826 "{" [] [Whitespace(" ")] 1: CSS_DECLARATION_LIST@826..826 2: R_CURLY@826..827 "}" [] [] - 40: CSS_RULE@827..847 + 40: CSS_QUALIFIED_RULE@827..847 0: CSS_SELECTOR_LIST@827..845 0: CSS_COMPOUND_SELECTOR@827..845 0: (empty) @@ -2618,7 +2618,7 @@ CssRoot { 0: L_CURLY@845..846 "{" [] [] 1: CSS_DECLARATION_LIST@846..846 2: R_CURLY@846..847 "}" [] [] - 41: CSS_RULE@847..869 + 41: CSS_QUALIFIED_RULE@847..869 0: CSS_SELECTOR_LIST@847..867 0: CSS_COMPOUND_SELECTOR@847..867 0: (empty) @@ -2645,7 +2645,7 @@ CssRoot { 0: L_CURLY@867..868 "{" [] [] 1: CSS_DECLARATION_LIST@868..868 2: R_CURLY@868..869 "}" [] [] - 42: CSS_RULE@869..886 + 42: CSS_QUALIFIED_RULE@869..886 0: CSS_SELECTOR_LIST@869..884 0: CSS_COMPOUND_SELECTOR@869..884 0: (empty) @@ -2672,7 +2672,7 @@ CssRoot { 0: L_CURLY@884..885 "{" [] [] 1: CSS_DECLARATION_LIST@885..885 2: R_CURLY@885..886 "}" [] [] - 43: CSS_RULE@886..897 + 43: CSS_QUALIFIED_RULE@886..897 0: CSS_SELECTOR_LIST@886..895 0: CSS_COMPOUND_SELECTOR@886..895 0: (empty) @@ -2693,7 +2693,7 @@ CssRoot { 0: L_CURLY@895..896 "{" [] [] 1: CSS_DECLARATION_LIST@896..896 2: R_CURLY@896..897 "}" [] [] - 44: CSS_RULE@897..914 + 44: CSS_QUALIFIED_RULE@897..914 0: CSS_SELECTOR_LIST@897..912 0: CSS_COMPOUND_SELECTOR@897..912 0: (empty) @@ -2714,7 +2714,7 @@ CssRoot { 0: L_CURLY@912..913 "{" [] [] 1: CSS_DECLARATION_LIST@913..913 2: R_CURLY@913..914 "}" [] [] - 45: CSS_RULE@914..924 + 45: CSS_QUALIFIED_RULE@914..924 0: CSS_SELECTOR_LIST@914..922 0: CSS_COMPOUND_SELECTOR@914..922 0: (empty) @@ -2734,7 +2734,7 @@ CssRoot { 0: L_CURLY@922..923 "{" [] [] 1: CSS_DECLARATION_LIST@923..923 2: R_CURLY@923..924 "}" [] [] - 46: CSS_RULE@924..936 + 46: CSS_QUALIFIED_RULE@924..936 0: CSS_SELECTOR_LIST@924..934 0: CSS_COMPOUND_SELECTOR@924..934 0: (empty) @@ -2754,7 +2754,7 @@ CssRoot { 0: L_CURLY@934..935 "{" [] [] 1: CSS_DECLARATION_LIST@935..935 2: R_CURLY@935..936 "}" [] [] - 47: CSS_RULE@936..952 + 47: CSS_QUALIFIED_RULE@936..952 0: CSS_SELECTOR_LIST@936..950 0: CSS_COMPOUND_SELECTOR@936..950 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/class.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/class.css.snap index 2858c6094b0e..eedeba0a5e8a 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/class.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/class.css.snap @@ -19,7 +19,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -77,7 +77,7 @@ CssRoot { 0: CSS_ROOT@0..34 0: (empty) 1: CSS_RULE_LIST@0..33 - 0: CSS_RULE@0..33 + 0: CSS_QUALIFIED_RULE@0..33 0: CSS_SELECTOR_LIST@0..29 0: CSS_COMPOUND_SELECTOR@0..9 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/complex.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/complex.css.snap index baedcddccf6c..038989b996c5 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/complex.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/complex.css.snap @@ -53,7 +53,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -89,7 +89,7 @@ CssRoot { r_curly_token: R_CURLY@13..14 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssComplexSelector { @@ -138,7 +138,7 @@ CssRoot { r_curly_token: R_CURLY@36..39 "}" [Newline("\n"), Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -174,7 +174,7 @@ CssRoot { r_curly_token: R_CURLY@54..55 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssComplexSelector { @@ -223,7 +223,7 @@ CssRoot { r_curly_token: R_CURLY@77..80 "}" [Newline("\n"), Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -259,7 +259,7 @@ CssRoot { r_curly_token: R_CURLY@95..96 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssComplexSelector { @@ -308,7 +308,7 @@ CssRoot { r_curly_token: R_CURLY@118..121 "}" [Newline("\n"), Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -344,7 +344,7 @@ CssRoot { r_curly_token: R_CURLY@137..138 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssComplexSelector { @@ -393,7 +393,7 @@ CssRoot { r_curly_token: R_CURLY@162..165 "}" [Newline("\n"), Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssComplexSelector { @@ -477,7 +477,7 @@ CssRoot { r_curly_token: R_CURLY@209..212 "}" [Newline("\n"), Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -513,7 +513,7 @@ CssRoot { r_curly_token: R_CURLY@225..226 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssComplexSelector { @@ -562,7 +562,7 @@ CssRoot { r_curly_token: R_CURLY@246..249 "}" [Newline("\n"), Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssComplexSelector { @@ -663,7 +663,7 @@ CssRoot { 0: CSS_ROOT@0..299 0: (empty) 1: CSS_RULE_LIST@0..298 - 0: CSS_RULE@0..14 + 0: CSS_QUALIFIED_RULE@0..14 0: CSS_SELECTOR_LIST@0..12 0: CSS_COMPLEX_SELECTOR@0..12 0: CSS_COMPOUND_SELECTOR@0..5 @@ -687,7 +687,7 @@ CssRoot { 0: L_CURLY@12..13 "{" [] [] 1: CSS_DECLARATION_LIST@13..13 2: R_CURLY@13..14 "}" [] [] - 1: CSS_RULE@14..39 + 1: CSS_QUALIFIED_RULE@14..39 0: CSS_SELECTOR_LIST@14..35 0: CSS_COMPLEX_SELECTOR@14..35 0: CSS_COMPLEX_SELECTOR@14..29 @@ -720,7 +720,7 @@ CssRoot { 0: L_CURLY@35..36 "{" [] [] 1: CSS_DECLARATION_LIST@36..36 2: R_CURLY@36..39 "}" [Newline("\n"), Newline("\n")] [] - 2: CSS_RULE@39..55 + 2: CSS_QUALIFIED_RULE@39..55 0: CSS_SELECTOR_LIST@39..53 0: CSS_COMPLEX_SELECTOR@39..53 0: CSS_COMPOUND_SELECTOR@39..46 @@ -744,7 +744,7 @@ CssRoot { 0: L_CURLY@53..54 "{" [] [] 1: CSS_DECLARATION_LIST@54..54 2: R_CURLY@54..55 "}" [] [] - 3: CSS_RULE@55..80 + 3: CSS_QUALIFIED_RULE@55..80 0: CSS_SELECTOR_LIST@55..76 0: CSS_COMPLEX_SELECTOR@55..76 0: CSS_COMPLEX_SELECTOR@55..70 @@ -777,7 +777,7 @@ CssRoot { 0: L_CURLY@76..77 "{" [] [] 1: CSS_DECLARATION_LIST@77..77 2: R_CURLY@77..80 "}" [Newline("\n"), Newline("\n")] [] - 4: CSS_RULE@80..96 + 4: CSS_QUALIFIED_RULE@80..96 0: CSS_SELECTOR_LIST@80..94 0: CSS_COMPLEX_SELECTOR@80..94 0: CSS_COMPOUND_SELECTOR@80..87 @@ -801,7 +801,7 @@ CssRoot { 0: L_CURLY@94..95 "{" [] [] 1: CSS_DECLARATION_LIST@95..95 2: R_CURLY@95..96 "}" [] [] - 5: CSS_RULE@96..121 + 5: CSS_QUALIFIED_RULE@96..121 0: CSS_SELECTOR_LIST@96..117 0: CSS_COMPLEX_SELECTOR@96..117 0: CSS_COMPLEX_SELECTOR@96..111 @@ -834,7 +834,7 @@ CssRoot { 0: L_CURLY@117..118 "{" [] [] 1: CSS_DECLARATION_LIST@118..118 2: R_CURLY@118..121 "}" [Newline("\n"), Newline("\n")] [] - 6: CSS_RULE@121..138 + 6: CSS_QUALIFIED_RULE@121..138 0: CSS_SELECTOR_LIST@121..136 0: CSS_COMPLEX_SELECTOR@121..136 0: CSS_COMPOUND_SELECTOR@121..128 @@ -858,7 +858,7 @@ CssRoot { 0: L_CURLY@136..137 "{" [] [] 1: CSS_DECLARATION_LIST@137..137 2: R_CURLY@137..138 "}" [] [] - 7: CSS_RULE@138..165 + 7: CSS_QUALIFIED_RULE@138..165 0: CSS_SELECTOR_LIST@138..161 0: CSS_COMPLEX_SELECTOR@138..161 0: CSS_COMPLEX_SELECTOR@138..154 @@ -891,7 +891,7 @@ CssRoot { 0: L_CURLY@161..162 "{" [] [] 1: CSS_DECLARATION_LIST@162..162 2: R_CURLY@162..165 "}" [Newline("\n"), Newline("\n")] [] - 8: CSS_RULE@165..212 + 8: CSS_QUALIFIED_RULE@165..212 0: CSS_SELECTOR_LIST@165..208 0: CSS_COMPLEX_SELECTOR@165..208 0: CSS_COMPLEX_SELECTOR@165..198 @@ -947,7 +947,7 @@ CssRoot { 0: L_CURLY@208..209 "{" [] [] 1: CSS_DECLARATION_LIST@209..209 2: R_CURLY@209..212 "}" [Newline("\n"), Newline("\n")] [] - 9: CSS_RULE@212..226 + 9: CSS_QUALIFIED_RULE@212..226 0: CSS_SELECTOR_LIST@212..224 0: CSS_COMPLEX_SELECTOR@212..224 0: CSS_COMPOUND_SELECTOR@212..218 @@ -971,7 +971,7 @@ CssRoot { 0: L_CURLY@224..225 "{" [] [] 1: CSS_DECLARATION_LIST@225..225 2: R_CURLY@225..226 "}" [] [] - 10: CSS_RULE@226..249 + 10: CSS_QUALIFIED_RULE@226..249 0: CSS_SELECTOR_LIST@226..245 0: CSS_COMPLEX_SELECTOR@226..245 0: CSS_COMPLEX_SELECTOR@226..239 @@ -1004,7 +1004,7 @@ CssRoot { 0: L_CURLY@245..246 "{" [] [] 1: CSS_DECLARATION_LIST@246..246 2: R_CURLY@246..249 "}" [Newline("\n"), Newline("\n")] [] - 11: CSS_RULE@249..298 + 11: CSS_QUALIFIED_RULE@249..298 0: CSS_SELECTOR_LIST@249..294 0: CSS_COMPLEX_SELECTOR@249..294 0: CSS_COMPLEX_SELECTOR@249..279 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/id.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/id.css.snap index 7ba7c13efed3..b323e325aa89 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/id.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/id.css.snap @@ -19,7 +19,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -77,7 +77,7 @@ CssRoot { 0: CSS_ROOT@0..34 0: (empty) 1: CSS_RULE_LIST@0..33 - 0: CSS_RULE@0..33 + 0: CSS_QUALIFIED_RULE@0..33 0: CSS_SELECTOR_LIST@0..29 0: CSS_COMPOUND_SELECTOR@0..9 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_an_plus_b.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_an_plus_b.css.snap index d51a83b43e8a..5288bac75d8f 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_an_plus_b.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_an_plus_b.css.snap @@ -124,7 +124,7 @@ tr:nth-child(even of :not([hidden])) {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -163,7 +163,7 @@ CssRoot { r_curly_token: R_CURLY@18..19 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -202,7 +202,7 @@ CssRoot { r_curly_token: R_CURLY@39..40 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -241,7 +241,7 @@ CssRoot { r_curly_token: R_CURLY@61..62 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -280,7 +280,7 @@ CssRoot { r_curly_token: R_CURLY@82..83 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -319,7 +319,7 @@ CssRoot { r_curly_token: R_CURLY@102..103 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -358,7 +358,7 @@ CssRoot { r_curly_token: R_CURLY@123..124 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -397,7 +397,7 @@ CssRoot { r_curly_token: R_CURLY@144..145 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -436,7 +436,7 @@ CssRoot { r_curly_token: R_CURLY@166..167 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -475,7 +475,7 @@ CssRoot { r_curly_token: R_CURLY@187..188 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -514,7 +514,7 @@ CssRoot { r_curly_token: R_CURLY@209..210 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -553,7 +553,7 @@ CssRoot { r_curly_token: R_CURLY@232..233 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -592,7 +592,7 @@ CssRoot { r_curly_token: R_CURLY@254..255 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -631,7 +631,7 @@ CssRoot { r_curly_token: R_CURLY@275..276 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -670,7 +670,7 @@ CssRoot { r_curly_token: R_CURLY@297..298 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -709,7 +709,7 @@ CssRoot { r_curly_token: R_CURLY@320..321 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -748,7 +748,7 @@ CssRoot { r_curly_token: R_CURLY@341..342 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -787,7 +787,7 @@ CssRoot { r_curly_token: R_CURLY@363..364 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -826,7 +826,7 @@ CssRoot { r_curly_token: R_CURLY@386..387 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -865,7 +865,7 @@ CssRoot { r_curly_token: R_CURLY@408..409 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -904,7 +904,7 @@ CssRoot { r_curly_token: R_CURLY@429..430 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -943,7 +943,7 @@ CssRoot { r_curly_token: R_CURLY@451..452 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -982,7 +982,7 @@ CssRoot { r_curly_token: R_CURLY@473..474 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1021,7 +1021,7 @@ CssRoot { r_curly_token: R_CURLY@496..497 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1058,7 +1058,7 @@ CssRoot { r_curly_token: R_CURLY@515..516 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1095,7 +1095,7 @@ CssRoot { r_curly_token: R_CURLY@535..536 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1132,7 +1132,7 @@ CssRoot { r_curly_token: R_CURLY@556..557 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1169,7 +1169,7 @@ CssRoot { r_curly_token: R_CURLY@576..577 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1206,7 +1206,7 @@ CssRoot { r_curly_token: R_CURLY@595..596 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1243,7 +1243,7 @@ CssRoot { r_curly_token: R_CURLY@615..616 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1280,7 +1280,7 @@ CssRoot { r_curly_token: R_CURLY@635..636 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1317,7 +1317,7 @@ CssRoot { r_curly_token: R_CURLY@656..657 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1354,7 +1354,7 @@ CssRoot { r_curly_token: R_CURLY@676..677 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1391,7 +1391,7 @@ CssRoot { r_curly_token: R_CURLY@697..698 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1428,7 +1428,7 @@ CssRoot { r_curly_token: R_CURLY@719..720 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1465,7 +1465,7 @@ CssRoot { r_curly_token: R_CURLY@740..741 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1502,7 +1502,7 @@ CssRoot { r_curly_token: R_CURLY@760..761 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1539,7 +1539,7 @@ CssRoot { r_curly_token: R_CURLY@781..782 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1576,7 +1576,7 @@ CssRoot { r_curly_token: R_CURLY@802..803 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1613,7 +1613,7 @@ CssRoot { r_curly_token: R_CURLY@824..825 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1650,7 +1650,7 @@ CssRoot { r_curly_token: R_CURLY@844..845 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1687,7 +1687,7 @@ CssRoot { r_curly_token: R_CURLY@865..866 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1724,7 +1724,7 @@ CssRoot { r_curly_token: R_CURLY@887..888 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1761,7 +1761,7 @@ CssRoot { r_curly_token: R_CURLY@908..909 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1798,7 +1798,7 @@ CssRoot { r_curly_token: R_CURLY@928..929 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1835,7 +1835,7 @@ CssRoot { r_curly_token: R_CURLY@949..950 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1872,7 +1872,7 @@ CssRoot { r_curly_token: R_CURLY@970..971 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1909,7 +1909,7 @@ CssRoot { r_curly_token: R_CURLY@992..993 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1941,7 +1941,7 @@ CssRoot { r_curly_token: R_CURLY@1009..1010 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1973,7 +1973,7 @@ CssRoot { r_curly_token: R_CURLY@1027..1028 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2005,7 +2005,7 @@ CssRoot { r_curly_token: R_CURLY@1045..1046 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2039,7 +2039,7 @@ CssRoot { r_curly_token: R_CURLY@1063..1064 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2073,7 +2073,7 @@ CssRoot { r_curly_token: R_CURLY@1082..1083 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2107,7 +2107,7 @@ CssRoot { r_curly_token: R_CURLY@1101..1102 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2139,7 +2139,7 @@ CssRoot { r_curly_token: R_CURLY@1118..1119 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2171,7 +2171,7 @@ CssRoot { r_curly_token: R_CURLY@1136..1137 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2203,7 +2203,7 @@ CssRoot { r_curly_token: R_CURLY@1154..1155 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2237,7 +2237,7 @@ CssRoot { r_curly_token: R_CURLY@1172..1173 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2271,7 +2271,7 @@ CssRoot { r_curly_token: R_CURLY@1191..1192 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2305,7 +2305,7 @@ CssRoot { r_curly_token: R_CURLY@1210..1211 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2337,7 +2337,7 @@ CssRoot { r_curly_token: R_CURLY@1227..1228 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2369,7 +2369,7 @@ CssRoot { r_curly_token: R_CURLY@1245..1246 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2401,7 +2401,7 @@ CssRoot { r_curly_token: R_CURLY@1263..1264 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2440,7 +2440,7 @@ CssRoot { r_curly_token: R_CURLY@1295..1296 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2479,7 +2479,7 @@ CssRoot { r_curly_token: R_CURLY@1316..1317 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2518,7 +2518,7 @@ CssRoot { r_curly_token: R_CURLY@1336..1337 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2547,7 +2547,7 @@ CssRoot { r_curly_token: R_CURLY@1356..1357 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2576,7 +2576,7 @@ CssRoot { r_curly_token: R_CURLY@1375..1376 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2605,7 +2605,7 @@ CssRoot { r_curly_token: R_CURLY@1394..1395 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2634,7 +2634,7 @@ CssRoot { r_curly_token: R_CURLY@1414..1415 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2663,7 +2663,7 @@ CssRoot { r_curly_token: R_CURLY@1434..1435 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2692,7 +2692,7 @@ CssRoot { r_curly_token: R_CURLY@1454..1455 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2731,7 +2731,7 @@ CssRoot { r_curly_token: R_CURLY@1507..1508 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2770,7 +2770,7 @@ CssRoot { r_curly_token: R_CURLY@1565..1566 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2809,7 +2809,7 @@ CssRoot { r_curly_token: R_CURLY@1594..1595 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2848,7 +2848,7 @@ CssRoot { r_curly_token: R_CURLY@1628..1629 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2887,7 +2887,7 @@ CssRoot { r_curly_token: R_CURLY@1650..1651 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2926,7 +2926,7 @@ CssRoot { r_curly_token: R_CURLY@1675..1676 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -2965,7 +2965,7 @@ CssRoot { r_curly_token: R_CURLY@1697..1698 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3004,7 +3004,7 @@ CssRoot { r_curly_token: R_CURLY@1724..1725 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3033,7 +3033,7 @@ CssRoot { r_curly_token: R_CURLY@1742..1743 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3072,7 +3072,7 @@ CssRoot { r_curly_token: R_CURLY@1760..1761 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3101,7 +3101,7 @@ CssRoot { r_curly_token: R_CURLY@1782..1783 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3140,7 +3140,7 @@ CssRoot { r_curly_token: R_CURLY@1805..1806 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3177,7 +3177,7 @@ CssRoot { r_curly_token: R_CURLY@1824..1825 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3214,7 +3214,7 @@ CssRoot { r_curly_token: R_CURLY@1842..1843 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3251,7 +3251,7 @@ CssRoot { r_curly_token: R_CURLY@1860..1861 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3288,7 +3288,7 @@ CssRoot { r_curly_token: R_CURLY@1877..1878 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3325,7 +3325,7 @@ CssRoot { r_curly_token: R_CURLY@1895..1896 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3362,7 +3362,7 @@ CssRoot { r_curly_token: R_CURLY@1913..1914 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3399,7 +3399,7 @@ CssRoot { r_curly_token: R_CURLY@1930..1931 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3436,7 +3436,7 @@ CssRoot { r_curly_token: R_CURLY@1948..1949 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3473,7 +3473,7 @@ CssRoot { r_curly_token: R_CURLY@1966..1967 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3526,7 +3526,7 @@ CssRoot { r_curly_token: R_CURLY@1993..1994 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3579,7 +3579,7 @@ CssRoot { r_curly_token: R_CURLY@2025..2026 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3645,7 +3645,7 @@ CssRoot { r_curly_token: R_CURLY@2057..2058 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3711,7 +3711,7 @@ CssRoot { r_curly_token: R_CURLY@2090..2091 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3769,7 +3769,7 @@ CssRoot { r_curly_token: R_CURLY@2126..2127 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -3840,7 +3840,7 @@ CssRoot { r_curly_token: R_CURLY@2166..2167 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -3905,7 +3905,7 @@ CssRoot { 0: CSS_ROOT@0..2195 0: (empty) 1: CSS_RULE_LIST@0..2194 - 0: CSS_RULE@0..19 + 0: CSS_QUALIFIED_RULE@0..19 0: CSS_SELECTOR_LIST@0..17 0: CSS_COMPOUND_SELECTOR@0..17 0: (empty) @@ -3932,7 +3932,7 @@ CssRoot { 0: L_CURLY@17..18 "{" [] [] 1: CSS_DECLARATION_LIST@18..18 2: R_CURLY@18..19 "}" [] [] - 1: CSS_RULE@19..40 + 1: CSS_QUALIFIED_RULE@19..40 0: CSS_SELECTOR_LIST@19..38 0: CSS_COMPOUND_SELECTOR@19..38 0: (empty) @@ -3959,7 +3959,7 @@ CssRoot { 0: L_CURLY@38..39 "{" [] [] 1: CSS_DECLARATION_LIST@39..39 2: R_CURLY@39..40 "}" [] [] - 2: CSS_RULE@40..62 + 2: CSS_QUALIFIED_RULE@40..62 0: CSS_SELECTOR_LIST@40..60 0: CSS_COMPOUND_SELECTOR@40..60 0: (empty) @@ -3986,7 +3986,7 @@ CssRoot { 0: L_CURLY@60..61 "{" [] [] 1: CSS_DECLARATION_LIST@61..61 2: R_CURLY@61..62 "}" [] [] - 3: CSS_RULE@62..83 + 3: CSS_QUALIFIED_RULE@62..83 0: CSS_SELECTOR_LIST@62..81 0: CSS_COMPOUND_SELECTOR@62..81 0: (empty) @@ -4013,7 +4013,7 @@ CssRoot { 0: L_CURLY@81..82 "{" [] [] 1: CSS_DECLARATION_LIST@82..82 2: R_CURLY@82..83 "}" [] [] - 4: CSS_RULE@83..103 + 4: CSS_QUALIFIED_RULE@83..103 0: CSS_SELECTOR_LIST@83..101 0: CSS_COMPOUND_SELECTOR@83..101 0: (empty) @@ -4040,7 +4040,7 @@ CssRoot { 0: L_CURLY@101..102 "{" [] [] 1: CSS_DECLARATION_LIST@102..102 2: R_CURLY@102..103 "}" [] [] - 5: CSS_RULE@103..124 + 5: CSS_QUALIFIED_RULE@103..124 0: CSS_SELECTOR_LIST@103..122 0: CSS_COMPOUND_SELECTOR@103..122 0: (empty) @@ -4067,7 +4067,7 @@ CssRoot { 0: L_CURLY@122..123 "{" [] [] 1: CSS_DECLARATION_LIST@123..123 2: R_CURLY@123..124 "}" [] [] - 6: CSS_RULE@124..145 + 6: CSS_QUALIFIED_RULE@124..145 0: CSS_SELECTOR_LIST@124..143 0: CSS_COMPOUND_SELECTOR@124..143 0: (empty) @@ -4094,7 +4094,7 @@ CssRoot { 0: L_CURLY@143..144 "{" [] [] 1: CSS_DECLARATION_LIST@144..144 2: R_CURLY@144..145 "}" [] [] - 7: CSS_RULE@145..167 + 7: CSS_QUALIFIED_RULE@145..167 0: CSS_SELECTOR_LIST@145..165 0: CSS_COMPOUND_SELECTOR@145..165 0: (empty) @@ -4121,7 +4121,7 @@ CssRoot { 0: L_CURLY@165..166 "{" [] [] 1: CSS_DECLARATION_LIST@166..166 2: R_CURLY@166..167 "}" [] [] - 8: CSS_RULE@167..188 + 8: CSS_QUALIFIED_RULE@167..188 0: CSS_SELECTOR_LIST@167..186 0: CSS_COMPOUND_SELECTOR@167..186 0: (empty) @@ -4148,7 +4148,7 @@ CssRoot { 0: L_CURLY@186..187 "{" [] [] 1: CSS_DECLARATION_LIST@187..187 2: R_CURLY@187..188 "}" [] [] - 9: CSS_RULE@188..210 + 9: CSS_QUALIFIED_RULE@188..210 0: CSS_SELECTOR_LIST@188..208 0: CSS_COMPOUND_SELECTOR@188..208 0: (empty) @@ -4175,7 +4175,7 @@ CssRoot { 0: L_CURLY@208..209 "{" [] [] 1: CSS_DECLARATION_LIST@209..209 2: R_CURLY@209..210 "}" [] [] - 10: CSS_RULE@210..233 + 10: CSS_QUALIFIED_RULE@210..233 0: CSS_SELECTOR_LIST@210..231 0: CSS_COMPOUND_SELECTOR@210..231 0: (empty) @@ -4202,7 +4202,7 @@ CssRoot { 0: L_CURLY@231..232 "{" [] [] 1: CSS_DECLARATION_LIST@232..232 2: R_CURLY@232..233 "}" [] [] - 11: CSS_RULE@233..255 + 11: CSS_QUALIFIED_RULE@233..255 0: CSS_SELECTOR_LIST@233..253 0: CSS_COMPOUND_SELECTOR@233..253 0: (empty) @@ -4229,7 +4229,7 @@ CssRoot { 0: L_CURLY@253..254 "{" [] [] 1: CSS_DECLARATION_LIST@254..254 2: R_CURLY@254..255 "}" [] [] - 12: CSS_RULE@255..276 + 12: CSS_QUALIFIED_RULE@255..276 0: CSS_SELECTOR_LIST@255..274 0: CSS_COMPOUND_SELECTOR@255..274 0: (empty) @@ -4256,7 +4256,7 @@ CssRoot { 0: L_CURLY@274..275 "{" [] [] 1: CSS_DECLARATION_LIST@275..275 2: R_CURLY@275..276 "}" [] [] - 13: CSS_RULE@276..298 + 13: CSS_QUALIFIED_RULE@276..298 0: CSS_SELECTOR_LIST@276..296 0: CSS_COMPOUND_SELECTOR@276..296 0: (empty) @@ -4283,7 +4283,7 @@ CssRoot { 0: L_CURLY@296..297 "{" [] [] 1: CSS_DECLARATION_LIST@297..297 2: R_CURLY@297..298 "}" [] [] - 14: CSS_RULE@298..321 + 14: CSS_QUALIFIED_RULE@298..321 0: CSS_SELECTOR_LIST@298..319 0: CSS_COMPOUND_SELECTOR@298..319 0: (empty) @@ -4310,7 +4310,7 @@ CssRoot { 0: L_CURLY@319..320 "{" [] [] 1: CSS_DECLARATION_LIST@320..320 2: R_CURLY@320..321 "}" [] [] - 15: CSS_RULE@321..342 + 15: CSS_QUALIFIED_RULE@321..342 0: CSS_SELECTOR_LIST@321..340 0: CSS_COMPOUND_SELECTOR@321..340 0: (empty) @@ -4337,7 +4337,7 @@ CssRoot { 0: L_CURLY@340..341 "{" [] [] 1: CSS_DECLARATION_LIST@341..341 2: R_CURLY@341..342 "}" [] [] - 16: CSS_RULE@342..364 + 16: CSS_QUALIFIED_RULE@342..364 0: CSS_SELECTOR_LIST@342..362 0: CSS_COMPOUND_SELECTOR@342..362 0: (empty) @@ -4364,7 +4364,7 @@ CssRoot { 0: L_CURLY@362..363 "{" [] [] 1: CSS_DECLARATION_LIST@363..363 2: R_CURLY@363..364 "}" [] [] - 17: CSS_RULE@364..387 + 17: CSS_QUALIFIED_RULE@364..387 0: CSS_SELECTOR_LIST@364..385 0: CSS_COMPOUND_SELECTOR@364..385 0: (empty) @@ -4391,7 +4391,7 @@ CssRoot { 0: L_CURLY@385..386 "{" [] [] 1: CSS_DECLARATION_LIST@386..386 2: R_CURLY@386..387 "}" [] [] - 18: CSS_RULE@387..409 + 18: CSS_QUALIFIED_RULE@387..409 0: CSS_SELECTOR_LIST@387..407 0: CSS_COMPOUND_SELECTOR@387..407 0: (empty) @@ -4418,7 +4418,7 @@ CssRoot { 0: L_CURLY@407..408 "{" [] [] 1: CSS_DECLARATION_LIST@408..408 2: R_CURLY@408..409 "}" [] [] - 19: CSS_RULE@409..430 + 19: CSS_QUALIFIED_RULE@409..430 0: CSS_SELECTOR_LIST@409..428 0: CSS_COMPOUND_SELECTOR@409..428 0: (empty) @@ -4445,7 +4445,7 @@ CssRoot { 0: L_CURLY@428..429 "{" [] [] 1: CSS_DECLARATION_LIST@429..429 2: R_CURLY@429..430 "}" [] [] - 20: CSS_RULE@430..452 + 20: CSS_QUALIFIED_RULE@430..452 0: CSS_SELECTOR_LIST@430..450 0: CSS_COMPOUND_SELECTOR@430..450 0: (empty) @@ -4472,7 +4472,7 @@ CssRoot { 0: L_CURLY@450..451 "{" [] [] 1: CSS_DECLARATION_LIST@451..451 2: R_CURLY@451..452 "}" [] [] - 21: CSS_RULE@452..474 + 21: CSS_QUALIFIED_RULE@452..474 0: CSS_SELECTOR_LIST@452..472 0: CSS_COMPOUND_SELECTOR@452..472 0: (empty) @@ -4499,7 +4499,7 @@ CssRoot { 0: L_CURLY@472..473 "{" [] [] 1: CSS_DECLARATION_LIST@473..473 2: R_CURLY@473..474 "}" [] [] - 22: CSS_RULE@474..497 + 22: CSS_QUALIFIED_RULE@474..497 0: CSS_SELECTOR_LIST@474..495 0: CSS_COMPOUND_SELECTOR@474..495 0: (empty) @@ -4526,7 +4526,7 @@ CssRoot { 0: L_CURLY@495..496 "{" [] [] 1: CSS_DECLARATION_LIST@496..496 2: R_CURLY@496..497 "}" [] [] - 23: CSS_RULE@497..516 + 23: CSS_QUALIFIED_RULE@497..516 0: CSS_SELECTOR_LIST@497..514 0: CSS_COMPOUND_SELECTOR@497..514 0: (empty) @@ -4552,7 +4552,7 @@ CssRoot { 0: L_CURLY@514..515 "{" [] [] 1: CSS_DECLARATION_LIST@515..515 2: R_CURLY@515..516 "}" [] [] - 24: CSS_RULE@516..536 + 24: CSS_QUALIFIED_RULE@516..536 0: CSS_SELECTOR_LIST@516..534 0: CSS_COMPOUND_SELECTOR@516..534 0: (empty) @@ -4578,7 +4578,7 @@ CssRoot { 0: L_CURLY@534..535 "{" [] [] 1: CSS_DECLARATION_LIST@535..535 2: R_CURLY@535..536 "}" [] [] - 25: CSS_RULE@536..557 + 25: CSS_QUALIFIED_RULE@536..557 0: CSS_SELECTOR_LIST@536..555 0: CSS_COMPOUND_SELECTOR@536..555 0: (empty) @@ -4604,7 +4604,7 @@ CssRoot { 0: L_CURLY@555..556 "{" [] [] 1: CSS_DECLARATION_LIST@556..556 2: R_CURLY@556..557 "}" [] [] - 26: CSS_RULE@557..577 + 26: CSS_QUALIFIED_RULE@557..577 0: CSS_SELECTOR_LIST@557..575 0: CSS_COMPOUND_SELECTOR@557..575 0: (empty) @@ -4630,7 +4630,7 @@ CssRoot { 0: L_CURLY@575..576 "{" [] [] 1: CSS_DECLARATION_LIST@576..576 2: R_CURLY@576..577 "}" [] [] - 27: CSS_RULE@577..596 + 27: CSS_QUALIFIED_RULE@577..596 0: CSS_SELECTOR_LIST@577..594 0: CSS_COMPOUND_SELECTOR@577..594 0: (empty) @@ -4656,7 +4656,7 @@ CssRoot { 0: L_CURLY@594..595 "{" [] [] 1: CSS_DECLARATION_LIST@595..595 2: R_CURLY@595..596 "}" [] [] - 28: CSS_RULE@596..616 + 28: CSS_QUALIFIED_RULE@596..616 0: CSS_SELECTOR_LIST@596..614 0: CSS_COMPOUND_SELECTOR@596..614 0: (empty) @@ -4682,7 +4682,7 @@ CssRoot { 0: L_CURLY@614..615 "{" [] [] 1: CSS_DECLARATION_LIST@615..615 2: R_CURLY@615..616 "}" [] [] - 29: CSS_RULE@616..636 + 29: CSS_QUALIFIED_RULE@616..636 0: CSS_SELECTOR_LIST@616..634 0: CSS_COMPOUND_SELECTOR@616..634 0: (empty) @@ -4708,7 +4708,7 @@ CssRoot { 0: L_CURLY@634..635 "{" [] [] 1: CSS_DECLARATION_LIST@635..635 2: R_CURLY@635..636 "}" [] [] - 30: CSS_RULE@636..657 + 30: CSS_QUALIFIED_RULE@636..657 0: CSS_SELECTOR_LIST@636..655 0: CSS_COMPOUND_SELECTOR@636..655 0: (empty) @@ -4734,7 +4734,7 @@ CssRoot { 0: L_CURLY@655..656 "{" [] [] 1: CSS_DECLARATION_LIST@656..656 2: R_CURLY@656..657 "}" [] [] - 31: CSS_RULE@657..677 + 31: CSS_QUALIFIED_RULE@657..677 0: CSS_SELECTOR_LIST@657..675 0: CSS_COMPOUND_SELECTOR@657..675 0: (empty) @@ -4760,7 +4760,7 @@ CssRoot { 0: L_CURLY@675..676 "{" [] [] 1: CSS_DECLARATION_LIST@676..676 2: R_CURLY@676..677 "}" [] [] - 32: CSS_RULE@677..698 + 32: CSS_QUALIFIED_RULE@677..698 0: CSS_SELECTOR_LIST@677..696 0: CSS_COMPOUND_SELECTOR@677..696 0: (empty) @@ -4786,7 +4786,7 @@ CssRoot { 0: L_CURLY@696..697 "{" [] [] 1: CSS_DECLARATION_LIST@697..697 2: R_CURLY@697..698 "}" [] [] - 33: CSS_RULE@698..720 + 33: CSS_QUALIFIED_RULE@698..720 0: CSS_SELECTOR_LIST@698..718 0: CSS_COMPOUND_SELECTOR@698..718 0: (empty) @@ -4812,7 +4812,7 @@ CssRoot { 0: L_CURLY@718..719 "{" [] [] 1: CSS_DECLARATION_LIST@719..719 2: R_CURLY@719..720 "}" [] [] - 34: CSS_RULE@720..741 + 34: CSS_QUALIFIED_RULE@720..741 0: CSS_SELECTOR_LIST@720..739 0: CSS_COMPOUND_SELECTOR@720..739 0: (empty) @@ -4838,7 +4838,7 @@ CssRoot { 0: L_CURLY@739..740 "{" [] [] 1: CSS_DECLARATION_LIST@740..740 2: R_CURLY@740..741 "}" [] [] - 35: CSS_RULE@741..761 + 35: CSS_QUALIFIED_RULE@741..761 0: CSS_SELECTOR_LIST@741..759 0: CSS_COMPOUND_SELECTOR@741..759 0: (empty) @@ -4864,7 +4864,7 @@ CssRoot { 0: L_CURLY@759..760 "{" [] [] 1: CSS_DECLARATION_LIST@760..760 2: R_CURLY@760..761 "}" [] [] - 36: CSS_RULE@761..782 + 36: CSS_QUALIFIED_RULE@761..782 0: CSS_SELECTOR_LIST@761..780 0: CSS_COMPOUND_SELECTOR@761..780 0: (empty) @@ -4890,7 +4890,7 @@ CssRoot { 0: L_CURLY@780..781 "{" [] [] 1: CSS_DECLARATION_LIST@781..781 2: R_CURLY@781..782 "}" [] [] - 37: CSS_RULE@782..803 + 37: CSS_QUALIFIED_RULE@782..803 0: CSS_SELECTOR_LIST@782..801 0: CSS_COMPOUND_SELECTOR@782..801 0: (empty) @@ -4916,7 +4916,7 @@ CssRoot { 0: L_CURLY@801..802 "{" [] [] 1: CSS_DECLARATION_LIST@802..802 2: R_CURLY@802..803 "}" [] [] - 38: CSS_RULE@803..825 + 38: CSS_QUALIFIED_RULE@803..825 0: CSS_SELECTOR_LIST@803..823 0: CSS_COMPOUND_SELECTOR@803..823 0: (empty) @@ -4942,7 +4942,7 @@ CssRoot { 0: L_CURLY@823..824 "{" [] [] 1: CSS_DECLARATION_LIST@824..824 2: R_CURLY@824..825 "}" [] [] - 39: CSS_RULE@825..845 + 39: CSS_QUALIFIED_RULE@825..845 0: CSS_SELECTOR_LIST@825..843 0: CSS_COMPOUND_SELECTOR@825..843 0: (empty) @@ -4968,7 +4968,7 @@ CssRoot { 0: L_CURLY@843..844 "{" [] [] 1: CSS_DECLARATION_LIST@844..844 2: R_CURLY@844..845 "}" [] [] - 40: CSS_RULE@845..866 + 40: CSS_QUALIFIED_RULE@845..866 0: CSS_SELECTOR_LIST@845..864 0: CSS_COMPOUND_SELECTOR@845..864 0: (empty) @@ -4994,7 +4994,7 @@ CssRoot { 0: L_CURLY@864..865 "{" [] [] 1: CSS_DECLARATION_LIST@865..865 2: R_CURLY@865..866 "}" [] [] - 41: CSS_RULE@866..888 + 41: CSS_QUALIFIED_RULE@866..888 0: CSS_SELECTOR_LIST@866..886 0: CSS_COMPOUND_SELECTOR@866..886 0: (empty) @@ -5020,7 +5020,7 @@ CssRoot { 0: L_CURLY@886..887 "{" [] [] 1: CSS_DECLARATION_LIST@887..887 2: R_CURLY@887..888 "}" [] [] - 42: CSS_RULE@888..909 + 42: CSS_QUALIFIED_RULE@888..909 0: CSS_SELECTOR_LIST@888..907 0: CSS_COMPOUND_SELECTOR@888..907 0: (empty) @@ -5046,7 +5046,7 @@ CssRoot { 0: L_CURLY@907..908 "{" [] [] 1: CSS_DECLARATION_LIST@908..908 2: R_CURLY@908..909 "}" [] [] - 43: CSS_RULE@909..929 + 43: CSS_QUALIFIED_RULE@909..929 0: CSS_SELECTOR_LIST@909..927 0: CSS_COMPOUND_SELECTOR@909..927 0: (empty) @@ -5072,7 +5072,7 @@ CssRoot { 0: L_CURLY@927..928 "{" [] [] 1: CSS_DECLARATION_LIST@928..928 2: R_CURLY@928..929 "}" [] [] - 44: CSS_RULE@929..950 + 44: CSS_QUALIFIED_RULE@929..950 0: CSS_SELECTOR_LIST@929..948 0: CSS_COMPOUND_SELECTOR@929..948 0: (empty) @@ -5098,7 +5098,7 @@ CssRoot { 0: L_CURLY@948..949 "{" [] [] 1: CSS_DECLARATION_LIST@949..949 2: R_CURLY@949..950 "}" [] [] - 45: CSS_RULE@950..971 + 45: CSS_QUALIFIED_RULE@950..971 0: CSS_SELECTOR_LIST@950..969 0: CSS_COMPOUND_SELECTOR@950..969 0: (empty) @@ -5124,7 +5124,7 @@ CssRoot { 0: L_CURLY@969..970 "{" [] [] 1: CSS_DECLARATION_LIST@970..970 2: R_CURLY@970..971 "}" [] [] - 46: CSS_RULE@971..993 + 46: CSS_QUALIFIED_RULE@971..993 0: CSS_SELECTOR_LIST@971..991 0: CSS_COMPOUND_SELECTOR@971..991 0: (empty) @@ -5150,7 +5150,7 @@ CssRoot { 0: L_CURLY@991..992 "{" [] [] 1: CSS_DECLARATION_LIST@992..992 2: R_CURLY@992..993 "}" [] [] - 47: CSS_RULE@993..1010 + 47: CSS_QUALIFIED_RULE@993..1010 0: CSS_SELECTOR_LIST@993..1008 0: CSS_COMPOUND_SELECTOR@993..1008 0: (empty) @@ -5173,7 +5173,7 @@ CssRoot { 0: L_CURLY@1008..1009 "{" [] [] 1: CSS_DECLARATION_LIST@1009..1009 2: R_CURLY@1009..1010 "}" [] [] - 48: CSS_RULE@1010..1028 + 48: CSS_QUALIFIED_RULE@1010..1028 0: CSS_SELECTOR_LIST@1010..1026 0: CSS_COMPOUND_SELECTOR@1010..1026 0: (empty) @@ -5196,7 +5196,7 @@ CssRoot { 0: L_CURLY@1026..1027 "{" [] [] 1: CSS_DECLARATION_LIST@1027..1027 2: R_CURLY@1027..1028 "}" [] [] - 49: CSS_RULE@1028..1046 + 49: CSS_QUALIFIED_RULE@1028..1046 0: CSS_SELECTOR_LIST@1028..1044 0: CSS_COMPOUND_SELECTOR@1028..1044 0: (empty) @@ -5219,7 +5219,7 @@ CssRoot { 0: L_CURLY@1044..1045 "{" [] [] 1: CSS_DECLARATION_LIST@1045..1045 2: R_CURLY@1045..1046 "}" [] [] - 50: CSS_RULE@1046..1064 + 50: CSS_QUALIFIED_RULE@1046..1064 0: CSS_SELECTOR_LIST@1046..1062 0: CSS_COMPOUND_SELECTOR@1046..1062 0: (empty) @@ -5243,7 +5243,7 @@ CssRoot { 0: L_CURLY@1062..1063 "{" [] [] 1: CSS_DECLARATION_LIST@1063..1063 2: R_CURLY@1063..1064 "}" [] [] - 51: CSS_RULE@1064..1083 + 51: CSS_QUALIFIED_RULE@1064..1083 0: CSS_SELECTOR_LIST@1064..1081 0: CSS_COMPOUND_SELECTOR@1064..1081 0: (empty) @@ -5267,7 +5267,7 @@ CssRoot { 0: L_CURLY@1081..1082 "{" [] [] 1: CSS_DECLARATION_LIST@1082..1082 2: R_CURLY@1082..1083 "}" [] [] - 52: CSS_RULE@1083..1102 + 52: CSS_QUALIFIED_RULE@1083..1102 0: CSS_SELECTOR_LIST@1083..1100 0: CSS_COMPOUND_SELECTOR@1083..1100 0: (empty) @@ -5291,7 +5291,7 @@ CssRoot { 0: L_CURLY@1100..1101 "{" [] [] 1: CSS_DECLARATION_LIST@1101..1101 2: R_CURLY@1101..1102 "}" [] [] - 53: CSS_RULE@1102..1119 + 53: CSS_QUALIFIED_RULE@1102..1119 0: CSS_SELECTOR_LIST@1102..1117 0: CSS_COMPOUND_SELECTOR@1102..1117 0: (empty) @@ -5314,7 +5314,7 @@ CssRoot { 0: L_CURLY@1117..1118 "{" [] [] 1: CSS_DECLARATION_LIST@1118..1118 2: R_CURLY@1118..1119 "}" [] [] - 54: CSS_RULE@1119..1137 + 54: CSS_QUALIFIED_RULE@1119..1137 0: CSS_SELECTOR_LIST@1119..1135 0: CSS_COMPOUND_SELECTOR@1119..1135 0: (empty) @@ -5337,7 +5337,7 @@ CssRoot { 0: L_CURLY@1135..1136 "{" [] [] 1: CSS_DECLARATION_LIST@1136..1136 2: R_CURLY@1136..1137 "}" [] [] - 55: CSS_RULE@1137..1155 + 55: CSS_QUALIFIED_RULE@1137..1155 0: CSS_SELECTOR_LIST@1137..1153 0: CSS_COMPOUND_SELECTOR@1137..1153 0: (empty) @@ -5360,7 +5360,7 @@ CssRoot { 0: L_CURLY@1153..1154 "{" [] [] 1: CSS_DECLARATION_LIST@1154..1154 2: R_CURLY@1154..1155 "}" [] [] - 56: CSS_RULE@1155..1173 + 56: CSS_QUALIFIED_RULE@1155..1173 0: CSS_SELECTOR_LIST@1155..1171 0: CSS_COMPOUND_SELECTOR@1155..1171 0: (empty) @@ -5384,7 +5384,7 @@ CssRoot { 0: L_CURLY@1171..1172 "{" [] [] 1: CSS_DECLARATION_LIST@1172..1172 2: R_CURLY@1172..1173 "}" [] [] - 57: CSS_RULE@1173..1192 + 57: CSS_QUALIFIED_RULE@1173..1192 0: CSS_SELECTOR_LIST@1173..1190 0: CSS_COMPOUND_SELECTOR@1173..1190 0: (empty) @@ -5408,7 +5408,7 @@ CssRoot { 0: L_CURLY@1190..1191 "{" [] [] 1: CSS_DECLARATION_LIST@1191..1191 2: R_CURLY@1191..1192 "}" [] [] - 58: CSS_RULE@1192..1211 + 58: CSS_QUALIFIED_RULE@1192..1211 0: CSS_SELECTOR_LIST@1192..1209 0: CSS_COMPOUND_SELECTOR@1192..1209 0: (empty) @@ -5432,7 +5432,7 @@ CssRoot { 0: L_CURLY@1209..1210 "{" [] [] 1: CSS_DECLARATION_LIST@1210..1210 2: R_CURLY@1210..1211 "}" [] [] - 59: CSS_RULE@1211..1228 + 59: CSS_QUALIFIED_RULE@1211..1228 0: CSS_SELECTOR_LIST@1211..1226 0: CSS_COMPOUND_SELECTOR@1211..1226 0: (empty) @@ -5454,7 +5454,7 @@ CssRoot { 0: L_CURLY@1226..1227 "{" [] [] 1: CSS_DECLARATION_LIST@1227..1227 2: R_CURLY@1227..1228 "}" [] [] - 60: CSS_RULE@1228..1246 + 60: CSS_QUALIFIED_RULE@1228..1246 0: CSS_SELECTOR_LIST@1228..1244 0: CSS_COMPOUND_SELECTOR@1228..1244 0: (empty) @@ -5476,7 +5476,7 @@ CssRoot { 0: L_CURLY@1244..1245 "{" [] [] 1: CSS_DECLARATION_LIST@1245..1245 2: R_CURLY@1245..1246 "}" [] [] - 61: CSS_RULE@1246..1264 + 61: CSS_QUALIFIED_RULE@1246..1264 0: CSS_SELECTOR_LIST@1246..1262 0: CSS_COMPOUND_SELECTOR@1246..1262 0: (empty) @@ -5498,7 +5498,7 @@ CssRoot { 0: L_CURLY@1262..1263 "{" [] [] 1: CSS_DECLARATION_LIST@1263..1263 2: R_CURLY@1263..1264 "}" [] [] - 62: CSS_RULE@1264..1296 + 62: CSS_QUALIFIED_RULE@1264..1296 0: CSS_SELECTOR_LIST@1264..1294 0: CSS_COMPOUND_SELECTOR@1264..1294 0: (empty) @@ -5525,7 +5525,7 @@ CssRoot { 0: L_CURLY@1294..1295 "{" [] [] 1: CSS_DECLARATION_LIST@1295..1295 2: R_CURLY@1295..1296 "}" [] [] - 63: CSS_RULE@1296..1317 + 63: CSS_QUALIFIED_RULE@1296..1317 0: CSS_SELECTOR_LIST@1296..1315 0: CSS_COMPOUND_SELECTOR@1296..1315 0: (empty) @@ -5552,7 +5552,7 @@ CssRoot { 0: L_CURLY@1315..1316 "{" [] [] 1: CSS_DECLARATION_LIST@1316..1316 2: R_CURLY@1316..1317 "}" [] [] - 64: CSS_RULE@1317..1337 + 64: CSS_QUALIFIED_RULE@1317..1337 0: CSS_SELECTOR_LIST@1317..1335 0: CSS_COMPOUND_SELECTOR@1317..1335 0: (empty) @@ -5579,7 +5579,7 @@ CssRoot { 0: L_CURLY@1335..1336 "{" [] [] 1: CSS_DECLARATION_LIST@1336..1336 2: R_CURLY@1336..1337 "}" [] [] - 65: CSS_RULE@1337..1357 + 65: CSS_QUALIFIED_RULE@1337..1357 0: CSS_SELECTOR_LIST@1337..1355 0: CSS_COMPOUND_SELECTOR@1337..1355 0: (empty) @@ -5599,7 +5599,7 @@ CssRoot { 0: L_CURLY@1355..1356 "{" [] [] 1: CSS_DECLARATION_LIST@1356..1356 2: R_CURLY@1356..1357 "}" [] [] - 66: CSS_RULE@1357..1376 + 66: CSS_QUALIFIED_RULE@1357..1376 0: CSS_SELECTOR_LIST@1357..1374 0: CSS_COMPOUND_SELECTOR@1357..1374 0: (empty) @@ -5619,7 +5619,7 @@ CssRoot { 0: L_CURLY@1374..1375 "{" [] [] 1: CSS_DECLARATION_LIST@1375..1375 2: R_CURLY@1375..1376 "}" [] [] - 67: CSS_RULE@1376..1395 + 67: CSS_QUALIFIED_RULE@1376..1395 0: CSS_SELECTOR_LIST@1376..1393 0: CSS_COMPOUND_SELECTOR@1376..1393 0: (empty) @@ -5639,7 +5639,7 @@ CssRoot { 0: L_CURLY@1393..1394 "{" [] [] 1: CSS_DECLARATION_LIST@1394..1394 2: R_CURLY@1394..1395 "}" [] [] - 68: CSS_RULE@1395..1415 + 68: CSS_QUALIFIED_RULE@1395..1415 0: CSS_SELECTOR_LIST@1395..1413 0: CSS_COMPOUND_SELECTOR@1395..1413 0: (empty) @@ -5659,7 +5659,7 @@ CssRoot { 0: L_CURLY@1413..1414 "{" [] [] 1: CSS_DECLARATION_LIST@1414..1414 2: R_CURLY@1414..1415 "}" [] [] - 69: CSS_RULE@1415..1435 + 69: CSS_QUALIFIED_RULE@1415..1435 0: CSS_SELECTOR_LIST@1415..1433 0: CSS_COMPOUND_SELECTOR@1415..1433 0: (empty) @@ -5679,7 +5679,7 @@ CssRoot { 0: L_CURLY@1433..1434 "{" [] [] 1: CSS_DECLARATION_LIST@1434..1434 2: R_CURLY@1434..1435 "}" [] [] - 70: CSS_RULE@1435..1455 + 70: CSS_QUALIFIED_RULE@1435..1455 0: CSS_SELECTOR_LIST@1435..1453 0: CSS_COMPOUND_SELECTOR@1435..1453 0: (empty) @@ -5699,7 +5699,7 @@ CssRoot { 0: L_CURLY@1453..1454 "{" [] [] 1: CSS_DECLARATION_LIST@1454..1454 2: R_CURLY@1454..1455 "}" [] [] - 71: CSS_RULE@1455..1508 + 71: CSS_QUALIFIED_RULE@1455..1508 0: CSS_SELECTOR_LIST@1455..1506 0: CSS_COMPOUND_SELECTOR@1455..1506 0: (empty) @@ -5726,7 +5726,7 @@ CssRoot { 0: L_CURLY@1506..1507 "{" [] [] 1: CSS_DECLARATION_LIST@1507..1507 2: R_CURLY@1507..1508 "}" [] [] - 72: CSS_RULE@1508..1566 + 72: CSS_QUALIFIED_RULE@1508..1566 0: CSS_SELECTOR_LIST@1508..1564 0: CSS_COMPOUND_SELECTOR@1508..1564 0: (empty) @@ -5753,7 +5753,7 @@ CssRoot { 0: L_CURLY@1564..1565 "{" [] [] 1: CSS_DECLARATION_LIST@1565..1565 2: R_CURLY@1565..1566 "}" [] [] - 73: CSS_RULE@1566..1595 + 73: CSS_QUALIFIED_RULE@1566..1595 0: CSS_SELECTOR_LIST@1566..1593 0: CSS_COMPOUND_SELECTOR@1566..1593 0: (empty) @@ -5780,7 +5780,7 @@ CssRoot { 0: L_CURLY@1593..1594 "{" [] [] 1: CSS_DECLARATION_LIST@1594..1594 2: R_CURLY@1594..1595 "}" [] [] - 74: CSS_RULE@1595..1629 + 74: CSS_QUALIFIED_RULE@1595..1629 0: CSS_SELECTOR_LIST@1595..1627 0: CSS_COMPOUND_SELECTOR@1595..1627 0: (empty) @@ -5807,7 +5807,7 @@ CssRoot { 0: L_CURLY@1627..1628 "{" [] [] 1: CSS_DECLARATION_LIST@1628..1628 2: R_CURLY@1628..1629 "}" [] [] - 75: CSS_RULE@1629..1651 + 75: CSS_QUALIFIED_RULE@1629..1651 0: CSS_SELECTOR_LIST@1629..1649 0: CSS_COMPOUND_SELECTOR@1629..1649 0: (empty) @@ -5834,7 +5834,7 @@ CssRoot { 0: L_CURLY@1649..1650 "{" [] [] 1: CSS_DECLARATION_LIST@1650..1650 2: R_CURLY@1650..1651 "}" [] [] - 76: CSS_RULE@1651..1676 + 76: CSS_QUALIFIED_RULE@1651..1676 0: CSS_SELECTOR_LIST@1651..1674 0: CSS_COMPOUND_SELECTOR@1651..1674 0: (empty) @@ -5861,7 +5861,7 @@ CssRoot { 0: L_CURLY@1674..1675 "{" [] [] 1: CSS_DECLARATION_LIST@1675..1675 2: R_CURLY@1675..1676 "}" [] [] - 77: CSS_RULE@1676..1698 + 77: CSS_QUALIFIED_RULE@1676..1698 0: CSS_SELECTOR_LIST@1676..1696 0: CSS_COMPOUND_SELECTOR@1676..1696 0: (empty) @@ -5888,7 +5888,7 @@ CssRoot { 0: L_CURLY@1696..1697 "{" [] [] 1: CSS_DECLARATION_LIST@1697..1697 2: R_CURLY@1697..1698 "}" [] [] - 78: CSS_RULE@1698..1725 + 78: CSS_QUALIFIED_RULE@1698..1725 0: CSS_SELECTOR_LIST@1698..1723 0: CSS_COMPOUND_SELECTOR@1698..1723 0: (empty) @@ -5915,7 +5915,7 @@ CssRoot { 0: L_CURLY@1723..1724 "{" [] [] 1: CSS_DECLARATION_LIST@1724..1724 2: R_CURLY@1724..1725 "}" [] [] - 79: CSS_RULE@1725..1743 + 79: CSS_QUALIFIED_RULE@1725..1743 0: CSS_SELECTOR_LIST@1725..1741 0: CSS_COMPOUND_SELECTOR@1725..1741 0: (empty) @@ -5935,7 +5935,7 @@ CssRoot { 0: L_CURLY@1741..1742 "{" [] [] 1: CSS_DECLARATION_LIST@1742..1742 2: R_CURLY@1742..1743 "}" [] [] - 80: CSS_RULE@1743..1761 + 80: CSS_QUALIFIED_RULE@1743..1761 0: CSS_SELECTOR_LIST@1743..1759 0: CSS_COMPOUND_SELECTOR@1743..1759 0: (empty) @@ -5962,7 +5962,7 @@ CssRoot { 0: L_CURLY@1759..1760 "{" [] [] 1: CSS_DECLARATION_LIST@1760..1760 2: R_CURLY@1760..1761 "}" [] [] - 81: CSS_RULE@1761..1783 + 81: CSS_QUALIFIED_RULE@1761..1783 0: CSS_SELECTOR_LIST@1761..1781 0: CSS_COMPOUND_SELECTOR@1761..1781 0: (empty) @@ -5982,7 +5982,7 @@ CssRoot { 0: L_CURLY@1781..1782 "{" [] [] 1: CSS_DECLARATION_LIST@1782..1782 2: R_CURLY@1782..1783 "}" [] [] - 82: CSS_RULE@1783..1806 + 82: CSS_QUALIFIED_RULE@1783..1806 0: CSS_SELECTOR_LIST@1783..1804 0: CSS_COMPOUND_SELECTOR@1783..1804 0: (empty) @@ -6009,7 +6009,7 @@ CssRoot { 0: L_CURLY@1804..1805 "{" [] [] 1: CSS_DECLARATION_LIST@1805..1805 2: R_CURLY@1805..1806 "}" [] [] - 83: CSS_RULE@1806..1825 + 83: CSS_QUALIFIED_RULE@1806..1825 0: CSS_SELECTOR_LIST@1806..1823 0: CSS_COMPOUND_SELECTOR@1806..1823 0: (empty) @@ -6034,7 +6034,7 @@ CssRoot { 0: L_CURLY@1823..1824 "{" [] [] 1: CSS_DECLARATION_LIST@1824..1824 2: R_CURLY@1824..1825 "}" [] [] - 84: CSS_RULE@1825..1843 + 84: CSS_QUALIFIED_RULE@1825..1843 0: CSS_SELECTOR_LIST@1825..1841 0: CSS_COMPOUND_SELECTOR@1825..1841 0: (empty) @@ -6059,7 +6059,7 @@ CssRoot { 0: L_CURLY@1841..1842 "{" [] [] 1: CSS_DECLARATION_LIST@1842..1842 2: R_CURLY@1842..1843 "}" [] [] - 85: CSS_RULE@1843..1861 + 85: CSS_QUALIFIED_RULE@1843..1861 0: CSS_SELECTOR_LIST@1843..1859 0: CSS_COMPOUND_SELECTOR@1843..1859 0: (empty) @@ -6084,7 +6084,7 @@ CssRoot { 0: L_CURLY@1859..1860 "{" [] [] 1: CSS_DECLARATION_LIST@1860..1860 2: R_CURLY@1860..1861 "}" [] [] - 86: CSS_RULE@1861..1878 + 86: CSS_QUALIFIED_RULE@1861..1878 0: CSS_SELECTOR_LIST@1861..1876 0: CSS_COMPOUND_SELECTOR@1861..1876 0: (empty) @@ -6109,7 +6109,7 @@ CssRoot { 0: L_CURLY@1876..1877 "{" [] [] 1: CSS_DECLARATION_LIST@1877..1877 2: R_CURLY@1877..1878 "}" [] [] - 87: CSS_RULE@1878..1896 + 87: CSS_QUALIFIED_RULE@1878..1896 0: CSS_SELECTOR_LIST@1878..1894 0: CSS_COMPOUND_SELECTOR@1878..1894 0: (empty) @@ -6134,7 +6134,7 @@ CssRoot { 0: L_CURLY@1894..1895 "{" [] [] 1: CSS_DECLARATION_LIST@1895..1895 2: R_CURLY@1895..1896 "}" [] [] - 88: CSS_RULE@1896..1914 + 88: CSS_QUALIFIED_RULE@1896..1914 0: CSS_SELECTOR_LIST@1896..1912 0: CSS_COMPOUND_SELECTOR@1896..1912 0: (empty) @@ -6159,7 +6159,7 @@ CssRoot { 0: L_CURLY@1912..1913 "{" [] [] 1: CSS_DECLARATION_LIST@1913..1913 2: R_CURLY@1913..1914 "}" [] [] - 89: CSS_RULE@1914..1931 + 89: CSS_QUALIFIED_RULE@1914..1931 0: CSS_SELECTOR_LIST@1914..1929 0: CSS_COMPOUND_SELECTOR@1914..1929 0: (empty) @@ -6184,7 +6184,7 @@ CssRoot { 0: L_CURLY@1929..1930 "{" [] [] 1: CSS_DECLARATION_LIST@1930..1930 2: R_CURLY@1930..1931 "}" [] [] - 90: CSS_RULE@1931..1949 + 90: CSS_QUALIFIED_RULE@1931..1949 0: CSS_SELECTOR_LIST@1931..1947 0: CSS_COMPOUND_SELECTOR@1931..1947 0: (empty) @@ -6209,7 +6209,7 @@ CssRoot { 0: L_CURLY@1947..1948 "{" [] [] 1: CSS_DECLARATION_LIST@1948..1948 2: R_CURLY@1948..1949 "}" [] [] - 91: CSS_RULE@1949..1967 + 91: CSS_QUALIFIED_RULE@1949..1967 0: CSS_SELECTOR_LIST@1949..1965 0: CSS_COMPOUND_SELECTOR@1949..1965 0: (empty) @@ -6234,7 +6234,7 @@ CssRoot { 0: L_CURLY@1965..1966 "{" [] [] 1: CSS_DECLARATION_LIST@1966..1966 2: R_CURLY@1966..1967 "}" [] [] - 92: CSS_RULE@1967..1994 + 92: CSS_QUALIFIED_RULE@1967..1994 0: CSS_SELECTOR_LIST@1967..1992 0: CSS_COMPOUND_SELECTOR@1967..1992 0: (empty) @@ -6270,7 +6270,7 @@ CssRoot { 0: L_CURLY@1992..1993 "{" [] [] 1: CSS_DECLARATION_LIST@1993..1993 2: R_CURLY@1993..1994 "}" [] [] - 93: CSS_RULE@1994..2026 + 93: CSS_QUALIFIED_RULE@1994..2026 0: CSS_SELECTOR_LIST@1994..2024 0: CSS_COMPOUND_SELECTOR@1994..2024 0: (empty) @@ -6306,7 +6306,7 @@ CssRoot { 0: L_CURLY@2024..2025 "{" [] [] 1: CSS_DECLARATION_LIST@2025..2025 2: R_CURLY@2025..2026 "}" [] [] - 94: CSS_RULE@2026..2058 + 94: CSS_QUALIFIED_RULE@2026..2058 0: CSS_SELECTOR_LIST@2026..2056 0: CSS_COMPOUND_SELECTOR@2026..2056 0: (empty) @@ -6351,7 +6351,7 @@ CssRoot { 0: L_CURLY@2056..2057 "{" [] [] 1: CSS_DECLARATION_LIST@2057..2057 2: R_CURLY@2057..2058 "}" [] [] - 95: CSS_RULE@2058..2091 + 95: CSS_QUALIFIED_RULE@2058..2091 0: CSS_SELECTOR_LIST@2058..2089 0: CSS_COMPOUND_SELECTOR@2058..2089 0: (empty) @@ -6396,7 +6396,7 @@ CssRoot { 0: L_CURLY@2089..2090 "{" [] [] 1: CSS_DECLARATION_LIST@2090..2090 2: R_CURLY@2090..2091 "}" [] [] - 96: CSS_RULE@2091..2127 + 96: CSS_QUALIFIED_RULE@2091..2127 0: CSS_SELECTOR_LIST@2091..2125 0: CSS_COMPOUND_SELECTOR@2091..2125 0: (empty) @@ -6435,7 +6435,7 @@ CssRoot { 0: L_CURLY@2125..2126 "{" [] [] 1: CSS_DECLARATION_LIST@2126..2126 2: R_CURLY@2126..2127 "}" [] [] - 97: CSS_RULE@2127..2167 + 97: CSS_QUALIFIED_RULE@2127..2167 0: CSS_SELECTOR_LIST@2127..2165 0: CSS_COMPOUND_SELECTOR@2127..2165 0: (empty) @@ -6483,7 +6483,7 @@ CssRoot { 0: L_CURLY@2165..2166 "{" [] [] 1: CSS_DECLARATION_LIST@2166..2166 2: R_CURLY@2166..2167 "}" [] [] - 98: CSS_RULE@2167..2194 + 98: CSS_QUALIFIED_RULE@2167..2194 0: CSS_SELECTOR_LIST@2167..2192 0: CSS_COMPLEX_SELECTOR@2167..2192 0: CSS_COMPOUND_SELECTOR@2167..2184 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_any.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_any.css.snap index 976f3bede679..4340549c4afd 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_any.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_any.css.snap @@ -34,7 +34,7 @@ h1:-webkit-any(.h1class, #bar) {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -69,7 +69,7 @@ CssRoot { r_curly_token: R_CURLY@24..25 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -104,7 +104,7 @@ CssRoot { r_curly_token: R_CURLY@47..48 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -183,7 +183,7 @@ CssRoot { r_curly_token: R_CURLY@93..94 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -262,7 +262,7 @@ CssRoot { r_curly_token: R_CURLY@136..137 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -310,7 +310,7 @@ CssRoot { r_curly_token: R_CURLY@166..167 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -358,7 +358,7 @@ CssRoot { r_curly_token: R_CURLY@193..194 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -419,7 +419,7 @@ CssRoot { r_curly_token: R_CURLY@231..232 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -480,7 +480,7 @@ CssRoot { r_curly_token: R_CURLY@266..267 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -670,7 +670,7 @@ CssRoot { r_curly_token: R_CURLY@374..375 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -871,7 +871,7 @@ CssRoot { r_curly_token: R_CURLY@524..525 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -932,7 +932,7 @@ CssRoot { 0: CSS_ROOT@0..554 0: (empty) 1: CSS_RULE_LIST@0..553 - 0: CSS_RULE@0..25 + 0: CSS_QUALIFIED_RULE@0..25 0: CSS_SELECTOR_LIST@0..23 0: CSS_COMPOUND_SELECTOR@0..23 0: (empty) @@ -956,7 +956,7 @@ CssRoot { 0: L_CURLY@23..24 "{" [] [] 1: CSS_DECLARATION_LIST@24..24 2: R_CURLY@24..25 "}" [] [] - 1: CSS_RULE@25..48 + 1: CSS_QUALIFIED_RULE@25..48 0: CSS_SELECTOR_LIST@25..46 0: CSS_COMPOUND_SELECTOR@25..46 0: (empty) @@ -980,7 +980,7 @@ CssRoot { 0: L_CURLY@46..47 "{" [] [] 1: CSS_DECLARATION_LIST@47..47 2: R_CURLY@47..48 "}" [] [] - 2: CSS_RULE@48..94 + 2: CSS_QUALIFIED_RULE@48..94 0: CSS_SELECTOR_LIST@48..92 0: CSS_COMPLEX_SELECTOR@48..92 0: CSS_COMPOUND_SELECTOR@48..83 @@ -1034,7 +1034,7 @@ CssRoot { 0: L_CURLY@92..93 "{" [] [] 1: CSS_DECLARATION_LIST@93..93 2: R_CURLY@93..94 "}" [] [] - 3: CSS_RULE@94..137 + 3: CSS_QUALIFIED_RULE@94..137 0: CSS_SELECTOR_LIST@94..135 0: CSS_COMPLEX_SELECTOR@94..135 0: CSS_COMPOUND_SELECTOR@94..126 @@ -1088,7 +1088,7 @@ CssRoot { 0: L_CURLY@135..136 "{" [] [] 1: CSS_DECLARATION_LIST@136..136 2: R_CURLY@136..137 "}" [] [] - 4: CSS_RULE@137..167 + 4: CSS_QUALIFIED_RULE@137..167 0: CSS_SELECTOR_LIST@137..165 0: CSS_COMPOUND_SELECTOR@137..165 0: (empty) @@ -1121,7 +1121,7 @@ CssRoot { 0: L_CURLY@165..166 "{" [] [] 1: CSS_DECLARATION_LIST@166..166 2: R_CURLY@166..167 "}" [] [] - 5: CSS_RULE@167..194 + 5: CSS_QUALIFIED_RULE@167..194 0: CSS_SELECTOR_LIST@167..192 0: CSS_COMPOUND_SELECTOR@167..192 0: (empty) @@ -1154,7 +1154,7 @@ CssRoot { 0: L_CURLY@192..193 "{" [] [] 1: CSS_DECLARATION_LIST@193..193 2: R_CURLY@193..194 "}" [] [] - 6: CSS_RULE@194..232 + 6: CSS_QUALIFIED_RULE@194..232 0: CSS_SELECTOR_LIST@194..230 0: CSS_COMPOUND_SELECTOR@194..230 0: (empty) @@ -1196,7 +1196,7 @@ CssRoot { 0: L_CURLY@230..231 "{" [] [] 1: CSS_DECLARATION_LIST@231..231 2: R_CURLY@231..232 "}" [] [] - 7: CSS_RULE@232..267 + 7: CSS_QUALIFIED_RULE@232..267 0: CSS_SELECTOR_LIST@232..265 0: CSS_COMPOUND_SELECTOR@232..265 0: (empty) @@ -1238,7 +1238,7 @@ CssRoot { 0: L_CURLY@265..266 "{" [] [] 1: CSS_DECLARATION_LIST@266..266 2: R_CURLY@266..267 "}" [] [] - 8: CSS_RULE@267..375 + 8: CSS_QUALIFIED_RULE@267..375 0: CSS_SELECTOR_LIST@267..373 0: CSS_COMPOUND_SELECTOR@267..284 0: (empty) @@ -1369,7 +1369,7 @@ CssRoot { 0: L_CURLY@373..374 "{" [] [] 1: CSS_DECLARATION_LIST@374..374 2: R_CURLY@374..375 "}" [] [] - 9: CSS_RULE@375..525 + 9: CSS_QUALIFIED_RULE@375..525 0: CSS_SELECTOR_LIST@375..523 0: CSS_COMPLEX_SELECTOR@375..419 0: CSS_COMPOUND_SELECTOR@375..393 @@ -1504,7 +1504,7 @@ CssRoot { 0: L_CURLY@523..524 "{" [] [] 1: CSS_DECLARATION_LIST@524..524 2: R_CURLY@524..525 "}" [] [] - 10: CSS_RULE@525..553 + 10: CSS_QUALIFIED_RULE@525..553 0: CSS_SELECTOR_LIST@525..551 0: CSS_COMPLEX_SELECTOR@525..551 0: CSS_COMPOUND_SELECTOR@525..545 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_basic.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_basic.css.snap index eb0250e26b08..6103a68e1234 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_basic.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_basic.css.snap @@ -35,7 +35,7 @@ a:hOvEr {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -58,7 +58,7 @@ CssRoot { r_curly_token: R_CURLY@7..8 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -81,7 +81,7 @@ CssRoot { r_curly_token: R_CURLY@20..21 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -109,7 +109,7 @@ CssRoot { r_curly_token: R_CURLY@36..37 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -128,7 +128,7 @@ CssRoot { r_curly_token: R_CURLY@51..52 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -156,7 +156,7 @@ CssRoot { r_curly_token: R_CURLY@67..68 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -175,7 +175,7 @@ CssRoot { r_curly_token: R_CURLY@76..77 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -256,7 +256,7 @@ CssRoot { r_curly_token: R_CURLY@121..122 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -311,7 +311,7 @@ CssRoot { r_curly_token: R_CURLY@151..152 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -431,7 +431,7 @@ CssRoot { r_curly_token: R_CURLY@212..213 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -462,7 +462,7 @@ CssRoot { r_curly_token: R_CURLY@257..258 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -501,7 +501,7 @@ CssRoot { r_curly_token: R_CURLY@308..309 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -546,7 +546,7 @@ CssRoot { r_curly_token: R_CURLY@364..365 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -582,7 +582,7 @@ CssRoot { r_curly_token: R_CURLY@375..376 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -605,7 +605,7 @@ CssRoot { r_curly_token: R_CURLY@389..390 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -633,7 +633,7 @@ CssRoot { r_curly_token: R_CURLY@411..412 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -669,7 +669,7 @@ CssRoot { r_curly_token: R_CURLY@430..431 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -714,7 +714,7 @@ CssRoot { r_curly_token: R_CURLY@451..452 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -742,7 +742,7 @@ CssRoot { r_curly_token: R_CURLY@462..463 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -789,7 +789,7 @@ CssRoot { 0: CSS_ROOT@0..490 0: (empty) 1: CSS_RULE_LIST@0..489 - 0: CSS_RULE@0..8 + 0: CSS_QUALIFIED_RULE@0..8 0: CSS_SELECTOR_LIST@0..6 0: CSS_COMPOUND_SELECTOR@0..6 0: (empty) @@ -804,7 +804,7 @@ CssRoot { 0: L_CURLY@6..7 "{" [] [] 1: CSS_DECLARATION_LIST@7..7 2: R_CURLY@7..8 "}" [] [] - 1: CSS_RULE@8..21 + 1: CSS_QUALIFIED_RULE@8..21 0: CSS_SELECTOR_LIST@8..19 0: CSS_COMPOUND_SELECTOR@8..19 0: (empty) @@ -819,7 +819,7 @@ CssRoot { 0: L_CURLY@19..20 "{" [] [] 1: CSS_DECLARATION_LIST@20..20 2: R_CURLY@20..21 "}" [] [] - 2: CSS_RULE@21..37 + 2: CSS_QUALIFIED_RULE@21..37 0: CSS_SELECTOR_LIST@21..35 0: CSS_COMPOUND_SELECTOR@21..35 0: (empty) @@ -837,7 +837,7 @@ CssRoot { 0: L_CURLY@35..36 "{" [] [] 1: CSS_DECLARATION_LIST@36..36 2: R_CURLY@36..37 "}" [] [] - 3: CSS_RULE@37..52 + 3: CSS_QUALIFIED_RULE@37..52 0: CSS_SELECTOR_LIST@37..50 0: CSS_COMPOUND_SELECTOR@37..50 0: (empty) @@ -850,7 +850,7 @@ CssRoot { 0: L_CURLY@50..51 "{" [] [] 1: CSS_DECLARATION_LIST@51..51 2: R_CURLY@51..52 "}" [] [] - 4: CSS_RULE@52..68 + 4: CSS_QUALIFIED_RULE@52..68 0: CSS_SELECTOR_LIST@52..66 0: CSS_COMPOUND_SELECTOR@52..66 0: (empty) @@ -868,7 +868,7 @@ CssRoot { 0: L_CURLY@66..67 "{" [] [] 1: CSS_DECLARATION_LIST@67..67 2: R_CURLY@67..68 "}" [] [] - 5: CSS_RULE@68..77 + 5: CSS_QUALIFIED_RULE@68..77 0: CSS_SELECTOR_LIST@68..75 0: CSS_COMPOUND_SELECTOR@68..75 0: (empty) @@ -881,7 +881,7 @@ CssRoot { 0: L_CURLY@75..76 "{" [] [] 1: CSS_DECLARATION_LIST@76..76 2: R_CURLY@76..77 "}" [] [] - 6: CSS_RULE@77..122 + 6: CSS_QUALIFIED_RULE@77..122 0: CSS_SELECTOR_LIST@77..120 0: CSS_COMPLEX_SELECTOR@77..120 0: CSS_COMPOUND_SELECTOR@77..116 @@ -938,7 +938,7 @@ CssRoot { 0: L_CURLY@120..121 "{" [] [] 1: CSS_DECLARATION_LIST@121..121 2: R_CURLY@121..122 "}" [] [] - 7: CSS_RULE@122..152 + 7: CSS_QUALIFIED_RULE@122..152 0: CSS_SELECTOR_LIST@122..150 0: CSS_COMPOUND_SELECTOR@122..150 0: (empty) @@ -975,7 +975,7 @@ CssRoot { 0: L_CURLY@150..151 "{" [] [] 1: CSS_DECLARATION_LIST@151..151 2: R_CURLY@151..152 "}" [] [] - 8: CSS_RULE@152..213 + 8: CSS_QUALIFIED_RULE@152..213 0: CSS_SELECTOR_LIST@152..211 0: CSS_COMPOUND_SELECTOR@152..211 0: (empty) @@ -1057,7 +1057,7 @@ CssRoot { 0: L_CURLY@211..212 "{" [] [] 1: CSS_DECLARATION_LIST@212..212 2: R_CURLY@212..213 "}" [] [] - 9: CSS_RULE@213..258 + 9: CSS_QUALIFIED_RULE@213..258 0: CSS_SELECTOR_LIST@213..256 0: CSS_COMPOUND_SELECTOR@213..256 0: (empty) @@ -1077,7 +1077,7 @@ CssRoot { 0: L_CURLY@256..257 "{" [] [] 1: CSS_DECLARATION_LIST@257..257 2: R_CURLY@257..258 "}" [] [] - 10: CSS_RULE@258..309 + 10: CSS_QUALIFIED_RULE@258..309 0: CSS_SELECTOR_LIST@258..307 0: CSS_COMPOUND_SELECTOR@258..307 0: (empty) @@ -1102,7 +1102,7 @@ CssRoot { 0: L_CURLY@307..308 "{" [] [] 1: CSS_DECLARATION_LIST@308..308 2: R_CURLY@308..309 "}" [] [] - 11: CSS_RULE@309..365 + 11: CSS_QUALIFIED_RULE@309..365 0: CSS_SELECTOR_LIST@309..363 0: CSS_COMPOUND_SELECTOR@309..363 0: (empty) @@ -1131,7 +1131,7 @@ CssRoot { 0: L_CURLY@363..364 "{" [] [] 1: CSS_DECLARATION_LIST@364..364 2: R_CURLY@364..365 "}" [] [] - 12: CSS_RULE@365..376 + 12: CSS_QUALIFIED_RULE@365..376 0: CSS_SELECTOR_LIST@365..374 0: CSS_COMPOUND_SELECTOR@365..374 0: (empty) @@ -1156,7 +1156,7 @@ CssRoot { 0: L_CURLY@374..375 "{" [] [] 1: CSS_DECLARATION_LIST@375..375 2: R_CURLY@375..376 "}" [] [] - 13: CSS_RULE@376..390 + 13: CSS_QUALIFIED_RULE@376..390 0: CSS_SELECTOR_LIST@376..388 0: CSS_COMPOUND_SELECTOR@376..388 0: (empty) @@ -1171,7 +1171,7 @@ CssRoot { 0: L_CURLY@388..389 "{" [] [] 1: CSS_DECLARATION_LIST@389..389 2: R_CURLY@389..390 "}" [] [] - 14: CSS_RULE@390..412 + 14: CSS_QUALIFIED_RULE@390..412 0: CSS_SELECTOR_LIST@390..410 0: CSS_COMPOUND_SELECTOR@390..410 0: (empty) @@ -1189,7 +1189,7 @@ CssRoot { 0: L_CURLY@410..411 "{" [] [] 1: CSS_DECLARATION_LIST@411..411 2: R_CURLY@411..412 "}" [] [] - 15: CSS_RULE@412..431 + 15: CSS_QUALIFIED_RULE@412..431 0: CSS_SELECTOR_LIST@412..429 0: CSS_COMPOUND_SELECTOR@412..429 0: (empty) @@ -1212,7 +1212,7 @@ CssRoot { 0: L_CURLY@429..430 "{" [] [] 1: CSS_DECLARATION_LIST@430..430 2: R_CURLY@430..431 "}" [] [] - 16: CSS_RULE@431..452 + 16: CSS_QUALIFIED_RULE@431..452 0: CSS_SELECTOR_LIST@431..450 0: CSS_COMPLEX_SELECTOR@431..450 0: CSS_COMPOUND_SELECTOR@431..435 @@ -1243,7 +1243,7 @@ CssRoot { 0: L_CURLY@450..451 "{" [] [] 1: CSS_DECLARATION_LIST@451..451 2: R_CURLY@451..452 "}" [] [] - 17: CSS_RULE@452..463 + 17: CSS_QUALIFIED_RULE@452..463 0: CSS_SELECTOR_LIST@452..461 0: CSS_COMPOUND_SELECTOR@452..461 0: (empty) @@ -1261,7 +1261,7 @@ CssRoot { 0: L_CURLY@461..462 "{" [] [] 1: CSS_DECLARATION_LIST@462..462 2: R_CURLY@462..463 "}" [] [] - 18: CSS_RULE@463..489 + 18: CSS_QUALIFIED_RULE@463..489 0: CSS_SELECTOR_LIST@463..487 0: CSS_COMPLEX_SELECTOR@463..487 0: CSS_COMPOUND_SELECTOR@463..484 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_current.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_current.css.snap index 8c29e316d43c..53a1fca06d7f 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_current.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_current.css.snap @@ -18,7 +18,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -86,7 +86,7 @@ CssRoot { r_curly_token: R_CURLY@25..26 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -180,7 +180,7 @@ CssRoot { 0: CSS_ROOT@0..59 0: (empty) 1: CSS_RULE_LIST@0..58 - 0: CSS_RULE@0..26 + 0: CSS_QUALIFIED_RULE@0..26 0: CSS_SELECTOR_LIST@0..24 0: CSS_COMPOUND_SELECTOR@0..24 0: (empty) @@ -228,7 +228,7 @@ CssRoot { 0: L_CURLY@24..25 "{" [] [] 1: CSS_DECLARATION_LIST@25..25 2: R_CURLY@25..26 "}" [] [] - 1: CSS_RULE@26..58 + 1: CSS_QUALIFIED_RULE@26..58 0: CSS_SELECTOR_LIST@26..56 0: CSS_COMPLEX_SELECTOR@26..56 0: CSS_COMPOUND_SELECTOR@26..50 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_dir.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_dir.css.snap index 58e7b4269478..6e432d2675d0 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_dir.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_dir.css.snap @@ -22,7 +22,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -48,7 +48,7 @@ CssRoot { r_curly_token: R_CURLY@11..12 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -74,7 +74,7 @@ CssRoot { r_curly_token: R_CURLY@30..31 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -100,7 +100,7 @@ CssRoot { r_curly_token: R_CURLY@43..44 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -126,7 +126,7 @@ CssRoot { r_curly_token: R_CURLY@62..63 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -152,7 +152,7 @@ CssRoot { r_curly_token: R_CURLY@81..82 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -204,7 +204,7 @@ CssRoot { 0: CSS_ROOT@0..101 0: (empty) 1: CSS_RULE_LIST@0..100 - 0: CSS_RULE@0..12 + 0: CSS_QUALIFIED_RULE@0..12 0: CSS_SELECTOR_LIST@0..10 0: CSS_COMPOUND_SELECTOR@0..10 0: (empty) @@ -222,7 +222,7 @@ CssRoot { 0: L_CURLY@10..11 "{" [] [] 1: CSS_DECLARATION_LIST@11..11 2: R_CURLY@11..12 "}" [] [] - 1: CSS_RULE@12..31 + 1: CSS_QUALIFIED_RULE@12..31 0: CSS_SELECTOR_LIST@12..29 0: CSS_COMPOUND_SELECTOR@12..29 0: (empty) @@ -240,7 +240,7 @@ CssRoot { 0: L_CURLY@29..30 "{" [] [] 1: CSS_DECLARATION_LIST@30..30 2: R_CURLY@30..31 "}" [] [] - 2: CSS_RULE@31..44 + 2: CSS_QUALIFIED_RULE@31..44 0: CSS_SELECTOR_LIST@31..42 0: CSS_COMPOUND_SELECTOR@31..42 0: (empty) @@ -258,7 +258,7 @@ CssRoot { 0: L_CURLY@42..43 "{" [] [] 1: CSS_DECLARATION_LIST@43..43 2: R_CURLY@43..44 "}" [] [] - 3: CSS_RULE@44..63 + 3: CSS_QUALIFIED_RULE@44..63 0: CSS_SELECTOR_LIST@44..61 0: CSS_COMPOUND_SELECTOR@44..61 0: (empty) @@ -276,7 +276,7 @@ CssRoot { 0: L_CURLY@61..62 "{" [] [] 1: CSS_DECLARATION_LIST@62..62 2: R_CURLY@62..63 "}" [] [] - 4: CSS_RULE@63..82 + 4: CSS_QUALIFIED_RULE@63..82 0: CSS_SELECTOR_LIST@63..80 0: CSS_COMPOUND_SELECTOR@63..80 0: (empty) @@ -294,7 +294,7 @@ CssRoot { 0: L_CURLY@80..81 "{" [] [] 1: CSS_DECLARATION_LIST@81..81 2: R_CURLY@81..82 "}" [] [] - 5: CSS_RULE@82..100 + 5: CSS_QUALIFIED_RULE@82..100 0: CSS_SELECTOR_LIST@82..98 0: CSS_COMPLEX_SELECTOR@82..98 0: CSS_COMPOUND_SELECTOR@82..92 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_future.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_future.css.snap index 6ca3858ae96a..d07ddebd976b 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_future.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_future.css.snap @@ -18,7 +18,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -86,7 +86,7 @@ CssRoot { r_curly_token: R_CURLY@24..25 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -180,7 +180,7 @@ CssRoot { 0: CSS_ROOT@0..57 0: (empty) 1: CSS_RULE_LIST@0..56 - 0: CSS_RULE@0..25 + 0: CSS_QUALIFIED_RULE@0..25 0: CSS_SELECTOR_LIST@0..23 0: CSS_COMPOUND_SELECTOR@0..23 0: (empty) @@ -228,7 +228,7 @@ CssRoot { 0: L_CURLY@23..24 "{" [] [] 1: CSS_DECLARATION_LIST@24..24 2: R_CURLY@24..25 "}" [] [] - 1: CSS_RULE@25..56 + 1: CSS_QUALIFIED_RULE@25..56 0: CSS_SELECTOR_LIST@25..54 0: CSS_COMPLEX_SELECTOR@25..54 0: CSS_COMPOUND_SELECTOR@25..48 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_has.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_has.css.snap index 64f37593a338..20aeadb610df 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_has.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_has.css.snap @@ -27,7 +27,7 @@ a:has(> img) .div {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -70,7 +70,7 @@ CssRoot { r_curly_token: R_CURLY@14..15 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -113,7 +113,7 @@ CssRoot { r_curly_token: R_CURLY@36..37 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -156,7 +156,7 @@ CssRoot { r_curly_token: R_CURLY@60..61 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -213,7 +213,7 @@ CssRoot { r_curly_token: R_CURLY@98..99 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -256,7 +256,7 @@ CssRoot { r_curly_token: R_CURLY@118..119 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -299,7 +299,7 @@ CssRoot { r_curly_token: R_CURLY@134..135 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -428,7 +428,7 @@ CssRoot { r_curly_token: R_CURLY@179..180 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -542,7 +542,7 @@ CssRoot { r_curly_token: R_CURLY@224..225 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -585,7 +585,7 @@ CssRoot { r_curly_token: R_CURLY@238..239 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -667,7 +667,7 @@ CssRoot { r_curly_token: R_CURLY@281..282 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -736,7 +736,7 @@ CssRoot { 0: CSS_ROOT@0..304 0: (empty) 1: CSS_RULE_LIST@0..303 - 0: CSS_RULE@0..15 + 0: CSS_QUALIFIED_RULE@0..15 0: CSS_SELECTOR_LIST@0..13 0: CSS_COMPOUND_SELECTOR@0..13 0: (empty) @@ -765,7 +765,7 @@ CssRoot { 0: L_CURLY@13..14 "{" [] [] 1: CSS_DECLARATION_LIST@14..14 2: R_CURLY@14..15 "}" [] [] - 1: CSS_RULE@15..37 + 1: CSS_QUALIFIED_RULE@15..37 0: CSS_SELECTOR_LIST@15..35 0: CSS_COMPOUND_SELECTOR@15..35 0: (empty) @@ -794,7 +794,7 @@ CssRoot { 0: L_CURLY@35..36 "{" [] [] 1: CSS_DECLARATION_LIST@36..36 2: R_CURLY@36..37 "}" [] [] - 2: CSS_RULE@37..61 + 2: CSS_QUALIFIED_RULE@37..61 0: CSS_SELECTOR_LIST@37..59 0: CSS_COMPOUND_SELECTOR@37..59 0: (empty) @@ -823,7 +823,7 @@ CssRoot { 0: L_CURLY@59..60 "{" [] [] 1: CSS_DECLARATION_LIST@60..60 2: R_CURLY@60..61 "}" [] [] - 3: CSS_RULE@61..99 + 3: CSS_QUALIFIED_RULE@61..99 0: CSS_SELECTOR_LIST@61..97 0: CSS_COMPOUND_SELECTOR@61..97 0: (empty) @@ -862,7 +862,7 @@ CssRoot { 0: L_CURLY@97..98 "{" [] [] 1: CSS_DECLARATION_LIST@98..98 2: R_CURLY@98..99 "}" [] [] - 4: CSS_RULE@99..119 + 4: CSS_QUALIFIED_RULE@99..119 0: CSS_SELECTOR_LIST@99..117 0: CSS_COMPOUND_SELECTOR@99..117 0: (empty) @@ -891,7 +891,7 @@ CssRoot { 0: L_CURLY@117..118 "{" [] [] 1: CSS_DECLARATION_LIST@118..118 2: R_CURLY@118..119 "}" [] [] - 5: CSS_RULE@119..135 + 5: CSS_QUALIFIED_RULE@119..135 0: CSS_SELECTOR_LIST@119..133 0: CSS_COMPOUND_SELECTOR@119..133 0: (empty) @@ -920,7 +920,7 @@ CssRoot { 0: L_CURLY@133..134 "{" [] [] 1: CSS_DECLARATION_LIST@134..134 2: R_CURLY@134..135 "}" [] [] - 6: CSS_RULE@135..180 + 6: CSS_QUALIFIED_RULE@135..180 0: CSS_SELECTOR_LIST@135..178 0: CSS_COMPOUND_SELECTOR@135..178 0: (empty) @@ -1010,7 +1010,7 @@ CssRoot { 0: L_CURLY@178..179 "{" [] [] 1: CSS_DECLARATION_LIST@179..179 2: R_CURLY@179..180 "}" [] [] - 7: CSS_RULE@180..225 + 7: CSS_QUALIFIED_RULE@180..225 0: CSS_SELECTOR_LIST@180..223 0: CSS_COMPOUND_SELECTOR@180..223 0: (empty) @@ -1090,7 +1090,7 @@ CssRoot { 0: L_CURLY@223..224 "{" [] [] 1: CSS_DECLARATION_LIST@224..224 2: R_CURLY@224..225 "}" [] [] - 8: CSS_RULE@225..239 + 8: CSS_QUALIFIED_RULE@225..239 0: CSS_SELECTOR_LIST@225..237 0: CSS_COMPOUND_SELECTOR@225..237 0: (empty) @@ -1119,7 +1119,7 @@ CssRoot { 0: L_CURLY@237..238 "{" [] [] 1: CSS_DECLARATION_LIST@238..238 2: R_CURLY@238..239 "}" [] [] - 9: CSS_RULE@239..282 + 9: CSS_QUALIFIED_RULE@239..282 0: CSS_SELECTOR_LIST@239..280 0: CSS_COMPLEX_SELECTOR@239..280 0: CSS_COMPOUND_SELECTOR@239..276 @@ -1175,7 +1175,7 @@ CssRoot { 0: L_CURLY@280..281 "{" [] [] 1: CSS_DECLARATION_LIST@281..281 2: R_CURLY@281..282 "}" [] [] - 10: CSS_RULE@282..303 + 10: CSS_QUALIFIED_RULE@282..303 0: CSS_SELECTOR_LIST@282..301 0: CSS_COMPLEX_SELECTOR@282..301 0: CSS_COMPOUND_SELECTOR@282..295 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_host.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_host.css.snap index 45b026c11023..e508381b99c0 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_host.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_host.css.snap @@ -21,7 +21,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -56,7 +56,7 @@ CssRoot { r_curly_token: R_CURLY@32..33 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -91,7 +91,7 @@ CssRoot { r_curly_token: R_CURLY@72..73 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -126,7 +126,7 @@ CssRoot { r_curly_token: R_CURLY@90..91 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -149,7 +149,7 @@ CssRoot { r_curly_token: R_CURLY@99..100 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -210,7 +210,7 @@ CssRoot { 0: CSS_ROOT@0..124 0: (empty) 1: CSS_RULE_LIST@0..123 - 0: CSS_RULE@0..33 + 0: CSS_QUALIFIED_RULE@0..33 0: CSS_SELECTOR_LIST@0..31 0: CSS_COMPOUND_SELECTOR@0..31 0: (empty) @@ -234,7 +234,7 @@ CssRoot { 0: L_CURLY@31..32 "{" [] [] 1: CSS_DECLARATION_LIST@32..32 2: R_CURLY@32..33 "}" [] [] - 1: CSS_RULE@33..73 + 1: CSS_QUALIFIED_RULE@33..73 0: CSS_SELECTOR_LIST@33..71 0: CSS_COMPOUND_SELECTOR@33..71 0: (empty) @@ -258,7 +258,7 @@ CssRoot { 0: L_CURLY@71..72 "{" [] [] 1: CSS_DECLARATION_LIST@72..72 2: R_CURLY@72..73 "}" [] [] - 2: CSS_RULE@73..91 + 2: CSS_QUALIFIED_RULE@73..91 0: CSS_SELECTOR_LIST@73..89 0: CSS_COMPOUND_SELECTOR@73..89 0: (empty) @@ -282,7 +282,7 @@ CssRoot { 0: L_CURLY@89..90 "{" [] [] 1: CSS_DECLARATION_LIST@90..90 2: R_CURLY@90..91 "}" [] [] - 3: CSS_RULE@91..100 + 3: CSS_QUALIFIED_RULE@91..100 0: CSS_SELECTOR_LIST@91..98 0: CSS_COMPOUND_SELECTOR@91..98 0: (empty) @@ -297,7 +297,7 @@ CssRoot { 0: L_CURLY@98..99 "{" [] [] 1: CSS_DECLARATION_LIST@99..99 2: R_CURLY@99..100 "}" [] [] - 4: CSS_RULE@100..123 + 4: CSS_QUALIFIED_RULE@100..123 0: CSS_SELECTOR_LIST@100..121 0: CSS_COMPLEX_SELECTOR@100..121 0: CSS_COMPOUND_SELECTOR@100..115 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_host_context.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_host_context.css.snap index 79d14b2dbbfb..98ba98ddbb59 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_host_context.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_host_context.css.snap @@ -19,7 +19,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -52,7 +52,7 @@ CssRoot { r_curly_token: R_CURLY@19..20 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -85,7 +85,7 @@ CssRoot { r_curly_token: R_CURLY@46..47 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -144,7 +144,7 @@ CssRoot { 0: CSS_ROOT@0..74 0: (empty) 1: CSS_RULE_LIST@0..73 - 0: CSS_RULE@0..20 + 0: CSS_QUALIFIED_RULE@0..20 0: CSS_SELECTOR_LIST@0..18 0: CSS_COMPOUND_SELECTOR@0..18 0: (empty) @@ -167,7 +167,7 @@ CssRoot { 0: L_CURLY@18..19 "{" [] [] 1: CSS_DECLARATION_LIST@19..19 2: R_CURLY@19..20 "}" [] [] - 1: CSS_RULE@20..47 + 1: CSS_QUALIFIED_RULE@20..47 0: CSS_SELECTOR_LIST@20..45 0: CSS_COMPOUND_SELECTOR@20..45 0: (empty) @@ -190,7 +190,7 @@ CssRoot { 0: L_CURLY@45..46 "{" [] [] 1: CSS_DECLARATION_LIST@46..46 2: R_CURLY@46..47 "}" [] [] - 2: CSS_RULE@47..73 + 2: CSS_QUALIFIED_RULE@47..73 0: CSS_SELECTOR_LIST@47..71 0: CSS_COMPLEX_SELECTOR@47..71 0: CSS_COMPOUND_SELECTOR@47..65 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_ident.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_ident.css.snap index 8e21b566faf9..f4b0297e77e9 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_ident.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_ident.css.snap @@ -24,7 +24,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -47,7 +47,7 @@ CssRoot { r_curly_token: R_CURLY@16..17 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -70,7 +70,7 @@ CssRoot { r_curly_token: R_CURLY@32..33 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -93,7 +93,7 @@ CssRoot { r_curly_token: R_CURLY@42..43 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -116,7 +116,7 @@ CssRoot { r_curly_token: R_CURLY@53..54 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -139,7 +139,7 @@ CssRoot { r_curly_token: R_CURLY@66..67 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -162,7 +162,7 @@ CssRoot { r_curly_token: R_CURLY@79..80 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -185,7 +185,7 @@ CssRoot { r_curly_token: R_CURLY@89..90 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -219,7 +219,7 @@ CssRoot { 0: CSS_ROOT@0..101 0: (empty) 1: CSS_RULE_LIST@0..100 - 0: CSS_RULE@0..17 + 0: CSS_QUALIFIED_RULE@0..17 0: CSS_SELECTOR_LIST@0..15 0: CSS_COMPOUND_SELECTOR@0..15 0: (empty) @@ -234,7 +234,7 @@ CssRoot { 0: L_CURLY@15..16 "{" [] [] 1: CSS_DECLARATION_LIST@16..16 2: R_CURLY@16..17 "}" [] [] - 1: CSS_RULE@17..33 + 1: CSS_QUALIFIED_RULE@17..33 0: CSS_SELECTOR_LIST@17..31 0: CSS_COMPOUND_SELECTOR@17..31 0: (empty) @@ -249,7 +249,7 @@ CssRoot { 0: L_CURLY@31..32 "{" [] [] 1: CSS_DECLARATION_LIST@32..32 2: R_CURLY@32..33 "}" [] [] - 2: CSS_RULE@33..43 + 2: CSS_QUALIFIED_RULE@33..43 0: CSS_SELECTOR_LIST@33..41 0: CSS_COMPOUND_SELECTOR@33..41 0: (empty) @@ -264,7 +264,7 @@ CssRoot { 0: L_CURLY@41..42 "{" [] [] 1: CSS_DECLARATION_LIST@42..42 2: R_CURLY@42..43 "}" [] [] - 3: CSS_RULE@43..54 + 3: CSS_QUALIFIED_RULE@43..54 0: CSS_SELECTOR_LIST@43..52 0: CSS_COMPOUND_SELECTOR@43..52 0: (empty) @@ -279,7 +279,7 @@ CssRoot { 0: L_CURLY@52..53 "{" [] [] 1: CSS_DECLARATION_LIST@53..53 2: R_CURLY@53..54 "}" [] [] - 4: CSS_RULE@54..67 + 4: CSS_QUALIFIED_RULE@54..67 0: CSS_SELECTOR_LIST@54..65 0: CSS_COMPOUND_SELECTOR@54..65 0: (empty) @@ -294,7 +294,7 @@ CssRoot { 0: L_CURLY@65..66 "{" [] [] 1: CSS_DECLARATION_LIST@66..66 2: R_CURLY@66..67 "}" [] [] - 5: CSS_RULE@67..80 + 5: CSS_QUALIFIED_RULE@67..80 0: CSS_SELECTOR_LIST@67..78 0: CSS_COMPOUND_SELECTOR@67..78 0: (empty) @@ -309,7 +309,7 @@ CssRoot { 0: L_CURLY@78..79 "{" [] [] 1: CSS_DECLARATION_LIST@79..79 2: R_CURLY@79..80 "}" [] [] - 6: CSS_RULE@80..90 + 6: CSS_QUALIFIED_RULE@80..90 0: CSS_SELECTOR_LIST@80..88 0: CSS_COMPOUND_SELECTOR@80..88 0: (empty) @@ -324,7 +324,7 @@ CssRoot { 0: L_CURLY@88..89 "{" [] [] 1: CSS_DECLARATION_LIST@89..89 2: R_CURLY@89..90 "}" [] [] - 7: CSS_RULE@90..100 + 7: CSS_QUALIFIED_RULE@90..100 0: CSS_SELECTOR_LIST@90..98 0: CSS_COMPOUND_SELECTOR@90..98 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_is.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_is.css.snap index 901fc0080de4..757fb78a1e68 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_is.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_is.css.snap @@ -32,7 +32,7 @@ a:is(:not(:hover)) {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -80,7 +80,7 @@ CssRoot { r_curly_token: R_CURLY@12..13 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -139,7 +139,7 @@ CssRoot { r_curly_token: R_CURLY@30..31 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -218,7 +218,7 @@ CssRoot { r_curly_token: R_CURLY@67..68 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -273,7 +273,7 @@ CssRoot { r_curly_token: R_CURLY@90..91 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssComplexSelector { @@ -454,7 +454,7 @@ CssRoot { r_curly_token: R_CURLY@158..159 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -511,7 +511,7 @@ CssRoot { r_curly_token: R_CURLY@182..183 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -574,7 +574,7 @@ CssRoot { r_curly_token: R_CURLY@208..209 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -653,7 +653,7 @@ CssRoot { r_curly_token: R_CURLY@241..242 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -708,7 +708,7 @@ CssRoot { r_curly_token: R_CURLY@266..267 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -762,7 +762,7 @@ CssRoot { r_curly_token: R_CURLY@295..296 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -822,7 +822,7 @@ CssRoot { r_curly_token: R_CURLY@317..318 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -974,7 +974,7 @@ CssRoot { r_curly_token: R_CURLY@382..383 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -1053,7 +1053,7 @@ CssRoot { r_curly_token: R_CURLY@428..429 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -1132,7 +1132,7 @@ CssRoot { r_curly_token: R_CURLY@471..472 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -1211,7 +1211,7 @@ CssRoot { r_curly_token: R_CURLY@513..514 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -1301,7 +1301,7 @@ CssRoot { 0: CSS_ROOT@0..552 0: (empty) 1: CSS_RULE_LIST@0..551 - 0: CSS_RULE@0..13 + 0: CSS_QUALIFIED_RULE@0..13 0: CSS_SELECTOR_LIST@0..11 0: CSS_COMPLEX_SELECTOR@0..11 0: CSS_COMPOUND_SELECTOR@0..7 @@ -1334,7 +1334,7 @@ CssRoot { 0: L_CURLY@11..12 "{" [] [] 1: CSS_DECLARATION_LIST@12..12 2: R_CURLY@12..13 "}" [] [] - 1: CSS_RULE@13..31 + 1: CSS_QUALIFIED_RULE@13..31 0: CSS_SELECTOR_LIST@13..29 0: CSS_COMPLEX_SELECTOR@13..29 0: CSS_COMPOUND_SELECTOR@13..25 @@ -1375,7 +1375,7 @@ CssRoot { 0: L_CURLY@29..30 "{" [] [] 1: CSS_DECLARATION_LIST@30..30 2: R_CURLY@30..31 "}" [] [] - 2: CSS_RULE@31..68 + 2: CSS_QUALIFIED_RULE@31..68 0: CSS_SELECTOR_LIST@31..66 0: CSS_COMPLEX_SELECTOR@31..66 0: CSS_COMPOUND_SELECTOR@31..57 @@ -1429,7 +1429,7 @@ CssRoot { 0: L_CURLY@66..67 "{" [] [] 1: CSS_DECLARATION_LIST@67..67 2: R_CURLY@67..68 "}" [] [] - 3: CSS_RULE@68..91 + 3: CSS_QUALIFIED_RULE@68..91 0: CSS_SELECTOR_LIST@68..89 0: CSS_COMPOUND_SELECTOR@68..89 0: (empty) @@ -1466,7 +1466,7 @@ CssRoot { 0: L_CURLY@89..90 "{" [] [] 1: CSS_DECLARATION_LIST@90..90 2: R_CURLY@90..91 "}" [] [] - 4: CSS_RULE@91..159 + 4: CSS_QUALIFIED_RULE@91..159 0: CSS_SELECTOR_LIST@91..157 0: CSS_COMPLEX_SELECTOR@91..157 0: CSS_COMPLEX_SELECTOR@91..137 @@ -1594,7 +1594,7 @@ CssRoot { 0: L_CURLY@157..158 "{" [] [] 1: CSS_DECLARATION_LIST@158..158 2: R_CURLY@158..159 "}" [] [] - 5: CSS_RULE@159..183 + 5: CSS_QUALIFIED_RULE@159..183 0: CSS_SELECTOR_LIST@159..181 0: CSS_COMPOUND_SELECTOR@159..181 0: (empty) @@ -1632,7 +1632,7 @@ CssRoot { 0: L_CURLY@181..182 "{" [] [] 1: CSS_DECLARATION_LIST@182..182 2: R_CURLY@182..183 "}" [] [] - 6: CSS_RULE@183..209 + 6: CSS_QUALIFIED_RULE@183..209 0: CSS_SELECTOR_LIST@183..207 0: CSS_COMPOUND_SELECTOR@183..207 0: (empty) @@ -1674,7 +1674,7 @@ CssRoot { 0: L_CURLY@207..208 "{" [] [] 1: CSS_DECLARATION_LIST@208..208 2: R_CURLY@208..209 "}" [] [] - 7: CSS_RULE@209..242 + 7: CSS_QUALIFIED_RULE@209..242 0: CSS_SELECTOR_LIST@209..240 0: CSS_COMPLEX_SELECTOR@209..240 0: CSS_COMPOUND_SELECTOR@209..229 @@ -1729,7 +1729,7 @@ CssRoot { 0: L_CURLY@240..241 "{" [] [] 1: CSS_DECLARATION_LIST@241..241 2: R_CURLY@241..242 "}" [] [] - 8: CSS_RULE@242..267 + 8: CSS_QUALIFIED_RULE@242..267 0: CSS_SELECTOR_LIST@242..265 0: CSS_COMPOUND_SELECTOR@242..265 0: (empty) @@ -1766,7 +1766,7 @@ CssRoot { 0: L_CURLY@265..266 "{" [] [] 1: CSS_DECLARATION_LIST@266..266 2: R_CURLY@266..267 "}" [] [] - 9: CSS_RULE@267..296 + 9: CSS_QUALIFIED_RULE@267..296 0: CSS_SELECTOR_LIST@267..294 0: CSS_COMPOUND_SELECTOR@267..294 0: (empty) @@ -1802,7 +1802,7 @@ CssRoot { 0: L_CURLY@294..295 "{" [] [] 1: CSS_DECLARATION_LIST@295..295 2: R_CURLY@295..296 "}" [] [] - 10: CSS_RULE@296..318 + 10: CSS_QUALIFIED_RULE@296..318 0: CSS_SELECTOR_LIST@296..316 0: CSS_COMPOUND_SELECTOR@296..316 0: (empty) @@ -1842,7 +1842,7 @@ CssRoot { 0: L_CURLY@316..317 "{" [] [] 1: CSS_DECLARATION_LIST@317..317 2: R_CURLY@317..318 "}" [] [] - 11: CSS_RULE@318..383 + 11: CSS_QUALIFIED_RULE@318..383 0: CSS_SELECTOR_LIST@318..381 0: CSS_COMPLEX_SELECTOR@318..381 0: CSS_COMPOUND_SELECTOR@318..352 @@ -1950,7 +1950,7 @@ CssRoot { 0: L_CURLY@381..382 "{" [] [] 1: CSS_DECLARATION_LIST@382..382 2: R_CURLY@382..383 "}" [] [] - 12: CSS_RULE@383..429 + 12: CSS_QUALIFIED_RULE@383..429 0: CSS_SELECTOR_LIST@383..427 0: CSS_COMPLEX_SELECTOR@383..427 0: CSS_COMPOUND_SELECTOR@383..418 @@ -2004,7 +2004,7 @@ CssRoot { 0: L_CURLY@427..428 "{" [] [] 1: CSS_DECLARATION_LIST@428..428 2: R_CURLY@428..429 "}" [] [] - 13: CSS_RULE@429..472 + 13: CSS_QUALIFIED_RULE@429..472 0: CSS_SELECTOR_LIST@429..470 0: CSS_COMPLEX_SELECTOR@429..470 0: CSS_COMPOUND_SELECTOR@429..461 @@ -2058,7 +2058,7 @@ CssRoot { 0: L_CURLY@470..471 "{" [] [] 1: CSS_DECLARATION_LIST@471..471 2: R_CURLY@471..472 "}" [] [] - 14: CSS_RULE@472..514 + 14: CSS_QUALIFIED_RULE@472..514 0: CSS_SELECTOR_LIST@472..512 0: CSS_COMPLEX_SELECTOR@472..512 0: CSS_COMPOUND_SELECTOR@472..503 @@ -2112,7 +2112,7 @@ CssRoot { 0: L_CURLY@512..513 "{" [] [] 1: CSS_DECLARATION_LIST@513..513 2: R_CURLY@513..514 "}" [] [] - 15: CSS_RULE@514..551 + 15: CSS_QUALIFIED_RULE@514..551 0: CSS_SELECTOR_LIST@514..549 0: CSS_COMPLEX_SELECTOR@514..549 0: CSS_COMPOUND_SELECTOR@514..540 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_lang.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_lang.css.snap index 5dad619a2d9d..0ccb6b81ec9b 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_lang.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_lang.css.snap @@ -24,7 +24,7 @@ html:lang(de, fr) {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -52,7 +52,7 @@ CssRoot { r_curly_token: R_CURLY@16..17 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -80,7 +80,7 @@ CssRoot { r_curly_token: R_CURLY@35..36 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -113,7 +113,7 @@ CssRoot { r_curly_token: R_CURLY@55..56 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -146,7 +146,7 @@ CssRoot { r_curly_token: R_CURLY@72..73 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -183,7 +183,7 @@ CssRoot { r_curly_token: R_CURLY@93..94 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -224,7 +224,7 @@ CssRoot { r_curly_token: R_CURLY@113..114 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -265,7 +265,7 @@ CssRoot { r_curly_token: R_CURLY@130..131 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -319,7 +319,7 @@ CssRoot { 0: CSS_ROOT@0..155 0: (empty) 1: CSS_RULE_LIST@0..154 - 0: CSS_RULE@0..17 + 0: CSS_QUALIFIED_RULE@0..17 0: CSS_SELECTOR_LIST@0..15 0: CSS_COMPOUND_SELECTOR@0..15 0: (empty) @@ -338,7 +338,7 @@ CssRoot { 0: L_CURLY@15..16 "{" [] [] 1: CSS_DECLARATION_LIST@16..16 2: R_CURLY@16..17 "}" [] [] - 1: CSS_RULE@17..36 + 1: CSS_QUALIFIED_RULE@17..36 0: CSS_SELECTOR_LIST@17..34 0: CSS_COMPOUND_SELECTOR@17..34 0: (empty) @@ -357,7 +357,7 @@ CssRoot { 0: L_CURLY@34..35 "{" [] [] 1: CSS_DECLARATION_LIST@35..35 2: R_CURLY@35..36 "}" [] [] - 2: CSS_RULE@36..56 + 2: CSS_QUALIFIED_RULE@36..56 0: CSS_SELECTOR_LIST@36..54 0: CSS_COMPOUND_SELECTOR@36..54 0: (empty) @@ -379,7 +379,7 @@ CssRoot { 0: L_CURLY@54..55 "{" [] [] 1: CSS_DECLARATION_LIST@55..55 2: R_CURLY@55..56 "}" [] [] - 3: CSS_RULE@56..73 + 3: CSS_QUALIFIED_RULE@56..73 0: CSS_SELECTOR_LIST@56..71 0: CSS_COMPOUND_SELECTOR@56..71 0: (empty) @@ -401,7 +401,7 @@ CssRoot { 0: L_CURLY@71..72 "{" [] [] 1: CSS_DECLARATION_LIST@72..72 2: R_CURLY@72..73 "}" [] [] - 4: CSS_RULE@73..94 + 4: CSS_QUALIFIED_RULE@73..94 0: CSS_SELECTOR_LIST@73..92 0: CSS_COMPOUND_SELECTOR@73..92 0: (empty) @@ -426,7 +426,7 @@ CssRoot { 0: L_CURLY@92..93 "{" [] [] 1: CSS_DECLARATION_LIST@93..93 2: R_CURLY@93..94 "}" [] [] - 5: CSS_RULE@94..114 + 5: CSS_QUALIFIED_RULE@94..114 0: CSS_SELECTOR_LIST@94..112 0: CSS_COMPLEX_SELECTOR@94..112 0: CSS_COMPOUND_SELECTOR@94..108 @@ -454,7 +454,7 @@ CssRoot { 0: L_CURLY@112..113 "{" [] [] 1: CSS_DECLARATION_LIST@113..113 2: R_CURLY@113..114 "}" [] [] - 6: CSS_RULE@114..131 + 6: CSS_QUALIFIED_RULE@114..131 0: CSS_SELECTOR_LIST@114..129 0: CSS_COMPLEX_SELECTOR@114..129 0: CSS_COMPOUND_SELECTOR@114..125 @@ -482,7 +482,7 @@ CssRoot { 0: L_CURLY@129..130 "{" [] [] 1: CSS_DECLARATION_LIST@130..130 2: R_CURLY@130..131 "}" [] [] - 7: CSS_RULE@131..154 + 7: CSS_QUALIFIED_RULE@131..154 0: CSS_SELECTOR_LIST@131..152 0: CSS_COMPLEX_SELECTOR@131..152 0: CSS_COMPOUND_SELECTOR@131..144 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_matches.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_matches.css.snap index edf1f3da11e6..94846a976af3 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_matches.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_matches.css.snap @@ -18,7 +18,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -66,7 +66,7 @@ CssRoot { r_curly_token: R_CURLY@17..18 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -136,7 +136,7 @@ CssRoot { 0: CSS_ROOT@0..42 0: (empty) 1: CSS_RULE_LIST@0..41 - 0: CSS_RULE@0..18 + 0: CSS_QUALIFIED_RULE@0..18 0: CSS_SELECTOR_LIST@0..16 0: CSS_COMPLEX_SELECTOR@0..16 0: CSS_COMPOUND_SELECTOR@0..12 @@ -169,7 +169,7 @@ CssRoot { 0: L_CURLY@16..17 "{" [] [] 1: CSS_DECLARATION_LIST@17..17 2: R_CURLY@17..18 "}" [] [] - 1: CSS_RULE@18..41 + 1: CSS_QUALIFIED_RULE@18..41 0: CSS_SELECTOR_LIST@18..39 0: CSS_COMPLEX_SELECTOR@18..39 0: CSS_COMPOUND_SELECTOR@18..35 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_module.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_module.css.snap index 0833eb58c187..c5c6bccba111 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_module.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_module.css.snap @@ -19,7 +19,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -67,7 +67,7 @@ CssRoot { r_curly_token: R_CURLY@21..22 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -130,7 +130,7 @@ CssRoot { r_curly_token: R_CURLY@49..50 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -204,7 +204,7 @@ CssRoot { 0: CSS_ROOT@0..79 0: (empty) 1: CSS_RULE_LIST@0..78 - 0: CSS_RULE@0..22 + 0: CSS_QUALIFIED_RULE@0..22 0: CSS_SELECTOR_LIST@0..20 0: CSS_COMPOUND_SELECTOR@0..20 0: (empty) @@ -237,7 +237,7 @@ CssRoot { 0: L_CURLY@20..21 "{" [] [] 1: CSS_DECLARATION_LIST@21..21 2: R_CURLY@21..22 "}" [] [] - 1: CSS_RULE@22..50 + 1: CSS_QUALIFIED_RULE@22..50 0: CSS_SELECTOR_LIST@22..48 0: CSS_COMPOUND_SELECTOR@22..48 0: (empty) @@ -280,7 +280,7 @@ CssRoot { 0: L_CURLY@48..49 "{" [] [] 1: CSS_DECLARATION_LIST@49..49 2: R_CURLY@49..50 "}" [] [] - 2: CSS_RULE@50..78 + 2: CSS_QUALIFIED_RULE@50..78 0: CSS_SELECTOR_LIST@50..76 0: CSS_COMPLEX_SELECTOR@50..76 0: CSS_COMPOUND_SELECTOR@50..70 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_not.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_not.css.snap index 2c28dbce48bb..ab0b57dad75f 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_not.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_not.css.snap @@ -42,7 +42,7 @@ ul li:not(:first-of-type) {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -77,7 +77,7 @@ CssRoot { r_curly_token: R_CURLY@9..10 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -112,7 +112,7 @@ CssRoot { r_curly_token: R_CURLY@26..27 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -147,7 +147,7 @@ CssRoot { r_curly_token: R_CURLY@39..40 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -194,7 +194,7 @@ CssRoot { r_curly_token: R_CURLY@65..66 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -232,7 +232,7 @@ CssRoot { r_curly_token: R_CURLY@79..80 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -298,7 +298,7 @@ CssRoot { r_curly_token: R_CURLY@109..110 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -346,7 +346,7 @@ CssRoot { r_curly_token: R_CURLY@134..135 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -397,7 +397,7 @@ CssRoot { r_curly_token: R_CURLY@158..159 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -439,7 +439,7 @@ CssRoot { r_curly_token: R_CURLY@175..176 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -487,7 +487,7 @@ CssRoot { r_curly_token: R_CURLY@191..192 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -555,7 +555,7 @@ CssRoot { r_curly_token: R_CURLY@219..220 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -616,7 +616,7 @@ CssRoot { r_curly_token: R_CURLY@245..246 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -671,7 +671,7 @@ CssRoot { r_curly_token: R_CURLY@266..267 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -752,7 +752,7 @@ CssRoot { r_curly_token: R_CURLY@318..319 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -805,7 +805,7 @@ CssRoot { r_curly_token: R_CURLY@342..343 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -871,7 +871,7 @@ CssRoot { r_curly_token: R_CURLY@372..373 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -909,7 +909,7 @@ CssRoot { r_curly_token: R_CURLY@386..387 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -956,7 +956,7 @@ CssRoot { r_curly_token: R_CURLY@412..413 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1000,7 +1000,7 @@ CssRoot { r_curly_token: R_CURLY@429..430 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1060,7 +1060,7 @@ CssRoot { r_curly_token: R_CURLY@452..453 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1171,7 +1171,7 @@ CssRoot { r_curly_token: R_CURLY@497..498 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -1282,7 +1282,7 @@ CssRoot { r_curly_token: R_CURLY@542..543 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -1339,7 +1339,7 @@ CssRoot { r_curly_token: R_CURLY@571..572 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -1400,7 +1400,7 @@ CssRoot { 0: CSS_ROOT@0..589 0: (empty) 1: CSS_RULE_LIST@0..588 - 0: CSS_RULE@0..10 + 0: CSS_QUALIFIED_RULE@0..10 0: CSS_SELECTOR_LIST@0..8 0: CSS_COMPOUND_SELECTOR@0..8 0: (empty) @@ -1424,7 +1424,7 @@ CssRoot { 0: L_CURLY@8..9 "{" [] [] 1: CSS_DECLARATION_LIST@9..9 2: R_CURLY@9..10 "}" [] [] - 1: CSS_RULE@10..27 + 1: CSS_QUALIFIED_RULE@10..27 0: CSS_SELECTOR_LIST@10..25 0: CSS_COMPOUND_SELECTOR@10..25 0: (empty) @@ -1448,7 +1448,7 @@ CssRoot { 0: L_CURLY@25..26 "{" [] [] 1: CSS_DECLARATION_LIST@26..26 2: R_CURLY@26..27 "}" [] [] - 2: CSS_RULE@27..40 + 2: CSS_QUALIFIED_RULE@27..40 0: CSS_SELECTOR_LIST@27..38 0: CSS_COMPOUND_SELECTOR@27..38 0: (empty) @@ -1472,7 +1472,7 @@ CssRoot { 0: L_CURLY@38..39 "{" [] [] 1: CSS_DECLARATION_LIST@39..39 2: R_CURLY@39..40 "}" [] [] - 3: CSS_RULE@40..66 + 3: CSS_QUALIFIED_RULE@40..66 0: CSS_SELECTOR_LIST@40..64 0: CSS_COMPOUND_SELECTOR@40..64 0: (empty) @@ -1504,7 +1504,7 @@ CssRoot { 0: L_CURLY@64..65 "{" [] [] 1: CSS_DECLARATION_LIST@65..65 2: R_CURLY@65..66 "}" [] [] - 4: CSS_RULE@66..80 + 4: CSS_QUALIFIED_RULE@66..80 0: CSS_SELECTOR_LIST@66..78 0: CSS_COMPOUND_SELECTOR@66..78 0: (empty) @@ -1530,7 +1530,7 @@ CssRoot { 0: L_CURLY@78..79 "{" [] [] 1: CSS_DECLARATION_LIST@79..79 2: R_CURLY@79..80 "}" [] [] - 5: CSS_RULE@80..110 + 5: CSS_QUALIFIED_RULE@80..110 0: CSS_SELECTOR_LIST@80..108 0: CSS_COMPOUND_SELECTOR@80..108 0: (empty) @@ -1574,7 +1574,7 @@ CssRoot { 0: L_CURLY@108..109 "{" [] [] 1: CSS_DECLARATION_LIST@109..109 2: R_CURLY@109..110 "}" [] [] - 6: CSS_RULE@110..135 + 6: CSS_QUALIFIED_RULE@110..135 0: CSS_SELECTOR_LIST@110..133 0: CSS_COMPOUND_SELECTOR@110..133 0: (empty) @@ -1606,7 +1606,7 @@ CssRoot { 0: L_CURLY@133..134 "{" [] [] 1: CSS_DECLARATION_LIST@134..134 2: R_CURLY@134..135 "}" [] [] - 7: CSS_RULE@135..159 + 7: CSS_QUALIFIED_RULE@135..159 0: CSS_SELECTOR_LIST@135..157 0: CSS_COMPOUND_SELECTOR@135..157 0: (empty) @@ -1641,7 +1641,7 @@ CssRoot { 0: L_CURLY@157..158 "{" [] [] 1: CSS_DECLARATION_LIST@158..158 2: R_CURLY@158..159 "}" [] [] - 8: CSS_RULE@159..176 + 8: CSS_QUALIFIED_RULE@159..176 0: CSS_SELECTOR_LIST@159..174 0: CSS_COMPOUND_SELECTOR@159..174 0: (empty) @@ -1669,7 +1669,7 @@ CssRoot { 0: L_CURLY@174..175 "{" [] [] 1: CSS_DECLARATION_LIST@175..175 2: R_CURLY@175..176 "}" [] [] - 9: CSS_RULE@176..192 + 9: CSS_QUALIFIED_RULE@176..192 0: CSS_SELECTOR_LIST@176..190 0: CSS_COMPLEX_SELECTOR@176..190 0: CSS_COMPOUND_SELECTOR@176..181 @@ -1702,7 +1702,7 @@ CssRoot { 0: L_CURLY@190..191 "{" [] [] 1: CSS_DECLARATION_LIST@191..191 2: R_CURLY@191..192 "}" [] [] - 10: CSS_RULE@192..220 + 10: CSS_QUALIFIED_RULE@192..220 0: CSS_SELECTOR_LIST@192..218 0: CSS_COMPLEX_SELECTOR@192..218 0: CSS_COMPOUND_SELECTOR@192..197 @@ -1749,7 +1749,7 @@ CssRoot { 0: L_CURLY@218..219 "{" [] [] 1: CSS_DECLARATION_LIST@219..219 2: R_CURLY@219..220 "}" [] [] - 11: CSS_RULE@220..246 + 11: CSS_QUALIFIED_RULE@220..246 0: CSS_SELECTOR_LIST@220..244 0: CSS_COMPLEX_SELECTOR@220..244 0: CSS_COMPOUND_SELECTOR@220..225 @@ -1791,7 +1791,7 @@ CssRoot { 0: L_CURLY@244..245 "{" [] [] 1: CSS_DECLARATION_LIST@245..245 2: R_CURLY@245..246 "}" [] [] - 12: CSS_RULE@246..267 + 12: CSS_QUALIFIED_RULE@246..267 0: CSS_SELECTOR_LIST@246..265 0: CSS_COMPLEX_SELECTOR@246..265 0: CSS_COMPOUND_SELECTOR@246..249 @@ -1828,7 +1828,7 @@ CssRoot { 0: L_CURLY@265..266 "{" [] [] 1: CSS_DECLARATION_LIST@266..266 2: R_CURLY@266..267 "}" [] [] - 13: CSS_RULE@267..319 + 13: CSS_QUALIFIED_RULE@267..319 0: CSS_SELECTOR_LIST@267..317 0: CSS_COMPLEX_SELECTOR@267..317 0: CSS_COMPOUND_SELECTOR@267..273 @@ -1882,7 +1882,7 @@ CssRoot { 0: L_CURLY@317..318 "{" [] [] 1: CSS_DECLARATION_LIST@318..318 2: R_CURLY@318..319 "}" [] [] - 14: CSS_RULE@319..343 + 14: CSS_QUALIFIED_RULE@319..343 0: CSS_SELECTOR_LIST@319..341 0: CSS_COMPOUND_SELECTOR@319..341 0: (empty) @@ -1918,7 +1918,7 @@ CssRoot { 0: L_CURLY@341..342 "{" [] [] 1: CSS_DECLARATION_LIST@342..342 2: R_CURLY@342..343 "}" [] [] - 15: CSS_RULE@343..373 + 15: CSS_QUALIFIED_RULE@343..373 0: CSS_SELECTOR_LIST@343..371 0: CSS_COMPOUND_SELECTOR@343..371 0: (empty) @@ -1962,7 +1962,7 @@ CssRoot { 0: L_CURLY@371..372 "{" [] [] 1: CSS_DECLARATION_LIST@372..372 2: R_CURLY@372..373 "}" [] [] - 16: CSS_RULE@373..387 + 16: CSS_QUALIFIED_RULE@373..387 0: CSS_SELECTOR_LIST@373..385 0: CSS_COMPOUND_SELECTOR@373..385 0: (empty) @@ -1988,7 +1988,7 @@ CssRoot { 0: L_CURLY@385..386 "{" [] [] 1: CSS_DECLARATION_LIST@386..386 2: R_CURLY@386..387 "}" [] [] - 17: CSS_RULE@387..413 + 17: CSS_QUALIFIED_RULE@387..413 0: CSS_SELECTOR_LIST@387..411 0: CSS_COMPOUND_SELECTOR@387..411 0: (empty) @@ -2020,7 +2020,7 @@ CssRoot { 0: L_CURLY@411..412 "{" [] [] 1: CSS_DECLARATION_LIST@412..412 2: R_CURLY@412..413 "}" [] [] - 18: CSS_RULE@413..430 + 18: CSS_QUALIFIED_RULE@413..430 0: CSS_SELECTOR_LIST@413..428 0: CSS_COMPOUND_SELECTOR@413..428 0: (empty) @@ -2049,7 +2049,7 @@ CssRoot { 0: L_CURLY@428..429 "{" [] [] 1: CSS_DECLARATION_LIST@429..429 2: R_CURLY@429..430 "}" [] [] - 19: CSS_RULE@430..453 + 19: CSS_QUALIFIED_RULE@430..453 0: CSS_SELECTOR_LIST@430..451 0: CSS_COMPOUND_SELECTOR@430..451 0: (empty) @@ -2089,7 +2089,7 @@ CssRoot { 0: L_CURLY@451..452 "{" [] [] 1: CSS_DECLARATION_LIST@452..452 2: R_CURLY@452..453 "}" [] [] - 20: CSS_RULE@453..498 + 20: CSS_QUALIFIED_RULE@453..498 0: CSS_SELECTOR_LIST@453..496 0: CSS_COMPOUND_SELECTOR@453..496 0: (empty) @@ -2167,7 +2167,7 @@ CssRoot { 0: L_CURLY@496..497 "{" [] [] 1: CSS_DECLARATION_LIST@497..497 2: R_CURLY@497..498 "}" [] [] - 21: CSS_RULE@498..543 + 21: CSS_QUALIFIED_RULE@498..543 0: CSS_SELECTOR_LIST@498..541 0: CSS_COMPOUND_SELECTOR@498..541 0: (empty) @@ -2245,7 +2245,7 @@ CssRoot { 0: L_CURLY@541..542 "{" [] [] 1: CSS_DECLARATION_LIST@542..542 2: R_CURLY@542..543 "}" [] [] - 22: CSS_RULE@543..572 + 22: CSS_QUALIFIED_RULE@543..572 0: CSS_SELECTOR_LIST@543..570 0: CSS_COMPLEX_SELECTOR@543..570 0: CSS_COMPOUND_SELECTOR@543..546 @@ -2283,7 +2283,7 @@ CssRoot { 0: L_CURLY@570..571 "{" [] [] 1: CSS_DECLARATION_LIST@571..571 2: R_CURLY@571..572 "}" [] [] - 23: CSS_RULE@572..588 + 23: CSS_QUALIFIED_RULE@572..588 0: CSS_SELECTOR_LIST@572..586 0: CSS_COMPLEX_SELECTOR@572..586 0: CSS_COMPOUND_SELECTOR@572..580 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_past.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_past.css.snap index 22e7b7942723..1667c29fed8f 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_past.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_past.css.snap @@ -18,7 +18,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -86,7 +86,7 @@ CssRoot { r_curly_token: R_CURLY@22..23 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -180,7 +180,7 @@ CssRoot { 0: CSS_ROOT@0..53 0: (empty) 1: CSS_RULE_LIST@0..52 - 0: CSS_RULE@0..23 + 0: CSS_QUALIFIED_RULE@0..23 0: CSS_SELECTOR_LIST@0..21 0: CSS_COMPOUND_SELECTOR@0..21 0: (empty) @@ -228,7 +228,7 @@ CssRoot { 0: L_CURLY@21..22 "{" [] [] 1: CSS_DECLARATION_LIST@22..22 2: R_CURLY@22..23 "}" [] [] - 1: CSS_RULE@23..52 + 1: CSS_QUALIFIED_RULE@23..52 0: CSS_SELECTOR_LIST@23..50 0: CSS_COMPLEX_SELECTOR@23..50 0: CSS_COMPOUND_SELECTOR@23..44 diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_where.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_where.css.snap index caa5464e5fd5..fbb60291239f 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_where.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_class/pseudo_class_where.css.snap @@ -27,7 +27,7 @@ a:where(:not(:hover)) {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -75,7 +75,7 @@ CssRoot { r_curly_token: R_CURLY@15..16 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -134,7 +134,7 @@ CssRoot { r_curly_token: R_CURLY@36..37 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -213,7 +213,7 @@ CssRoot { r_curly_token: R_CURLY@76..77 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -268,7 +268,7 @@ CssRoot { r_curly_token: R_CURLY@102..103 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssComplexSelector { @@ -449,7 +449,7 @@ CssRoot { r_curly_token: R_CURLY@179..180 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -506,7 +506,7 @@ CssRoot { r_curly_token: R_CURLY@206..207 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -569,7 +569,7 @@ CssRoot { r_curly_token: R_CURLY@235..236 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -648,7 +648,7 @@ CssRoot { r_curly_token: R_CURLY@274..275 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -703,7 +703,7 @@ CssRoot { r_curly_token: R_CURLY@302..303 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -757,7 +757,7 @@ CssRoot { r_curly_token: R_CURLY@334..335 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -828,7 +828,7 @@ CssRoot { 0: CSS_ROOT@0..361 0: (empty) 1: CSS_RULE_LIST@0..360 - 0: CSS_RULE@0..16 + 0: CSS_QUALIFIED_RULE@0..16 0: CSS_SELECTOR_LIST@0..14 0: CSS_COMPLEX_SELECTOR@0..14 0: CSS_COMPOUND_SELECTOR@0..10 @@ -861,7 +861,7 @@ CssRoot { 0: L_CURLY@14..15 "{" [] [] 1: CSS_DECLARATION_LIST@15..15 2: R_CURLY@15..16 "}" [] [] - 1: CSS_RULE@16..37 + 1: CSS_QUALIFIED_RULE@16..37 0: CSS_SELECTOR_LIST@16..35 0: CSS_COMPLEX_SELECTOR@16..35 0: CSS_COMPOUND_SELECTOR@16..31 @@ -902,7 +902,7 @@ CssRoot { 0: L_CURLY@35..36 "{" [] [] 1: CSS_DECLARATION_LIST@36..36 2: R_CURLY@36..37 "}" [] [] - 2: CSS_RULE@37..77 + 2: CSS_QUALIFIED_RULE@37..77 0: CSS_SELECTOR_LIST@37..75 0: CSS_COMPLEX_SELECTOR@37..75 0: CSS_COMPOUND_SELECTOR@37..66 @@ -956,7 +956,7 @@ CssRoot { 0: L_CURLY@75..76 "{" [] [] 1: CSS_DECLARATION_LIST@76..76 2: R_CURLY@76..77 "}" [] [] - 3: CSS_RULE@77..103 + 3: CSS_QUALIFIED_RULE@77..103 0: CSS_SELECTOR_LIST@77..101 0: CSS_COMPOUND_SELECTOR@77..101 0: (empty) @@ -993,7 +993,7 @@ CssRoot { 0: L_CURLY@101..102 "{" [] [] 1: CSS_DECLARATION_LIST@102..102 2: R_CURLY@102..103 "}" [] [] - 4: CSS_RULE@103..180 + 4: CSS_QUALIFIED_RULE@103..180 0: CSS_SELECTOR_LIST@103..178 0: CSS_COMPLEX_SELECTOR@103..178 0: CSS_COMPLEX_SELECTOR@103..155 @@ -1121,7 +1121,7 @@ CssRoot { 0: L_CURLY@178..179 "{" [] [] 1: CSS_DECLARATION_LIST@179..179 2: R_CURLY@179..180 "}" [] [] - 5: CSS_RULE@180..207 + 5: CSS_QUALIFIED_RULE@180..207 0: CSS_SELECTOR_LIST@180..205 0: CSS_COMPOUND_SELECTOR@180..205 0: (empty) @@ -1159,7 +1159,7 @@ CssRoot { 0: L_CURLY@205..206 "{" [] [] 1: CSS_DECLARATION_LIST@206..206 2: R_CURLY@206..207 "}" [] [] - 6: CSS_RULE@207..236 + 6: CSS_QUALIFIED_RULE@207..236 0: CSS_SELECTOR_LIST@207..234 0: CSS_COMPOUND_SELECTOR@207..234 0: (empty) @@ -1201,7 +1201,7 @@ CssRoot { 0: L_CURLY@234..235 "{" [] [] 1: CSS_DECLARATION_LIST@235..235 2: R_CURLY@235..236 "}" [] [] - 7: CSS_RULE@236..275 + 7: CSS_QUALIFIED_RULE@236..275 0: CSS_SELECTOR_LIST@236..273 0: CSS_COMPLEX_SELECTOR@236..273 0: CSS_COMPOUND_SELECTOR@236..262 @@ -1256,7 +1256,7 @@ CssRoot { 0: L_CURLY@273..274 "{" [] [] 1: CSS_DECLARATION_LIST@274..274 2: R_CURLY@274..275 "}" [] [] - 8: CSS_RULE@275..303 + 8: CSS_QUALIFIED_RULE@275..303 0: CSS_SELECTOR_LIST@275..301 0: CSS_COMPOUND_SELECTOR@275..301 0: (empty) @@ -1293,7 +1293,7 @@ CssRoot { 0: L_CURLY@301..302 "{" [] [] 1: CSS_DECLARATION_LIST@302..302 2: R_CURLY@302..303 "}" [] [] - 9: CSS_RULE@303..335 + 9: CSS_QUALIFIED_RULE@303..335 0: CSS_SELECTOR_LIST@303..333 0: CSS_COMPOUND_SELECTOR@303..333 0: (empty) @@ -1329,7 +1329,7 @@ CssRoot { 0: L_CURLY@333..334 "{" [] [] 1: CSS_DECLARATION_LIST@334..334 2: R_CURLY@334..335 "}" [] [] - 10: CSS_RULE@335..360 + 10: CSS_QUALIFIED_RULE@335..360 0: CSS_SELECTOR_LIST@335..358 0: CSS_COMPOUND_SELECTOR@335..358 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/basic.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/basic.css.snap index c68e81ff4acf..4a456172de02 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/basic.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/basic.css.snap @@ -50,7 +50,7 @@ a, b > .foo::before {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -78,7 +78,7 @@ CssRoot { r_curly_token: R_CURLY@10..11 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -106,7 +106,7 @@ CssRoot { r_curly_token: R_CURLY@31..32 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -134,7 +134,7 @@ CssRoot { r_curly_token: R_CURLY@45..46 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -162,7 +162,7 @@ CssRoot { r_curly_token: R_CURLY@60..61 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -202,7 +202,7 @@ CssRoot { r_curly_token: R_CURLY@77..78 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -230,7 +230,7 @@ CssRoot { r_curly_token: R_CURLY@99..100 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -287,7 +287,7 @@ CssRoot { r_curly_token: R_CURLY@136..137 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -310,7 +310,7 @@ CssRoot { r_curly_token: R_CURLY@156..157 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -333,7 +333,7 @@ CssRoot { r_curly_token: R_CURLY@169..170 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -364,7 +364,7 @@ CssRoot { r_curly_token: R_CURLY@206..207 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -387,7 +387,7 @@ CssRoot { r_curly_token: R_CURLY@224..225 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -410,7 +410,7 @@ CssRoot { r_curly_token: R_CURLY@240..241 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -443,7 +443,7 @@ CssRoot { r_curly_token: R_CURLY@257..258 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -478,7 +478,7 @@ CssRoot { r_curly_token: R_CURLY@276..277 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -501,7 +501,7 @@ CssRoot { r_curly_token: R_CURLY@297..298 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -524,7 +524,7 @@ CssRoot { r_curly_token: R_CURLY@315..316 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -553,7 +553,7 @@ CssRoot { r_curly_token: R_CURLY@353..354 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -581,7 +581,7 @@ CssRoot { r_curly_token: R_CURLY@367..368 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -645,7 +645,7 @@ CssRoot { 0: CSS_ROOT@0..393 0: (empty) 1: CSS_RULE_LIST@0..392 - 0: CSS_RULE@0..11 + 0: CSS_QUALIFIED_RULE@0..11 0: CSS_SELECTOR_LIST@0..9 0: CSS_COMPOUND_SELECTOR@0..9 0: (empty) @@ -663,7 +663,7 @@ CssRoot { 0: L_CURLY@9..10 "{" [] [] 1: CSS_DECLARATION_LIST@10..10 2: R_CURLY@10..11 "}" [] [] - 1: CSS_RULE@11..32 + 1: CSS_QUALIFIED_RULE@11..32 0: CSS_SELECTOR_LIST@11..30 0: CSS_COMPOUND_SELECTOR@11..30 0: (empty) @@ -681,7 +681,7 @@ CssRoot { 0: L_CURLY@30..31 "{" [] [] 1: CSS_DECLARATION_LIST@31..31 2: R_CURLY@31..32 "}" [] [] - 2: CSS_RULE@32..46 + 2: CSS_QUALIFIED_RULE@32..46 0: CSS_SELECTOR_LIST@32..44 0: CSS_COMPOUND_SELECTOR@32..44 0: (empty) @@ -699,7 +699,7 @@ CssRoot { 0: L_CURLY@44..45 "{" [] [] 1: CSS_DECLARATION_LIST@45..45 2: R_CURLY@45..46 "}" [] [] - 3: CSS_RULE@46..61 + 3: CSS_QUALIFIED_RULE@46..61 0: CSS_SELECTOR_LIST@46..59 0: CSS_COMPOUND_SELECTOR@46..59 0: (empty) @@ -717,7 +717,7 @@ CssRoot { 0: L_CURLY@59..60 "{" [] [] 1: CSS_DECLARATION_LIST@60..60 2: R_CURLY@60..61 "}" [] [] - 4: CSS_RULE@61..78 + 4: CSS_QUALIFIED_RULE@61..78 0: CSS_SELECTOR_LIST@61..76 0: CSS_COMPOUND_SELECTOR@61..76 0: (empty) @@ -744,7 +744,7 @@ CssRoot { 0: L_CURLY@76..77 "{" [] [] 1: CSS_DECLARATION_LIST@77..77 2: R_CURLY@77..78 "}" [] [] - 5: CSS_RULE@78..100 + 5: CSS_QUALIFIED_RULE@78..100 0: CSS_SELECTOR_LIST@78..98 0: CSS_COMPOUND_SELECTOR@78..98 0: (empty) @@ -762,7 +762,7 @@ CssRoot { 0: L_CURLY@98..99 "{" [] [] 1: CSS_DECLARATION_LIST@99..99 2: R_CURLY@99..100 "}" [] [] - 6: CSS_RULE@100..137 + 6: CSS_QUALIFIED_RULE@100..137 0: CSS_SELECTOR_LIST@100..135 0: CSS_COMPOUND_SELECTOR@100..135 0: (empty) @@ -800,7 +800,7 @@ CssRoot { 0: L_CURLY@135..136 "{" [] [] 1: CSS_DECLARATION_LIST@136..136 2: R_CURLY@136..137 "}" [] [] - 7: CSS_RULE@137..157 + 7: CSS_QUALIFIED_RULE@137..157 0: CSS_SELECTOR_LIST@137..155 0: CSS_COMPOUND_SELECTOR@137..155 0: (empty) @@ -815,7 +815,7 @@ CssRoot { 0: L_CURLY@155..156 "{" [] [] 1: CSS_DECLARATION_LIST@156..156 2: R_CURLY@156..157 "}" [] [] - 8: CSS_RULE@157..170 + 8: CSS_QUALIFIED_RULE@157..170 0: CSS_SELECTOR_LIST@157..168 0: CSS_COMPOUND_SELECTOR@157..168 0: (empty) @@ -830,7 +830,7 @@ CssRoot { 0: L_CURLY@168..169 "{" [] [] 1: CSS_DECLARATION_LIST@169..169 2: R_CURLY@169..170 "}" [] [] - 9: CSS_RULE@170..207 + 9: CSS_QUALIFIED_RULE@170..207 0: CSS_SELECTOR_LIST@170..205 0: CSS_COMPOUND_SELECTOR@170..205 0: (empty) @@ -851,7 +851,7 @@ CssRoot { 0: L_CURLY@205..206 "{" [] [] 1: CSS_DECLARATION_LIST@206..206 2: R_CURLY@206..207 "}" [] [] - 10: CSS_RULE@207..225 + 10: CSS_QUALIFIED_RULE@207..225 0: CSS_SELECTOR_LIST@207..223 0: CSS_COMPOUND_SELECTOR@207..223 0: (empty) @@ -866,7 +866,7 @@ CssRoot { 0: L_CURLY@223..224 "{" [] [] 1: CSS_DECLARATION_LIST@224..224 2: R_CURLY@224..225 "}" [] [] - 11: CSS_RULE@225..241 + 11: CSS_QUALIFIED_RULE@225..241 0: CSS_SELECTOR_LIST@225..239 0: CSS_COMPOUND_SELECTOR@225..239 0: (empty) @@ -881,7 +881,7 @@ CssRoot { 0: L_CURLY@239..240 "{" [] [] 1: CSS_DECLARATION_LIST@240..240 2: R_CURLY@240..241 "}" [] [] - 12: CSS_RULE@241..258 + 12: CSS_QUALIFIED_RULE@241..258 0: CSS_SELECTOR_LIST@241..256 0: CSS_COMPOUND_SELECTOR@241..256 0: (empty) @@ -904,7 +904,7 @@ CssRoot { 0: L_CURLY@256..257 "{" [] [] 1: CSS_DECLARATION_LIST@257..257 2: R_CURLY@257..258 "}" [] [] - 13: CSS_RULE@258..277 + 13: CSS_QUALIFIED_RULE@258..277 0: CSS_SELECTOR_LIST@258..275 0: CSS_COMPOUND_SELECTOR@258..275 0: (empty) @@ -928,7 +928,7 @@ CssRoot { 0: L_CURLY@275..276 "{" [] [] 1: CSS_DECLARATION_LIST@276..276 2: R_CURLY@276..277 "}" [] [] - 14: CSS_RULE@277..298 + 14: CSS_QUALIFIED_RULE@277..298 0: CSS_SELECTOR_LIST@277..296 0: CSS_COMPOUND_SELECTOR@277..296 0: (empty) @@ -943,7 +943,7 @@ CssRoot { 0: L_CURLY@296..297 "{" [] [] 1: CSS_DECLARATION_LIST@297..297 2: R_CURLY@297..298 "}" [] [] - 15: CSS_RULE@298..316 + 15: CSS_QUALIFIED_RULE@298..316 0: CSS_SELECTOR_LIST@298..314 0: CSS_COMPOUND_SELECTOR@298..314 0: (empty) @@ -958,7 +958,7 @@ CssRoot { 0: L_CURLY@314..315 "{" [] [] 1: CSS_DECLARATION_LIST@315..315 2: R_CURLY@315..316 "}" [] [] - 16: CSS_RULE@316..354 + 16: CSS_QUALIFIED_RULE@316..354 0: CSS_SELECTOR_LIST@316..352 0: CSS_COMPOUND_SELECTOR@316..352 0: (empty) @@ -977,7 +977,7 @@ CssRoot { 0: L_CURLY@352..353 "{" [] [] 1: CSS_DECLARATION_LIST@353..353 2: R_CURLY@353..354 "}" [] [] - 17: CSS_RULE@354..368 + 17: CSS_QUALIFIED_RULE@354..368 0: CSS_SELECTOR_LIST@354..366 0: CSS_COMPOUND_SELECTOR@354..366 0: (empty) @@ -995,7 +995,7 @@ CssRoot { 0: L_CURLY@366..367 "{" [] [] 1: CSS_DECLARATION_LIST@367..367 2: R_CURLY@367..368 "}" [] [] - 18: CSS_RULE@368..392 + 18: CSS_QUALIFIED_RULE@368..392 0: CSS_SELECTOR_LIST@368..390 0: CSS_COMPOUND_SELECTOR@368..371 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/cue-region.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/cue-region.css.snap index 6153f47e9def..c7a11203f0cc 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/cue-region.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/cue-region.css.snap @@ -19,7 +19,7 @@ video::cue-region( #scroll ) {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -47,7 +47,7 @@ CssRoot { r_curly_token: R_CURLY@19..20 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -89,7 +89,7 @@ CssRoot { r_curly_token: R_CURLY@49..50 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -142,7 +142,7 @@ CssRoot { 0: CSS_ROOT@0..87 0: (empty) 1: CSS_RULE_LIST@0..86 - 0: CSS_RULE@0..20 + 0: CSS_QUALIFIED_RULE@0..20 0: CSS_SELECTOR_LIST@0..18 0: CSS_COMPOUND_SELECTOR@0..18 0: (empty) @@ -160,7 +160,7 @@ CssRoot { 0: L_CURLY@18..19 "{" [] [] 1: CSS_DECLARATION_LIST@19..19 2: R_CURLY@19..20 "}" [] [] - 1: CSS_RULE@20..50 + 1: CSS_QUALIFIED_RULE@20..50 0: CSS_SELECTOR_LIST@20..48 0: CSS_COMPOUND_SELECTOR@20..48 0: (empty) @@ -188,7 +188,7 @@ CssRoot { 0: L_CURLY@48..49 "{" [] [] 1: CSS_DECLARATION_LIST@49..49 2: R_CURLY@49..50 "}" [] [] - 2: CSS_RULE@50..86 + 2: CSS_QUALIFIED_RULE@50..86 0: CSS_SELECTOR_LIST@50..84 0: CSS_COMPOUND_SELECTOR@50..84 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/cue.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/cue.css.snap index a21199841e35..5d9e8c7d57a3 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/cue.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/cue.css.snap @@ -22,7 +22,7 @@ video::cue(#cue1) {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -45,7 +45,7 @@ CssRoot { r_curly_token: R_CURLY@7..8 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -100,7 +100,7 @@ CssRoot { r_curly_token: R_CURLY@33..34 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -155,7 +155,7 @@ CssRoot { r_curly_token: R_CURLY@65..66 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -183,7 +183,7 @@ CssRoot { r_curly_token: R_CURLY@79..80 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -223,7 +223,7 @@ CssRoot { r_curly_token: R_CURLY@96..97 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -276,7 +276,7 @@ CssRoot { 0: CSS_ROOT@0..119 0: (empty) 1: CSS_RULE_LIST@0..118 - 0: CSS_RULE@0..8 + 0: CSS_QUALIFIED_RULE@0..8 0: CSS_SELECTOR_LIST@0..6 0: CSS_COMPOUND_SELECTOR@0..6 0: (empty) @@ -291,7 +291,7 @@ CssRoot { 0: L_CURLY@6..7 "{" [] [] 1: CSS_DECLARATION_LIST@7..7 2: R_CURLY@7..8 "}" [] [] - 1: CSS_RULE@8..34 + 1: CSS_QUALIFIED_RULE@8..34 0: CSS_SELECTOR_LIST@8..32 0: CSS_COMPOUND_SELECTOR@8..32 0: (empty) @@ -328,7 +328,7 @@ CssRoot { 0: L_CURLY@32..33 "{" [] [] 1: CSS_DECLARATION_LIST@33..33 2: R_CURLY@33..34 "}" [] [] - 2: CSS_RULE@34..66 + 2: CSS_QUALIFIED_RULE@34..66 0: CSS_SELECTOR_LIST@34..64 0: CSS_COMPOUND_SELECTOR@34..64 0: (empty) @@ -365,7 +365,7 @@ CssRoot { 0: L_CURLY@64..65 "{" [] [] 1: CSS_DECLARATION_LIST@65..65 2: R_CURLY@65..66 "}" [] [] - 3: CSS_RULE@66..80 + 3: CSS_QUALIFIED_RULE@66..80 0: CSS_SELECTOR_LIST@66..78 0: CSS_COMPOUND_SELECTOR@66..78 0: (empty) @@ -383,7 +383,7 @@ CssRoot { 0: L_CURLY@78..79 "{" [] [] 1: CSS_DECLARATION_LIST@79..79 2: R_CURLY@79..80 "}" [] [] - 4: CSS_RULE@80..97 + 4: CSS_QUALIFIED_RULE@80..97 0: CSS_SELECTOR_LIST@80..95 0: CSS_COMPOUND_SELECTOR@80..95 0: (empty) @@ -410,7 +410,7 @@ CssRoot { 0: L_CURLY@95..96 "{" [] [] 1: CSS_DECLARATION_LIST@96..96 2: R_CURLY@96..97 "}" [] [] - 5: CSS_RULE@97..118 + 5: CSS_QUALIFIED_RULE@97..118 0: CSS_SELECTOR_LIST@97..116 0: CSS_COMPOUND_SELECTOR@97..116 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/escaped.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/escaped.css.snap index 46a32fc672f4..0ba7941b020f 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/escaped.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/escaped.css.snap @@ -17,7 +17,7 @@ div::bef\ore {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -56,7 +56,7 @@ CssRoot { 0: CSS_ROOT@0..16 0: (empty) 1: CSS_RULE_LIST@0..15 - 0: CSS_RULE@0..15 + 0: CSS_QUALIFIED_RULE@0..15 0: CSS_SELECTOR_LIST@0..13 0: CSS_COMPOUND_SELECTOR@0..13 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/highlight.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/highlight.css.snap index 31c51c14cf36..282a6c660a82 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/highlight.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/highlight.css.snap @@ -24,7 +24,7 @@ div::highlight(foo) { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -50,7 +50,7 @@ CssRoot { r_curly_token: R_CURLY@21..23 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -81,7 +81,7 @@ CssRoot { r_curly_token: R_CURLY@46..48 "}" [Newline("\n")] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -123,7 +123,7 @@ CssRoot { 0: CSS_ROOT@0..74 0: (empty) 1: CSS_RULE_LIST@0..73 - 0: CSS_RULE@0..23 + 0: CSS_QUALIFIED_RULE@0..23 0: CSS_SELECTOR_LIST@0..20 0: CSS_COMPOUND_SELECTOR@0..20 0: (empty) @@ -141,7 +141,7 @@ CssRoot { 0: L_CURLY@20..21 "{" [] [] 1: CSS_DECLARATION_LIST@21..21 2: R_CURLY@21..23 "}" [Newline("\n")] [] - 1: CSS_RULE@23..48 + 1: CSS_QUALIFIED_RULE@23..48 0: CSS_SELECTOR_LIST@23..45 0: CSS_COMPOUND_SELECTOR@23..45 0: (empty) @@ -162,7 +162,7 @@ CssRoot { 0: L_CURLY@45..46 "{" [] [] 1: CSS_DECLARATION_LIST@46..46 2: R_CURLY@46..48 "}" [Newline("\n")] [] - 2: CSS_RULE@48..73 + 2: CSS_QUALIFIED_RULE@48..73 0: CSS_SELECTOR_LIST@48..70 0: CSS_COMPOUND_SELECTOR@48..70 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/part.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/part.css.snap index f360bc2e79b8..8aaca7e04a12 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/part.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/part.css.snap @@ -18,7 +18,7 @@ tabbed-custom-element::part( active ) {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -49,7 +49,7 @@ CssRoot { r_curly_token: R_CURLY@37..38 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -91,7 +91,7 @@ CssRoot { 0: CSS_ROOT@0..84 0: (empty) 1: CSS_RULE_LIST@0..83 - 0: CSS_RULE@0..38 + 0: CSS_QUALIFIED_RULE@0..38 0: CSS_SELECTOR_LIST@0..36 0: CSS_COMPOUND_SELECTOR@0..36 0: (empty) @@ -112,7 +112,7 @@ CssRoot { 0: L_CURLY@36..37 "{" [] [] 1: CSS_DECLARATION_LIST@37..37 2: R_CURLY@37..38 "}" [] [] - 1: CSS_RULE@38..83 + 1: CSS_QUALIFIED_RULE@38..83 0: CSS_SELECTOR_LIST@38..81 0: CSS_COMPOUND_SELECTOR@38..81 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/presudo_complex.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/presudo_complex.css.snap index 1a76bfa201f8..105e1979239a 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/presudo_complex.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/presudo_complex.css.snap @@ -22,7 +22,7 @@ video::cue(b) div {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -63,7 +63,7 @@ CssRoot { r_curly_token: R_CURLY@14..15 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -104,7 +104,7 @@ CssRoot { r_curly_token: R_CURLY@32..33 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -157,7 +157,7 @@ CssRoot { r_curly_token: R_CURLY@53..54 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -196,7 +196,7 @@ CssRoot { r_curly_token: R_CURLY@80..81 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssComplexSelector { left: CssCompoundSelector { @@ -235,7 +235,7 @@ CssRoot { r_curly_token: R_CURLY@102..103 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -301,7 +301,7 @@ CssRoot { 0: CSS_ROOT@0..131 0: (empty) 1: CSS_RULE_LIST@0..130 - 0: CSS_RULE@0..15 + 0: CSS_QUALIFIED_RULE@0..15 0: CSS_SELECTOR_LIST@0..13 0: CSS_COMPLEX_SELECTOR@0..13 0: CSS_COMPOUND_SELECTOR@0..8 @@ -328,7 +328,7 @@ CssRoot { 0: L_CURLY@13..14 "{" [] [] 1: CSS_DECLARATION_LIST@14..14 2: R_CURLY@14..15 "}" [] [] - 1: CSS_RULE@15..33 + 1: CSS_QUALIFIED_RULE@15..33 0: CSS_SELECTOR_LIST@15..31 0: CSS_COMPLEX_SELECTOR@15..31 0: CSS_COMPOUND_SELECTOR@15..26 @@ -355,7 +355,7 @@ CssRoot { 0: L_CURLY@31..32 "{" [] [] 1: CSS_DECLARATION_LIST@32..32 2: R_CURLY@32..33 "}" [] [] - 2: CSS_RULE@33..54 + 2: CSS_QUALIFIED_RULE@33..54 0: CSS_SELECTOR_LIST@33..52 0: CSS_COMPLEX_SELECTOR@33..52 0: CSS_COMPOUND_SELECTOR@33..47 @@ -391,7 +391,7 @@ CssRoot { 0: L_CURLY@52..53 "{" [] [] 1: CSS_DECLARATION_LIST@53..53 2: R_CURLY@53..54 "}" [] [] - 3: CSS_RULE@54..81 + 3: CSS_QUALIFIED_RULE@54..81 0: CSS_SELECTOR_LIST@54..79 0: CSS_COMPLEX_SELECTOR@54..79 0: CSS_COMPOUND_SELECTOR@54..74 @@ -418,7 +418,7 @@ CssRoot { 0: L_CURLY@79..80 "{" [] [] 1: CSS_DECLARATION_LIST@80..80 2: R_CURLY@80..81 "}" [] [] - 4: CSS_RULE@81..103 + 4: CSS_QUALIFIED_RULE@81..103 0: CSS_SELECTOR_LIST@81..101 0: CSS_COMPLEX_SELECTOR@81..101 0: CSS_COMPOUND_SELECTOR@81..96 @@ -445,7 +445,7 @@ CssRoot { 0: L_CURLY@101..102 "{" [] [] 1: CSS_DECLARATION_LIST@102..102 2: R_CURLY@102..103 "}" [] [] - 5: CSS_RULE@103..130 + 5: CSS_QUALIFIED_RULE@103..130 0: CSS_SELECTOR_LIST@103..128 0: CSS_COMPOUND_SELECTOR@103..128 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/slotted.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/slotted.css.snap index a5440f8204c1..ac060002c776 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/slotted.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/pseudo_element/slotted.css.snap @@ -21,7 +21,7 @@ expression: snapshot CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -54,7 +54,7 @@ CssRoot { r_curly_token: R_CURLY@14..15 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -89,7 +89,7 @@ CssRoot { r_curly_token: R_CURLY@33..34 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -124,7 +124,7 @@ CssRoot { r_curly_token: R_CURLY@58..59 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -170,7 +170,7 @@ CssRoot { 0: CSS_ROOT@0..80 0: (empty) 1: CSS_RULE_LIST@0..79 - 0: CSS_RULE@0..15 + 0: CSS_QUALIFIED_RULE@0..15 0: CSS_SELECTOR_LIST@0..13 0: CSS_COMPOUND_SELECTOR@0..13 0: (empty) @@ -193,7 +193,7 @@ CssRoot { 0: L_CURLY@13..14 "{" [] [] 1: CSS_DECLARATION_LIST@14..14 2: R_CURLY@14..15 "}" [] [] - 1: CSS_RULE@15..34 + 1: CSS_QUALIFIED_RULE@15..34 0: CSS_SELECTOR_LIST@15..32 0: CSS_COMPOUND_SELECTOR@15..32 0: (empty) @@ -217,7 +217,7 @@ CssRoot { 0: L_CURLY@32..33 "{" [] [] 1: CSS_DECLARATION_LIST@33..33 2: R_CURLY@33..34 "}" [] [] - 2: CSS_RULE@34..59 + 2: CSS_QUALIFIED_RULE@34..59 0: CSS_SELECTOR_LIST@34..57 0: CSS_COMPOUND_SELECTOR@34..57 0: (empty) @@ -241,7 +241,7 @@ CssRoot { 0: L_CURLY@57..58 "{" [] [] 1: CSS_DECLARATION_LIST@58..58 2: R_CURLY@58..59 "}" [] [] - 3: CSS_RULE@59..79 + 3: CSS_QUALIFIED_RULE@59..79 0: CSS_SELECTOR_LIST@59..76 0: CSS_COMPOUND_SELECTOR@59..76 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/subselector.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/subselector.css.snap index ca5f62bbad07..dc89a8b84eb4 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/subselector.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/subselector.css.snap @@ -21,7 +21,7 @@ div.class.content#id#id, *.class.content#id#id1, .class.content#id#id1 {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -65,7 +65,7 @@ CssRoot { r_curly_token: R_CURLY@25..26 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -107,7 +107,7 @@ CssRoot { r_curly_token: R_CURLY@51..52 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -146,7 +146,7 @@ CssRoot { r_curly_token: R_CURLY@76..77 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -266,7 +266,7 @@ CssRoot { 0: CSS_ROOT@0..153 0: (empty) 1: CSS_RULE_LIST@0..152 - 0: CSS_RULE@0..26 + 0: CSS_QUALIFIED_RULE@0..26 0: CSS_SELECTOR_LIST@0..24 0: CSS_COMPOUND_SELECTOR@0..24 0: (empty) @@ -295,7 +295,7 @@ CssRoot { 0: L_CURLY@24..25 "{" [] [] 1: CSS_DECLARATION_LIST@25..25 2: R_CURLY@25..26 "}" [] [] - 1: CSS_RULE@26..52 + 1: CSS_QUALIFIED_RULE@26..52 0: CSS_SELECTOR_LIST@26..50 0: CSS_COMPOUND_SELECTOR@26..50 0: (empty) @@ -323,7 +323,7 @@ CssRoot { 0: L_CURLY@50..51 "{" [] [] 1: CSS_DECLARATION_LIST@51..51 2: R_CURLY@51..52 "}" [] [] - 2: CSS_RULE@52..77 + 2: CSS_QUALIFIED_RULE@52..77 0: CSS_SELECTOR_LIST@52..75 0: CSS_COMPOUND_SELECTOR@52..75 0: (empty) @@ -349,7 +349,7 @@ CssRoot { 0: L_CURLY@75..76 "{" [] [] 1: CSS_DECLARATION_LIST@76..76 2: R_CURLY@76..77 "}" [] [] - 3: CSS_RULE@77..152 + 3: CSS_QUALIFIED_RULE@77..152 0: CSS_SELECTOR_LIST@77..150 0: CSS_COMPOUND_SELECTOR@77..102 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/type.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/type.css.snap index 4490bf80d2b6..019297259536 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/type.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/type.css.snap @@ -20,7 +20,7 @@ foo|h1 {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -50,7 +50,7 @@ CssRoot { r_curly_token: R_CURLY@8..9 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -76,7 +76,7 @@ CssRoot { r_curly_token: R_CURLY@18..19 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -98,7 +98,7 @@ CssRoot { r_curly_token: R_CURLY@25..26 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -133,7 +133,7 @@ CssRoot { 0: CSS_ROOT@0..35 0: (empty) 1: CSS_RULE_LIST@0..34 - 0: CSS_RULE@0..9 + 0: CSS_QUALIFIED_RULE@0..9 0: CSS_SELECTOR_LIST@0..7 0: CSS_COMPOUND_SELECTOR@0..3 0: (empty) @@ -154,7 +154,7 @@ CssRoot { 0: L_CURLY@7..8 "{" [] [] 1: CSS_DECLARATION_LIST@8..8 2: R_CURLY@8..9 "}" [] [] - 1: CSS_RULE@9..19 + 1: CSS_QUALIFIED_RULE@9..19 0: CSS_SELECTOR_LIST@9..17 0: CSS_COMPOUND_SELECTOR@9..17 0: (empty) @@ -171,7 +171,7 @@ CssRoot { 0: L_CURLY@17..18 "{" [] [] 1: CSS_DECLARATION_LIST@18..18 2: R_CURLY@18..19 "}" [] [] - 2: CSS_RULE@19..26 + 2: CSS_QUALIFIED_RULE@19..26 0: CSS_SELECTOR_LIST@19..24 0: CSS_COMPOUND_SELECTOR@19..24 0: (empty) @@ -186,7 +186,7 @@ CssRoot { 0: L_CURLY@24..25 "{" [] [] 1: CSS_DECLARATION_LIST@25..25 2: R_CURLY@25..26 "}" [] [] - 3: CSS_RULE@26..34 + 3: CSS_QUALIFIED_RULE@26..34 0: CSS_SELECTOR_LIST@26..32 0: CSS_COMPOUND_SELECTOR@26..32 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/selector/universal.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/selector/universal.css.snap index ffc4e252388d..4e5dff17f02f 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/selector/universal.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/selector/universal.css.snap @@ -19,7 +19,7 @@ foo|* {} CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -45,7 +45,7 @@ CssRoot { r_curly_token: R_CURLY@7..8 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -67,7 +67,7 @@ CssRoot { r_curly_token: R_CURLY@14..15 "}" [] [], }, }, - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -102,7 +102,7 @@ CssRoot { 0: CSS_ROOT@0..25 0: (empty) 1: CSS_RULE_LIST@0..24 - 0: CSS_RULE@0..8 + 0: CSS_QUALIFIED_RULE@0..8 0: CSS_SELECTOR_LIST@0..6 0: CSS_COMPOUND_SELECTOR@0..2 0: (empty) @@ -121,7 +121,7 @@ CssRoot { 0: L_CURLY@6..7 "{" [] [] 1: CSS_DECLARATION_LIST@7..7 2: R_CURLY@7..8 "}" [] [] - 1: CSS_RULE@8..15 + 1: CSS_QUALIFIED_RULE@8..15 0: CSS_SELECTOR_LIST@8..13 0: CSS_COMPOUND_SELECTOR@8..13 0: (empty) @@ -136,7 +136,7 @@ CssRoot { 0: L_CURLY@13..14 "{" [] [] 1: CSS_DECLARATION_LIST@14..14 2: R_CURLY@14..15 "}" [] [] - 2: CSS_RULE@15..24 + 2: CSS_QUALIFIED_RULE@15..24 0: CSS_SELECTOR_LIST@15..22 0: CSS_COMPOUND_SELECTOR@15..22 0: (empty) diff --git a/crates/biome_css_parser/tests/css_test_suite/ok/values/url_value.css.snap b/crates/biome_css_parser/tests/css_test_suite/ok/values/url_value.css.snap index 09927b4b0305..f7a323e17a5b 100644 --- a/crates/biome_css_parser/tests/css_test_suite/ok/values/url_value.css.snap +++ b/crates/biome_css_parser/tests/css_test_suite/ok/values/url_value.css.snap @@ -56,7 +56,7 @@ div { CssRoot { bom_token: missing (optional), rules: CssRuleList [ - CssRule { + CssQualifiedRule { prelude: CssSelectorList [ CssCompoundSelector { nesting_selector_token: missing (optional), @@ -690,7 +690,7 @@ CssRoot { 0: CSS_ROOT@0..1291 0: (empty) 1: CSS_RULE_LIST@0..1290 - 0: CSS_RULE@0..1290 + 0: CSS_QUALIFIED_RULE@0..1290 0: CSS_SELECTOR_LIST@0..4 0: CSS_COMPOUND_SELECTOR@0..4 0: (empty) diff --git a/crates/biome_css_syntax/src/generated/kind.rs b/crates/biome_css_syntax/src/generated/kind.rs index bfe9bf9d4b27..772580ce5f3c 100644 --- a/crates/biome_css_syntax/src/generated/kind.rs +++ b/crates/biome_css_syntax/src/generated/kind.rs @@ -236,7 +236,7 @@ pub enum CssSyntaxKind { MULTILINE_COMMENT, CSS_ROOT, CSS_RULE_LIST, - CSS_RULE, + CSS_QUALIFIED_RULE, CSS_SELECTOR_LIST, CSS_ANY_FUNCTION, CSS_DECLARATION_LIST_BLOCK, diff --git a/crates/biome_css_syntax/src/generated/macros.rs b/crates/biome_css_syntax/src/generated/macros.rs index 26c056aadf01..60f16d090829 100644 --- a/crates/biome_css_syntax/src/generated/macros.rs +++ b/crates/biome_css_syntax/src/generated/macros.rs @@ -447,6 +447,10 @@ macro_rules! map_syntax_node { let $pattern = unsafe { $crate::CssPseudoElementSelector::new_unchecked(node) }; $body } + $crate::CssSyntaxKind::CSS_QUALIFIED_RULE => { + let $pattern = unsafe { $crate::CssQualifiedRule::new_unchecked(node) }; + $body + } $crate::CssSyntaxKind::CSS_QUERY_FEATURE_BOOLEAN => { let $pattern = unsafe { $crate::CssQueryFeatureBoolean::new_unchecked(node) }; $body @@ -490,10 +494,6 @@ macro_rules! map_syntax_node { let $pattern = unsafe { $crate::CssRoot::new_unchecked(node) }; $body } - $crate::CssSyntaxKind::CSS_RULE => { - let $pattern = unsafe { $crate::CssRule::new_unchecked(node) }; - $body - } $crate::CssSyntaxKind::CSS_RULE_LIST_BLOCK => { let $pattern = unsafe { $crate::CssRuleListBlock::new_unchecked(node) }; $body diff --git a/crates/biome_css_syntax/src/generated/nodes.rs b/crates/biome_css_syntax/src/generated/nodes.rs index 1921acaf391a..7460341c6cf0 100644 --- a/crates/biome_css_syntax/src/generated/nodes.rs +++ b/crates/biome_css_syntax/src/generated/nodes.rs @@ -4417,6 +4417,47 @@ pub struct CssPseudoElementSelectorFields { pub element: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] +pub struct CssQualifiedRule { + pub(crate) syntax: SyntaxNode, +} +impl CssQualifiedRule { + #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] + #[doc = r""] + #[doc = r" # Safety"] + #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] + #[doc = r" or a match on [SyntaxNode::kind]"] + #[inline] + pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { + Self { syntax } + } + pub fn as_fields(&self) -> CssQualifiedRuleFields { + CssQualifiedRuleFields { + prelude: self.prelude(), + block: self.block(), + } + } + pub fn prelude(&self) -> CssSelectorList { + support::list(&self.syntax, 0usize) + } + pub fn block(&self) -> SyntaxResult { + support::required_node(&self.syntax, 1usize) + } +} +#[cfg(feature = "serde")] +impl Serialize for CssQualifiedRule { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.as_fields().serialize(serializer) + } +} +#[cfg_attr(feature = "serde", derive(Serialize))] +pub struct CssQualifiedRuleFields { + pub prelude: CssSelectorList, + pub block: SyntaxResult, +} +#[derive(Clone, PartialEq, Eq, Hash)] pub struct CssQueryFeatureBoolean { pub(crate) syntax: SyntaxNode, } @@ -4855,47 +4896,6 @@ pub struct CssRootFields { pub eof_token: SyntaxResult, } #[derive(Clone, PartialEq, Eq, Hash)] -pub struct CssRule { - pub(crate) syntax: SyntaxNode, -} -impl CssRule { - #[doc = r" Create an AstNode from a SyntaxNode without checking its kind"] - #[doc = r""] - #[doc = r" # Safety"] - #[doc = r" This function must be guarded with a call to [AstNode::can_cast]"] - #[doc = r" or a match on [SyntaxNode::kind]"] - #[inline] - pub const unsafe fn new_unchecked(syntax: SyntaxNode) -> Self { - Self { syntax } - } - pub fn as_fields(&self) -> CssRuleFields { - CssRuleFields { - prelude: self.prelude(), - block: self.block(), - } - } - pub fn prelude(&self) -> CssSelectorList { - support::list(&self.syntax, 0usize) - } - pub fn block(&self) -> SyntaxResult { - support::required_node(&self.syntax, 1usize) - } -} -#[cfg(feature = "serde")] -impl Serialize for CssRule { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.as_fields().serialize(serializer) - } -} -#[cfg_attr(feature = "serde", derive(Serialize))] -pub struct CssRuleFields { - pub prelude: CssSelectorList, - pub block: SyntaxResult, -} -#[derive(Clone, PartialEq, Eq, Hash)] pub struct CssRuleListBlock { pub(crate) syntax: SyntaxNode, } @@ -7420,7 +7420,7 @@ impl AnyCssRelativeSelector { pub enum AnyCssRule { CssAtRule(CssAtRule), CssBogusRule(CssBogusRule), - CssRule(CssRule), + CssQualifiedRule(CssQualifiedRule), } impl AnyCssRule { pub fn as_css_at_rule(&self) -> Option<&CssAtRule> { @@ -7435,9 +7435,9 @@ impl AnyCssRule { _ => None, } } - pub fn as_css_rule(&self) -> Option<&CssRule> { + pub fn as_css_qualified_rule(&self) -> Option<&CssQualifiedRule> { match &self { - AnyCssRule::CssRule(item) => Some(item), + AnyCssRule::CssQualifiedRule(item) => Some(item), _ => None, } } @@ -12147,6 +12147,45 @@ impl From for SyntaxElement { n.syntax.into() } } +impl AstNode for CssQualifiedRule { + type Language = Language; + const KIND_SET: SyntaxKindSet = + SyntaxKindSet::from_raw(RawSyntaxKind(CSS_QUALIFIED_RULE as u16)); + fn can_cast(kind: SyntaxKind) -> bool { + kind == CSS_QUALIFIED_RULE + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } + fn into_syntax(self) -> SyntaxNode { + self.syntax + } +} +impl std::fmt::Debug for CssQualifiedRule { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("CssQualifiedRule") + .field("prelude", &self.prelude()) + .field("block", &support::DebugSyntaxResult(self.block())) + .finish() + } +} +impl From for SyntaxNode { + fn from(n: CssQualifiedRule) -> SyntaxNode { + n.syntax + } +} +impl From for SyntaxElement { + fn from(n: CssQualifiedRule) -> SyntaxElement { + n.syntax.into() + } +} impl AstNode for CssQueryFeatureBoolean { type Language = Language; const KIND_SET: SyntaxKindSet = @@ -12567,45 +12606,6 @@ impl From for SyntaxElement { n.syntax.into() } } -impl AstNode for CssRule { - type Language = Language; - const KIND_SET: SyntaxKindSet = - SyntaxKindSet::from_raw(RawSyntaxKind(CSS_RULE as u16)); - fn can_cast(kind: SyntaxKind) -> bool { - kind == CSS_RULE - } - fn cast(syntax: SyntaxNode) -> Option { - if Self::can_cast(syntax.kind()) { - Some(Self { syntax }) - } else { - None - } - } - fn syntax(&self) -> &SyntaxNode { - &self.syntax - } - fn into_syntax(self) -> SyntaxNode { - self.syntax - } -} -impl std::fmt::Debug for CssRule { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("CssRule") - .field("prelude", &self.prelude()) - .field("block", &support::DebugSyntaxResult(self.block())) - .finish() - } -} -impl From for SyntaxNode { - fn from(n: CssRule) -> SyntaxNode { - n.syntax - } -} -impl From for SyntaxElement { - fn from(n: CssRule) -> SyntaxElement { - n.syntax.into() - } -} impl AstNode for CssRuleListBlock { type Language = Language; const KIND_SET: SyntaxKindSet = @@ -17892,24 +17892,24 @@ impl From for AnyCssRule { AnyCssRule::CssBogusRule(node) } } -impl From for AnyCssRule { - fn from(node: CssRule) -> AnyCssRule { - AnyCssRule::CssRule(node) +impl From for AnyCssRule { + fn from(node: CssQualifiedRule) -> AnyCssRule { + AnyCssRule::CssQualifiedRule(node) } } impl AstNode for AnyCssRule { type Language = Language; const KIND_SET: SyntaxKindSet = CssAtRule::KIND_SET .union(CssBogusRule::KIND_SET) - .union(CssRule::KIND_SET); + .union(CssQualifiedRule::KIND_SET); fn can_cast(kind: SyntaxKind) -> bool { - matches!(kind, CSS_AT_RULE | CSS_BOGUS_RULE | CSS_RULE) + matches!(kind, CSS_AT_RULE | CSS_BOGUS_RULE | CSS_QUALIFIED_RULE) } fn cast(syntax: SyntaxNode) -> Option { let res = match syntax.kind() { CSS_AT_RULE => AnyCssRule::CssAtRule(CssAtRule { syntax }), CSS_BOGUS_RULE => AnyCssRule::CssBogusRule(CssBogusRule { syntax }), - CSS_RULE => AnyCssRule::CssRule(CssRule { syntax }), + CSS_QUALIFIED_RULE => AnyCssRule::CssQualifiedRule(CssQualifiedRule { syntax }), _ => return None, }; Some(res) @@ -17918,14 +17918,14 @@ impl AstNode for AnyCssRule { match self { AnyCssRule::CssAtRule(it) => &it.syntax, AnyCssRule::CssBogusRule(it) => &it.syntax, - AnyCssRule::CssRule(it) => &it.syntax, + AnyCssRule::CssQualifiedRule(it) => &it.syntax, } } fn into_syntax(self) -> SyntaxNode { match self { AnyCssRule::CssAtRule(it) => it.syntax, AnyCssRule::CssBogusRule(it) => it.syntax, - AnyCssRule::CssRule(it) => it.syntax, + AnyCssRule::CssQualifiedRule(it) => it.syntax, } } } @@ -17934,7 +17934,7 @@ impl std::fmt::Debug for AnyCssRule { match self { AnyCssRule::CssAtRule(it) => std::fmt::Debug::fmt(it, f), AnyCssRule::CssBogusRule(it) => std::fmt::Debug::fmt(it, f), - AnyCssRule::CssRule(it) => std::fmt::Debug::fmt(it, f), + AnyCssRule::CssQualifiedRule(it) => std::fmt::Debug::fmt(it, f), } } } @@ -17943,7 +17943,7 @@ impl From for SyntaxNode { match n { AnyCssRule::CssAtRule(it) => it.into(), AnyCssRule::CssBogusRule(it) => it.into(), - AnyCssRule::CssRule(it) => it.into(), + AnyCssRule::CssQualifiedRule(it) => it.into(), } } } @@ -20035,6 +20035,11 @@ impl std::fmt::Display for CssPseudoElementSelector { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for CssQualifiedRule { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for CssQueryFeatureBoolean { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -20085,11 +20090,6 @@ impl std::fmt::Display for CssRoot { std::fmt::Display::fmt(self.syntax(), f) } } -impl std::fmt::Display for CssRule { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(self.syntax(), f) - } -} impl std::fmt::Display for CssRuleListBlock { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/crates/biome_css_syntax/src/generated/nodes_mut.rs b/crates/biome_css_syntax/src/generated/nodes_mut.rs index a1bd3300110e..69f34b9eb69b 100644 --- a/crates/biome_css_syntax/src/generated/nodes_mut.rs +++ b/crates/biome_css_syntax/src/generated/nodes_mut.rs @@ -1742,6 +1742,20 @@ impl CssPseudoElementSelector { ) } } +impl CssQualifiedRule { + pub fn with_prelude(self, element: CssSelectorList) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(0usize..=0usize, once(Some(element.into_syntax().into()))), + ) + } + pub fn with_block(self, element: AnyCssDeclarationListBlock) -> Self { + Self::unwrap_cast( + self.syntax + .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), + ) + } +} impl CssQueryFeatureBoolean { pub fn with_name(self, element: CssIdentifier) -> Self { Self::unwrap_cast( @@ -1918,20 +1932,6 @@ impl CssRoot { ) } } -impl CssRule { - pub fn with_prelude(self, element: CssSelectorList) -> Self { - Self::unwrap_cast( - self.syntax - .splice_slots(0usize..=0usize, once(Some(element.into_syntax().into()))), - ) - } - pub fn with_block(self, element: AnyCssDeclarationListBlock) -> Self { - Self::unwrap_cast( - self.syntax - .splice_slots(1usize..=1usize, once(Some(element.into_syntax().into()))), - ) - } -} impl CssRuleListBlock { pub fn with_l_curly_token(self, element: SyntaxToken) -> Self { Self::unwrap_cast( diff --git a/crates/biome_unicode_table/src/tables.rs b/crates/biome_unicode_table/src/tables.rs index 7700038e9f9c..3ed00b032140 100644 --- a/crates/biome_unicode_table/src/tables.rs +++ b/crates/biome_unicode_table/src/tables.rs @@ -318,7 +318,6 @@ pub mod derived_property { ('ῠ', 'Ῥ'), ('ῲ', 'ῴ'), ('ῶ', 'ῼ'), - ('\u{200c}', '\u{200d}'), ('‿', '⁀'), ('⁔', '⁔'), ('ⁱ', 'ⁱ'), @@ -363,7 +362,8 @@ pub mod derived_property { ('〸', '〼'), ('ぁ', 'ゖ'), ('\u{3099}', 'ゟ'), - ('ァ', 'ヿ'), + ('ァ', 'ヺ'), + ('ー', 'ヿ'), ('ㄅ', 'ㄯ'), ('ㄱ', 'ㆎ'), ('ㆠ', 'ㆿ'), @@ -441,7 +441,7 @@ pub mod derived_property { ('A', 'Z'), ('_', '_'), ('a', 'z'), - ('・', 'ᄒ'), + ('ヲ', 'ᄒ'), ('ᅡ', 'ᅦ'), ('ᅧ', 'ᅬ'), ('ᅭ', 'ᅲ'), @@ -782,7 +782,6 @@ pub mod derived_property { ('𫝀', '𫠝'), ('𫠠', '𬺡'), ('𬺰', '𮯠'), - ('\u{2ebf0}', '\u{2ee5d}'), ('丽', '𪘀'), ('𰀀', '𱍊'), ('𱍐', '𲎯'), @@ -1448,7 +1447,6 @@ pub mod derived_property { ('𫝀', '𫠝'), ('𫠠', '𬺡'), ('𬺰', '𮯠'), - ('\u{2ebf0}', '\u{2ee5d}'), ('丽', '𪘀'), ('𰀀', '𱍊'), ('𱍐', '𲎯'), diff --git a/xtask/codegen/css.ungram b/xtask/codegen/css.ungram index 45496400ae0f..e1557dfeb9bc 100644 --- a/xtask/codegen/css.ungram +++ b/xtask/codegen/css.ungram @@ -64,13 +64,13 @@ CssRoot = CssRuleList = AnyCssRule* AnyCssRule = - CssRule + CssQualifiedRule | CssAtRule | CssBogusRule // .header { color: red } // ^^^^^^^^^^^^^^^^^^^^^ -CssRule = +CssQualifiedRule = prelude: CssSelectorList block: AnyCssDeclarationListBlock diff --git a/xtask/codegen/src/css_kinds_src.rs b/xtask/codegen/src/css_kinds_src.rs index 973577f64568..0ee75c1ece88 100644 --- a/xtask/codegen/src/css_kinds_src.rs +++ b/xtask/codegen/src/css_kinds_src.rs @@ -260,7 +260,7 @@ pub const CSS_KINDS_SRC: KindsSrc = KindsSrc { nodes: &[ "CSS_ROOT", "CSS_RULE_LIST", - "CSS_RULE", + "CSS_QUALIFIED_RULE", "CSS_SELECTOR_LIST", "CSS_ANY_FUNCTION", "CSS_DECLARATION_LIST_BLOCK", From cf3434ca87a6654672d48de45d0be2b457bf8f39 Mon Sep 17 00:00:00 2001 From: Victorien Elvinger Date: Fri, 12 Jan 2024 23:29:51 +0100 Subject: [PATCH 04/49] fix(js_formatter): fix #1511 (#1547) Co-authored-by: Emanuele Stoppa --- CHANGELOG.md | 4 +- crates/biome_formatter/src/buffer.rs | 4 -- .../tests/specs/ts/issue1511.ts | 3 ++ .../tests/specs/ts/issue1511.ts.snap | 43 +++++++++++++++++++ .../src/content/docs/internals/changelog.mdx | 4 +- .../docs/zh-cn/internals/changelog.mdx | 4 +- 6 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 crates/biome_js_formatter/tests/specs/ts/issue1511.ts create mode 100644 crates/biome_js_formatter/tests/specs/ts/issue1511.ts.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index dd6f5460d814..060b9d77b307 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,8 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom - Fix [#1172](https://github.com/biomejs/biome/issues/1172). Fix placement of line comment after function expression parentheses, they are now attached to first statement in body. Contributed by @kalleep +- Fix [#1511](https://github.com/biomejs/biome/issues/1511) that made the JavaScript formatter crash. Contributed @Conaclos + ### JavaScript APIs ### Linter @@ -1916,7 +1918,7 @@ The following rules are now recommended: The code action now removes any whitespace between the parameter name and its initialization. -- Relax [noConfusingArrow](https://biomejs.dev/linter/rules/no-confusing-arrow/) +- Relax `noConfusingArrow` All arrow functions that enclose its parameter with parenthesis are allowed. Thus, the following snippet no longer trigger the rule: diff --git a/crates/biome_formatter/src/buffer.rs b/crates/biome_formatter/src/buffer.rs index 420990336ca7..5012067d2c96 100644 --- a/crates/biome_formatter/src/buffer.rs +++ b/crates/biome_formatter/src/buffer.rs @@ -557,10 +557,6 @@ fn clean_interned( Some((mut cleaned, rest)) => { let mut is_in_expanded_conditional_content = false; for element in rest { - if is_in_expanded_conditional_content { - continue; - } - let element = match element { FormatElement::Tag(Tag::StartConditionalContent(condition)) if condition.mode == PrintMode::Expanded => diff --git a/crates/biome_js_formatter/tests/specs/ts/issue1511.ts b/crates/biome_js_formatter/tests/specs/ts/issue1511.ts new file mode 100644 index 000000000000..5ea570eb2e82 --- /dev/null +++ b/crates/biome_js_formatter/tests/specs/ts/issue1511.ts @@ -0,0 +1,3 @@ +call(a, function (b: () => t1 | t2) {}); + +call(a, (b: () => t1 | t2) => {}); diff --git a/crates/biome_js_formatter/tests/specs/ts/issue1511.ts.snap b/crates/biome_js_formatter/tests/specs/ts/issue1511.ts.snap new file mode 100644 index 000000000000..c39f8cb433b1 --- /dev/null +++ b/crates/biome_js_formatter/tests/specs/ts/issue1511.ts.snap @@ -0,0 +1,43 @@ +--- +source: crates/biome_formatter_test/src/snapshot_builder.rs +info: ts/issue1511.ts +--- + +# Input + +```ts +call(a, function (b: () => t1 | t2) {}); + +call(a, (b: () => t1 | t2) => {}); + +``` + + +============================= + +# Outputs + +## Output 1 + +----- +Indent style: Tab +Indent width: 2 +Line ending: LF +Line width: 80 +Quote style: Double Quotes +JSX quote style: Double Quotes +Quote properties: As needed +Trailing comma: All +Semicolons: Always +Arrow parentheses: Always +Bracket spacing: true +Bracket same line: false +----- + +```ts +call(a, function (b: () => t1 | t2) {}); + +call(a, (b: () => t1 | t2) => {}); +``` + + diff --git a/website/src/content/docs/internals/changelog.mdx b/website/src/content/docs/internals/changelog.mdx index bd9a6ce29c19..0ceda15560e9 100644 --- a/website/src/content/docs/internals/changelog.mdx +++ b/website/src/content/docs/internals/changelog.mdx @@ -43,6 +43,8 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom - Fix [#1172](https://github.com/biomejs/biome/issues/1172). Fix placement of line comment after function expression parentheses, they are now attached to first statement in body. Contributed by @kalleep +- Fix [#1511](https://github.com/biomejs/biome/issues/1511) that made the JavaScript formatter crash. Contributed @Conaclos + ### JavaScript APIs ### Linter @@ -1922,7 +1924,7 @@ The following rules are now recommended: The code action now removes any whitespace between the parameter name and its initialization. -- Relax [noConfusingArrow](https://biomejs.dev/linter/rules/no-confusing-arrow/) +- Relax `noConfusingArrow` All arrow functions that enclose its parameter with parenthesis are allowed. Thus, the following snippet no longer trigger the rule: diff --git a/website/src/content/docs/zh-cn/internals/changelog.mdx b/website/src/content/docs/zh-cn/internals/changelog.mdx index 0eb0fdcdc773..36ce590a7b15 100644 --- a/website/src/content/docs/zh-cn/internals/changelog.mdx +++ b/website/src/content/docs/zh-cn/internals/changelog.mdx @@ -1216,7 +1216,7 @@ The following rules are promoted: #### Removed rules -- Remove [noConfusingArrow](https://biomejs.dev/linter/rules/no-confusing-arrow/). +- Remove `noConfusingArrow` Code formatters, such as prettier and Biome, always adds parentheses around the parameter or the body of an arrow function. This makes the rule useless. @@ -1876,7 +1876,7 @@ The following rules are now recommended: The code action now removes any whitespace between the parameter name and its initialization. -- Relax [noConfusingArrow](https://biomejs.dev/linter/rules/no-confusing-arrow/) +- Relax `noConfusingArrow` All arrow functions that enclose its parameter with parenthesis are allowed. Thus, the following snippet no longer trigger the rule: From 029ec57f27b112c0a3691932b3004f42926fd20d Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Sat, 13 Jan 2024 10:42:15 +0000 Subject: [PATCH 05/49] feat: foudations for migration from prettier (#1545) --- crates/biome_cli/Cargo.toml | 1 + crates/biome_cli/src/commands/migrate.rs | 2 + crates/biome_cli/src/commands/mod.rs | 25 +- crates/biome_cli/src/execute/migrate.rs | 29 +- .../biome_cli/src/execute/migrate/prettier.rs | 461 ++++++++++++++++++ crates/biome_cli/src/execute/mod.rs | 15 +- crates/biome_cli/src/lib.rs | 8 +- crates/biome_deserialize/README.md | 2 +- crates/biome_js_formatter/src/context.rs | 2 +- 9 files changed, 521 insertions(+), 24 deletions(-) create mode 100644 crates/biome_cli/src/execute/migrate/prettier.rs diff --git a/crates/biome_cli/Cargo.toml b/crates/biome_cli/Cargo.toml index 95bbdc367539..06f847fab337 100644 --- a/crates/biome_cli/Cargo.toml +++ b/crates/biome_cli/Cargo.toml @@ -26,6 +26,7 @@ biome_diagnostics = { workspace = true } biome_flags = { workspace = true } biome_formatter = { workspace = true } biome_fs = { workspace = true } +biome_js_formatter = { workspace = true } biome_json_formatter = { workspace = true } biome_json_parser = { workspace = true } biome_json_syntax = { workspace = true } diff --git a/crates/biome_cli/src/commands/migrate.rs b/crates/biome_cli/src/commands/migrate.rs index f1a643ce677b..c84e0dfd86d5 100644 --- a/crates/biome_cli/src/commands/migrate.rs +++ b/crates/biome_cli/src/commands/migrate.rs @@ -11,6 +11,7 @@ pub(crate) fn migrate( session: CliSession, cli_options: CliOptions, write: bool, + prettier: bool, ) -> Result<(), CliDiagnostic> { let base_path = match cli_options.config_path.as_ref() { None => ConfigurationBasePath::default(), @@ -30,6 +31,7 @@ pub(crate) fn migrate( write, configuration_file_path: path, configuration_directory_path: directory_path, + prettier, }), session, &cli_options, diff --git a/crates/biome_cli/src/commands/mod.rs b/crates/biome_cli/src/commands/mod.rs index bb5b66b98cb3..3c78c5097dba 100644 --- a/crates/biome_cli/src/commands/mod.rs +++ b/crates/biome_cli/src/commands/mod.rs @@ -248,12 +248,19 @@ pub enum BiomeCommand { ), /// It updates the configuration when there are breaking changes #[bpaf(command)] - Migrate( - #[bpaf(external(cli_options), hide_usage)] CliOptions, + Migrate { + /// It attempts to find the files `.prettierrc`/`prettier.json` and `.prettierignore`, and map + /// Prettier's configuration into `biome.json` + #[bpaf(long("prettier"), switch, hide, hide_usage)] + prettier: bool, + + #[bpaf(external, hide_usage)] + cli_options: CliOptions, + /// Writes the new configuration file to disk #[bpaf(long("write"), switch)] - bool, - ), + write: bool, + }, /// A command to retrieve the documentation of various aspects of the CLI. /// @@ -294,7 +301,7 @@ impl BiomeCommand { | BiomeCommand::Lint { cli_options, .. } | BiomeCommand::Ci { cli_options, .. } | BiomeCommand::Format { cli_options, .. } - | BiomeCommand::Migrate(cli_options, _) => cli_options.colors.as_ref(), + | BiomeCommand::Migrate { cli_options, .. } => cli_options.colors.as_ref(), BiomeCommand::LspProxy(_) | BiomeCommand::Start(_) | BiomeCommand::Stop @@ -313,7 +320,7 @@ impl BiomeCommand { | BiomeCommand::Lint { cli_options, .. } | BiomeCommand::Ci { cli_options, .. } | BiomeCommand::Format { cli_options, .. } - | BiomeCommand::Migrate(cli_options, _) => cli_options.use_server, + | BiomeCommand::Migrate { cli_options, .. } => cli_options.use_server, BiomeCommand::Init | BiomeCommand::Start(_) | BiomeCommand::Stop @@ -334,7 +341,7 @@ impl BiomeCommand { | BiomeCommand::Lint { cli_options, .. } | BiomeCommand::Format { cli_options, .. } | BiomeCommand::Ci { cli_options, .. } - | BiomeCommand::Migrate(cli_options, _) => cli_options.verbose, + | BiomeCommand::Migrate { cli_options, .. } => cli_options.verbose, BiomeCommand::Version(_) | BiomeCommand::Rage(..) | BiomeCommand::Start(_) @@ -353,7 +360,7 @@ impl BiomeCommand { | BiomeCommand::Lint { cli_options, .. } | BiomeCommand::Format { cli_options, .. } | BiomeCommand::Ci { cli_options, .. } - | BiomeCommand::Migrate(cli_options, _) => cli_options.log_level.clone(), + | BiomeCommand::Migrate { cli_options, .. } => cli_options.log_level.clone(), BiomeCommand::Version(_) | BiomeCommand::LspProxy(_) | BiomeCommand::Rage(..) @@ -371,7 +378,7 @@ impl BiomeCommand { | BiomeCommand::Lint { cli_options, .. } | BiomeCommand::Format { cli_options, .. } | BiomeCommand::Ci { cli_options, .. } - | BiomeCommand::Migrate(cli_options, _) => cli_options.log_kind.clone(), + | BiomeCommand::Migrate { cli_options, .. } => cli_options.log_kind.clone(), BiomeCommand::Version(_) | BiomeCommand::Rage(..) | BiomeCommand::LspProxy(_) diff --git a/crates/biome_cli/src/execute/migrate.rs b/crates/biome_cli/src/execute/migrate.rs index 51598e88a88a..fe3b8645eadf 100644 --- a/crates/biome_cli/src/execute/migrate.rs +++ b/crates/biome_cli/src/execute/migrate.rs @@ -1,3 +1,5 @@ +mod prettier; + use crate::execute::diagnostics::{ContentDiffAdvice, MigrateDiffDiagnostic}; use crate::{CliDiagnostic, CliSession}; use biome_console::{markup, ConsoleExt}; @@ -14,13 +16,26 @@ use std::borrow::Cow; use std::ffi::OsStr; use std::path::PathBuf; -pub(crate) fn run( - session: CliSession, - write: bool, - configuration_file_path: PathBuf, - configuration_directory_path: PathBuf, - verbose: bool, -) -> Result<(), CliDiagnostic> { +pub(crate) struct MigratePayload<'a> { + pub(crate) session: CliSession<'a>, + pub(crate) write: bool, + pub(crate) configuration_file_path: PathBuf, + pub(crate) configuration_directory_path: PathBuf, + pub(crate) verbose: bool, + #[allow(unused)] + pub(crate) prettier: bool, +} + +pub(crate) fn run(migrate_payload: MigratePayload) -> Result<(), CliDiagnostic> { + let MigratePayload { + session, + write, + configuration_file_path, + configuration_directory_path, + verbose, + // we will use it later + prettier: _, + } = migrate_payload; let fs = &*session.app.fs; let has_deprecated_configuration = configuration_file_path.file_name() == Some(OsStr::new("rome.json")); diff --git a/crates/biome_cli/src/execute/migrate/prettier.rs b/crates/biome_cli/src/execute/migrate/prettier.rs new file mode 100644 index 000000000000..4ab3054c0863 --- /dev/null +++ b/crates/biome_cli/src/execute/migrate/prettier.rs @@ -0,0 +1,461 @@ +use biome_deserialize::{ + Deserializable, DeserializableValue, DeserializationDiagnostic, DeserializationVisitor, Text, + VisitableType, +}; +use biome_formatter::{LineEnding, LineWidth, QuoteStyle}; +use biome_js_formatter::context::{ArrowParentheses, QuoteProperties, Semicolons, TrailingComma}; +use biome_service::configuration::{FormatterConfiguration, PlainIndentStyle}; +use biome_service::JavascriptFormatter; +use biome_text_size::TextRange; + +#[derive(Debug, Eq, PartialEq)] +struct PrettierConfiguration { + /// https://prettier.io/docs/en/options#print-width + print_width: u16, + /// https://prettier.io/docs/en/options#use-tabs + use_tabs: bool, + /// https://prettier.io/docs/en/options#trailing-comma + trailing_comma: PrettierTrailingComma, + /// https://prettier.io/docs/en/options#tab-width + tab_width: u8, + /// https://prettier.io/docs/en/options#semicolons + semi: bool, + /// https://prettier.io/docs/en/options#quotes + single_quote: bool, + /// https://prettier.io/docs/en/options#bracket-spcing + bracket_spacing: bool, + /// https://prettier.io/docs/en/options#bracket-line + bracket_line: bool, + /// https://prettier.io/docs/en/options#quote-props + quote_props: QuoteProps, + /// https://prettier.io/docs/en/options#jsx-quotes + jsx_single_quote: bool, + /// https://prettier.io/docs/en/options#arrow-function-parentheses + arrow_parens: ArrowParens, + /// https://prettier.io/docs/en/options#end-of-line + end_of_line: EndOfLine, +} + +#[derive(Debug, Eq, PartialEq, Default)] +enum EndOfLine { + #[default] + Lf, + Crlf, + Cr, +} + +impl Deserializable for EndOfLine { + fn deserialize( + value: &impl DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + match String::deserialize(value, name, diagnostics)?.as_str() { + "lf" => Some(Self::Lf), + "crlf" => Some(Self::Crlf), + "cr" => Some(Self::Cr), + unknown_variant => { + const ALLOWED_VARIANTS: &[&str] = &["lf", "crlf", "cr"]; + diagnostics.push(DeserializationDiagnostic::new_unknown_value( + unknown_variant, + value.range(), + ALLOWED_VARIANTS, + )); + None + } + } + } +} + +#[derive(Debug, Eq, PartialEq, Default)] +enum ArrowParens { + #[default] + Always, + Avoid, +} + +impl Deserializable for ArrowParens { + fn deserialize( + value: &impl DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + match String::deserialize(value, name, diagnostics)?.as_str() { + "always" => Some(Self::Always), + "avoid" => Some(Self::Avoid), + unknown_variant => { + const ALLOWED_VARIANTS: &[&str] = &["always", "avoid"]; + diagnostics.push(DeserializationDiagnostic::new_unknown_value( + unknown_variant, + value.range(), + ALLOWED_VARIANTS, + )); + None + } + } + } +} + +#[derive(Debug, Eq, PartialEq, Default)] +enum PrettierTrailingComma { + #[default] + All, + None, + Es5, +} + +impl Deserializable for PrettierTrailingComma { + fn deserialize( + value: &impl DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + match String::deserialize(value, name, diagnostics)?.as_str() { + "all" => Some(Self::All), + "none" => Some(Self::None), + "es5" => Some(Self::Es5), + unknown_variant => { + const ALLOWED_VARIANTS: &[&str] = &["all", "none", "es5"]; + diagnostics.push(DeserializationDiagnostic::new_unknown_value( + unknown_variant, + value.range(), + ALLOWED_VARIANTS, + )); + None + } + } + } +} + +#[derive(Debug, Eq, PartialEq, Default)] + +enum QuoteProps { + #[default] + AsNeeded, + Preserve, +} + +impl Deserializable for QuoteProps { + fn deserialize( + value: &impl DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + match String::deserialize(value, name, diagnostics)?.as_str() { + "as-needed" => Some(Self::AsNeeded), + "preserve" => Some(Self::Preserve), + unknown_variant => { + const ALLOWED_VARIANTS: &[&str] = &["as-needed", "preserve"]; + diagnostics.push(DeserializationDiagnostic::new_unknown_value( + unknown_variant, + value.range(), + ALLOWED_VARIANTS, + )); + None + } + } + } +} + +impl TryFrom<&str> for PrettierTrailingComma { + type Error = String; + fn try_from(value: &str) -> Result { + match value { + "all" => Ok(Self::All), + "none" => Ok(Self::None), + "es5" => Ok(Self::Es5), + _ => Err("Option not supported".to_string()), + } + } +} + +impl Default for PrettierConfiguration { + fn default() -> Self { + Self { + print_width: 80, + + use_tabs: false, + trailing_comma: PrettierTrailingComma::default(), + tab_width: 4, + semi: false, + single_quote: true, + bracket_spacing: true, + bracket_line: false, + quote_props: QuoteProps::default(), + jsx_single_quote: false, + arrow_parens: ArrowParens::default(), + end_of_line: EndOfLine::default(), + } + } +} + +impl Deserializable for PrettierConfiguration { + fn deserialize( + value: &impl DeserializableValue, + name: &str, + diagnostics: &mut Vec, + ) -> Option { + value.deserialize(PrettierVisitor, name, diagnostics) + } +} + +struct PrettierVisitor; + +impl DeserializationVisitor for PrettierVisitor { + type Output = PrettierConfiguration; + const EXPECTED_TYPE: VisitableType = VisitableType::MAP; + + fn visit_map( + self, + members: impl Iterator>, + _range: TextRange, + _name: &str, + diagnostics: &mut Vec, + ) -> Option { + let mut result = PrettierConfiguration::default(); + for (key, value) in members.flatten() { + let Some(key_text) = Text::deserialize(&key, "", diagnostics) else { + continue; + }; + match key_text.text() { + "endOfLine" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.end_of_line = val; + } + } + "arrowParens" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.arrow_parens = val; + } + } + "useTabs" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.use_tabs = val; + } + } + + "printWidth" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.print_width = val; + } + } + + "trailingComma" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.trailing_comma = val; + } + } + + "quoteProps" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.quote_props = val; + } + } + + "semi" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.semi = val; + } + } + + "bracketSpacing" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.bracket_spacing = val; + } + } + + "bracketLine" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.bracket_line = val; + } + } + + "jsxSingleQuote" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.jsx_single_quote = val; + } + } + + "singleQuote" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.single_quote = val; + } + } + + "tabWidth" => { + if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) { + result.tab_width = val; + } + } + + _ => {} + } + } + + Some(result) + } +} + +impl From for TrailingComma { + fn from(value: PrettierTrailingComma) -> Self { + match value { + PrettierTrailingComma::All => Self::All, + PrettierTrailingComma::None => Self::None, + PrettierTrailingComma::Es5 => Self::Es5, + } + } +} + +impl From for ArrowParentheses { + fn from(value: ArrowParens) -> Self { + match value { + ArrowParens::Always => Self::Always, + ArrowParens::Avoid => Self::AsNeeded, + } + } +} + +impl From for LineEnding { + fn from(value: EndOfLine) -> Self { + match value { + EndOfLine::Lf => LineEnding::Lf, + EndOfLine::Crlf => LineEnding::Crlf, + EndOfLine::Cr => LineEnding::Cr, + } + } +} + +impl From for QuoteProperties { + fn from(value: QuoteProps) -> Self { + match value { + QuoteProps::AsNeeded => Self::AsNeeded, + QuoteProps::Preserve => Self::Preserve, + } + } +} + +impl TryFrom for FormatterConfiguration { + type Error = String; + fn try_from(value: PrettierConfiguration) -> Result { + // TODO: handle error + let line_width = LineWidth::try_from(value.print_width).unwrap(); + let indent_style = if value.use_tabs { + PlainIndentStyle::Tab + } else { + PlainIndentStyle::Space + }; + Ok(Self { + indent_width: Some(value.tab_width), + line_width: Some(line_width), + indent_style: Some(indent_style), + line_ending: Some(value.end_of_line.into()), + format_with_errors: Some(false), + ignore: None, + include: None, + enabled: Some(true), + // deprecated + indent_size: None, + }) + } +} + +impl TryFrom for JavascriptFormatter { + type Error = String; + fn try_from(value: PrettierConfiguration) -> Result { + let semicolons = if value.semi { + Semicolons::Always + } else { + Semicolons::AsNeeded + }; + let quote_style = if value.single_quote { + QuoteStyle::Single + } else { + QuoteStyle::Double + }; + let jsx_quote_style = if value.jsx_single_quote { + QuoteStyle::Single + } else { + QuoteStyle::Double + }; + Ok(Self { + indent_width: None, + line_width: None, + indent_style: None, + line_ending: None, + enabled: None, + // deprecated + indent_size: None, + + // js ones + bracket_same_line: Some(value.bracket_line), + arrow_parentheses: Some(value.arrow_parens.into()), + semicolons: Some(semicolons), + trailing_comma: Some(value.trailing_comma.into()), + quote_style: Some(quote_style), + quote_properties: Some(value.quote_props.into()), + bracket_spacing: Some(value.bracket_spacing), + jsx_quote_style: Some(jsx_quote_style), + }) + } +} + +#[cfg(test)] +mod test { + use crate::execute::migrate::prettier::{PrettierConfiguration, PrettierTrailingComma}; + use biome_deserialize::json::deserialize_from_json_str; + use biome_json_parser::JsonParserOptions; + + #[test] + fn ok() { + let configuration = deserialize_from_json_str::( + r#"{ "useTabs": true }"#, + JsonParserOptions::default(), + "", + ) + .into_deserialized() + .unwrap(); + + assert_eq!( + configuration, + PrettierConfiguration { + use_tabs: true, + ..PrettierConfiguration::default() + } + ) + } + + #[test] + fn some_properties() { + let configuration = deserialize_from_json_str::( + r#" +{ + "printWidth": 100, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5", + "useTabs": true, + "jsxSingleQuote": true +} + "#, + JsonParserOptions::default(), + "", + ) + .into_deserialized() + .unwrap(); + + assert_eq!( + configuration, + PrettierConfiguration { + use_tabs: true, + print_width: 100, + semi: true, + single_quote: true, + tab_width: 2, + trailing_comma: PrettierTrailingComma::Es5, + jsx_single_quote: true, + ..PrettierConfiguration::default() + } + ) + } +} diff --git a/crates/biome_cli/src/execute/mod.rs b/crates/biome_cli/src/execute/mod.rs index c3d26fcd5e5a..abf4437f5cf6 100644 --- a/crates/biome_cli/src/execute/mod.rs +++ b/crates/biome_cli/src/execute/mod.rs @@ -5,6 +5,7 @@ mod std_in; mod traverse; use crate::cli_options::CliOptions; +use crate::execute::migrate::MigratePayload; use crate::execute::traverse::traverse; use crate::{CliDiagnostic, CliSession}; use biome_diagnostics::{category, Category}; @@ -109,9 +110,14 @@ pub(crate) enum TraversalMode { }, /// This mode is enabled when running the command `biome migrate` Migrate { + /// Write result to disk write: bool, + /// The path directory where `biome.json` is placed configuration_file_path: PathBuf, + /// The path to `biome.json` configuration_directory_path: PathBuf, + /// Migrate from prettier + prettier: bool, }, } @@ -298,15 +304,18 @@ pub(crate) fn execute_mode( write, configuration_file_path, configuration_directory_path, + prettier, } = mode.traversal_mode { - migrate::run( + let payload = MigratePayload { session, write, configuration_file_path, configuration_directory_path, - cli_options.verbose, - ) + verbose: cli_options.verbose, + prettier, + }; + migrate::run(payload) } else { traverse(mode, session, cli_options, paths) } diff --git a/crates/biome_cli/src/lib.rs b/crates/biome_cli/src/lib.rs index 5359df0c9d15..b59c416f4e47 100644 --- a/crates/biome_cli/src/lib.rs +++ b/crates/biome_cli/src/lib.rs @@ -187,9 +187,11 @@ impl<'app> CliSession<'app> { BiomeCommand::Explain { doc } => commands::explain::explain(self, doc), BiomeCommand::Init => commands::init::init(self), BiomeCommand::LspProxy(config_path) => commands::daemon::lsp_proxy(config_path), - BiomeCommand::Migrate(cli_options, write) => { - commands::migrate::migrate(self, cli_options, write) - } + BiomeCommand::Migrate { + cli_options, + write, + prettier, + } => commands::migrate::migrate(self, cli_options, write, prettier), BiomeCommand::RunServer { stop_on_disconnect, config_path, diff --git a/crates/biome_deserialize/README.md b/crates/biome_deserialize/README.md index 297af4e5074f..1b580a9ec1fd 100644 --- a/crates/biome_deserialize/README.md +++ b/crates/biome_deserialize/README.md @@ -312,7 +312,7 @@ impl Deserializable for Person { diagnostics: &mut Vec, ) -> Option { // Delegate the deserialization to `PersonVisitor`. - // `value` will call the `PersonVisitor::viist_` method that corresponds to its type. + // `value` will call the `PersonVisitor::visit_` method that corresponds to its type. value.deserialize(PersonVisitor, name, diagnostics) } } diff --git a/crates/biome_js_formatter/src/context.rs b/crates/biome_js_formatter/src/context.rs index 2e054c2a2e78..4669c5bf1902 100644 --- a/crates/biome_js_formatter/src/context.rs +++ b/crates/biome_js_formatter/src/context.rs @@ -1,5 +1,5 @@ use crate::comments::{FormatJsLeadingComment, JsCommentStyle, JsComments}; -use crate::context::trailing_comma::TrailingComma; +pub use crate::context::trailing_comma::TrailingComma; use biome_deserialize::{Deserializable, DeserializableValue, DeserializationDiagnostic, Text}; use biome_deserialize_macros::Merge; use biome_formatter::printer::PrinterOptions; From bc3bd4e18cd08c19855999247bb711644f273e14 Mon Sep 17 00:00:00 2001 From: Victorien Elvinger Date: Sat, 13 Jan 2024 12:23:55 +0100 Subject: [PATCH 06/49] fix(config): don't ignore `include` when `ignore` is set (#1548) --- CHANGELOG.md | 7 ++ crates/biome_cli/tests/commands/format.rs | 92 +++++++++++++++++++ ...at_ignored_file_in_included_directory.snap | 35 +++++++ ...format_non_included_and_ignored_files.snap | 46 ++++++++++ crates/biome_service/src/settings.rs | 10 +- crates/biome_service/src/workspace/server.rs | 40 +++----- .../content/docs/guides/how-biome-works.mdx | 19 ++-- .../src/content/docs/internals/changelog.mdx | 7 ++ 8 files changed, 217 insertions(+), 39 deletions(-) create mode 100644 crates/biome_cli/tests/snapshots/main_commands_format/does_not_format_ignored_file_in_included_directory.snap create mode 100644 crates/biome_cli/tests/snapshots/main_commands_format/does_not_format_non_included_and_ignored_files.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 060b9d77b307..502b3f8d2c23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,13 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom - Fix [1440](https://github.com/biomejs/biome/issues/1440), a case where `extends` and `overrides` weren't correctly emitting the final configuration. Contributed by @arendjr +- Correctly handle `include` when `ignore` is set (#1468). Contributed by @Conaclos + + Previously, Biome ignored `include` if `ignore` was set. + Now, Biome check both `include` and `ignore`. + A file is processed if it is included and not ignored. + If `include` is not set all files are considered included. + ### Editors ### Formatter diff --git a/crates/biome_cli/tests/commands/format.rs b/crates/biome_cli/tests/commands/format.rs index a7b6d8b77c5c..064b1db208ed 100644 --- a/crates/biome_cli/tests/commands/format.rs +++ b/crates/biome_cli/tests/commands/format.rs @@ -1340,6 +1340,98 @@ fn does_not_format_ignored_directories() { )); } +#[test] +fn does_not_format_non_included_and_ignored_files() { + let config = r#"{ + "files": { + "include": ["file1.js", "file2.js", "file3.js"], + "ignore": ["file2.js"] + }, + "formatter": { + "include": ["file2.js"], + "ignore": ["file3.js"] + } + }"#; + let files = [("file1.js", true), ("file2.js", true), ("file3.js", false)]; + + let mut console = BufferConsole::default(); + let mut fs = MemoryFileSystem::default(); + let file_path = Path::new("biome.json"); + fs.insert(file_path.into(), config); + for (file_path, _) in files { + let file_path = Path::new(file_path); + fs.insert(file_path.into(), UNFORMATTED.as_bytes()); + } + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("format"), ("."), ("--write")].as_slice()), + ); + assert!(result.is_ok(), "run_cli returned {result:?}"); + + for (file_path, expect_formatted) in files { + let expected = if expect_formatted { + FORMATTED + } else { + UNFORMATTED + }; + assert_file_contents(&fs, Path::new(file_path), expected); + } + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "does_not_format_non_included_and_ignored_files", + fs, + console, + result, + )); +} + +#[test] +fn does_not_format_ignored_file_in_included_directory() { + let config = r#"{ + "formatter": { + "include": ["src"], + "ignore": ["src/file2.js"] + } + }"#; + let files = [("src/file1.js", true), ("src/file2.js", false)]; + + let mut console = BufferConsole::default(); + let mut fs = MemoryFileSystem::default(); + let file_path = Path::new("biome.json"); + fs.insert(file_path.into(), config); + for (file_path, _) in files { + let file_path = Path::new(file_path); + fs.insert(file_path.into(), UNFORMATTED.as_bytes()); + } + + let result = run_cli( + DynRef::Borrowed(&mut fs), + &mut console, + Args::from([("format"), ("."), ("--write")].as_slice()), + ); + assert!(result.is_ok(), "run_cli returned {result:?}"); + + for (file_path, expect_formatted) in files { + let expected = if expect_formatted { + FORMATTED + } else { + UNFORMATTED + }; + assert_file_contents(&fs, Path::new(file_path), expected); + } + + assert_cli_snapshot(SnapshotPayload::new( + module_path!(), + "does_not_format_ignored_file_in_included_directory", + fs, + console, + result, + )); +} + #[test] fn fs_error_read_only() { let mut fs = MemoryFileSystem::new_read_only(); diff --git a/crates/biome_cli/tests/snapshots/main_commands_format/does_not_format_ignored_file_in_included_directory.snap b/crates/biome_cli/tests/snapshots/main_commands_format/does_not_format_ignored_file_in_included_directory.snap new file mode 100644 index 000000000000..224b027e8bec --- /dev/null +++ b/crates/biome_cli/tests/snapshots/main_commands_format/does_not_format_ignored_file_in_included_directory.snap @@ -0,0 +1,35 @@ +--- +source: crates/biome_cli/tests/snap_test.rs +expression: content +--- +## `biome.json` + +```json +{ + "formatter": { + "include": ["src"], + "ignore": ["src/file2.js"] + } +} +``` + +## `src/file1.js` + +```js +statement(); + +``` + +## `src/file2.js` + +```js + statement( ) +``` + +# Emitted Messages + +```block +Formatted 2 file(s) in
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
-   This hook does not specify all of its dependencies.
+   This hook does not specify all of its dependencies: a
   
     3 │ function component() {
     4 │     let a = 1;
@@ -84,7 +84,7 @@ function component() {
 
 
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
-   This hook specifies more dependencies than necessary.
+   This hook specifies more dependencies than necessary: b
   
     3 │ function component() {
     4 │     let b = 1;
@@ -118,7 +118,7 @@ function component() {
 
 
correctness/useExhaustiveDependencies.js:5:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
-   This hook specifies more dependencies than necessary.
+   This hook specifies more dependencies than necessary: setName
   
     3 │ function component() {
     4 │     const [name, setName] = useState();
@@ -152,7 +152,7 @@ function component() {
 
 
correctness/useExhaustiveDependencies.js:6:5 lint/correctness/useExhaustiveDependencies ━━━━━━━━━━━━
 
-   This hook does not specify all of its dependencies.
+   This hook does not specify all of its dependencies: b
   
     4 │     let a = 1;
     5 │     const b = a + 1;

From cd9623d6184f5a91192bd301184d2c84c0135895 Mon Sep 17 00:00:00 2001
From: Jon 
Date: Tue, 16 Jan 2024 07:43:01 -0800
Subject: [PATCH 16/49] feat(css_formatter): Formatting for `border` property
 (#1453)

---
 .../src/css/auxiliary/border.rs               |  23 ++-
 .../src/css/auxiliary/line_style.rs           |   9 +-
 .../src/css/auxiliary/line_width_keyword.rs   |   9 +-
 .../src/css/properties/border_property.rs     |  14 +-
 crates/biome_css_formatter/src/prelude.rs     |   4 +-
 crates/biome_css_formatter/src/utils/mod.rs   |   1 +
 .../src/utils/properties.rs                   | 172 ++++++++++++++++++
 .../biome_css_formatter/tests/quick_test.rs   |   8 +-
 .../tests/specs/css/properties/border.css     |  39 ++++
 .../specs/css/properties/border.css.snap      |  94 ++++++++++
 .../biome_css_syntax/src/generated/nodes.rs   |   8 +-
 crates/biome_formatter/src/arguments.rs       |   9 +-
 crates/biome_js_syntax/src/generated/nodes.rs |   3 +-
 .../biome_json_syntax/src/generated/nodes.rs  |   3 +-
 crates/biome_rowan/src/ast/mod.rs             |  77 ++++++++
 xtask/codegen/src/generate_nodes.rs           |  18 +-
 16 files changed, 468 insertions(+), 23 deletions(-)
 create mode 100644 crates/biome_css_formatter/src/utils/properties.rs
 create mode 100644 crates/biome_css_formatter/tests/specs/css/properties/border.css
 create mode 100644 crates/biome_css_formatter/tests/specs/css/properties/border.css.snap

diff --git a/crates/biome_css_formatter/src/css/auxiliary/border.rs b/crates/biome_css_formatter/src/css/auxiliary/border.rs
index 47bd8b26d03b..f98dd59d8f30 100644
--- a/crates/biome_css_formatter/src/css/auxiliary/border.rs
+++ b/crates/biome_css_formatter/src/css/auxiliary/border.rs
@@ -1,10 +1,25 @@
-use crate::prelude::*;
-use biome_css_syntax::CssBorder;
-use biome_rowan::AstNode;
+use crate::{prelude::*, utils::properties::FormatPropertyValueFields};
+use biome_css_syntax::{CssBorder, CssBorderFields};
+use biome_formatter::{format_args, write};
+
 #[derive(Debug, Clone, Default)]
 pub(crate) struct FormatCssBorder;
 impl FormatNodeRule for FormatCssBorder {
     fn fmt_fields(&self, node: &CssBorder, f: &mut CssFormatter) -> FormatResult<()> {
-        format_verbatim_node(node.syntax()).fmt(f)
+        let CssBorderFields {
+            line_width,
+            line_style,
+            color,
+        } = node.as_fields();
+
+        write!(
+            f,
+            [FormatPropertyValueFields::new(&format_args![
+                line_width.format(),
+                line_style.format(),
+                color.format(),
+            ])
+            .with_slot_map(node.concrete_order_slot_map())]
+        )
     }
 }
diff --git a/crates/biome_css_formatter/src/css/auxiliary/line_style.rs b/crates/biome_css_formatter/src/css/auxiliary/line_style.rs
index 0858d1cf27af..fa68dee4e8e6 100644
--- a/crates/biome_css_formatter/src/css/auxiliary/line_style.rs
+++ b/crates/biome_css_formatter/src/css/auxiliary/line_style.rs
@@ -1,10 +1,13 @@
 use crate::prelude::*;
-use biome_css_syntax::CssLineStyle;
-use biome_rowan::AstNode;
+use biome_css_syntax::{CssLineStyle, CssLineStyleFields};
+use biome_formatter::write;
+
 #[derive(Debug, Clone, Default)]
 pub(crate) struct FormatCssLineStyle;
 impl FormatNodeRule for FormatCssLineStyle {
     fn fmt_fields(&self, node: &CssLineStyle, f: &mut CssFormatter) -> FormatResult<()> {
-        format_verbatim_node(node.syntax()).fmt(f)
+        let CssLineStyleFields { keyword } = node.as_fields();
+
+        write!(f, [keyword.format()])
     }
 }
diff --git a/crates/biome_css_formatter/src/css/auxiliary/line_width_keyword.rs b/crates/biome_css_formatter/src/css/auxiliary/line_width_keyword.rs
index f1eae653ee34..dffbbc50cc16 100644
--- a/crates/biome_css_formatter/src/css/auxiliary/line_width_keyword.rs
+++ b/crates/biome_css_formatter/src/css/auxiliary/line_width_keyword.rs
@@ -1,10 +1,13 @@
 use crate::prelude::*;
-use biome_css_syntax::CssLineWidthKeyword;
-use biome_rowan::AstNode;
+use biome_css_syntax::{CssLineWidthKeyword, CssLineWidthKeywordFields};
+use biome_formatter::write;
+
 #[derive(Debug, Clone, Default)]
 pub(crate) struct FormatCssLineWidthKeyword;
 impl FormatNodeRule for FormatCssLineWidthKeyword {
     fn fmt_fields(&self, node: &CssLineWidthKeyword, f: &mut CssFormatter) -> FormatResult<()> {
-        format_verbatim_node(node.syntax()).fmt(f)
+        let CssLineWidthKeywordFields { keyword } = node.as_fields();
+
+        write!(f, [keyword.format()])
     }
 }
diff --git a/crates/biome_css_formatter/src/css/properties/border_property.rs b/crates/biome_css_formatter/src/css/properties/border_property.rs
index 6e9a0e1b2795..952e94504b5c 100644
--- a/crates/biome_css_formatter/src/css/properties/border_property.rs
+++ b/crates/biome_css_formatter/src/css/properties/border_property.rs
@@ -1,10 +1,18 @@
 use crate::prelude::*;
-use biome_css_syntax::CssBorderProperty;
-use biome_rowan::AstNode;
+use biome_css_syntax::{CssBorderProperty, CssBorderPropertyFields};
+use biome_formatter::write;
 #[derive(Debug, Clone, Default)]
 pub(crate) struct FormatCssBorderProperty;
 impl FormatNodeRule for FormatCssBorderProperty {
     fn fmt_fields(&self, node: &CssBorderProperty, f: &mut CssFormatter) -> FormatResult<()> {
-        format_verbatim_node(node.syntax()).fmt(f)
+        let CssBorderPropertyFields {
+            name,
+            colon_token,
+            value,
+        } = node.as_fields();
+        write!(
+            f,
+            [name.format(), colon_token.format(), space(), value.format()]
+        )
     }
 }
diff --git a/crates/biome_css_formatter/src/prelude.rs b/crates/biome_css_formatter/src/prelude.rs
index 69e4a0665984..9d74d80aa65e 100644
--- a/crates/biome_css_formatter/src/prelude.rs
+++ b/crates/biome_css_formatter/src/prelude.rs
@@ -7,6 +7,8 @@ pub(crate) use crate::{
 };
 pub(crate) use biome_formatter::prelude::*;
 #[allow(unused_imports)]
-pub(crate) use biome_rowan::{AstNode as _, AstNodeList as _, AstSeparatedList as _};
+pub(crate) use biome_rowan::{
+    AstNode as _, AstNodeList as _, AstNodeSlotMap as _, AstSeparatedList as _,
+};
 
 pub(crate) use crate::separated::FormatAstSeparatedListExtension;
diff --git a/crates/biome_css_formatter/src/utils/mod.rs b/crates/biome_css_formatter/src/utils/mod.rs
index bc7584a88994..159a66203376 100644
--- a/crates/biome_css_formatter/src/utils/mod.rs
+++ b/crates/biome_css_formatter/src/utils/mod.rs
@@ -1,2 +1,3 @@
 pub(crate) mod component_value_list;
+pub(crate) mod properties;
 pub(crate) mod string_utils;
diff --git a/crates/biome_css_formatter/src/utils/properties.rs b/crates/biome_css_formatter/src/utils/properties.rs
new file mode 100644
index 000000000000..2d6b9d1b97df
--- /dev/null
+++ b/crates/biome_css_formatter/src/utils/properties.rs
@@ -0,0 +1,172 @@
+use crate::prelude::*;
+use biome_formatter::{write, Arguments};
+
+/// Format all of the fields of a `PropertyValue` node in an arbitrary order,
+/// given by `slot_map`.
+///
+/// Because the CSS grammar allows rules to specify fields that can appear
+/// in any order, there isn't always a linear mapping between the _declared_
+/// order (how they appear in the grammar) and the _concrete_ order (how they
+/// appear in the source text) of the fields. The parser supports this by
+/// building a `slot_map` to map the declared order to the concrete order.
+///
+/// When formatting, by default we want to preserve the ordering of fields as
+/// they were written in the source, but just using the `AstNode` alone will
+/// naturally re-write the value in the _declared_ order. To preserve the
+/// _concrete_ order, we can invert the `slot_map` and sort it to re-determine
+/// the ordering of fields and then iterate that list to format each field
+/// individually.
+///
+/// ## Fields
+///
+/// The caller provides a list of _pre-formatted_ fields, using the
+/// [`biome_formatter::format_args!`] macro. This way, it can either pass
+/// through a field as-is with default formatting, or it can apply any other
+/// formatting it once for that field:
+///
+/// ```rust,ignore
+/// let formatted = format!(CssFormatContext::default(), [
+///     FormatPropertyValueFields::new(&format_args![
+///         text("a"),
+///         text("b"),
+///         group(&block_indent(&format_args![text("c"), hard_line_break(), text("d")]))
+///     ])
+///     .with_slot_map([1, 2, 0])
+/// ])?;
+///
+/// assert_eq!("b
+/// \tc
+/// \td
+/// a", formatted.print()?.as_code());
+/// ```
+///
+/// ## Concrete Ordering
+///
+/// By default, using this struct will format the fields of the node in order.
+/// This is sufficient for nodes that don't have any dynamically-ordered
+/// fields, but for dynamic nodes that want to preserve the order of fields as
+/// they were given in the input, or for any node that wants to change the
+/// ordering of the fields, the caller will need to provide a `slot_map` that
+/// this struct can use to re-order the fields.
+///
+/// To preserve the field order as it was written in the original source, use
+/// [biome_rowan::AstNodeSlotMap::concrete_order_slot_map], which will ensure
+/// the ordering matches what was given. This should be the default for most
+/// if not all dynamic nodes.
+///
+/// ```rust,ignore
+/// .with_slot_map(node.concrete_order_slot_map())
+/// ```
+///
+/// Any other method of building a slot map is also valid, but should generally
+/// be avoided, as ensuring consistency across formats is difficult without a
+/// strong heuristic.
+///
+/// ## Grouping Fields (Future)
+///
+/// In some cases, a property may want to group certain fields together in
+/// order to apply special formatting. As an example, consider a grammar like:
+///
+/// ```ebnf
+///     font =
+///         (style: CssFontStyle ||
+///         variant: CssFontVariant ||
+///         weight: CssFontWeight)?
+///         size: CssNumber ( '/' line_height: CssLineHeight)?
+/// ```
+///
+/// Here, the `style`, `variant`, and `weight` fields can appear conditionally
+/// and in any order, but if `line_height` is present, it (and the slash token)
+/// must appear immediately adjacent to the `size` field. While it would be
+/// valid to just have the fields fill and wrap over lines as needed, the
+/// formatter might want to preserve the adjacency and ensure that `size` and
+/// `line_height` always get written on the same line.
+///
+/// To do this, the value formatter can write both fields in a single group,
+/// and then use an `empty_field_slot` value in the slots where the other
+/// fields have been taken from:
+///
+/// ```rust,ignore
+/// FormatPropertyValueFields::new(&format_args![
+///         style.format(),
+///         variant.format(),
+///         weight.format(),
+///         group(&format_args![
+///             size.format(), slash_token.format(), line_height.format()
+///         ]),
+///         empty_field_slot(),
+///         empty_field_slot()
+///     ])
+///     .with_slot_map(node.concrete_order_slot_map())
+/// ```
+///
+/// The `empty_field_slot()` values will tell this struct to skip formatting
+/// for that field, with the assumption that another field includes its value.
+pub struct FormatPropertyValueFields<'fmt, const N: usize> {
+    slot_map: Option<[u8; N]>,
+    fields: &'fmt Arguments<'fmt, CssFormatContext>,
+}
+
+impl<'fmt, const N: usize> FormatPropertyValueFields<'fmt, N> {
+    pub fn new(fields: &'fmt Arguments<'fmt, CssFormatContext>) -> Self {
+        Self {
+            slot_map: None,
+            fields,
+        }
+    }
+
+    pub fn with_slot_map(mut self, slot_map: [u8; N]) -> Self {
+        debug_assert!(
+            self.fields.items().len() == N,
+            "slot_map must specify the same number of fields as this struct contains"
+        );
+        self.slot_map = Some(slot_map);
+        self
+    }
+}
+
+impl<'fmt, const N: usize> Format for FormatPropertyValueFields<'fmt, N> {
+    fn fmt(&self, f: &mut CssFormatter) -> FormatResult<()> {
+        let values = format_with(|f: &mut Formatter<'_, CssFormatContext>| {
+            let mut filler = f.fill();
+
+            // First, determine the ordering of fields to use. If no slot_map is
+            // provided along with the fields, then they can just be used in the
+            // same order, but if a `slot_map` is present, then the fields are
+            // re-ordered to match the concrete ordering from the source syntax.
+            //
+            // The fields are wrapped with `Option` for two reasons: for nodes
+            // with slot maps, it simplifies how the re-ordered slice is built, and
+            // it also allows empty/missing fields to be removed in the next step.
+            match self.slot_map {
+                None => {
+                    for field in self.fields.items() {
+                        filler.entry(&soft_line_break_or_space(), field);
+                    }
+                }
+                Some(slot_map) => {
+                    for slot in slot_map {
+                        // This condition ensures that missing values are _not_ included in the
+                        // fill. The generated `slot_map` for an AstNode guarantees that all
+                        // present fields have a tangible value here, while all absent fields
+                        // have this sentinel value ([biome_css_syntax::SLOT_MAP_EMPTY_VALUE]).
+                        //
+                        // This check is important to ensure that we don't add empty values to
+                        // the fill, since that would add double separators when we don't want
+                        // them.
+                        if slot == u8::MAX {
+                            continue;
+                        }
+
+                        let field = &self.fields.items()[slot as usize];
+                        filler.entry(&soft_line_break_or_space(), field);
+                    }
+                }
+            };
+
+            filler.finish()
+        });
+
+        write!(f, [group(&indent(&values))])
+    }
+}
diff --git a/crates/biome_css_formatter/tests/quick_test.rs b/crates/biome_css_formatter/tests/quick_test.rs
index 81de0a5b3248..079a9b62b44c 100644
--- a/crates/biome_css_formatter/tests/quick_test.rs
+++ b/crates/biome_css_formatter/tests/quick_test.rs
@@ -14,9 +14,11 @@ mod language {
 fn quick_test() {
     let src = r#"
     div {
-        prod: fn(100px);
-        prod: --fn(100px);
-        prod: --fn--fn(100px);
+        border: #fff    solid
+        
+        2px;
+        border: THICK   #000;
+        border: medium;
     }
 
 "#;
diff --git a/crates/biome_css_formatter/tests/specs/css/properties/border.css b/crates/biome_css_formatter/tests/specs/css/properties/border.css
new file mode 100644
index 000000000000..5d842f5d1c86
--- /dev/null
+++ b/crates/biome_css_formatter/tests/specs/css/properties/border.css
@@ -0,0 +1,39 @@
+div {
+    /* Generic property tests */
+    border: InItial;
+    border
+    :
+    inherit
+    ;
+
+    border  :   zzz-unknown-value  ;
+    border  : a,
+    value list ;
+
+
+    /*  */
+    border : SOLID;
+    border: none
+    ;
+
+    /*  */
+    border : ThIn;
+    border: 
+    medium
+    ;
+    border:   100px;
+
+    /*  */
+    border: 
+    #fff;
+
+    /* combinations */
+    border: 2px
+    dotted;
+    border  :   outset   #f33;
+    border:#000 medium  
+     
+    dashed
+        
+        ;
+}
diff --git a/crates/biome_css_formatter/tests/specs/css/properties/border.css.snap b/crates/biome_css_formatter/tests/specs/css/properties/border.css.snap
new file mode 100644
index 000000000000..c17a650c7980
--- /dev/null
+++ b/crates/biome_css_formatter/tests/specs/css/properties/border.css.snap
@@ -0,0 +1,94 @@
+---
+source: crates/biome_formatter_test/src/snapshot_builder.rs
+info: css/properties/border.css
+---
+
+# Input
+
+```css
+div {
+    /* Generic property tests */
+    border: InItial;
+    border
+    :
+    inherit
+    ;
+
+    border  :   zzz-unknown-value  ;
+    border  : a,
+    value list ;
+
+
+    /*  */
+    border : SOLID;
+    border: none
+    ;
+
+    /*  */
+    border : ThIn;
+    border: 
+    medium
+    ;
+    border:   100px;
+
+    /*  */
+    border: 
+    #fff;
+
+    /* combinations */
+    border: 2px
+    dotted;
+    border  :   outset   #f33;
+    border:#000 medium  
+     
+    dashed
+        
+        ;
+}
+
+```
+
+
+=============================
+
+# Outputs
+
+## Output 1
+
+-----
+Indent style: Tab
+Indent width: 2
+Line ending: LF
+Line width: 80
+Quote style: Double Quotes
+-----
+
+```css
+div {
+	/* Generic property tests */
+	border: initial;
+	border: inherit;
+
+	border: zzz-unknown-value;
+	border: a , value list;
+
+	/*  */
+	border: solid;
+	border: none;
+
+	/*  */
+	border: thin;
+	border: medium;
+	border: 100px;
+
+	/*  */
+	border: #fff;
+
+	/* combinations */
+	border: 2px dotted;
+	border: outset #f33;
+	border: #000 medium dashed;
+}
+```
+
+
diff --git a/crates/biome_css_syntax/src/generated/nodes.rs b/crates/biome_css_syntax/src/generated/nodes.rs
index 7460341c6cf0..d9b357814976 100644
--- a/crates/biome_css_syntax/src/generated/nodes.rs
+++ b/crates/biome_css_syntax/src/generated/nodes.rs
@@ -12,7 +12,8 @@ use crate::{
 use biome_rowan::{support, AstNode, RawSyntaxKind, SyntaxKindSet, SyntaxResult};
 #[allow(unused)]
 use biome_rowan::{
-    AstNodeList, AstNodeListIterator, AstSeparatedList, AstSeparatedListNodesIterator,
+    AstNodeList, AstNodeListIterator, AstNodeSlotMap, AstSeparatedList,
+    AstSeparatedListNodesIterator,
 };
 #[cfg(feature = "serde")]
 use serde::ser::SerializeSeq;
@@ -8245,6 +8246,11 @@ impl AstNode for CssBorder {
         self.syntax
     }
 }
+impl AstNodeSlotMap<3usize> for CssBorder {
+    fn slot_map(&self) -> &[u8; 3usize] {
+        &self.slot_map
+    }
+}
 impl std::fmt::Debug for CssBorder {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("CssBorder")
diff --git a/crates/biome_formatter/src/arguments.rs b/crates/biome_formatter/src/arguments.rs
index ff96b33e0d89..4e40e10fcc74 100644
--- a/crates/biome_formatter/src/arguments.rs
+++ b/crates/biome_formatter/src/arguments.rs
@@ -56,6 +56,13 @@ impl<'fmt, Context> Argument<'fmt, Context> {
     }
 }
 
+impl<'fmt, Context> Format for Argument<'fmt, Context> {
+    #[inline(always)]
+    fn fmt(&self, f: &mut Formatter) -> FormatResult<()> {
+        self.format(f)
+    }
+}
+
 /// Sequence of objects that should be formatted in the specified order.
 ///
 /// The [`format_args!`] macro will safely create an instance of this structure.
@@ -87,7 +94,7 @@ impl<'fmt, Context> Arguments<'fmt, Context> {
 
     /// Returns the arguments
     #[inline]
-    pub(super) fn items(&self) -> &'fmt [Argument<'fmt, Context>] {
+    pub fn items(&self) -> &'fmt [Argument<'fmt, Context>] {
         self.0
     }
 }
diff --git a/crates/biome_js_syntax/src/generated/nodes.rs b/crates/biome_js_syntax/src/generated/nodes.rs
index dfa42cc07991..15cbdccbfd41 100644
--- a/crates/biome_js_syntax/src/generated/nodes.rs
+++ b/crates/biome_js_syntax/src/generated/nodes.rs
@@ -12,7 +12,8 @@ use crate::{
 use biome_rowan::{support, AstNode, RawSyntaxKind, SyntaxKindSet, SyntaxResult};
 #[allow(unused)]
 use biome_rowan::{
-    AstNodeList, AstNodeListIterator, AstSeparatedList, AstSeparatedListNodesIterator,
+    AstNodeList, AstNodeListIterator, AstNodeSlotMap, AstSeparatedList,
+    AstSeparatedListNodesIterator,
 };
 #[cfg(feature = "serde")]
 use serde::ser::SerializeSeq;
diff --git a/crates/biome_json_syntax/src/generated/nodes.rs b/crates/biome_json_syntax/src/generated/nodes.rs
index b755da777f4c..6da549e9f223 100644
--- a/crates/biome_json_syntax/src/generated/nodes.rs
+++ b/crates/biome_json_syntax/src/generated/nodes.rs
@@ -12,7 +12,8 @@ use crate::{
 use biome_rowan::{support, AstNode, RawSyntaxKind, SyntaxKindSet, SyntaxResult};
 #[allow(unused)]
 use biome_rowan::{
-    AstNodeList, AstNodeListIterator, AstSeparatedList, AstSeparatedListNodesIterator,
+    AstNodeList, AstNodeListIterator, AstNodeSlotMap, AstSeparatedList,
+    AstSeparatedListNodesIterator,
 };
 #[cfg(feature = "serde")]
 use serde::ser::SerializeSeq;
diff --git a/crates/biome_rowan/src/ast/mod.rs b/crates/biome_rowan/src/ast/mod.rs
index 4556537a4b22..0462d6dd642c 100644
--- a/crates/biome_rowan/src/ast/mod.rs
+++ b/crates/biome_rowan/src/ast/mod.rs
@@ -319,6 +319,83 @@ pub trait AstNode: Clone {
     }
 }
 
+/// An AstNode that supports dynamic ordering of the fields it contains uses a
+/// `slot_map` to map the _declared_ order of fields to the _concrete_ order
+/// as parsed from the source content. Implementing this trait lets consumers
+///
+pub trait AstNodeSlotMap {
+    /// Return the internal slot_map that was built when constructed from the
+    /// underlying [SyntaxNode].
+    fn slot_map(&self) -> &[u8; N];
+
+    /// Invert and sort the `slot_map` for the [AstNode] to return a mapping of
+    /// _concrete_ field ordering from the source to the _declared_ ordering of
+    /// the [AstNode].
+    ///
+    /// Note that the _entire_ slot map is inverted and returned, including
+    /// both the ordered and the unordered fields. Ordered fields will have
+    /// their slot positions fixed in both the original and the inverted slot
+    /// maps, since they can't be moved. Ordered fields also act as boundary
+    /// points for unordered fields, meaning the concrete order will never
+    /// allow the concrete slot of an unordered field to appear on the opposite
+    /// side of an ordered field, even if the field is empty, and the ordered
+    /// fields will _always_ have the same slot in both maps.
+    ///
+    /// Example: Given a grammar like:
+    ///   MultiplyVectorsNode =
+    ///     (Color
+    ///     || Number
+    ///     || String)
+    ///     'x'
+    ///     (Color
+    ///     || Number
+    ///     || String)
+    /// There are two sets of unordered fields here (the groups combined with
+    /// `||` operators). Each contains three fields, and then there is a single
+    /// ordered field between them, the `x` token. This Node declares a
+    /// `slot_map` with 7 indices. The first three can be mapped in any order,
+    /// and the last three can be mapped in any order, but the `x` token will
+    /// _always_ occupy the fourth slot (zero-based index 3).
+    ///
+    /// Now, given an input like `10 "hello" #fff x "bye" #000 20`, the
+    /// constructed [AstNode]'s slot_map would look like
+    /// `[2, 0, 1, 3, 6, 4, 5]`. The first `Color` field, declared as index 0,
+    /// appears at the 2nd index in the concrete source, so the value at index
+    /// 0 is 2, and so on for the rest of the fields.
+    ///
+    /// The inversion of this slot map, then, is `[1, 2, 0, 3, 5, 6, 4]`. To
+    /// compare these, think: the value 0 in the original `slot_map` appeared
+    /// at index 1, so index 0 in the inverted map has the _value_ 1, then
+    /// apply that for of the slots. As you can see `3` is still in the same
+    /// position, because it is an ordered field.
+    ///
+    /// ## Optional Fields
+    ///
+    /// It's also possible for unordered fields to be _optional_, meaning they
+    /// are not present in the concrete source. In this case, the sentinel
+    /// value of `255` ([`std::u8::MAX`]) is placed in the slot map. When
+    /// inverting the map, if a slot index cannot be found in the map, it is
+    /// preserved as the same sentinel value in the inverted map.
+    ///
+    /// Using the same grammar as before, the input `10 x #000` is also valid,
+    /// but is missing many of the optional fields. The `slot_map` for this
+    /// node would include sentinel values for all of the missing fields, like:
+    /// `[255, 0, 255, 3, 4, 255, 255]`. Inverting this map would then yield:
+    /// `[1, 255, 255, 3, 4, 255, 255]`. Each declared slot is still
+    /// represented in the inverted map, but only the fields that exist in the
+    /// concrete source have usable values.
+    fn concrete_order_slot_map(&self) -> [u8; N] {
+        let mut inverted = [u8::MAX; N];
+        for (declared_slot, concrete_slot) in self.slot_map().iter().enumerate() {
+            if *concrete_slot != u8::MAX {
+                inverted[*concrete_slot as usize] = declared_slot as u8;
+            }
+        }
+
+        inverted
+    }
+}
+
 pub trait SyntaxNodeCast {
     /// Tries to cast the current syntax node to specified AST node.
     ///
diff --git a/xtask/codegen/src/generate_nodes.rs b/xtask/codegen/src/generate_nodes.rs
index e29589e888ef..3302a7e9138e 100644
--- a/xtask/codegen/src/generate_nodes.rs
+++ b/xtask/codegen/src/generate_nodes.rs
@@ -224,6 +224,18 @@ pub fn generate_nodes(ast: &AstSrc, language_kind: LanguageKind) -> Result for #name {
+                        fn slot_map(&self) -> &#slot_map_type {
+                            &self.slot_map
+                        }
+                    }
+                }
+            } else {
+                Default::default()
+            };
+
             (
                 quote! {
                     // TODO: review documentation
@@ -278,6 +290,8 @@ pub fn generate_nodes(ast: &AstSrc, language_kind: LanguageKind) -> Result SyntaxNode { self.syntax }
                     }
 
+                    #ast_node_slot_map_impl
+
                     impl std::fmt::Debug for #name {
                         fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                             f.debug_struct(#string_name)
@@ -884,9 +898,9 @@ pub fn generate_nodes(ast: &AstSrc, language_kind: LanguageKind) -> Result
Date: Wed, 17 Jan 2024 04:41:15 +0900
Subject: [PATCH 17/49] fix(exhaustiveDeps): perform nested capture check in a
 correct way (#1327)

Co-authored-by: Emanuele Stoppa 
---
 .../biome_html_syntax/src/generated/nodes.rs  |   3 +-
 crates/biome_js_analyze/src/lib.rs            |  14 +-
 .../use_exhaustive_dependencies.rs            | 121 +++++++++++-------
 .../useExhaustiveDependencies/valid.js        |  14 +-
 .../useExhaustiveDependencies/valid.js.snap   |  14 +-
 5 files changed, 108 insertions(+), 58 deletions(-)

diff --git a/crates/biome_html_syntax/src/generated/nodes.rs b/crates/biome_html_syntax/src/generated/nodes.rs
index 31da15ef7872..430859542684 100644
--- a/crates/biome_html_syntax/src/generated/nodes.rs
+++ b/crates/biome_html_syntax/src/generated/nodes.rs
@@ -12,7 +12,8 @@ use crate::{
 use biome_rowan::{support, AstNode, RawSyntaxKind, SyntaxKindSet, SyntaxResult};
 #[allow(unused)]
 use biome_rowan::{
-    AstNodeList, AstNodeListIterator, AstSeparatedList, AstSeparatedListNodesIterator,
+    AstNodeList, AstNodeListIterator, AstNodeSlotMap, AstSeparatedList,
+    AstSeparatedListNodesIterator,
 };
 #[cfg(feature = "serde")]
 use serde::ser::SerializeSeq;
diff --git a/crates/biome_js_analyze/src/lib.rs b/crates/biome_js_analyze/src/lib.rs
index 31910cfa92a8..d138a39feb6d 100644
--- a/crates/biome_js_analyze/src/lib.rs
+++ b/crates/biome_js_analyze/src/lib.rs
@@ -243,7 +243,17 @@ mod tests {
             String::from_utf8(buffer).unwrap()
         }
 
-        const SOURCE: &str = r#"require("fs")
+        const SOURCE: &str = r#"
+        import { useEffect } from "react";
+        function MyComponent7() {
+    let someObj = getObj();
+    useEffect(() => {
+        console.log(
+					someObj
+							.name
+				);
+    }, [someObj]);
+}
         "#;
         // const SOURCE: &str = r#"document.querySelector("foo").value = document.querySelector("foo").value
         //
@@ -258,7 +268,7 @@ mod tests {
             closure_index: Some(0),
             dependencies_index: Some(1),
         };
-        let rule_filter = RuleFilter::Rule("nursery", "useNodejsImportProtocol");
+        let rule_filter = RuleFilter::Rule("correctness", "useExhaustiveDependencies");
         options.configuration.rules.push_rule(
             RuleKey::new("nursery", "useHookAtTopLevel"),
             RuleOptions::new(HooksOptions { hooks: vec![hook] }),
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 1a1a1ed9013f..f763c2f03828 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
@@ -9,10 +9,12 @@ use biome_deserialize::{
 };
 use biome_js_semantic::{Capture, SemanticModel};
 use biome_js_syntax::{
-    binding_ext::AnyJsBindingDeclaration, JsCallExpression, JsStaticMemberExpression, JsSyntaxKind,
-    JsSyntaxNode, JsVariableDeclaration, TextRange,
+    binding_ext::AnyJsBindingDeclaration, JsCallExpression, JsSyntaxKind, JsSyntaxNode,
+    JsVariableDeclaration, TextRange,
+};
+use biome_js_syntax::{
+    AnyJsExpression, AnyJsMemberExpression, JsIdentifierExpression, TsTypeofType,
 };
-use biome_js_syntax::{AnyJsExpression, JsIdentifierExpression, TsTypeofType};
 use biome_rowan::{AstNode, SyntaxNodeCast};
 use rustc_hash::{FxHashMap, FxHashSet};
 use serde::{Deserialize, Serialize};
@@ -396,13 +398,11 @@ pub enum Fix {
     },
 }
 
-fn get_whole_static_member_expression(
-    reference: &JsSyntaxNode,
-) -> Option {
+fn get_whole_static_member_expression(reference: &JsSyntaxNode) -> Option {
     let root = reference
         .ancestors()
         .skip(2) //IDENT and JS_REFERENCE_IDENTIFIER
-        .take_while(|x| x.kind() == JsSyntaxKind::JS_STATIC_MEMBER_EXPRESSION)
+        .take_while(|x| AnyJsMemberExpression::can_cast(x.kind()))
         .last()?;
     root.cast()
 }
@@ -527,6 +527,55 @@ fn is_out_of_function_scope(
     )
 }
 
+fn into_member_vec(node: &JsSyntaxNode) -> Vec {
+    let mut vec = vec![];
+    let mut next = Some(node.clone());
+
+    while let Some(node) = &next {
+        match AnyJsMemberExpression::cast_ref(node) {
+            Some(member_expr) => {
+                let member_name = member_expr
+                    .member_name()
+                    .and_then(|it| it.as_string_constant().map(|it| it.to_owned()));
+                match member_name {
+                    Some(name) => {
+                        vec.insert(0, name);
+                        next = member_expr.object().ok().map(AstNode::into_syntax);
+                    }
+                    None => break,
+                }
+            }
+            None => {
+                vec.insert(0, node.text_trimmed().to_string());
+                break;
+            }
+        }
+    }
+
+    vec
+}
+
+fn compare_member_depth(a: &JsSyntaxNode, b: &JsSyntaxNode) -> (bool, bool) {
+    let mut a_member_iter = into_member_vec(a).into_iter();
+    let mut b_member_iter = into_member_vec(b).into_iter();
+
+    loop {
+        let a_member = a_member_iter.next();
+        let b_member = b_member_iter.next();
+
+        match (a_member, b_member) {
+            (Some(a_member), Some(b_member)) => {
+                if a_member != b_member {
+                    return (false, false);
+                }
+            }
+            (Some(_), None) => return (true, false),
+            (None, Some(_)) => return (false, true),
+            (None, None) => return (true, true),
+        }
+    }
+}
+
 impl Rule for UseExhaustiveDependencies {
     type Query = Semantic;
     type State = Fix;
@@ -566,19 +615,18 @@ impl Rule for UseExhaustiveDependencies {
                 .map(|capture| {
                     let path = get_whole_static_member_expression(capture.node());
 
-                    let (text, range) = if let Some(path) = path {
-                        (
+                    match path {
+                        Some(path) => (
                             path.syntax().text_trimmed().to_string(),
                             path.syntax().text_trimmed_range(),
-                        )
-                    } else {
-                        (
+                            path.syntax().clone(),
+                        ),
+                        None => (
                             capture.node().text_trimmed().to_string(),
                             capture.node().text_trimmed_range(),
-                        )
-                    };
-
-                    (text, range, capture)
+                            capture.node().clone(),
+                        ),
+                    }
                 })
                 .collect();
 
@@ -588,24 +636,14 @@ impl Rule for UseExhaustiveDependencies {
             let mut add_deps: BTreeMap> = BTreeMap::new();
 
             // Evaluate all the captures
-            for (capture_text, capture_range, _) in captures.iter() {
+            for (capture_text, capture_range, capture_path) in captures.iter() {
                 let mut suggested_fix = None;
                 let mut is_captured_covered = false;
                 for dep 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 =
-                        dep.syntax().text_trimmed().to_string().replace('?', "");
-                    let capture_deeper_than_dependency =
-                        filter_capture_text.starts_with(&filter_dependency_text);
-                    let dependency_deeper_than_capture =
-                        filter_dependency_text.starts_with(&filter_capture_text);
-
-                    match (
-                        capture_deeper_than_dependency,
-                        dependency_deeper_than_capture,
-                    ) {
+                    let (capture_contains_dep, dep_contains_capture) =
+                        compare_member_depth(capture_path, dep.syntax());
+
+                    match (capture_contains_dep, dep_contains_capture) {
                         // capture == dependency
                         (true, true) => {
                             suggested_fix = None;
@@ -653,22 +691,11 @@ impl Rule for UseExhaustiveDependencies {
             let mut remove_deps: Vec = vec![];
             // Search for dependencies not captured
             for dep in deps {
-                let mut covers_any_capture = false;
-                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 =
-                        dep.syntax().text_trimmed().to_string().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;
-                    }
-                }
+                let covers_any_capture = captures.iter().any(|(_, _, capture_path)| {
+                    let (capture_contains_dep, dep_contains_capture) =
+                        compare_member_depth(capture_path, dep.syntax());
+                    capture_contains_dep || dep_contains_capture
+                });
 
                 if !covers_any_capture {
                     remove_deps.push(dep);
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 633cd459c125..1fd330dd96de 100644
--- a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js
+++ b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/valid.js
@@ -108,17 +108,23 @@ function MyComponent6() {
 function MyComponent7() {
     let someObj = getObj();
     useEffect(() => {
-        console.log(someObj.name);
-        console.log(someObj.age)
+        console.log(
+					someObj
+							.name
+				);
+        console.log(someObj["age"])
     }, [someObj.name, someObj.age]);
 }
 
 // Specified dependency cover captures
 function MyComponent8({ a }) {
     useEffect(() => {
-      console.log(a.b);
+      console.log(
+				a
+			  		.b
+			);
     }, [a]);
-}
+}l
 
 // Capturing const outside of component
 // https://github.com/rome/tools/issues/3727
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 36b6869a3291..5c723559bbcd 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
@@ -114,17 +114,23 @@ function MyComponent6() {
 function MyComponent7() {
     let someObj = getObj();
     useEffect(() => {
-        console.log(someObj.name);
-        console.log(someObj.age)
+        console.log(
+					someObj
+							.name
+				);
+        console.log(someObj["age"])
     }, [someObj.name, someObj.age]);
 }
 
 // Specified dependency cover captures
 function MyComponent8({ a }) {
     useEffect(() => {
-      console.log(a.b);
+      console.log(
+				a
+			  		.b
+			);
     }, [a]);
-}
+}l
 
 // Capturing const outside of component
 // https://github.com/rome/tools/issues/3727

From a46230dc34949dc0f32ce10748cf92976a67aa3a Mon Sep 17 00:00:00 2001
From: Zheyu Zhang 
Date: Wed, 17 Jan 2024 16:02:30 +0800
Subject: [PATCH 18/49] fix(js_formatter): fix invalid formatting of nested
 multiline comments (#1581)

---
 CHANGELOG.md                                  |  4 +
 crates/biome_js_formatter/src/comments.rs     | 29 +++----
 .../nested_comments/nested_comments.js        |  8 ++
 .../nested_comments/nested_comments.js.snap   | 84 +++++++++++++++++++
 .../comments/nested_comments/options.json     |  8 ++
 .../src/content/docs/internals/changelog.mdx  |  4 +
 6 files changed, 123 insertions(+), 14 deletions(-)
 create mode 100644 crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/nested_comments.js
 create mode 100644 crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/nested_comments.js.snap
 create mode 100644 crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/options.json

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9a2d16bfbc05..36f69c4b874f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,10 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom
 
 ### Formatter
 
+#### Bug fixed
+
+- Fix [#1571](https://github.com/biomejs/biome/issues/1571). Fix invalid formatting of nested multiline comments. Contributed by @ah-yu
+
 ### JavaScript APIs
 
 ### Linter
diff --git a/crates/biome_js_formatter/src/comments.rs b/crates/biome_js_formatter/src/comments.rs
index db7429917799..4b938e6079c1 100644
--- a/crates/biome_js_formatter/src/comments.rs
+++ b/crates/biome_js_formatter/src/comments.rs
@@ -47,21 +47,22 @@ impl FormatRule> for FormatJsLeadingComment {
             // Indent the remaining lines by one space so that all `*` are aligned.
             write!(
                 f,
-                [align(
-                    1,
-                    &format_once(|f| {
-                        for line in lines {
-                            write!(
-                                f,
-                                [hard_line_break(), dynamic_text(line.trim(), source_offset)]
-                            )?;
-
-                            source_offset += line.text_len();
-                        }
+                [&format_once(|f| {
+                    for line in lines {
+                        write!(
+                            f,
+                            [
+                                hard_line_break(),
+                                text(" "),
+                                dynamic_text(line.trim(), source_offset)
+                            ]
+                        )?;
+
+                        source_offset += line.text_len();
+                    }
 
-                        Ok(())
-                    })
-                )]
+                    Ok(())
+                })]
             )
         } else {
             write!(f, [comment.piece().as_piece()])
diff --git a/crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/nested_comments.js b/crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/nested_comments.js
new file mode 100644
index 000000000000..c75f08ea6981
--- /dev/null
+++ b/crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/nested_comments.js
@@ -0,0 +1,8 @@
+condition ? {
+    a: 'a'
+} : {
+    /**
+    * comment
+    */
+    b: 'b'
+}
\ No newline at end of file
diff --git a/crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/nested_comments.js.snap b/crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/nested_comments.js.snap
new file mode 100644
index 000000000000..43e6a48d1ede
--- /dev/null
+++ b/crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/nested_comments.js.snap
@@ -0,0 +1,84 @@
+---
+source: crates/biome_formatter_test/src/snapshot_builder.rs
+info: js/module/comments/nested_comments/nested_comments.js
+---
+
+# Input
+
+```js
+condition ? {
+    a: 'a'
+} : {
+    /**
+    * comment
+    */
+    b: 'b'
+}
+```
+
+
+=============================
+
+# Outputs
+
+## Output 1
+
+-----
+Indent style: Tab
+Indent width: 2
+Line ending: LF
+Line width: 80
+Quote style: Double Quotes
+JSX quote style: Double Quotes
+Quote properties: As needed
+Trailing comma: All
+Semicolons: Always
+Arrow parentheses: Always
+Bracket spacing: true
+Bracket same line: false
+-----
+
+```js
+condition
+	? {
+			a: "a",
+	  }
+	: {
+			/**
+			 * comment
+			 */
+			b: "b",
+	  };
+```
+
+## Output 2
+
+-----
+Indent style: Space
+Indent width: 4
+Line ending: LF
+Line width: 80
+Quote style: Double Quotes
+JSX quote style: Double Quotes
+Quote properties: As needed
+Trailing comma: All
+Semicolons: Always
+Arrow parentheses: Always
+Bracket spacing: true
+Bracket same line: false
+-----
+
+```js
+condition
+    ? {
+          a: "a",
+      }
+    : {
+          /**
+           * comment
+           */
+          b: "b",
+      };
+```
+
+
diff --git a/crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/options.json b/crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/options.json
new file mode 100644
index 000000000000..ead58282a73b
--- /dev/null
+++ b/crates/biome_js_formatter/tests/specs/js/module/comments/nested_comments/options.json
@@ -0,0 +1,8 @@
+{
+	"cases": [
+		{
+			"indent_style": "Space",
+			"indent_width": 4
+		}
+	]
+}
diff --git a/website/src/content/docs/internals/changelog.mdx b/website/src/content/docs/internals/changelog.mdx
index ebbcc9c8b336..d787f8e9baac 100644
--- a/website/src/content/docs/internals/changelog.mdx
+++ b/website/src/content/docs/internals/changelog.mdx
@@ -26,6 +26,10 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom
 
 ### Formatter
 
+#### Bug fixed
+
+- Fix [#1571](https://github.com/biomejs/biome/issues/1571). Fix invalid formatting of nested multiline comments. Contributed by @ah-yu
+
 ### JavaScript APIs
 
 ### Linter

From 09db85574034ff074b002a1981a790252f6187df Mon Sep 17 00:00:00 2001
From: Arend van Beelen jr 
Date: Wed, 17 Jan 2024 22:16:03 +0100
Subject: [PATCH 19/49] feat(project): `Deserializable` derive macro (#1564)

---
 Cargo.lock                                    |    7 +-
 Cargo.toml                                    |    3 +-
 crates/biome_analyze/CONTRIBUTING.md          |  116 +-
 crates/biome_cli/Cargo.toml                   |   67 +-
 crates/biome_cli/src/execute/migrate.rs       |    2 +-
 .../biome_cli/src/execute/migrate/prettier.rs |  214 +-
 crates/biome_deserialize/Cargo.toml           |   23 +-
 crates/biome_deserialize/README.md            |  278 +--
 crates/biome_deserialize/src/diagnostics.rs   |   13 +
 crates/biome_deserialize/src/json.rs          |   73 +-
 crates/biome_deserialize/src/lib.rs           |   38 +-
 crates/biome_deserialize/src/string_set.rs    |   15 +-
 crates/biome_deserialize/src/validator.rs     |   57 +
 crates/biome_deserialize_macros/Cargo.toml    |    3 +-
 .../src/deserializable_derive.rs              |  469 ++++
 .../enum_variant_attrs.rs                     |   73 +
 .../src/deserializable_derive/struct_attrs.rs |   64 +
 .../struct_field_attrs.rs                     |  221 ++
 crates/biome_deserialize_macros/src/lib.rs    |  239 ++
 crates/biome_formatter/src/lib.rs             |   98 +-
 crates/biome_js_analyze/Cargo.toml            |   45 +-
 .../no_excessive_cognitive_complexity.rs      |   53 +-
 .../nursery/use_consistent_array_type.rs      |   87 +-
 .../nursery/use_filenaming_convention.rs      |  101 +-
 .../a11y/use_valid_aria_role.rs               |   70 +-
 .../use_exhaustive_dependencies.rs            |  126 +-
 .../style/no_restricted_globals.rs            |   62 +-
 .../style/use_naming_convention.rs            |   86 +-
 .../emptyHookNameInOptions.js                 |    0
 .../emptyHookNameInOptions.js.snap            |   26 +
 .../emptyHookNameInOptions.options.json       |   21 +
 .../malformedOptions.js.snap                  |    4 +-
 crates/biome_js_formatter/src/context.rs      |   81 +-
 .../src/context/trailing_comma.rs             |   28 +-
 crates/biome_project/Cargo.toml               |   21 +-
 .../src/node_js_project/package_json.rs       |   16 +-
 crates/biome_service/Cargo.toml               |   17 +-
 crates/biome_service/src/configuration/css.rs |   15 +-
 .../src/configuration/formatter.rs            |   12 +-
 .../src/configuration/javascript/formatter.rs |   17 +-
 .../src/configuration/javascript/mod.rs       |   16 +-
 .../biome_service/src/configuration/json.rs   |   15 +-
 .../src/configuration/linter/mod.rs           |   33 +-
 .../src/configuration/linter/rules.rs         |  182 +-
 crates/biome_service/src/configuration/mod.rs |   58 +-
 .../src/configuration/organize_imports.rs     |    7 +-
 .../src/configuration/overrides.rs            |   23 +-
 .../configuration/parse/json/configuration.rs |   92 -
 .../src/configuration/parse/json/css/mod.rs   |  183 --
 .../src/configuration/parse/json/files.rs     |   60 -
 .../src/configuration/parse/json/formatter.rs |  115 -
 .../parse/json/javascript/formatter.rs        |  122 --
 .../parse/json/javascript/mod.rs              |  138 --
 .../configuration/parse/json/json_impl/mod.rs |  182 --
 .../src/configuration/parse/json/linter.rs    |  150 --
 .../src/configuration/parse/json/mod.rs       |   14 -
 .../parse/json/organize_imports.rs            |   56 -
 .../src/configuration/parse/json/overrides.rs |  272 ---
 .../src/configuration/parse/json/rules.rs     | 1923 -----------------
 .../src/configuration/parse/json/vcs.rs       |   98 -
 .../src/configuration/parse/mod.rs            |    1 -
 crates/biome_service/src/configuration/vcs.rs |   45 +-
 .../formatter_extraneous_field.json.snap      |    1 -
 .../invalid/formatter_quote_style.json.snap   |    1 -
 ...cript_formatter_quote_properties.json.snap |    2 +-
 .../invalid/overrides/incorrect_key.json.snap |    6 +-
 .../top_level_extraneous_field.json.snap      |    6 +-
 .../@biomejs/backend-jsonrpc/src/workspace.ts |    4 +-
 .../@biomejs/biome/configuration_schema.json  |   10 +-
 xtask/codegen/Cargo.toml                      |    2 +-
 xtask/codegen/src/generate_configuration.rs   |  223 +-
 xtask/lintdoc/Cargo.toml                      |    2 +-
 72 files changed, 1959 insertions(+), 5044 deletions(-)
 create mode 100644 crates/biome_deserialize/src/validator.rs
 create mode 100644 crates/biome_deserialize_macros/src/deserializable_derive.rs
 create mode 100644 crates/biome_deserialize_macros/src/deserializable_derive/enum_variant_attrs.rs
 create mode 100644 crates/biome_deserialize_macros/src/deserializable_derive/struct_attrs.rs
 create mode 100644 crates/biome_deserialize_macros/src/deserializable_derive/struct_field_attrs.rs
 create mode 100644 crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.js
 create mode 100644 crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.js.snap
 create mode 100644 crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.options.json
 delete mode 100644 crates/biome_service/src/configuration/parse/json/configuration.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/css/mod.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/files.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/formatter.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/javascript/formatter.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/javascript/mod.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/json_impl/mod.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/linter.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/mod.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/organize_imports.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/overrides.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/rules.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/json/vcs.rs
 delete mode 100644 crates/biome_service/src/configuration/parse/mod.rs

diff --git a/Cargo.lock b/Cargo.lock
index d0d2f43393c8..30443bc26a52 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -169,6 +169,7 @@ dependencies = [
  "biome_console",
  "biome_css_formatter",
  "biome_deserialize",
+ "biome_deserialize_macros",
  "biome_diagnostics",
  "biome_flags",
  "biome_formatter",
@@ -306,6 +307,7 @@ name = "biome_deserialize"
 version = "0.4.0"
 dependencies = [
  "biome_console",
+ "biome_deserialize_macros",
  "biome_diagnostics",
  "biome_json_parser",
  "biome_json_syntax",
@@ -320,8 +322,9 @@ dependencies = [
 
 [[package]]
 name = "biome_deserialize_macros"
-version = "0.3.1"
+version = "0.4.0"
 dependencies = [
+ "convert_case",
  "proc-macro-error",
  "proc-macro2",
  "quote",
@@ -454,6 +457,7 @@ dependencies = [
  "biome_console",
  "biome_control_flow",
  "biome_deserialize",
+ "biome_deserialize_macros",
  "biome_diagnostics",
  "biome_js_factory",
  "biome_js_parser",
@@ -737,6 +741,7 @@ version = "0.0.0"
 dependencies = [
  "biome_console",
  "biome_deserialize",
+ "biome_deserialize_macros",
  "biome_diagnostics",
  "biome_json_parser",
  "biome_json_syntax",
diff --git a/Cargo.toml b/Cargo.toml
index 4ac687785395..24f6f4725a08 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -81,7 +81,7 @@ biome_css_formatter          = { version = "0.4.0", path = "./crates/biome_css_f
 biome_css_parser             = { version = "0.4.0", path = "./crates/biome_css_parser" }
 biome_css_syntax             = { version = "0.4.0", path = "./crates/biome_css_syntax" }
 biome_deserialize            = { version = "0.4.0", path = "./crates/biome_deserialize" }
-biome_deserialize_macros     = { version = "0.3.1", path = "./crates/biome_deserialize_macros" }
+biome_deserialize_macros     = { version = "0.4.0", path = "./crates/biome_deserialize_macros" }
 biome_diagnostics            = { version = "0.4.0", path = "./crates/biome_diagnostics" }
 biome_diagnostics_categories = { version = "0.4.0", path = "./crates/biome_diagnostics_categories" }
 biome_diagnostics_macros     = { version = "0.4.0", path = "./crates/biome_diagnostics_macros" }
@@ -124,6 +124,7 @@ tests_macros         = { path = "./crates/tests_macros" }
 # Crates needed in the workspace
 bitflags          = "2.3.1"
 bpaf              = { version = "0.9.5", features = ["derive"] }
+convert_case      = "0.6.0"
 countme           = "3.0.1"
 dashmap           = "5.4.0"
 ignore            = "0.4.21"
diff --git a/crates/biome_analyze/CONTRIBUTING.md b/crates/biome_analyze/CONTRIBUTING.md
index 0b6e41db5ab9..761591f8f2aa 100644
--- a/crates/biome_analyze/CONTRIBUTING.md
+++ b/crates/biome_analyze/CONTRIBUTING.md
@@ -332,14 +332,16 @@ We would like to set the options in the `biome.json` configuration file:
 The first step is to create the Rust data representation of the rule's options.
 
 ```rust,ignore
-#[derive(Debug, Default, Clone)]
+use biome_deserializable_macros::Deserializable;
+
+#[derive(Clone, Debug, Default, Deserializable)]
 pub struct MyRuleOptions {
     behavior: Behavior,
     threshold: u8,
     behavior_exceptions: Vec
 }
 
-#[derive(Debug, Default, Clone)]
+#[derive(Clone, Debug, Default, Deserializable)]
 pub enum Behavior {
     #[default]
     A,
@@ -350,111 +352,11 @@ pub enum Behavior {
 
 To allow deserializing instances of the types `MyRuleOptions` and `Behavior`,
 they have to implement the `Deserializable` trait from the `biome_deserialize` crate.
+This is what the `Deserializable` keyword in the `#[derive]` statements above did.
+It's a so-called derive macros, which generates the implementation for the `Deserializable` trait
+for you.
 
-In the following code, we implement `Deserializable` for `Behavior`.
-We first deserialize the input into a `TokenText`.
-Then we validate the retrieved text by checking that it is one of the allowed string variants.
-If it is an unknown variant, we emit a diagnostic and return `None` to signal that the deserialization failed.
-Otherwise, we return the corresponding variant.
-
-```rust,ignore
-use biome_deserialize::{Deserializable, DeserializableValue, DeserializationVisitor, Text};
-
-impl Deserializable for Behavior {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match Text::deserialize(&value, name, diagnostics)?.text() {
-            "A" => Some(Behavior::A),
-            "B" => Some(Behavior::B),
-            "C" => Some(Behavior::C),
-            unknown_variant => {
-                const ALLOWED_VARIANTS: &[&str] = &["A", "B", "C"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_variant,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-```
-
-To implement `Deserializable` for `MyRuleOptions`,
-we cannot reuse an existing deserializer because a `struct` has custom fields.
-Instead, we delegate the deserialization to a visitor.
-We implement a visitor by implementing the `DeserializationVisitor` trait from the `biome_deserialize` crate.
-The visitor traverses every field (key-value pair) of our object and deserialize them.
-If an unknown field is found, we emit a diagnostic.
-
-```rust,ignore
-use biome_deserialize::{DeserializationDiagnostic,  Deserializable, DeserializableValue, DeserializationVisitor, Text, VisitableType};
-
-impl Deserializable for MyRuleOptions {
-    fn deserialize(
-        value: &impl DeserializableValue,
-name: &str,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        value.deserialize(MyRuleOptionsVisitor, name, diagnostics)
-    }
-}
-
-struct MyRuleOptionsVisitor;
-impl DeserializationVisitor for MyRuleOptionsVisitor {
-    type Output = MyRuleOptions;
-
-    const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-
-    fn visit_map(
-        self,
-        members: impl Iterator>,
-        _name: &str,
-        _range: TextRange,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        let mut result = Self::Output::default();
-        for (key, value) in members.flatten() {
-            let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                continue;
-            };
-            match key_text.text() {
-                "behavior" => {
-                    if let Some(behavior) = Deserialize::deserialize(&value, &key_text, diagnostics) {
-                        result.behavior = behavior;
-                    }
-                }
-                "threshold" => {
-                    if let Some(threshold) = Deserialize::deserialize(&value, &key_text, diagnostics) {
-                        result.behavior = threshold;
-                    }
-                }
-                "behaviorExceptions" => {
-                    if let Some(exceptions) = Deserialize::deserialize(&value, &key_text, diagnostics) {
-                        result.behavior_exceptions = exceptions;
-                    }
-                }
-                unknown_key => {
-                    const ALLOWED_KEYS: &[&str] = &["behavior", "threshold", "behaviorExceptions"];
-                    diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                        unknown_key,
-                        key.range(),
-                        ALLOWED_KEYS,
-                    ))
-                }
-            }
-        }
-        Some(result)
-    }
-}
-```
-
-Once done, you can set the associated type `Options` of the rule:
+With these types in place, you can set the associated type `Options` of the rule:
 
 ```rust,ignore
 impl Rule for MyRule {
@@ -467,7 +369,7 @@ impl Rule for MyRule {
 }
 ```
 
-A rule can retrieve its option with:
+A rule can retrieve its options with:
 
 ```rust,ignore
 let options = ctx.options();
diff --git a/crates/biome_cli/Cargo.toml b/crates/biome_cli/Cargo.toml
index 06f847fab337..b42646c6c703 100644
--- a/crates/biome_cli/Cargo.toml
+++ b/crates/biome_cli/Cargo.toml
@@ -18,39 +18,40 @@ name = "biome"
 path = "src/main.rs"
 
 [dependencies]
-anyhow               = "1.0.52"
-biome_analyze        = { workspace = true }
-biome_console        = { workspace = true }
-biome_deserialize    = { workspace = true }
-biome_diagnostics    = { workspace = true }
-biome_flags          = { workspace = true }
-biome_formatter      = { workspace = true }
-biome_fs             = { workspace = true }
-biome_js_formatter   = { workspace = true }
-biome_json_formatter = { workspace = true }
-biome_json_parser    = { workspace = true }
-biome_json_syntax    = { workspace = true }
-biome_lsp            = { workspace = true }
-biome_migrate        = { workspace = true }
-biome_rowan          = { workspace = true }
-biome_service        = { workspace = true }
-biome_text_edit      = { workspace = true }
-biome_text_size      = { workspace = true }
-bpaf                 = { workspace = true, features = ["bright-color"] }
-crossbeam            = "0.8.1"
-dashmap              = { workspace = true }
-hdrhistogram         = { version = "7.5.0", default-features = false }
-indexmap             = { workspace = true }
-lazy_static          = { workspace = true }
-rayon                = "1.5.1"
-rustc-hash           = { workspace = true }
-serde                = { workspace = true, features = ["derive"] }
-serde_json           = { workspace = true }
-tokio                = { workspace = true, features = ["io-std", "io-util", "net", "time", "rt", "sync", "rt-multi-thread", "macros"] }
-tracing              = { workspace = true }
-tracing-appender     = "0.2"
-tracing-subscriber   = { version = "0.3.16", features = ["env-filter", "json"] }
-tracing-tree         = "0.2.2"
+anyhow                   = "1.0.52"
+biome_analyze            = { workspace = true }
+biome_console            = { workspace = true }
+biome_deserialize        = { workspace = true }
+biome_deserialize_macros = { workspace = true }
+biome_diagnostics        = { workspace = true }
+biome_flags              = { workspace = true }
+biome_formatter          = { workspace = true }
+biome_fs                 = { workspace = true }
+biome_js_formatter       = { workspace = true }
+biome_json_formatter     = { workspace = true }
+biome_json_parser        = { workspace = true }
+biome_json_syntax        = { workspace = true }
+biome_lsp                = { workspace = true }
+biome_migrate            = { workspace = true }
+biome_rowan              = { workspace = true }
+biome_service            = { workspace = true }
+biome_text_edit          = { workspace = true }
+biome_text_size          = { workspace = true }
+bpaf                     = { workspace = true, features = ["bright-color"] }
+crossbeam                = "0.8.1"
+dashmap                  = { workspace = true }
+hdrhistogram             = { version = "7.5.0", default-features = false }
+indexmap                 = { workspace = true }
+lazy_static              = { workspace = true }
+rayon                    = "1.5.1"
+rustc-hash               = { workspace = true }
+serde                    = { workspace = true, features = ["derive"] }
+serde_json               = { workspace = true }
+tokio                    = { workspace = true, features = ["io-std", "io-util", "net", "time", "rt", "sync", "rt-multi-thread", "macros"] }
+tracing                  = { workspace = true }
+tracing-appender         = "0.2"
+tracing-subscriber       = { version = "0.3.16", features = ["env-filter", "json"] }
+tracing-tree             = "0.2.2"
 
 [target.'cfg(unix)'.dependencies]
 libc  = "0.2.127"
diff --git a/crates/biome_cli/src/execute/migrate.rs b/crates/biome_cli/src/execute/migrate.rs
index 4db51f35551b..e28db079b035 100644
--- a/crates/biome_cli/src/execute/migrate.rs
+++ b/crates/biome_cli/src/execute/migrate.rs
@@ -138,7 +138,7 @@ pub(crate) fn run(migrate_payload: MigratePayload) -> Result<(), CliDiagnostic>
                     formatter: Some(formatter_configuration.clone()),
                     javascript: Some(JavascriptConfiguration {
                         formatter: Some(javascript_configuration.clone()),
-                        ..NoneState::none()
+                        ..Default::default()
                     }),
                     ..NoneState::none()
                 });
diff --git a/crates/biome_cli/src/execute/migrate/prettier.rs b/crates/biome_cli/src/execute/migrate/prettier.rs
index d992ee127895..3c2eb5c3cb97 100644
--- a/crates/biome_cli/src/execute/migrate/prettier.rs
+++ b/crates/biome_cli/src/execute/migrate/prettier.rs
@@ -2,10 +2,7 @@ use crate::diagnostics::MigrationDiagnostic;
 use crate::CliDiagnostic;
 use biome_console::{markup, Console, ConsoleExt};
 use biome_deserialize::json::deserialize_from_json_str;
-use biome_deserialize::{
-    Deserializable, DeserializableValue, DeserializationDiagnostic, DeserializationVisitor, Text,
-    VisitableType,
-};
+use biome_deserialize_macros::Deserializable;
 use biome_diagnostics::{DiagnosticExt, PrintDiagnostic};
 use biome_formatter::{LineEnding, LineWidth, QuoteStyle};
 use biome_fs::{FileSystem, OpenOptions};
@@ -13,10 +10,9 @@ use biome_js_formatter::context::{ArrowParentheses, QuoteProperties, Semicolons,
 use biome_json_parser::JsonParserOptions;
 use biome_service::configuration::{FormatterConfiguration, PlainIndentStyle};
 use biome_service::{DynRef, JavascriptFormatter};
-use biome_text_size::TextRange;
 use std::path::{Path, PathBuf};
 
-#[derive(Debug, Eq, PartialEq, Clone)]
+#[derive(Clone, Debug, Deserializable, Eq, PartialEq)]
 pub(crate) struct PrettierConfiguration {
     /// https://prettier.io/docs/en/options#print-width
     print_width: u16,
@@ -64,7 +60,7 @@ impl Default for PrettierConfiguration {
     }
 }
 
-#[derive(Debug, Eq, PartialEq, Default, Clone)]
+#[derive(Clone, Debug, Default, Deserializable, Eq, PartialEq)]
 enum EndOfLine {
     #[default]
     Lf,
@@ -72,59 +68,14 @@ enum EndOfLine {
     Cr,
 }
 
-impl Deserializable for EndOfLine {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match String::deserialize(value, name, diagnostics)?.as_str() {
-            "lf" => Some(Self::Lf),
-            "crlf" => Some(Self::Crlf),
-            "cr" => Some(Self::Cr),
-            unknown_variant => {
-                const ALLOWED_VARIANTS: &[&str] = &["lf", "crlf", "cr"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_variant,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-
-#[derive(Debug, Eq, PartialEq, Default, Clone)]
+#[derive(Clone, Debug, Default, Deserializable, Eq, PartialEq)]
 enum ArrowParens {
     #[default]
     Always,
     Avoid,
 }
 
-impl Deserializable for ArrowParens {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match String::deserialize(value, name, diagnostics)?.as_str() {
-            "always" => Some(Self::Always),
-            "avoid" => Some(Self::Avoid),
-            unknown_variant => {
-                const ALLOWED_VARIANTS: &[&str] = &["always", "avoid"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_variant,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-
-#[derive(Debug, Default, Eq, PartialEq, Clone)]
+#[derive(Clone, Debug, Default, Deserializable, Eq, PartialEq)]
 enum PrettierTrailingComma {
     #[default]
     All,
@@ -132,58 +83,14 @@ enum PrettierTrailingComma {
     Es5,
 }
 
-impl Deserializable for PrettierTrailingComma {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match String::deserialize(value, name, diagnostics)?.as_str() {
-            "all" => Some(Self::All),
-            "none" => Some(Self::None),
-            "es5" => Some(Self::Es5),
-            unknown_variant => {
-                const ALLOWED_VARIANTS: &[&str] = &["all", "none", "es5"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_variant,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-
-#[derive(Debug, Eq, Default, PartialEq, Clone)]
+#[derive(Clone, Debug, Default, Deserializable, Eq, PartialEq)]
 enum QuoteProps {
     #[default]
+    #[deserializable(rename = "as-needed")]
     AsNeeded,
     Preserve,
 }
 
-impl Deserializable for QuoteProps {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match String::deserialize(value, name, diagnostics)?.as_str() {
-            "as-needed" => Some(Self::AsNeeded),
-            "preserve" => Some(Self::Preserve),
-            unknown_variant => {
-                const ALLOWED_VARIANTS: &[&str] = &["as-needed", "preserve"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_variant,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-
 impl TryFrom<&str> for PrettierTrailingComma {
     type Error = String;
     fn try_from(value: &str) -> Result {
@@ -196,113 +103,6 @@ impl TryFrom<&str> for PrettierTrailingComma {
     }
 }
 
-impl Deserializable for PrettierConfiguration {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        value.deserialize(PrettierVisitor, name, diagnostics)
-    }
-}
-
-struct PrettierVisitor;
-
-impl DeserializationVisitor for PrettierVisitor {
-    type Output = PrettierConfiguration;
-    const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-
-    fn visit_map(
-        self,
-        members: impl Iterator>,
-        _range: TextRange,
-        _name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        let mut result = PrettierConfiguration::default();
-        for (key, value) in members.flatten() {
-            let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                continue;
-            };
-            match key_text.text() {
-                "endOfLine" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.end_of_line = val;
-                    }
-                }
-                "arrowParens" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.arrow_parens = val;
-                    }
-                }
-                "useTabs" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.use_tabs = val;
-                    }
-                }
-
-                "printWidth" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.print_width = val;
-                    }
-                }
-
-                "trailingComma" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.trailing_comma = val;
-                    }
-                }
-
-                "quoteProps" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.quote_props = val;
-                    }
-                }
-
-                "semi" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.semi = val;
-                    }
-                }
-
-                "bracketSpacing" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.bracket_spacing = val;
-                    }
-                }
-
-                "bracketLine" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.bracket_line = val;
-                    }
-                }
-
-                "jsxSingleQuote" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.jsx_single_quote = val;
-                    }
-                }
-
-                "singleQuote" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.single_quote = val;
-                    }
-                }
-
-                "tabWidth" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.tab_width = val;
-                    }
-                }
-
-                _ => {}
-            }
-        }
-
-        Some(result)
-    }
-}
-
 impl From for TrailingComma {
     fn from(value: PrettierTrailingComma) -> Self {
         match value {
diff --git a/crates/biome_deserialize/Cargo.toml b/crates/biome_deserialize/Cargo.toml
index 40f249c22451..bf5a5a571204 100644
--- a/crates/biome_deserialize/Cargo.toml
+++ b/crates/biome_deserialize/Cargo.toml
@@ -11,17 +11,18 @@ repository.workspace = true
 version              = "0.4.0"
 
 [dependencies]
-biome_console     = { workspace = true }
-biome_diagnostics = { workspace = true }
-biome_json_parser = { workspace = true }
-biome_json_syntax = { workspace = true }
-biome_rowan       = { workspace = true }
-bitflags          = { workspace = true }
-indexmap          = { workspace = true, features = ["serde"] }
-schemars          = { workspace = true, optional = true }
-serde             = { workspace = true }
-serde_json        = { workspace = true }
-tracing           = { workspace = true }
+biome_console            = { workspace = true }
+biome_deserialize_macros = { workspace = true }
+biome_diagnostics        = { workspace = true }
+biome_json_parser        = { workspace = true }
+biome_json_syntax        = { workspace = true }
+biome_rowan              = { workspace = true }
+bitflags                 = { workspace = true }
+indexmap                 = { workspace = true, features = ["serde"] }
+schemars                 = { workspace = true, optional = true }
+serde                    = { workspace = true }
+serde_json               = { workspace = true }
+tracing                  = { workspace = true }
 
 [features]
 schema = ["schemars", "schemars/indexmap"]
diff --git a/crates/biome_deserialize/README.md b/crates/biome_deserialize/README.md
index 1b580a9ec1fd..05303631901b 100644
--- a/crates/biome_deserialize/README.md
+++ b/crates/biome_deserialize/README.md
@@ -78,7 +78,35 @@ assert_eq!(deserialized, Some(HashMap::from([("a".to_string(), 0), ("b".to_strin
 assert!(diagnostics.is_empty());
 ```
 
-### Deserializing map and array collections
+### Deserializable derive macro
+
+For more complex types, such as structs and enums, `biome_deserialize_macros` offers a derive macro
+which will generate an implementation of the `Deserializable` trait for you.
+
+For example:
+
+```rs
+#[derive(Clone, Debug, Default, Deserializable)]
+pub struct MyRuleOptions {
+    behavior: Behavior,
+    threshold: u8,
+    behavior_exceptions: Vec
+}
+```
+
+Extensive documentation for the macro is also available if you hover over it in your IDE.
+
+Note that the macro has two main limitations:
+
+- The current implementation only supports enums where none of the variants have custom fields,
+  structs with named fields, and newtypes.
+- Every field must also implement `Deserializable`.
+
+If you want to implement `Deserializable` for a new primitive type, or a complex type that falls
+outside the limitations above, you'll need to implement it manually. See below for the section about
+[Implementing a custom deserializer](#implementing-a-custom-deserializer).
+
+## Deserializing map and array collections
 
 `biome_deserialize` requires that every data format supports arrays and maps.
 A map and an array can be deserialized into several types in Rust.
@@ -98,6 +126,20 @@ If you hesitate between a collection that preserves the insertion order and one
 chooses the collection that preserves the insertion order.
 This often outputs less surprising behavior.
 
+## Implementing a custom deserializer
+
+For most enums and structs, an implementation can be generated by the `Deserializable` macro.
+However, for primitives, and certain complex types, you may need to implement
+`biome_deserialize::Deserializable` yourself.
+
+> [!NOTE]
+> If you are curious about the code generated by the macro, *Rust Analyzer* offers a great feature
+> from the command palette called "Expand macro recursively at caret". Just put your cursor on the
+> word `Deserializable` in the `#[derive(...)]` statement and invoke the command. A panel should
+> open with the expanded macro code.
+
+We provide a few examples for custom implementations below.
+
 ### Custom integer range
 
 Sometimes you want to deserialize an integer and ensure that it is between two given integers.
@@ -183,217 +225,72 @@ assert_eq!(deserialized, None);
 assert_eq!(diagnostics..len(), 1);
 ```
 
-### Deserializing an enumeration of values
-
-Let's assume that we want to deserialize a JSON string that is either `A`, or `B`.
-We represent this string by a Rust's `enum`:
-
-To implement `Deserializable` for `Variant`, we can reuse the `String`,
-because `biome_deserialize` implements `Deserializable` for the `String` type.
-
-Our implementation attempts to deserialize a string and creates the corresponding variant.
-If the variant is not known, we report a diagnostic.
-
-```rust
-use biome_deserialize::{Deserializable, DeserializableValue, DeserializationDiagnostic};
-
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
-pub enum Variant { A, B }
-
-impl Deserializable for Variant {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match String::deserialize(value, name, diagnostics)? {
-            "A" => Some(Variant::A),
-            "B" => Some(Variant::B),
-            unknown_variant => {
-                const ALLOWED_VARIANTS: &[&str] = &["A", "B"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_variant,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-
-use biome_deserialize::json::deserialize_from_json_str;
-use biome_deserialize::Deserialized;
-use biome_json_parser::JsonParserOptions;
-
-let json = "\"A\"";
-let Deserialized {
-    deserialized,
-    diagnostics,
-} = deserialize_from_json_str::(&source, JsonParserOptions::default());
-assert_eq!(deserialized, Some(Variant::A));
-assert!(diagnostics.is_empty());
-```
-
-We can improve our implementation by avoiding the heap-allocation of a string.
-To do this, we use `Text` instead of `String`.
-Internally `Text` borrows a slice of the source.
-
-```rust
-use biome_deserialize::{Deserializable, DeserializableValue, DeserializationDiagnostic, Text};
-
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
-pub enum Variant { A, B }
-
-impl Deserializable for Variant {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match Text::deserialize(value, name, diagnostics)?.text() {
-            "A" => Some(Variant::A),
-            "B" => Some(Variant::B),
-            unknown_variant => {
-                const ALLOWED_VARIANTS: &[&str] = &["A", "B"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_variant,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-```
-
-### Deserializing a struct
-
-Let's assume we want to deserialize a _JSON_ map (object) into an instance of a Rust `struct`.
-
-Because a `struct` has custom fields and types, we cannot reuse an existing deserializable type.
-We have to delegate the deserialization to a visitor.
-
-To do that, we create a zero-sized struct `PersonViistor` that implements `DeserializationVisitor`.
-A `DeserializationVisitor` provides several `visit_` methods.
-You must implement the `visit_` methods of the type you expect.
-Here we expect a map of key-value pairs.
-Thus, we implement `visit_map` and set the associated constant `EXPECTED_TYPE` to `VisitableType::MAP`.
-We also set the associated type `Output` to the type that we want to produce: `Person`.
-
-The implementation of `Deserialziable` for `Person` simply delegates the deserialization of the visitor.
-Internally, the deserialization of `value` calls the `visit_` method that corresponds to its type.
-If the value is a map of key-value pairs, then `visit_map` is called.
-Otherwise, another `visit_` method is called.
-The default implementation of a `visit_` method reports an incorrect type diagnostic.
+### Deserializing a union
 
-Our implementation of `visit_map` traverses the map of key-value pairs.
-It attempts to deserialize every key as a string and deserialize the value according the key's content.
-If the key is `name`, then we deserialize a `String`.
-If the key is `age`, then we deserialize a `u8`.
-`String` and `u8` implements `Deserializable`.
-Thus, we can reuse `String::deserialize` and `u8::deserialize`.
+Sometimes we want to allow several types for a single value.
+For instance let's assume that we cant to accept a JSON value that is either a string or a boolean.
 
-Note that if you use _Serde_ in tandem with `biome_deserialize`, you have to disambiguate the call to `deserialize`.
-Thus, instead of using `String::deserialize` and `u8::deserialize`, you should use `Deserialize::deserialize`.
+In this case, we'll need to inspect the type of the `DeserializableValue` to know which deserializer
+to use:
 
 ```rust
 use biome_deserialize::{DeserializationDiagnostic, Deserializable, DeserializableValue, DeserializationVisitor, Text, VisitableType};
 use biome_rowan::TextRange;
 
-#[derive(Debug, Default, Eq, PartialEq, Clone)]
-pub struct Person { name: String, age: u8 }
+#[derive(Debug, Eq, PartialEq)]
+enum Union {
+    Bool(bool),
+    Str(String),
+}
 
-impl Deserializable for Person {
+impl Deserializable for Union {
     fn deserialize(
         value: &impl DeserializableValue,
         name: &str,
         diagnostics: &mut Vec,
     ) -> Option {
-        // Delegate the deserialization to `PersonVisitor`.
-        // `value` will call the `PersonVisitor::visit_` method that corresponds to its type.
-        value.deserialize(PersonVisitor, name, diagnostics)
-    }
-}
-
-struct PersonVisitor;
-impl DeserializationVisitor for PersonVisitor {
-    // The visitor deserialize a [Person].
-    type Output = Person;
-
-    // We expect a `map` as data type.
-    const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-
-    // Because we expect a `map`, we have to implement the associated method `visit_map`.
-    fn visit_map(
-        self,
-        // Iterator of key-value pairs.
-        members: impl Iterator>,
-        // range of the map in the source text.
-        range: TextRange,
-        _name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        let mut result = Person::default();
-        for (key, value) in members.flatten() {
-            // Try to deserialize the key as a string.
-            // We use `Text` to avoid an heap-allocation.
-            let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                // If this failed, then pass to the next key-value pair.
-                continue;
-            };
-            match key_text.text() {
-                "name" => {
-                    if let Some(name) = String::deserialize(&value, &key_text, diagnostics) {
-                        result.name = name;
-                    }
-                },
-                "age" => {
-                    if let Some(age) = u8::deserialize(&value, &key_text, diagnostics) {
-                        result.age = age;
-                    }
-                },
-                unknown_key => {
-                    const ALLOWED_KEYS: &[&str] = &["name"];
-                    diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                        unknown_key,
-                        key.range(),
-                        ALLOWED_KEYS,
-                    ));
-                }
-            }
+        if value.is_type(VisitableType::BOOL) {
+            biome_deserialize::Deserializable::deserialize(value, rule_name, diagnostics)
+                .map(Self::Bool)
+        } else {
+            biome_deserialize::Deserializable::deserialize(value, rule_name, diagnostics)
+                .map(Self::Str)
         }
-        Some(result)
     }
 }
 
 use biome_deserialize::json::deserialize_from_json_str;
 use biome_json_parser::JsonParserOptions;
 
-let source = r#"{ "name": "Isaac Asimov" }"#;
-let deserialized = deserialize_from_json_str::(&source, JsonParserOptions::default());
+let source = r#" "string" "#;
+let deserialized = deserialize_from_json_str::(&source, JsonParserOptions::default());
+assert!(!deserialized.has_errors());
+assert_eq!(deserialized.into_deserialized(), Some(Union::Str("string".to_string())));
+
+let source = "true";
+let deserialized = deserialize_from_json_str::(&source, JsonParserOptions::default());
 assert!(!deserialized.has_errors());
-assert_eq!(deserialized.into_deserialized(), Some(Person { name: "Isaac Asimov".to_string() }));
+assert_eq!(deserialized.into_deserialized(), Some(Union::Bool(true)));
 ```
 
-### Deserializing a union
+Alternatively, we could implement the above using a custom visitor. Note that this approach is much
+more involved and should only be used as a last resort. Here, we will reimplement `Deserializable`
+for our `Union` type with a visitor for demonstration purposes.
 
-Sometimes we want to allow several types for a same value.
-For instance let's assume that we cant to accept a JSON value that is either a string or a boolean.
+To create your own visitor, start with a struct named after your type with a `Visitor` suffix. We'll
+call ours `UnionVisitor`.
 
-Because we accept several types, we have to use a visitor.
+The visitor struct doesn't need any fields, but we do need to implement `DeserializationVisitor` on
+it. A `DeserializationVisitor` provides several `visit_` methods and you must implement the `visit_`
+methods of the type(s) you expect. Here we expect either a boolean or a string, so we'll implement
+`visit_bool()` and `visit_str()`.
 
-```rust
-use biome_deserialize::{DeserializationDiagnostic, Deserializable, DeserializableValue, DeserializationVisitor, Text, VisitableType};
-use biome_rowan::TextRange;
+We also have to set the associated type `Output` to be a union of the types we expect:
+`VisitableType::BOOL.union(VisitableType::STR)`.
 
-#[derive(Debug, Eq, PartialEq)]
-enum Union {
-    Bool(bool),
-    Str(String),
-}
+The full example:
 
+```rust
 impl Deserializable for Union {
     fn deserialize(
         value: &impl DeserializableValue,
@@ -434,17 +331,4 @@ impl DeserializationVisitor for UnionVisitor {
         Some(Union::Str(value.text().to_string()))
     }
 }
-
-use biome_deserialize::json::deserialize_from_json_str;
-use biome_json_parser::JsonParserOptions;
-
-let source = r#" "string" "#;
-let deserialized = deserialize_from_json_str::(&source, JsonParserOptions::default());
-assert!(!deserialized.has_errors());
-assert_eq!(deserialized.into_deserialized(), Some(Union::Str("string".to_string())));
-
-let source = "true";
-let deserialized = deserialize_from_json_str::(&source, JsonParserOptions::default());
-assert!(!deserialized.has_errors());
-assert_eq!(deserialized.into_deserialized(), Some(Union::Bool(true)));
 ```
diff --git a/crates/biome_deserialize/src/diagnostics.rs b/crates/biome_deserialize/src/diagnostics.rs
index 0b42db58326f..98f8febca86a 100644
--- a/crates/biome_deserialize/src/diagnostics.rs
+++ b/crates/biome_deserialize/src/diagnostics.rs
@@ -100,6 +100,19 @@ impl DeserializationDiagnostic {
         .with_range(range)
     }
 
+    /// Emitted when a key is missing, against a set of required ones
+    pub fn new_missing_key(key_name: &str, range: impl AsSpan, required_keys: &[&str]) -> Self {
+        let diagnostic =
+            Self::new(markup!("The key `"{key_name}"` is missing." ))
+                .with_range(range);
+
+        if required_keys.len() > 1 {
+            diagnostic.note_with_list("Required keys", required_keys)
+        } else {
+            diagnostic
+        }
+    }
+
     /// Emitted when a generic node has an incorrect type
     pub fn new_out_of_bound_integer(
         min: impl std::fmt::Display,
diff --git a/crates/biome_deserialize/src/json.rs b/crates/biome_deserialize/src/json.rs
index ec58652a27f0..232953eed14a 100644
--- a/crates/biome_deserialize/src/json.rs
+++ b/crates/biome_deserialize/src/json.rs
@@ -1,7 +1,7 @@
 //! Implementation of [DeserializableValue] for the JSON data format.
 use crate::{
     Deserializable, DeserializableValue, DeserializationDiagnostic, DeserializationVisitor,
-    Deserialized, Text, TextNumber,
+    Deserialized, Text, TextNumber, VisitableType,
 };
 use biome_diagnostics::{DiagnosticExt, Error};
 use biome_json_parser::{parse_json, JsonParserOptions};
@@ -12,70 +12,23 @@ use biome_rowan::{AstNode, AstSeparatedList};
 /// are consumed and joined with the diagnostics emitted during the deserialization.
 ///
 /// The data structures that need to be deserialized have to implement the [Deserializable] trait.
-/// To implement [Deserializable], it can need to implement [DeserializationVisitor] that allows
-/// visiting a value.
+/// For most data structures, this can be achieved using the
+/// [biome_deserialize_macros::Deserializable] derive.
 ///
 /// `name` corresponds to the name used in a diagnostic to designate the deserialized value.
 ///
 /// ## Examples
 ///
 /// ```
-/// use biome_deserialize::{DeserializationDiagnostic, Deserializable, DeserializableValue, DeserializationVisitor, Text, VisitableType};
 /// use biome_deserialize::json::deserialize_from_json_str;
+/// use biome_deserialize_macros::Deserializable;
 /// use biome_json_parser::JsonParserOptions;
-/// use biome_rowan::{TextRange, TokenText};
 ///
-/// #[derive(Default, Debug, Eq, PartialEq)]
+/// #[derive(Debug, Default, Deserializable, Eq, PartialEq)]
 /// struct NewConfiguration {
 ///     lorem: String
 /// }
 ///
-/// impl Deserializable for NewConfiguration {
-///     fn deserialize(
-///         value: &impl DeserializableValue,
-///         name: &str,
-///         diagnostics: &mut Vec,
-///     ) -> Option {
-///         value.deserialize(Visitor, name, diagnostics)
-///     }
-/// }
-///
-/// struct Visitor;
-/// impl DeserializationVisitor for Visitor {
-///     type Output = NewConfiguration;
-///
-///     const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-///
-///     fn visit_map(
-///         self,
-///         members: impl Iterator>,
-///         _range: TextRange,
-///         _name: &str,
-///         diagnostics: &mut Vec,
-///     ) -> Option {
-///         const ALLOWED_KEYS: &[&str] = &["strictCase", "enumMemberCase"];
-///         let mut result = NewConfiguration::default();
-///         for (key, value) in members.flatten() {
-///             let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-///                 continue;
-///             };
-///             match key_text.text() {
-///                 "lorem" => {
-///                     if let Some(value) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-///                         result.lorem = value;
-///                     }
-///                 },
-///                 _ => diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-///                     &key_text,
-///                     key.range(),
-///                     ALLOWED_KEYS,
-///                 )),
-///             }
-///         }
-///         Some(result)
-///     }
-/// }
-///
 /// let source = r#"{ "lorem": "ipsum" }"#;
 /// let deserialized = deserialize_from_json_str::(&source, JsonParserOptions::default(), "");
 /// assert!(!deserialized.has_errors());
@@ -171,6 +124,18 @@ impl DeserializableValue for AnyJsonValue {
             }
         }
     }
+
+    fn is_type(&self, ty: VisitableType) -> bool {
+        match self {
+            AnyJsonValue::JsonArrayValue(_) => ty == VisitableType::ARRAY,
+            AnyJsonValue::JsonBogusValue(_) => false,
+            AnyJsonValue::JsonBooleanValue(_) => ty == VisitableType::BOOL,
+            AnyJsonValue::JsonNullValue(_) => ty == VisitableType::NULL,
+            AnyJsonValue::JsonNumberValue(_) => ty == VisitableType::NUMBER,
+            AnyJsonValue::JsonObjectValue(_) => ty == VisitableType::MAP,
+            AnyJsonValue::JsonStringValue(_) => ty == VisitableType::STR,
+        }
+    }
 }
 
 impl DeserializableValue for JsonMemberName {
@@ -187,6 +152,10 @@ impl DeserializableValue for JsonMemberName {
         let value = self.inner_string_text().ok()?;
         visitor.visit_str(Text(value), AstNode::range(self), name, diagnostics)
     }
+
+    fn is_type(&self, _ty: VisitableType) -> bool {
+        false
+    }
 }
 
 #[cfg(test)]
diff --git a/crates/biome_deserialize/src/lib.rs b/crates/biome_deserialize/src/lib.rs
index c894f4c259af..8972556c3a2d 100644
--- a/crates/biome_deserialize/src/lib.rs
+++ b/crates/biome_deserialize/src/lib.rs
@@ -35,15 +35,17 @@ pub mod json;
 mod merge;
 mod none_state;
 pub mod string_set;
+mod validator;
 
 use biome_diagnostics::{Error, Severity};
-use biome_rowan::TextRange;
+pub use biome_rowan::TextRange;
 pub use diagnostics::{DeserializationAdvice, DeserializationDiagnostic, VisitableType};
 pub use impls::*;
 pub use merge::Merge;
 pub use none_state::NoneState;
 use std::fmt::Debug;
 pub use string_set::StringSet;
+pub use validator::*;
 
 /// Implemented by data structures that can deserialize any [DeserializableValue].
 ///
@@ -51,46 +53,25 @@ pub use string_set::StringSet;
 /// To implement [Deserializable], you can reuse a type that implements [Deserializable] and
 /// turn the obtained value into what you want.
 ///
-/// When deserializing more complex types, such as a `struct`,
-/// you have to use a type that implements [DeserializationVisitor].
+/// When deserializing more complex types, such as a `struct` or `enum`, you can use the
+/// [Deserializable] derive macro.
 ///
 /// ## Example
 ///
 /// ```
-/// use biome_deserialize::{DeserializationDiagnostic,  Deserializable, Text, DeserializableValue};
+/// use biome_deserialize_macros::Deserializable;
 /// use biome_rowan::TextRange;
 ///
+/// #[derive(Deserializable)]
 /// pub enum Variant {
 ///     A,
 ///     B,
 /// }
 ///
-/// impl Deserializable for Variant {
-///     fn deserialize(
-///         value: &impl DeserializableValue,
-///         name: &str,
-///         diagnostics: &mut Vec,
-///     ) -> Option {
-///         match Text::deserialize(value, name, diagnostics)?.text() {
-///             "A" => Some(Variant::A),
-///             "B" => Some(Variant::B),
-///             unknown_variant => {
-///                 const ALLOWED_VARIANTS: &[&str] = &["A", "B"];
-///                 diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-///                     unknown_variant,
-///                     value.range(),
-///                     ALLOWED_VARIANTS,
-///                 ));
-///                 None
-///             }
-///         }
-///     }
-/// }
-///
 /// use biome_deserialize::json::deserialize_from_json_str;
 /// use biome_json_parser::JsonParserOptions;
 ///
-/// let source = r#""A""#;
+/// let source = r#""a""#;
 /// let deserialized = deserialize_from_json_str::(&source, JsonParserOptions::default(), "");
 /// assert!(!deserialized.has_errors());
 /// assert!(matches!(deserialized.into_deserialized(), Some(Variant::A)));
@@ -123,6 +104,9 @@ pub trait DeserializableValue: Sized {
         name: &str,
         diagnostics: &mut Vec,
     ) -> Option;
+
+    /// Returns whether the value is of the given type.
+    fn is_type(&self, ty: VisitableType) -> bool;
 }
 
 /// This trait represents a visitor that walks through a [DeserializableValue].
diff --git a/crates/biome_deserialize/src/string_set.rs b/crates/biome_deserialize/src/string_set.rs
index 0b715caea02c..ccac8b14a809 100644
--- a/crates/biome_deserialize/src/string_set.rs
+++ b/crates/biome_deserialize/src/string_set.rs
@@ -1,4 +1,5 @@
-use crate::{Deserializable, DeserializableValue, Merge};
+use crate::{self as biome_deserialize, Merge};
+use biome_deserialize_macros::Deserializable;
 use indexmap::set::IntoIter;
 use indexmap::IndexSet;
 use serde::de::{SeqAccess, Visitor};
@@ -9,7 +10,7 @@ use std::str::FromStr;
 
 // To implement serde's traits, we encapsulate `IndexSet` in a new type `StringSet`.
 
-#[derive(Default, Debug, Clone, Eq, PartialEq)]
+#[derive(Clone, Default, Debug, Deserializable, Eq, PartialEq)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 pub struct StringSet(IndexSet);
 
@@ -116,13 +117,3 @@ impl Serialize for StringSet {
         sequence.end()
     }
 }
-
-impl Deserializable for StringSet {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        Deserializable::deserialize(value, name, diagnostics).map(StringSet)
-    }
-}
diff --git a/crates/biome_deserialize/src/validator.rs b/crates/biome_deserialize/src/validator.rs
new file mode 100644
index 000000000000..ec24b1896b74
--- /dev/null
+++ b/crates/biome_deserialize/src/validator.rs
@@ -0,0 +1,57 @@
+use crate::DeserializationDiagnostic;
+use biome_console::markup;
+use biome_rowan::TextRange;
+
+/// Trait that should be implemented on types that use the
+/// `#[deserializable(with_validator)]` annotation with the
+/// [biome_deserialize_macros::Deserializable] derive macro.
+pub trait DeserializableValidator {
+    /// Validates the deserialized instance.
+    ///
+    /// May generate any kind of diagnostics.
+    ///
+    /// Returns `true` if the instance passes validation and `false` when it
+    /// should be rejected.
+    fn validate(
+        &self,
+        name: &str,
+        range: TextRange,
+        diagnostics: &mut Vec,
+    ) -> bool;
+}
+
+/// Validates whether the given value is non-empty.
+pub fn non_empty(
+    value: &T,
+    name: &str,
+    range: TextRange,
+    diagnostics: &mut Vec,
+) -> bool {
+    if value.is_empty() {
+        diagnostics.push(
+            DeserializationDiagnostic::new(markup! {
+                {name}" may not be empty"
+            })
+            .with_range(range),
+        );
+        false
+    } else {
+        true
+    }
+}
+
+pub trait IsEmpty {
+    fn is_empty(&self) -> bool;
+}
+
+impl IsEmpty for String {
+    fn is_empty(&self) -> bool {
+        String::is_empty(self)
+    }
+}
+
+impl IsEmpty for Vec {
+    fn is_empty(&self) -> bool {
+        Vec::is_empty(self)
+    }
+}
diff --git a/crates/biome_deserialize_macros/Cargo.toml b/crates/biome_deserialize_macros/Cargo.toml
index f34bd19e3841..44f7643665a2 100644
--- a/crates/biome_deserialize_macros/Cargo.toml
+++ b/crates/biome_deserialize_macros/Cargo.toml
@@ -8,12 +8,13 @@ keywords.workspace   = true
 license.workspace    = true
 name                 = "biome_deserialize_macros"
 repository.workspace = true
-version              = "0.3.1"
+version              = "0.4.0"
 
 [lib]
 proc-macro = true
 
 [dependencies]
+convert_case     = { workspace = true }
 proc-macro-error = { version = "1.0.4", default-features = false }
 proc-macro2      = "1.0.63"
 quote            = "1.0.14"
diff --git a/crates/biome_deserialize_macros/src/deserializable_derive.rs b/crates/biome_deserialize_macros/src/deserializable_derive.rs
new file mode 100644
index 000000000000..3f7b8674c9a1
--- /dev/null
+++ b/crates/biome_deserialize_macros/src/deserializable_derive.rs
@@ -0,0 +1,469 @@
+mod enum_variant_attrs;
+mod struct_attrs;
+mod struct_field_attrs;
+
+use self::struct_attrs::StructAttrs;
+use self::struct_field_attrs::DeprecatedField;
+use crate::deserializable_derive::enum_variant_attrs::EnumVariantAttrs;
+use crate::deserializable_derive::struct_field_attrs::StructFieldAttrs;
+use convert_case::{Case, Casing};
+use proc_macro2::{Ident, Span, TokenStream};
+use proc_macro_error::*;
+use quote::quote;
+use syn::{Data, GenericParam, Generics, Path, PathSegment, Type};
+
+pub(crate) struct DeriveInput {
+    pub ident: Ident,
+    pub generics: Generics,
+    pub data: DeserializableData,
+}
+
+impl DeriveInput {
+    pub fn parse(input: syn::DeriveInput) -> Self {
+        let data = match input.data {
+            Data::Enum(data) => {
+                let data = data
+                    .variants
+                    .into_iter()
+                    .filter(|variant| {
+                        if variant.fields.is_empty() {
+                            true
+                        } else {
+                            abort!(
+                                variant.fields,
+                                "Deserializable derive cannot handle enum variants with fields -- you may need a custom Deserializable implementation"
+                            )
+                        }
+                    })
+                    .map(|variant| {
+                        let attrs = EnumVariantAttrs::from_attrs(&variant.attrs);
+
+                        let ident = variant.ident;
+                        let key = attrs
+                            .rename
+                            .unwrap_or_else(|| ident.to_string().to_case(Case::Camel));
+
+                        DeserializableVariantData { ident, key }
+                    })
+                    .collect();
+                DeserializableData::Enum(data)
+            }
+            Data::Struct(data) => {
+                if data.fields.iter().all(|field| field.ident.is_some()) {
+                    let attrs = StructAttrs::from_attrs(&input.attrs);
+
+                    let fields = data
+                        .fields
+                        .clone()
+                        .into_iter()
+                        .filter_map(|field| field.ident.map(|ident| (ident, field.attrs, field.ty)))
+                        .map(|(ident, attrs, ty)| {
+                            let attrs = StructFieldAttrs::from_attrs(&attrs);
+                            let key = attrs
+                                .rename
+                                .unwrap_or_else(|| ident.to_string().to_case(Case::Camel));
+
+                            DeserializableFieldData {
+                                bail_on_error: attrs.bail_on_error,
+                                deprecated: attrs.deprecated,
+                                ident,
+                                key,
+                                passthrough_name: attrs.passthrough_name,
+                                required: attrs.required,
+                                ty,
+                                validate: attrs.validate,
+                            }
+                        })
+                        .collect();
+
+                    DeserializableData::Struct(DeserializableStructData {
+                        fields,
+                        from_none: attrs.from_none,
+                        with_validator: attrs.with_validator,
+                    })
+                } else if data.fields.len() == 1 {
+                    let attrs = StructAttrs::from_attrs(&input.attrs);
+
+                    DeserializableData::Newtype(DeserializableNewtypeData {
+                        with_validator: attrs.with_validator,
+                    })
+                } else {
+                    abort!(
+                        data.fields,
+                        "Deserializable derive requires structs to have named fields or a single unnamed one -- you may need a custom Deserializable implementation"
+                    )
+                }
+            }
+            _ => abort!(
+                input,
+                "Deserializable can only be derived for enums and structs"
+            ),
+        };
+
+        Self {
+            ident: input.ident,
+            generics: input.generics,
+            data,
+        }
+    }
+}
+
+#[derive(Debug)]
+pub enum DeserializableData {
+    Enum(Vec),
+    Newtype(DeserializableNewtypeData),
+    Struct(DeserializableStructData),
+}
+
+#[derive(Debug)]
+pub struct DeserializableNewtypeData {
+    with_validator: bool,
+}
+
+#[derive(Debug)]
+pub struct DeserializableStructData {
+    fields: Vec,
+    from_none: bool,
+    with_validator: bool,
+}
+
+#[derive(Clone, Debug)]
+pub struct DeserializableFieldData {
+    bail_on_error: bool,
+    deprecated: Option,
+    ident: Ident,
+    key: String,
+    passthrough_name: bool,
+    required: bool,
+    ty: Type,
+    validate: Option,
+}
+
+#[derive(Debug)]
+pub struct DeserializableVariantData {
+    ident: Ident,
+    key: String,
+}
+
+pub(crate) fn generate_deserializable(input: DeriveInput) -> TokenStream {
+    match input.data {
+        DeserializableData::Enum(variants) => {
+            generate_deserializable_enum(input.ident, input.generics, variants)
+        }
+        DeserializableData::Newtype(data) => {
+            generate_deserializable_newtype(input.ident, input.generics, data)
+        }
+        DeserializableData::Struct(data) => {
+            generate_deserializable_struct(input.ident, input.generics, data)
+        }
+    }
+}
+
+fn generate_deserializable_enum(
+    ident: Ident,
+    generics: Generics,
+    variants: Vec,
+) -> TokenStream {
+    let allowed_variants: Vec<_> = variants
+        .iter()
+        .map(|DeserializableVariantData { key, .. }| quote! { #key })
+        .collect();
+
+    let deserialize_variants: Vec<_> = variants
+        .iter()
+        .map(
+            |DeserializableVariantData {
+                 ident: variant_ident,
+                 key,
+             }| {
+                quote! { #key => Some(Self::#variant_ident) }
+            },
+        )
+        .collect();
+
+    let trait_bounds = generate_trait_bounds(&generics);
+
+    quote! {
+        impl #generics biome_deserialize::Deserializable for #ident #generics #trait_bounds{
+            fn deserialize(
+                value: &impl biome_deserialize::DeserializableValue,
+                name: &str,
+                diagnostics: &mut Vec,
+            ) -> Option {
+                match biome_deserialize::Text::deserialize(value, name, diagnostics)?.text() {
+                    #(#deserialize_variants),*,
+                    unknown_variant => {
+                        const ALLOWED_VARIANTS: &[&str] = &[#(#allowed_variants),*];
+                        diagnostics.push(biome_deserialize::DeserializationDiagnostic::new_unknown_value(
+                            unknown_variant,
+                            value.range(),
+                            ALLOWED_VARIANTS,
+                        ));
+                        None
+                    }
+                }
+            }
+        }
+    }
+}
+
+fn generate_deserializable_newtype(
+    ident: Ident,
+    generics: Generics,
+    data: DeserializableNewtypeData,
+) -> TokenStream {
+    let validator = if data.with_validator {
+        quote! {
+            if !biome_deserialize::DeserializableValidator::validate(&result, name, value.range(), diagnostics) {
+                return None;
+            }
+        }
+    } else {
+        quote! {}
+    };
+
+    let trait_bounds = generate_trait_bounds(&generics);
+
+    quote! {
+        impl #generics biome_deserialize::Deserializable for #ident #generics #trait_bounds {
+            fn deserialize(
+                value: &impl biome_deserialize::DeserializableValue,
+                name: &str,
+                diagnostics: &mut Vec,
+            ) -> Option {
+                let result = biome_deserialize::Deserializable::deserialize(value, name, diagnostics).map(Self)?;
+                #validator
+                Some(result)
+            }
+        }
+    }
+}
+
+fn generate_deserializable_struct(
+    ident: Ident,
+    generics: Generics,
+    data: DeserializableStructData,
+) -> TokenStream {
+    let allowed_keys: Vec<_> = data
+        .fields
+        .iter()
+        // It's not helpful to report deprecated keys as valid alternative.
+        .filter(|data| data.deprecated.is_none())
+        .map(|DeserializableFieldData { key, .. }| quote! { #key })
+        .collect();
+
+    let required_fields: Vec<_> = data
+        .fields
+        .iter()
+        .filter(|data| data.required)
+        .cloned()
+        .collect();
+
+    let deserialize_fields: Vec<_> = data
+        .fields
+        .into_iter()
+        .map(|field_data| {
+            let DeserializableFieldData { ident: field_ident, key, ty, .. } = field_data;
+
+            let is_optional = matches!(
+                &ty,
+                Type::Path(path) if path
+                    .path
+                    .segments
+                    .last()
+                    .is_some_and(|segment| segment.ident == "Option")
+            );
+
+            let deprecation_notice = field_data.deprecated.map(|deprecated| {
+                match deprecated {
+                    DeprecatedField::Message(message) => quote! {
+                        diagnostics.push(DeserializationDiagnostic::new_deprecated(
+                            key_text.text(),
+                            value.range()
+                        ).with_note(#message));
+                    },
+                    DeprecatedField::UseInstead(path) => quote! {
+                        diagnostics.push(DeserializationDiagnostic::new_deprecated_use_instead(
+                            &key_text,
+                            key.range(),
+                            #path,
+                        ));
+                    },
+                }
+            });
+
+            let name = match field_data.passthrough_name {
+                true => quote! { name },
+                false => quote! { &key_text }
+            };
+
+            let validate = field_data.validate.map(|validate| {
+                let path = Path {
+                    leading_colon: None,
+                    segments: validate
+                        .split("::")
+                        .map(|segment| {
+                            PathSegment::from(Ident::new(segment, Span::call_site()))
+                        })
+                        .collect(),
+                };
+
+                quote! {
+                    .filter(|v| #path(v, #key, value.range(), diagnostics))
+                }
+            });
+
+            if is_optional {
+                let error_result = if field_data.bail_on_error || field_data.required {
+                    quote! { return None }
+                } else {
+                    quote! { None }
+                };
+
+                quote! {
+                    #key => {
+                        result.#field_ident = match Deserializable::deserialize(&value, #name, diagnostics)#validate {
+                            Some(value) => {
+                                #deprecation_notice
+                                Some(value)
+                            }
+                            None => #error_result,
+                        };
+                    }
+                }
+            } else {
+                let error_result = if field_data.bail_on_error || field_data.required {
+                    quote! { return None, }
+                } else {
+                    quote! { {} }
+                };
+
+                quote! {
+                    #key => {
+                        match Deserializable::deserialize(&value, #name, diagnostics)#validate {
+                            Some(value) => {
+                                #deprecation_notice
+                                result.#field_ident = value;
+                            }
+                            None => #error_result
+                        }
+                    }
+                }
+            }
+        })
+        .collect();
+
+    let trait_bounds = generate_trait_bounds(&generics);
+
+    let validator = if required_fields.is_empty() {
+        quote! {}
+    } else {
+        let required_keys: Vec<_> = required_fields
+            .iter()
+            .map(|field_data| &field_data.key)
+            .collect();
+        let required_fields = required_fields.iter().map(|field_data| {
+            let DeserializableFieldData {
+                ident: field_ident,
+                key,
+                ty,
+                ..
+            } = field_data;
+            quote! {
+                if result.#field_ident == #ty::default() {
+                    diagnostics.push(DeserializationDiagnostic::new_missing_key(
+                        #key,
+                        range,
+                        REQUIRED_KEYS,
+                    ))
+                }
+            }
+        });
+        quote! {
+            const REQUIRED_KEYS: &[&str] = &[#(#required_keys),*];
+            #(#required_fields)*
+        }
+    };
+    let validator = if data.with_validator {
+        quote! {
+            #validator
+            if !biome_deserialize::DeserializableValidator::validate(&result, name, range, diagnostics) {
+                return None;
+            }
+        }
+    } else {
+        validator
+    };
+
+    let visitor_ident = Ident::new(&format!("{ident}Visitor"), Span::call_site());
+    let result_init = if data.from_none {
+        quote! { biome_deserialize::NoneState::none() }
+    } else {
+        quote! { Self::Output::default() }
+    };
+
+    quote! {
+        impl #generics biome_deserialize::Deserializable for #ident #generics #trait_bounds {
+            fn deserialize(
+                value: &impl biome_deserialize::DeserializableValue,
+                name: &str,
+                diagnostics: &mut Vec,
+            ) -> Option {
+                value.deserialize(#visitor_ident, name, diagnostics)
+            }
+        }
+
+        struct #visitor_ident #generics;
+        impl #generics biome_deserialize::DeserializationVisitor for #visitor_ident #generics {
+            type Output = #ident;
+
+            const EXPECTED_TYPE: biome_deserialize::VisitableType = biome_deserialize::VisitableType::MAP;
+
+            fn visit_map(
+                self,
+                members: impl Iterator>,
+                range: biome_deserialize::TextRange,
+                name: &str,
+                diagnostics: &mut Vec,
+            ) -> Option {
+                use biome_deserialize::{Deserializable, DeserializationDiagnostic, Text};
+                let mut result: Self::Output = #result_init;
+                for (key, value) in members.flatten() {
+                    let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
+                        continue;
+                    };
+                    match key_text.text() {
+                        #(#deserialize_fields)*
+                        unknown_key => {
+                            const ALLOWED_KEYS: &[&str] = &[#(#allowed_keys),*];
+                            diagnostics.push(DeserializationDiagnostic::new_unknown_key(
+                                unknown_key,
+                                key.range(),
+                                ALLOWED_KEYS,
+                            ))
+                        }
+                    }
+                }
+                #validator
+                Some(result)
+            }
+        }
+    }
+}
+
+fn generate_trait_bounds(generics: &Generics) -> TokenStream {
+    if generics.params.is_empty() {
+        quote! {}
+    } else {
+        let params = generics.params.iter().map(|param| match param {
+            GenericParam::Type(ty) => {
+                let ident = &ty.ident;
+                quote! { #ident: biome_deserialize::Deserializable }
+            }
+            _ => abort!(generics, "Unsupported generic parameter"),
+        });
+        quote! {
+            where #(#params),*
+        }
+    }
+}
diff --git a/crates/biome_deserialize_macros/src/deserializable_derive/enum_variant_attrs.rs b/crates/biome_deserialize_macros/src/deserializable_derive/enum_variant_attrs.rs
new file mode 100644
index 000000000000..0662e640d44d
--- /dev/null
+++ b/crates/biome_deserialize_macros/src/deserializable_derive/enum_variant_attrs.rs
@@ -0,0 +1,73 @@
+use proc_macro2::Ident;
+use quote::ToTokens;
+use syn::ext::IdentExt;
+use syn::parse::{Parse, ParseStream, Result};
+use syn::{parenthesized, Attribute, Error, LitStr, Token};
+
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+pub struct EnumVariantAttrs {
+    /// Optional name to use in the serialized format.
+    ///
+    /// See also: 
+    pub rename: Option,
+}
+
+impl EnumVariantAttrs {
+    pub fn from_attrs(attrs: &[Attribute]) -> Self {
+        let mut opts = Self::default();
+        for attr in attrs {
+            if attr.path.is_ident("deserializable") || attr.path.is_ident("serde") {
+                opts.merge_with(
+                    syn::parse2::(attr.tokens.clone())
+                        .expect("Could not parse variant attributes"),
+                );
+            }
+        }
+        opts
+    }
+
+    fn merge_with(&mut self, other: Self) {
+        if other.rename.is_some() {
+            self.rename = other.rename;
+        }
+    }
+}
+
+impl Parse for EnumVariantAttrs {
+    fn parse(input: ParseStream) -> Result {
+        let content;
+        parenthesized!(content in input);
+
+        let parse_value = || -> Result {
+            content.parse::()?;
+            Ok(content
+                .parse::()?
+                .to_token_stream()
+                .to_string()
+                .trim_matches('"')
+                .to_owned())
+        };
+
+        let mut result = Self::default();
+        loop {
+            let key: Ident = content.call(IdentExt::parse_any)?;
+            match key.to_string().as_ref() {
+                "rename" => result.rename = Some(parse_value()?),
+                other => {
+                    return Err(Error::new(
+                        content.span(),
+                        format!("Unexpected variant attribute: {other}"),
+                    ))
+                }
+            }
+
+            if content.is_empty() {
+                break;
+            }
+
+            content.parse::()?;
+        }
+
+        Ok(result)
+    }
+}
diff --git a/crates/biome_deserialize_macros/src/deserializable_derive/struct_attrs.rs b/crates/biome_deserialize_macros/src/deserializable_derive/struct_attrs.rs
new file mode 100644
index 000000000000..3b86ba6b169d
--- /dev/null
+++ b/crates/biome_deserialize_macros/src/deserializable_derive/struct_attrs.rs
@@ -0,0 +1,64 @@
+use proc_macro2::Ident;
+use syn::ext::IdentExt;
+use syn::parse::{Parse, ParseStream, Result};
+use syn::{parenthesized, Attribute, Error, Token};
+
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+pub struct StructAttrs {
+    pub from_none: bool,
+    pub with_validator: bool,
+}
+
+impl StructAttrs {
+    pub fn from_attrs(attrs: &[Attribute]) -> Self {
+        let mut opts = Self::default();
+        for attr in attrs {
+            if attr.path.is_ident("deserializable") {
+                opts.merge_with(
+                    syn::parse2::(attr.tokens.clone())
+                        .expect("Could not parse field attributes"),
+                );
+            }
+        }
+        opts
+    }
+
+    fn merge_with(&mut self, other: Self) {
+        if other.from_none {
+            self.from_none = other.from_none;
+        }
+        if other.with_validator {
+            self.with_validator = other.with_validator;
+        }
+    }
+}
+
+impl Parse for StructAttrs {
+    fn parse(input: ParseStream) -> Result {
+        let content;
+        parenthesized!(content in input);
+
+        let mut result = Self::default();
+        loop {
+            let key: Ident = content.call(IdentExt::parse_any)?;
+            match key.to_string().as_ref() {
+                "from_none" => result.from_none = true,
+                "with_validator" => result.with_validator = true,
+                other => {
+                    return Err(Error::new(
+                        content.span(),
+                        format!("Unexpected field attribute: {other}"),
+                    ))
+                }
+            }
+
+            if content.is_empty() {
+                break;
+            }
+
+            content.parse::()?;
+        }
+
+        Ok(result)
+    }
+}
diff --git a/crates/biome_deserialize_macros/src/deserializable_derive/struct_field_attrs.rs b/crates/biome_deserialize_macros/src/deserializable_derive/struct_field_attrs.rs
new file mode 100644
index 000000000000..74968e89652c
--- /dev/null
+++ b/crates/biome_deserialize_macros/src/deserializable_derive/struct_field_attrs.rs
@@ -0,0 +1,221 @@
+use proc_macro2::Ident;
+use quote::ToTokens;
+use syn::ext::IdentExt;
+use syn::parse::{Parse, ParseStream, Result};
+use syn::{parenthesized, Attribute, Error, LitStr, Token};
+
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+pub struct StructFieldAttrs {
+    /// If `true`, bails on deserializing the entire struct if validation for
+    /// this field fails.
+    ///
+    /// Note the struct may still be deserialized if the field is not present in
+    /// the serialized representation at all. In that case `Default::default()`
+    /// will be filled in.
+    pub bail_on_error: bool,
+
+    /// If set, this provides information about the deprecated of the field.
+    pub deprecated: Option,
+
+    /// If set, the name passed to the deserializer (which was passed by the
+    /// deserializer of the parent object) is also passed through to the
+    /// deserializer of the field value.
+    pub passthrough_name: bool,
+
+    /// Optional name to use in the serialized format.
+    ///
+    /// See also: 
+    pub rename: Option,
+
+    /// If `true`, presence of this field is required for successful
+    /// deserialization of the struct.
+    ///
+    /// Implies `bail_on_error`.
+    pub required: bool,
+
+    /// Optional validation function to be called on the field value.
+    pub validate: Option,
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum DeprecatedField {
+    /// A generic message that explains what to do or why the field is deprecated.
+    Message(String),
+
+    /// Provides the path for a new field to use instead.
+    UseInstead(String),
+}
+
+impl StructFieldAttrs {
+    pub fn from_attrs(attrs: &[Attribute]) -> Self {
+        let mut opts = Self::default();
+        for attr in attrs {
+            if attr.path.is_ident("deserializable") {
+                opts.merge_with(
+                    syn::parse2::(attr.tokens.clone())
+                        .expect("Could not parse field attributes"),
+                );
+            } else if attr.path.is_ident("serde") {
+                opts.merge_with_serde(
+                    syn::parse2::(attr.tokens.clone())
+                        .expect("Could not parse Serde field attributes"),
+                );
+            }
+        }
+        opts
+    }
+
+    fn merge_with(&mut self, other: Self) {
+        if other.bail_on_error {
+            self.bail_on_error = other.bail_on_error;
+        }
+        if other.deprecated.is_some() {
+            self.deprecated = other.deprecated;
+        }
+        if other.passthrough_name {
+            self.passthrough_name = other.passthrough_name;
+        }
+        if other.rename.is_some() {
+            self.rename = other.rename;
+        }
+        if other.required {
+            self.required = other.required;
+        }
+        if other.validate.is_some() {
+            self.validate = other.validate;
+        }
+    }
+
+    fn merge_with_serde(&mut self, other: SerdeStructFieldAttrs) {
+        if other.rename.is_some() {
+            self.rename = other.rename;
+        }
+    }
+}
+
+impl Parse for StructFieldAttrs {
+    fn parse(input: ParseStream) -> Result {
+        let content;
+        parenthesized!(content in input);
+
+        let parse_value = || -> Result {
+            content.parse::()?;
+            Ok(content
+                .parse::()?
+                .to_token_stream()
+                .to_string()
+                .trim_matches('"')
+                .to_owned())
+        };
+
+        let mut result = Self::default();
+        loop {
+            let key: Ident = content.call(IdentExt::parse_any)?;
+            match key.to_string().as_ref() {
+                "bail_on_error" => result.bail_on_error = true,
+                "deprecated" => {
+                    result.deprecated = Some(content.parse::()?);
+                }
+                "passthrough_name" => result.passthrough_name = true,
+                "rename" => result.rename = Some(parse_value()?),
+                "required" => result.required = true,
+                "validate" => result.validate = Some(parse_value()?),
+                other => {
+                    return Err(Error::new(
+                        content.span(),
+                        format!("Unexpected field attribute: {other}"),
+                    ))
+                }
+            }
+
+            if content.is_empty() {
+                break;
+            }
+
+            content.parse::()?;
+        }
+
+        Ok(result)
+    }
+}
+
+impl Parse for DeprecatedField {
+    fn parse(input: ParseStream) -> Result {
+        let content;
+        parenthesized!(content in input);
+
+        let parse_value = || -> Result {
+            content.parse::()?;
+            Ok(content
+                .parse::()?
+                .to_token_stream()
+                .to_string()
+                .trim_matches('"')
+                .to_owned())
+        };
+
+        let key: Ident = content.call(IdentExt::parse_any)?;
+        let result = match key.to_string().as_ref() {
+            "message" => Self::Message(parse_value()?),
+            "use_instead" => Self::UseInstead(parse_value()?),
+            other => {
+                return Err(Error::new(
+                    content.span(),
+                    format!("Unexpected field attribute inside deprecated(): {other}"),
+                ))
+            }
+        };
+
+        if !content.is_empty() {
+            return Err(Error::new(
+                content.span(),
+                "Only one attribute expected inside deprecated()",
+            ));
+        }
+
+        Ok(result)
+    }
+}
+
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+struct SerdeStructFieldAttrs {
+    rename: Option,
+}
+
+impl Parse for SerdeStructFieldAttrs {
+    fn parse(input: ParseStream) -> Result {
+        let content;
+        parenthesized!(content in input);
+
+        let parse_value = || -> Result {
+            content.parse::()?;
+            Ok(content
+                .parse::()?
+                .to_token_stream()
+                .to_string()
+                .trim_matches('"')
+                .to_owned())
+        };
+
+        let mut result = Self::default();
+        loop {
+            let key: Ident = content.call(IdentExt::parse_any)?;
+            match key.to_string().as_ref() {
+                "rename" => result.rename = Some(parse_value()?),
+                _ => {
+                    // Don't fail on unrecognized Serde attrs,
+                    // but consume values to advance the parser.
+                    let _result = parse_value();
+                }
+            }
+
+            if content.is_empty() {
+                break;
+            }
+
+            content.parse::()?;
+        }
+
+        Ok(result)
+    }
+}
diff --git a/crates/biome_deserialize_macros/src/lib.rs b/crates/biome_deserialize_macros/src/lib.rs
index 0a12c0123fa6..433aa2e78109 100644
--- a/crates/biome_deserialize_macros/src/lib.rs
+++ b/crates/biome_deserialize_macros/src/lib.rs
@@ -1,3 +1,4 @@
+mod deserializable_derive;
 mod merge_derive;
 mod none_state_derive;
 
@@ -5,6 +6,244 @@ use proc_macro::TokenStream;
 use proc_macro_error::*;
 use syn::{parse_macro_input, DeriveInput};
 
+/// Derives the [biome_deserialize::Deserializable] trait for a custom enum or
+/// struct.
+///
+/// It supports implementing the trait for the following data structures:
+/// - Structs with named fields where every field is of type `T` or `Option`
+///   and where `T` also implements [biome_deserialize::Deserializable]. The
+///   struct must also implement `Default`.
+/// - Structs with a single unnamed field (a so-called
+///   [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html)).
+/// - Enums, so long as the variants don't also have fields.
+///
+/// ## Examples
+///
+/// ```no_test
+/// #[derive(Default, Deserializable)]
+/// struct StructWithNamedFields {
+///     foo: String,
+///     bar: Option,
+/// }
+///
+/// #[derive(Deserializable)]
+/// struct NewType(u16);
+///
+/// #[derive(Deserializable)]
+/// enum EnumWithPlainVariants {
+///     Variant1,
+///     Variant2
+/// }
+/// ```
+///
+/// ## Struct attributes
+///
+/// When [Deserializable] is derived on a struct, its behavior may be adjusted
+/// through attributes.
+///
+/// ### `with_validator`
+///
+/// When the `with_validator` attribute is present, the deserializable type is
+/// expected to implement the `DeserializableValidator` trait. The generated
+/// deserializer will call its `validate()` method and reject the instance if
+/// it returns `false`.
+///
+/// ```no_test
+/// #[derive(Default, Deserializable)]
+/// #[deserializable(with_validator)]
+/// struct ValidatedStruct {
+///     // In real code, please use the `validate` attribute instead (see below)!
+///     non_empty: String,
+/// }
+///
+/// impl DeserializableValidator for ValidatedStruct {
+///     fn fn validate(
+///         &self,
+///         name: &str,
+///         range: biome_rowan::TextRange,
+///         diagnostics: &mut Vec,
+///     ) -> bool {
+///         if self.non_empty.is_empty() {
+///             diagnostics.push(
+///                 DeserializationDiagnostic::new(markup! {
+///                     "foo"" may not be empty"
+///                 })
+///                 .with_range(range),
+///             );
+///             false
+///         } else {
+///             true
+///         }
+///     }
+/// }
+/// ```
+///
+/// ## Struct field attributes
+///
+/// A struct's fields may also be adjusted through attributes.
+///
+/// ### `bail_on_error`
+///
+/// If present, bails on deserializing the entire struct if validation for this
+/// this field fails.
+///
+/// Note the struct may still be deserialized if the field is not present in the
+/// serialized representation at all. In that case `Default::default()` will be
+/// filled in. If this is not what you want, you probably want to use the
+/// `required` attribute instead.
+///
+/// ```no_test
+/// #[derive(Default, Deserializable)]
+/// pub struct ReactHook {
+///     #[deserializable(bail_on_error)]
+///     pub name: String,
+/// }
+/// ```
+///
+/// ### `deprecated`
+///
+/// Used to generate diagnostics when a deprecated field is deserialized. Note
+/// this does not alter the behavior of the deserializer, so you still need to
+/// account for the field's value after deserialization.
+///
+/// ```no_test
+/// #[derive(Default, Deserializable)]
+/// pub struct ReactHook {
+///     #[deserializable(deprecated(use_instead = "name"))]
+///     pub old_name: String,
+///
+///     #[deserializable(deprecated(message = "nick names are not used anymore"))]
+///     pub nick_name: String,
+///
+///     pub name: String,
+/// }
+/// ```
+///
+/// ### `passthrough_name`
+///
+/// A particularly noteworthy attribute is `passthrough_name`. Every
+/// deserializer receives a `name` argument which is used to add context to
+/// diagnostics reported when deserializing the value. Typically, when the value
+/// of an object property is deserialized, the `name` refers to the name of the
+/// property. In some cases however, you may want to pass through the name given
+/// to the object's deserializer instead, in order to prevent losing more
+/// "distant" context.
+///
+/// An example is the `RuleWithOptions` struct, where the name of the rule is
+/// passed through to the deserializer for `PossibleOptions`. Without this
+/// attribute, the name given to the field's deserializer would always be
+/// "options".
+///
+/// ```no_test
+/// #[derive(Default, Deserializable)]
+/// pub struct RuleWithOptions {
+///     pub level: RulePlainConfiguration,
+///
+///     #[deserializable(passthrough_name)]
+///     pub options: Option,
+/// }
+/// ```
+///
+/// ### `rename`
+///
+/// ```no_test
+/// #[derive(Default, Deserializable)]
+/// struct StructWithFields {
+///     // Use "$schema" as serialized property, instead of "schema". By
+///     // default, field names use "camelCase".
+///     #[deserializable(rename = "$schema")]
+///     schema: Option,
+/// }
+/// ```
+///
+/// For structs that also implement Serde's `Serialize` or `Deserialize`, it
+/// automatically picks up on Serde's `rename` attribute:
+///
+/// ```no_test
+/// #[derive(Default, Deserialize, Deserializable, Serialize)]
+/// struct StructWithFields {
+///     // This also works:
+///     #[serde(rename = "$schema")]
+///     schema: Option,
+/// }
+/// ```
+///
+/// ### `required`
+///
+/// If present, presence of this field is required for successful
+/// deserialization of the struct.
+///
+/// Note this does not check whether the value is meaningful. For instance, an
+/// empty string would still be accepted. For such use case, you may also want
+/// to use the `validate` attribute.
+///
+/// Implies `bail_on_error`.
+///
+/// ```no_test
+/// #[derive(Default, Deserializable)]
+/// pub struct StructWithRequiredName {
+///     #[deserializable(required)]
+///     pub name: String,
+/// }
+/// ```
+///
+/// ### `validate`
+///
+/// Like the `with_validator` annotation, this allows the invocation of a
+/// validation function that can emit diagnostics and reject instances. But
+/// unlike `with_validator`, this attribute takes an argument that allows you
+/// to specify the validation function.
+///
+/// Note the validator is not invoked if the field is not present in the
+/// serialized representation at all. To cover this, you may also want to use
+/// the `required` attribute.
+///
+/// ```no_test
+/// #[derive(Default, Deserializable)]
+/// struct ValidatedStruct {
+///     #[deserializable(required, validate = "biome_deserialize::non_empty")]
+///     non_empty: String,
+/// }
+/// ```
+///
+/// ## Enum variant attributes
+///
+/// When [Deserializable] is derived on a enum, the deserialization of its
+/// variants may also be adjusted through attributes.
+///
+/// ### `rename`
+///
+/// ```no_test
+/// #[derive(Deserializable)]
+/// enum Cases {
+///     // Serialized representation defaults to "camelCase", which is what we
+///     // want here.
+///     CamelCase,
+///     // The following attribute provides a custom serialization:
+///     #[deserializable(rename = "kebab-case")]
+///     KebabCase,
+/// }
+/// ```
+///
+/// Using Serde's attributes is supported on enums too.
+#[proc_macro_derive(Deserializable, attributes(deserializable))]
+#[proc_macro_error]
+pub fn derive_deserializable(input: TokenStream) -> TokenStream {
+    let input = parse_macro_input!(input as DeriveInput);
+
+    let input = deserializable_derive::DeriveInput::parse(input);
+
+    let tokens = deserializable_derive::generate_deserializable(input);
+
+    if false {
+        panic!("{tokens}");
+    }
+
+    TokenStream::from(tokens)
+}
+
+/// Derives the [biome_deserialize::Merge] trait for a custom enum or
+/// struct.
 #[proc_macro_derive(Merge)]
 #[proc_macro_error]
 pub fn derive_mergeable(input: TokenStream) -> TokenStream {
diff --git a/crates/biome_formatter/src/lib.rs b/crates/biome_formatter/src/lib.rs
index 382069558d58..f7b3b8031b7c 100644
--- a/crates/biome_formatter/src/lib.rs
+++ b/crates/biome_formatter/src/lib.rs
@@ -56,8 +56,9 @@ use crate::printer::{Printer, PrinterOptions};
 use crate::trivia::{format_skipped_token_trivia, format_trimmed_token};
 pub use arguments::{Argument, Arguments};
 use biome_deserialize::{
-    Deserializable, DeserializableValue, DeserializationDiagnostic, Text, TextNumber,
+    Deserializable, DeserializableValue, DeserializationDiagnostic, TextNumber,
 };
+use biome_deserialize_macros::Deserializable;
 use biome_deserialize_macros::Merge;
 use biome_rowan::{
     Language, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxResult, SyntaxToken, SyntaxTriviaPiece,
@@ -126,7 +127,7 @@ impl std::fmt::Display for IndentStyle {
     }
 }
 
-#[derive(Clone, Copy, Debug, Eq, Hash, Merge, PartialEq)]
+#[derive(Clone, Copy, Debug, Deserializable, Eq, Hash, Merge, PartialEq)]
 #[cfg_attr(
     feature = "serde",
     derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema),
@@ -195,27 +196,6 @@ impl std::fmt::Display for LineEnding {
     }
 }
 
-impl Deserializable for LineEnding {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        let value_text = Text::deserialize(value, name, diagnostics)?;
-        if let Ok(value) = value_text.parse::() {
-            Some(value)
-        } else {
-            const ALLOWED_VARIANTS: &[&str] = &["lf", "crlf", "cr"];
-            diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                &value_text,
-                value.range(),
-                ALLOWED_VARIANTS,
-            ));
-            None
-        }
-    }
-}
-
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 #[cfg_attr(
     feature = "serde",
@@ -357,7 +337,7 @@ impl From for u16 {
     }
 }
 
-#[derive(Clone, Copy, Debug, Default, Eq, Hash, Merge, PartialEq)]
+#[derive(Clone, Copy, Debug, Default, Deserializable, Eq, Hash, Merge, PartialEq)]
 #[cfg_attr(
     feature = "serde",
     derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema),
@@ -444,28 +424,6 @@ impl From for Quote {
     }
 }
 
-impl Deserializable for QuoteStyle {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        const ALLOWED_VARIANTS: &[&str] = &["double", "single"];
-        match Text::deserialize(value, name, diagnostics)?.text() {
-            "double" => Some(QuoteStyle::Double),
-            "single" => Some(QuoteStyle::Single),
-            unknown_variant => {
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_variant,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-
 /// Context object storing data relevant when formatting an object.
 pub trait FormatContext {
     type Options: FormatOptions;
@@ -1773,3 +1731,51 @@ pub struct FormatStateSnapshot {
     #[cfg(debug_assertions)]
     printed_tokens: printed_tokens::PrintedTokensSnapshot,
 }
+
+#[cfg(test)]
+mod tests {
+    use super::LineWidth;
+    use biome_deserialize::json::deserialize_from_json_str;
+    use biome_deserialize_macros::Deserializable;
+    use biome_diagnostics::Error;
+
+    #[test]
+    fn test_out_of_range_line_width() {
+        #[derive(Debug, Default, Deserializable, Eq, PartialEq)]
+        struct TestConfig {
+            line_width: LineWidth,
+        }
+
+        struct DiagnosticPrinter<'a> {
+            diagnostics: &'a [Error],
+        }
+
+        impl<'a> DiagnosticPrinter<'a> {
+            fn new(diagnostics: &'a [Error]) -> Self {
+                Self { diagnostics }
+            }
+        }
+
+        impl<'a> std::fmt::Display for DiagnosticPrinter<'a> {
+            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+                for diagnostic in self.diagnostics {
+                    diagnostic.description(f)?;
+                }
+                Ok(())
+            }
+        }
+
+        let source = r#"{ "lineWidth": 500 }"#;
+        let deserialized = deserialize_from_json_str::(source, Default::default(), "");
+        assert_eq!(
+            format!("{}", DiagnosticPrinter::new(deserialized.diagnostics())),
+            "The number should be an integer between 1 and 320."
+        );
+        assert_eq!(
+            deserialized.into_deserialized().unwrap(),
+            TestConfig {
+                line_width: LineWidth(80)
+            }
+        );
+    }
+}
diff --git a/crates/biome_js_analyze/Cargo.toml b/crates/biome_js_analyze/Cargo.toml
index 6b6812736955..e60e02d8cfc3 100644
--- a/crates/biome_js_analyze/Cargo.toml
+++ b/crates/biome_js_analyze/Cargo.toml
@@ -11,28 +11,29 @@ repository.workspace = true
 version              = "0.4.0"
 
 [dependencies]
-biome_analyze       = { workspace = true }
-biome_aria          = { workspace = true }
-biome_console       = { workspace = true }
-biome_control_flow  = { workspace = true }
-biome_deserialize   = { workspace = true }
-biome_diagnostics   = { workspace = true }
-biome_js_factory    = { workspace = true }
-biome_js_semantic   = { workspace = true }
-biome_js_syntax     = { workspace = true }
-biome_json_factory  = { workspace = true }
-biome_json_syntax   = { workspace = true }
-biome_rowan         = { workspace = true }
-biome_unicode_table = { workspace = true }
-lazy_static         = { workspace = true }
-log                 = "0.4.20"
-natord              = "1.0.9"
-roaring             = "0.10.1"
-rustc-hash          = { workspace = true }
-schemars            = { workspace = true, optional = true }
-serde               = { workspace = true, features = ["derive"] }
-serde_json          = { workspace = true }
-smallvec            = { workspace = true }
+biome_analyze            = { workspace = true }
+biome_aria               = { workspace = true }
+biome_console            = { workspace = true }
+biome_control_flow       = { workspace = true }
+biome_deserialize        = { workspace = true }
+biome_deserialize_macros = { workspace = true }
+biome_diagnostics        = { workspace = true }
+biome_js_factory         = { workspace = true }
+biome_js_semantic        = { workspace = true }
+biome_js_syntax          = { workspace = true }
+biome_json_factory       = { workspace = true }
+biome_json_syntax        = { workspace = true }
+biome_rowan              = { workspace = true }
+biome_unicode_table      = { workspace = true }
+lazy_static              = { workspace = true }
+log                      = "0.4.20"
+natord                   = "1.0.9"
+roaring                  = "0.10.1"
+rustc-hash               = { workspace = true }
+schemars                 = { workspace = true, optional = true }
+serde                    = { workspace = true, features = ["derive"] }
+serde_json               = { workspace = true }
+smallvec                 = { workspace = true }
 
 [dev-dependencies]
 biome_js_parser  = { path = "../biome_js_parser", features = ["tests"] }
diff --git a/crates/biome_js_analyze/src/analyzers/complexity/no_excessive_cognitive_complexity.rs b/crates/biome_js_analyze/src/analyzers/complexity/no_excessive_cognitive_complexity.rs
index b556c693d775..4a8c15233989 100644
--- a/crates/biome_js_analyze/src/analyzers/complexity/no_excessive_cognitive_complexity.rs
+++ b/crates/biome_js_analyze/src/analyzers/complexity/no_excessive_cognitive_complexity.rs
@@ -3,10 +3,7 @@ use biome_analyze::{
     RuleDiagnostic, RuleSource, ServiceBag, Visitor, VisitorContext,
 };
 use biome_console::markup;
-use biome_deserialize::{
-    Deserializable, DeserializableValue, DeserializationDiagnostic, DeserializationVisitor, Text,
-    VisitableType,
-};
+use biome_deserialize_macros::Deserializable;
 use biome_js_syntax::{
     AnyFunctionLike, JsBreakStatement, JsContinueStatement, JsElseClause, JsLanguage,
     JsLogicalExpression, JsLogicalOperator,
@@ -368,7 +365,7 @@ pub struct ComplexityScore {
 }
 
 /// Options for the rule `noExcessiveCognitiveComplexity`.
-#[derive(Deserialize, Serialize, Debug, Eq, PartialEq, Clone)]
+#[derive(Clone, Debug, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schema", derive(JsonSchema))]
 #[serde(rename_all = "camelCase", deny_unknown_fields)]
 pub struct ComplexityOptions {
@@ -383,49 +380,3 @@ impl Default for ComplexityOptions {
         }
     }
 }
-
-impl Deserializable for ComplexityOptions {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        value.deserialize(ComplexityOptionsVisitor, name, diagnostics)
-    }
-}
-
-struct ComplexityOptionsVisitor;
-impl DeserializationVisitor for ComplexityOptionsVisitor {
-    type Output = ComplexityOptions;
-
-    const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-
-    fn visit_map(
-        self,
-        members: impl Iterator>,
-        _range: TextRange,
-        _name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        const ALLOWED_KEYS: &[&str] = &["maxAllowedComplexity"];
-        let mut result = Self::Output::default();
-        for (key, value) in members.flatten() {
-            let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                continue;
-            };
-            match key_text.text() {
-                "maxAllowedComplexity" => {
-                    if let Some(val) = Deserializable::deserialize(&value, &key_text, diagnostics) {
-                        result.max_allowed_complexity = val;
-                    }
-                }
-                text => diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                    text,
-                    key.range(),
-                    ALLOWED_KEYS,
-                )),
-            }
-        }
-        Some(result)
-    }
-}
diff --git a/crates/biome_js_analyze/src/analyzers/nursery/use_consistent_array_type.rs b/crates/biome_js_analyze/src/analyzers/nursery/use_consistent_array_type.rs
index 71f7c1dd7c21..7c231478503f 100644
--- a/crates/biome_js_analyze/src/analyzers/nursery/use_consistent_array_type.rs
+++ b/crates/biome_js_analyze/src/analyzers/nursery/use_consistent_array_type.rs
@@ -1,28 +1,21 @@
-use std::str::FromStr;
-
+use crate::JsRuleAction;
 use biome_analyze::{
     context::RuleContext, declare_rule, ActionCategory, Ast, FixKind, Rule, RuleDiagnostic,
     RuleSource,
 };
 use biome_console::{markup, Markup, MarkupBuf};
-use biome_deserialize::{
-    Deserializable, DeserializableValue, DeserializationDiagnostic, DeserializationVisitor, Text,
-    VisitableType,
-};
+use biome_deserialize_macros::Deserializable;
 use biome_diagnostics::Applicability;
 use biome_js_factory::make;
 use biome_js_syntax::{
     AnyTsName, AnyTsType, JsSyntaxKind, JsSyntaxToken, TriviaPieceKind, TsReferenceType,
     TsTypeArguments, T,
 };
-use biome_rowan::{
-    AstNode, AstSeparatedList, BatchMutationExt, SyntaxNodeOptionExt, TextRange, TriviaPiece,
-};
+use biome_rowan::{AstNode, AstSeparatedList, BatchMutationExt, SyntaxNodeOptionExt, TriviaPiece};
 #[cfg(feature = "schemars")]
 use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
-
-use crate::JsRuleAction;
+use std::str::FromStr;
 
 declare_rule! {
     /// Require consistently using either `T[]` or `Array`
@@ -476,14 +469,14 @@ where
     )
 }
 
-#[derive(Deserialize, Serialize, Default, Debug, Clone, Eq, PartialEq)]
+#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schemars", derive(JsonSchema))]
 #[serde(rename_all = "camelCase", deny_unknown_fields)]
 pub struct ConsistentArrayTypeOptions {
     syntax: ConsistentArrayType,
 }
 
-#[derive(Deserialize, Serialize, Debug, Default, Clone, Copy, Eq, PartialEq)]
+#[derive(Clone, Copy, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schemars", derive(JsonSchema))]
 #[serde(rename_all = "camelCase")]
 pub enum ConsistentArrayType {
@@ -494,53 +487,6 @@ pub enum ConsistentArrayType {
     Generic,
 }
 
-impl Deserializable for ConsistentArrayTypeOptions {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        struct Visitor;
-        impl DeserializationVisitor for Visitor {
-            type Output = ConsistentArrayTypeOptions;
-            const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-            fn visit_map(
-                self,
-                members: impl Iterator<
-                    Item = Option<(impl DeserializableValue, impl DeserializableValue)>,
-                >,
-                _range: TextRange,
-                _name: &str,
-                diagnostics: &mut Vec,
-            ) -> Option {
-                const ALLOWED_KEYS: &[&str] = &["syntax"];
-                let mut result = Self::Output::default();
-                for (key, value) in members.flatten() {
-                    let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                        continue;
-                    };
-                    match key_text.text() {
-                        "syntax" => {
-                            if let Some(val) =
-                                Deserializable::deserialize(&value, &key_text, diagnostics)
-                            {
-                                result.syntax = val;
-                            }
-                        }
-                        text => diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                            text,
-                            key.range(),
-                            ALLOWED_KEYS,
-                        )),
-                    }
-                }
-                Some(result)
-            }
-        }
-        value.deserialize(Visitor, name, diagnostics)
-    }
-}
-
 impl FromStr for ConsistentArrayType {
     type Err = &'static str;
 
@@ -552,24 +498,3 @@ impl FromStr for ConsistentArrayType {
         }
     }
 }
-
-impl Deserializable for ConsistentArrayType {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        const ALLOWED_VARIANTS: &[&str] = &["shorthand", "generic"];
-        let value_text = Text::deserialize(value, name, diagnostics)?;
-        if let Ok(value) = value_text.parse::() {
-            Some(value)
-        } else {
-            diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                value_text.text(),
-                value.range(),
-                ALLOWED_VARIANTS,
-            ));
-            None
-        }
-    }
-}
diff --git a/crates/biome_js_analyze/src/analyzers/nursery/use_filenaming_convention.rs b/crates/biome_js_analyze/src/analyzers/nursery/use_filenaming_convention.rs
index 3f32fed32ea8..3369e918c563 100644
--- a/crates/biome_js_analyze/src/analyzers/nursery/use_filenaming_convention.rs
+++ b/crates/biome_js_analyze/src/analyzers/nursery/use_filenaming_convention.rs
@@ -1,17 +1,15 @@
-use std::{hash::Hash, str::FromStr};
-
 use crate::{semantic_services::SemanticServices, utils::case::Case};
 use biome_analyze::{
     context::RuleContext, declare_rule, Rule, RuleDiagnostic, RuleSource, RuleSourceKind,
 };
 use biome_console::markup;
-use biome_deserialize::{
-    Deserializable, DeserializationDiagnostic, DeserializationVisitor, Text, VisitableType,
-};
+use biome_deserialize_macros::Deserializable;
 use biome_rowan::TextRange;
 use rustc_hash::FxHashSet;
 use serde::{Deserialize, Serialize};
+use std::{hash::Hash, str::FromStr};
 
+use biome_deserialize::{DeserializableValue, DeserializationDiagnostic};
 #[cfg(feature = "schemars")]
 use schemars::JsonSchema;
 use smallvec::SmallVec;
@@ -213,7 +211,7 @@ pub(crate) enum FileNamingConventionState {
 }
 
 /// Rule's options.
-#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schemars", derive(JsonSchema))]
 #[serde(rename_all = "camelCase", deny_unknown_fields)]
 pub struct FilenamingConventionOptions {
@@ -251,67 +249,7 @@ impl Default for FilenamingConventionOptions {
     }
 }
 
-impl Deserializable for FilenamingConventionOptions {
-    fn deserialize(
-        value: &impl biome_deserialize::DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        value.deserialize(FilenamingConventionOptionsVisitor, name, diagnostics)
-    }
-}
-
-struct FilenamingConventionOptionsVisitor;
-impl DeserializationVisitor for FilenamingConventionOptionsVisitor {
-    type Output = FilenamingConventionOptions;
-
-    const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-
-    fn visit_map(
-        self,
-        members: impl Iterator<
-            Item = Option<(
-                impl biome_deserialize::DeserializableValue,
-                impl biome_deserialize::DeserializableValue,
-            )>,
-        >,
-        _range: biome_rowan::TextRange,
-        _name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        const ALLOWED_KEYS: &[&str] = &["strictCase", "filenameCases"];
-        let mut result = Self::Output::default();
-        for (key, value) in members.flatten() {
-            let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                continue;
-            };
-            match key_text.text() {
-                "strictCase" => {
-                    if let Some(strict_case) =
-                        Deserializable::deserialize(&value, &key_text, diagnostics)
-                    {
-                        result.strict_case = strict_case;
-                    }
-                }
-                "filenameCases" => {
-                    if let Some(filename_cases) =
-                        Deserializable::deserialize(&value, &key_text, diagnostics)
-                    {
-                        result.filename_cases = filename_cases;
-                    }
-                }
-                unknown_key => diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                    unknown_key,
-                    key.range(),
-                    ALLOWED_KEYS,
-                )),
-            }
-        }
-        Some(result)
-    }
-}
-
-#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schemars", derive(JsonSchema))]
 pub struct FilenameCases(FxHashSet);
 
@@ -335,13 +273,14 @@ impl Default for FilenameCases {
     }
 }
 
-impl Deserializable for FilenameCases {
+impl biome_deserialize::Deserializable for FilenameCases {
     fn deserialize(
-        value: &impl biome_deserialize::DeserializableValue,
+        value: &impl DeserializableValue,
         name: &str,
         diagnostics: &mut Vec,
     ) -> Option {
-        let cases: FxHashSet<_> = Deserializable::deserialize(value, name, diagnostics)?;
+        let cases: FxHashSet<_> =
+            biome_deserialize::Deserializable::deserialize(value, name, diagnostics)?;
         if cases.is_empty() {
             diagnostics.push(
                 DeserializationDiagnostic::new(markup! {
@@ -356,7 +295,7 @@ impl Deserializable for FilenameCases {
 }
 
 /// Supported cases for TypeScript `enum` member names.
-#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Deserializable, Eq, Hash, PartialEq, Serialize)]
 #[cfg_attr(feature = "schemars", derive(JsonSchema))]
 pub enum FilenameCase {
     /// camelCase
@@ -405,26 +344,6 @@ impl FromStr for FilenameCase {
     }
 }
 
-impl Deserializable for FilenameCase {
-    fn deserialize(
-        value: &impl biome_deserialize::DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        let value_text = Text::deserialize(value, name, diagnostics)?;
-        if let Ok(value) = value_text.parse::() {
-            Some(value)
-        } else {
-            diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                value_text.text(),
-                value.range(),
-                Self::ALLOWED_VARIANTS,
-            ));
-            None
-        }
-    }
-}
-
 impl TryFrom for Case {
     type Error = &'static str;
 
diff --git a/crates/biome_js_analyze/src/aria_analyzers/a11y/use_valid_aria_role.rs b/crates/biome_js_analyze/src/aria_analyzers/a11y/use_valid_aria_role.rs
index be36c2a0dcae..98a2094aad5a 100644
--- a/crates/biome_js_analyze/src/aria_analyzers/a11y/use_valid_aria_role.rs
+++ b/crates/biome_js_analyze/src/aria_analyzers/a11y/use_valid_aria_role.rs
@@ -3,9 +3,7 @@ use biome_analyze::{
     context::RuleContext, declare_rule, ActionCategory, FixKind, Rule, RuleDiagnostic, RuleSource,
 };
 use biome_console::markup;
-use biome_deserialize::{
-    Deserializable, DeserializationDiagnostic, DeserializationVisitor, Text, VisitableType,
-};
+use biome_deserialize_macros::Deserializable;
 use biome_diagnostics::Applicability;
 use biome_js_syntax::jsx_ext::AnyJsxElement;
 use biome_rowan::{AstNode, BatchMutationExt};
@@ -75,74 +73,14 @@ declare_rule! {
     }
 }
 
-#[derive(Default, Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(rename_all = "camelCase", deny_unknown_fields)]
 pub struct ValidAriaRoleOptions {
-    allowed_invalid_roles: Vec,
+    allow_invalid_roles: Vec,
     ignore_non_dom: bool,
 }
 
-impl Deserializable for ValidAriaRoleOptions {
-    fn deserialize(
-        value: &impl biome_deserialize::DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        value.deserialize(ValidAriaRoleOptionsVisitor, name, diagnostics)
-    }
-}
-
-struct ValidAriaRoleOptionsVisitor;
-impl DeserializationVisitor for ValidAriaRoleOptionsVisitor {
-    type Output = ValidAriaRoleOptions;
-
-    const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-
-    fn visit_map(
-        self,
-        members: impl Iterator<
-            Item = Option<(
-                impl biome_deserialize::DeserializableValue,
-                impl biome_deserialize::DeserializableValue,
-            )>,
-        >,
-        _range: biome_rowan::TextRange,
-        _name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        let mut result = Self::Output::default();
-        for (key, value) in members.flatten() {
-            let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                continue;
-            };
-            match key_text.text() {
-                "allowInvalidRoles" => {
-                    if let Some(roles) = Deserializable::deserialize(&value, &key_text, diagnostics)
-                    {
-                        result.allowed_invalid_roles = roles;
-                    }
-                }
-                "ignoreNonDom" => {
-                    if let Some(value) = Deserializable::deserialize(&value, &key_text, diagnostics)
-                    {
-                        result.ignore_non_dom = value;
-                    }
-                }
-                unknown_key => {
-                    const ALLOWED_KEYS: &[&str] = &["allowInvalidRoles", "ignoreNonDom"];
-                    diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                        unknown_key,
-                        key.range(),
-                        ALLOWED_KEYS,
-                    ));
-                }
-            }
-        }
-        Some(result)
-    }
-}
-
 impl Rule for UseValidAriaRole {
     type Query = Aria;
     type State = ();
@@ -155,7 +93,7 @@ impl Rule for UseValidAriaRole {
         let aria_roles = ctx.aria_roles();
 
         let ignore_non_dom = options.ignore_non_dom;
-        let allowed_invalid_roles = &options.allowed_invalid_roles;
+        let allowed_invalid_roles = &options.allow_invalid_roles;
 
         if ignore_non_dom && node.is_custom_component() {
             return None;
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 f763c2f03828..11928f5c79db 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
@@ -3,10 +3,8 @@ use crate::semantic_services::Semantic;
 use biome_analyze::RuleSource;
 use biome_analyze::{context::RuleContext, declare_rule, Rule, RuleDiagnostic};
 use biome_console::markup;
-use biome_deserialize::{
-    Deserializable, DeserializableValue, DeserializationDiagnostic, DeserializationVisitor, Text,
-    VisitableType,
-};
+use biome_deserialize::non_empty;
+use biome_deserialize_macros::Deserializable;
 use biome_js_semantic::{Capture, SemanticModel};
 use biome_js_syntax::{
     binding_ext::AnyJsBindingDeclaration, JsCallExpression, JsSyntaxKind, JsSyntaxNode,
@@ -222,71 +220,21 @@ impl Default for ReactExtensiveDependenciesOptions {
 }
 
 /// Options for the rule `useExhaustiveDependencies`
-#[derive(Default, Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schemars", derive(JsonSchema))]
 #[serde(rename_all = "camelCase", deny_unknown_fields)]
 pub struct HooksOptions {
     /// List of safe hooks
+    #[deserializable(validate = "non_empty")]
     pub hooks: Vec,
 }
 
-impl Deserializable for HooksOptions {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        value.deserialize(HooksOptionsVisitor, name, diagnostics)
-    }
-}
-
-struct HooksOptionsVisitor;
-impl DeserializationVisitor for HooksOptionsVisitor {
-    type Output = HooksOptions;
-
-    const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-
-    fn visit_map(
-        self,
-        members: impl Iterator>,
-        _range: TextRange,
-        _name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        const ALLOWED_KEYS: &[&str] = &["hooks"];
-        let mut result = Self::Output::default();
-        for (key, value) in members.flatten() {
-            let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                continue;
-            };
-            match key_text.text() {
-                "hooks" => {
-                    let val_range = value.range();
-                    result.hooks = Deserializable::deserialize(&value, &key_text, diagnostics)
-                        .unwrap_or_default();
-                    if result.hooks.is_empty() {
-                        diagnostics.push(
-                            DeserializationDiagnostic::new("At least one element is needed")
-                                .with_range(val_range),
-                        );
-                    }
-                }
-                text => diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                    text,
-                    key.range(),
-                    ALLOWED_KEYS,
-                )),
-            }
-        }
-        Some(result)
-    }
-}
-
-#[derive(Default, Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schemars", derive(JsonSchema))]
 #[serde(rename_all = "camelCase", deny_unknown_fields)]
 pub struct Hooks {
     /// The name of the hook
+    #[deserializable(validate = "non_empty")]
     pub name: String,
     /// The "position" of the closure function, starting from zero.
     ///
@@ -296,68 +244,6 @@ pub struct Hooks {
     pub dependencies_index: Option,
 }
 
-impl Deserializable for Hooks {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        value.deserialize(HooksVisitor, name, diagnostics)
-    }
-}
-
-struct HooksVisitor;
-impl DeserializationVisitor for HooksVisitor {
-    type Output = Hooks;
-
-    const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-
-    fn visit_map(
-        self,
-        members: impl Iterator>,
-        _range: TextRange,
-        _name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        const ALLOWED_KEYS: &[&str] = &["name", "closureIndex", "dependenciesIndex"];
-        let mut result = Self::Output::default();
-        for (key, value) in members.flatten() {
-            let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                continue;
-            };
-            match key_text.text() {
-                "name" => {
-                    let val_range = value.range();
-                    result.name = Deserializable::deserialize(&value, &key_text, diagnostics)
-                        .unwrap_or_default();
-                    if result.name.is_empty() {
-                        diagnostics.push(
-                            DeserializationDiagnostic::new(markup!(
-                                "The field ""name"" is mandatory"
-                            ))
-                            .with_range(val_range),
-                        )
-                    }
-                }
-                "closureIndex" => {
-                    result.closure_index =
-                        Deserializable::deserialize(&value, &key_text, diagnostics);
-                }
-                "dependenciesIndex" => {
-                    result.dependencies_index =
-                        Deserializable::deserialize(&value, &key_text, diagnostics);
-                }
-                unknown_key => diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                    unknown_key,
-                    key.range(),
-                    ALLOWED_KEYS,
-                )),
-            }
-        }
-        Some(result)
-    }
-}
-
 impl ReactExtensiveDependenciesOptions {
     pub fn new(hooks: HooksOptions) -> Self {
         let mut default = ReactExtensiveDependenciesOptions::default();
diff --git a/crates/biome_js_analyze/src/semantic_analyzers/style/no_restricted_globals.rs b/crates/biome_js_analyze/src/semantic_analyzers/style/no_restricted_globals.rs
index cb86ea0d7c89..38a6d57a00f0 100644
--- a/crates/biome_js_analyze/src/semantic_analyzers/style/no_restricted_globals.rs
+++ b/crates/biome_js_analyze/src/semantic_analyzers/style/no_restricted_globals.rs
@@ -2,10 +2,7 @@ use crate::semantic_services::SemanticServices;
 use biome_analyze::context::RuleContext;
 use biome_analyze::{declare_rule, Rule, RuleDiagnostic, RuleSource};
 use biome_console::markup;
-use biome_deserialize::{
-    Deserializable, DeserializableValue, DeserializationDiagnostic, DeserializationVisitor, Text,
-    VisitableType,
-};
+use biome_deserialize_macros::Deserializable;
 use biome_js_semantic::{Binding, BindingExtensions};
 use biome_js_syntax::{AnyJsIdentifierUsage, TextRange};
 use biome_rowan::AstNode;
@@ -59,57 +56,13 @@ declare_rule! {
 const RESTRICTED_GLOBALS: [&str; 2] = ["event", "error"];
 
 /// Options for the rule `noRestrictedGlobals`.
-#[derive(Default, Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
+#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(rename_all = "camelCase", deny_unknown_fields)]
 pub struct RestrictedGlobalsOptions {
     /// A list of names that should trigger the rule
-    #[serde(skip_serializing_if = "Option::is_none")]
-    denied_globals: Option>,
-}
-
-impl Deserializable for RestrictedGlobalsOptions {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        value.deserialize(RestrictedGlobalsOptionsVisitor, name, diagnostics)
-    }
-}
-
-struct RestrictedGlobalsOptionsVisitor;
-impl DeserializationVisitor for RestrictedGlobalsOptionsVisitor {
-    type Output = RestrictedGlobalsOptions;
-
-    const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-
-    fn visit_map(
-        self,
-        members: impl Iterator>,
-        _range: TextRange,
-        _name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        const ALLOWED_KEYS: &[&str] = &["deniedGlobals"];
-        let mut denied_globals = None;
-        for (key, value) in members.flatten() {
-            let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                continue;
-            };
-            match key_text.text() {
-                "deniedGlobals" => {
-                    denied_globals = Deserializable::deserialize(&value, &key_text, diagnostics);
-                }
-                unknown_key => diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                    unknown_key,
-                    key.range(),
-                    ALLOWED_KEYS,
-                )),
-            }
-        }
-        Some(Self::Output { denied_globals })
-    }
+    #[serde(skip_serializing_if = "Vec::is_empty")]
+    denied_globals: Vec,
 }
 
 impl Rule for NoRestrictedGlobals {
@@ -146,11 +99,8 @@ impl Rule for NoRestrictedGlobals {
                 };
                 let token = token.ok()?;
                 let text = token.text_trimmed();
-                let denied_globals = if let Some(denied_globals) = options.denied_globals.as_ref() {
-                    denied_globals.iter().map(AsRef::as_ref).collect::>()
-                } else {
-                    vec![]
-                };
+                let denied_globals: Vec<_> =
+                    options.denied_globals.iter().map(AsRef::as_ref).collect();
                 is_restricted(text, &binding, denied_globals.as_slice())
                     .map(|text| (token.text_trimmed_range(), text))
             })
diff --git a/crates/biome_js_analyze/src/semantic_analyzers/style/use_naming_convention.rs b/crates/biome_js_analyze/src/semantic_analyzers/style/use_naming_convention.rs
index a23cea9da9b7..f594c4e0e60c 100644
--- a/crates/biome_js_analyze/src/semantic_analyzers/style/use_naming_convention.rs
+++ b/crates/biome_js_analyze/src/semantic_analyzers/style/use_naming_convention.rs
@@ -12,10 +12,7 @@ use biome_analyze::{
     RuleSourceKind,
 };
 use biome_console::markup;
-use biome_deserialize::{
-    Deserializable, DeserializableValue, DeserializationDiagnostic, DeserializationVisitor, Text,
-    VisitableType,
-};
+use biome_deserialize_macros::Deserializable;
 use biome_diagnostics::Applicability;
 use biome_js_semantic::CanBeImportedExported;
 use biome_js_syntax::{
@@ -25,7 +22,7 @@ use biome_js_syntax::{
     JsVariableDeclarator, JsVariableKind, TsEnumMember, TsIdentifierBinding, TsTypeParameterName,
 };
 use biome_rowan::{
-    declare_node_union, AstNode, AstNodeList, BatchMutationExt, SyntaxResult, TextRange, TokenText,
+    declare_node_union, AstNode, AstNodeList, BatchMutationExt, SyntaxResult, TokenText,
 };
 use biome_unicode_table::is_js_ident;
 use serde::{Deserialize, Serialize};
@@ -459,7 +456,7 @@ pub(crate) struct State {
 }
 
 /// Rule's options.
-#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
+#[derive(Debug, Clone, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schemars", derive(JsonSchema))]
 #[serde(rename_all = "camelCase", deny_unknown_fields)]
 pub struct NamingConventionOptions {
@@ -497,62 +494,8 @@ impl Default for NamingConventionOptions {
     }
 }
 
-impl Deserializable for NamingConventionOptions {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        value.deserialize(NamingConventionOptionsVisitor, name, diagnostics)
-    }
-}
-
-struct NamingConventionOptionsVisitor;
-impl DeserializationVisitor for NamingConventionOptionsVisitor {
-    type Output = NamingConventionOptions;
-
-    const EXPECTED_TYPE: VisitableType = VisitableType::MAP;
-
-    fn visit_map(
-        self,
-        members: impl Iterator>,
-        _range: TextRange,
-        _name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        const ALLOWED_KEYS: &[&str] = &["strictCase", "enumMemberCase"];
-        let mut result = Self::Output::default();
-        for (key, value) in members.flatten() {
-            let Some(key_text) = Text::deserialize(&key, "", diagnostics) else {
-                continue;
-            };
-            match key_text.text() {
-                "strictCase" => {
-                    if let Some(strict_case) =
-                        Deserializable::deserialize(&value, &key_text, diagnostics)
-                    {
-                        result.strict_case = strict_case;
-                    }
-                }
-                "enumMemberCase" => {
-                    if let Some(case) = Deserializable::deserialize(&value, &key_text, diagnostics)
-                    {
-                        result.enum_member_case = case;
-                    }
-                }
-                unknown_key => diagnostics.push(DeserializationDiagnostic::new_unknown_key(
-                    unknown_key,
-                    key.range(),
-                    ALLOWED_KEYS,
-                )),
-            }
-        }
-        Some(result)
-    }
-}
-
 /// Supported cases for TypeScript `enum` member names.
-#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
+#[derive(Clone, Copy, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schemars", derive(JsonSchema))]
 pub enum EnumMemberCase {
     /// PascalCase
@@ -582,27 +525,6 @@ impl FromStr for EnumMemberCase {
     }
 }
 
-impl Deserializable for EnumMemberCase {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        const ALLOWED_VARIANTS: &[&str] = &["camelCase", "CONSTANT_CASE", "PascalCase"];
-        let value_text = Text::deserialize(value, name, diagnostics)?;
-        if let Ok(value) = value_text.parse::() {
-            Some(value)
-        } else {
-            diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                value_text.text(),
-                value.range(),
-                ALLOWED_VARIANTS,
-            ));
-            None
-        }
-    }
-}
-
 impl From for Case {
     fn from(case: EnumMemberCase) -> Case {
         match case {
diff --git a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.js b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.js
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.js.snap b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.js.snap
new file mode 100644
index 000000000000..a838f1481bd2
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.js.snap
@@ -0,0 +1,26 @@
+---
+source: crates/biome_js_analyze/tests/spec_tests.rs
+expression: emptyHookNameInOptions.js
+---
+# Input
+```jsx
+
+```
+
+# Diagnostics
+```
+emptyHookNameInOptions.options:11:17 deserialize ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  × name may not be empty
+  
+     9 │ 						"hooks": [
+    10 │ 							{
+  > 11 │ 								"name": "",
+       │ 								        ^^
+    12 │ 								"closureIndex": 0,
+    13 │ 								"dependenciesIndex": 1
+  
+
+```
+
+
diff --git a/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.options.json b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.options.json
new file mode 100644
index 000000000000..d524698e9eb7
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/correctness/useExhaustiveDependencies/emptyHookNameInOptions.options.json
@@ -0,0 +1,21 @@
+{
+	"$schema": "../../../../../../packages/@biomejs/biome/configuration_schema.json",
+	"linter": {
+		"rules": {
+			"correctness": {
+				"useExhaustiveDependencies": {
+					"level": "error",
+					"options": {
+						"hooks": [
+							{
+								"name": "",
+								"closureIndex": 0,
+								"dependenciesIndex": 1
+							}
+						]
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/crates/biome_js_analyze/tests/specs/style/useNamingConvention/malformedOptions.js.snap b/crates/biome_js_analyze/tests/specs/style/useNamingConvention/malformedOptions.js.snap
index 554b63c95810..d927f5069d9f 100644
--- a/crates/biome_js_analyze/tests/specs/style/useNamingConvention/malformedOptions.js.snap
+++ b/crates/biome_js_analyze/tests/specs/style/useNamingConvention/malformedOptions.js.snap
@@ -22,9 +22,9 @@ malformedOptions.options:9:25 deserialize ━━━━━━━━━━━━
   
   i Accepted values:
   
-  - camelCase
-  - CONSTANT_CASE
   - PascalCase
+  - CONSTANT_CASE
+  - camelCase
   
 
 ```
diff --git a/crates/biome_js_formatter/src/context.rs b/crates/biome_js_formatter/src/context.rs
index 4669c5bf1902..49156c319c13 100644
--- a/crates/biome_js_formatter/src/context.rs
+++ b/crates/biome_js_formatter/src/context.rs
@@ -1,7 +1,7 @@
+pub mod trailing_comma;
+
 use crate::comments::{FormatJsLeadingComment, JsCommentStyle, JsComments};
-pub use crate::context::trailing_comma::TrailingComma;
-use biome_deserialize::{Deserializable, DeserializableValue, DeserializationDiagnostic, Text};
-use biome_deserialize_macros::Merge;
+use biome_deserialize_macros::{Deserializable, Merge};
 use biome_formatter::printer::PrinterOptions;
 use biome_formatter::{
     CstFormatContext, FormatContext, FormatElement, FormatOptions, IndentStyle, IndentWidth,
@@ -12,8 +12,7 @@ use std::fmt;
 use std::fmt::Debug;
 use std::rc::Rc;
 use std::str::FromStr;
-
-pub mod trailing_comma;
+pub use trailing_comma::TrailingComma;
 
 #[derive(Debug, Clone)]
 pub struct JsFormatContext {
@@ -379,7 +378,7 @@ impl fmt::Display for JsFormatOptions {
     }
 }
 
-#[derive(Clone, Copy, Debug, Default, Eq, Hash, Merge, PartialEq)]
+#[derive(Clone, Copy, Debug, Default, Deserializable, Eq, Hash, Merge, PartialEq)]
 #[cfg_attr(
     feature = "serde",
     derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema),
@@ -413,29 +412,7 @@ impl fmt::Display for QuoteProperties {
     }
 }
 
-impl Deserializable for QuoteProperties {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match Text::deserialize(value, name, diagnostics)?.text() {
-            "asNeeded" => Some(QuoteProperties::AsNeeded),
-            "preserve" => Some(QuoteProperties::Preserve),
-            unknown_variant => {
-                const ALLOWED_VARIANTS: &[&str] = &["preserve", "asNeeded"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_variant,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-
-#[derive(Clone, Copy, Debug, Default, Eq, Hash, Merge, PartialEq)]
+#[derive(Clone, Copy, Debug, Default, Deserializable, Eq, Hash, Merge, PartialEq)]
 #[cfg_attr(
     feature = "serde",
     derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema),
@@ -478,29 +455,7 @@ impl fmt::Display for Semicolons {
     }
 }
 
-impl Deserializable for Semicolons {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match Text::deserialize(value, name, diagnostics)?.text() {
-            "always" => Some(Semicolons::Always),
-            "asNeeded" => Some(Semicolons::AsNeeded),
-            unknown_value => {
-                const ALLOWED_VARIANTS: &[&str] = &["always", "asNeeded"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_value,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-
-#[derive(Clone, Copy, Debug, Default, Eq, Hash, Merge, PartialEq)]
+#[derive(Clone, Copy, Debug, Default, Deserializable, Eq, Hash, Merge, PartialEq)]
 #[cfg_attr(
     feature = "serde",
     derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema),
@@ -544,28 +499,6 @@ impl fmt::Display for ArrowParentheses {
     }
 }
 
-impl Deserializable for ArrowParentheses {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match Text::deserialize(value, name, diagnostics)?.text() {
-            "always" => Some(ArrowParentheses::Always),
-            "asNeeded" => Some(ArrowParentheses::AsNeeded),
-            unknown_value => {
-                const ALLOWED_VARIANTS: &[&str] = &["asNeeded", "always"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_value,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
-
 #[derive(Clone, Copy, Debug, Eq, Hash, Merge, PartialEq)]
 #[cfg_attr(
     feature = "serde",
diff --git a/crates/biome_js_formatter/src/context/trailing_comma.rs b/crates/biome_js_formatter/src/context/trailing_comma.rs
index 8bf2b9c90fa9..84bcaf79c671 100644
--- a/crates/biome_js_formatter/src/context/trailing_comma.rs
+++ b/crates/biome_js_formatter/src/context/trailing_comma.rs
@@ -1,7 +1,6 @@
 use crate::prelude::*;
 use crate::{JsFormatContext, JsFormatOptions};
-use biome_deserialize::{Deserializable, DeserializableValue, DeserializationDiagnostic, Text};
-use biome_deserialize_macros::Merge;
+use biome_deserialize_macros::{Deserializable, Merge};
 use biome_formatter::prelude::{if_group_breaks, text};
 use biome_formatter::write;
 use biome_formatter::{Format, FormatResult};
@@ -52,7 +51,7 @@ impl Format for FormatTrailingComma {
 }
 
 /// Print trailing commas wherever possible in multi-line comma-separated syntactic structures.
-#[derive(Clone, Copy, Debug, Default, Eq, Hash, Merge, PartialEq)]
+#[derive(Clone, Copy, Default, Debug, Deserializable, Eq, Hash, Merge, PartialEq)]
 #[cfg_attr(
     feature = "serde",
     derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema),
@@ -103,26 +102,3 @@ impl fmt::Display for TrailingComma {
         }
     }
 }
-
-impl Deserializable for TrailingComma {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        match Text::deserialize(value, name, diagnostics)?.text() {
-            "all" => Some(TrailingComma::All),
-            "es5" => Some(TrailingComma::Es5),
-            "none" => Some(TrailingComma::None),
-            unknown_variant => {
-                const ALLOWED_VARIANTS: &[&str] = &["all", "es5", "none"];
-                diagnostics.push(DeserializationDiagnostic::new_unknown_value(
-                    unknown_variant,
-                    value.range(),
-                    ALLOWED_VARIANTS,
-                ));
-                None
-            }
-        }
-    }
-}
diff --git a/crates/biome_project/Cargo.toml b/crates/biome_project/Cargo.toml
index ab44e2a88944..94b5dac32b06 100644
--- a/crates/biome_project/Cargo.toml
+++ b/crates/biome_project/Cargo.toml
@@ -14,16 +14,17 @@ version              = "0.0.0"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-biome_console     = { workspace = true }
-biome_deserialize = { workspace = true }
-biome_diagnostics = { workspace = true }
-biome_json_syntax = { workspace = true }
-biome_parser      = { workspace = true }
-biome_rowan       = { workspace = true }
-biome_text_size   = { workspace = true }
-node-semver       = "2.1.0"
-rustc-hash        = { workspace = true }
-serde             = { workspace = true }
+biome_console            = { workspace = true }
+biome_deserialize        = { workspace = true }
+biome_deserialize_macros = { workspace = true }
+biome_diagnostics        = { workspace = true }
+biome_json_syntax        = { workspace = true }
+biome_parser             = { workspace = true }
+biome_rowan              = { workspace = true }
+biome_text_size          = { workspace = true }
+node-semver              = "2.1.0"
+rustc-hash               = { workspace = true }
+serde                    = { workspace = true }
 
 [dev-dependencies]
 biome_json_parser = { path = "../biome_json_parser" }
diff --git a/crates/biome_project/src/node_js_project/package_json.rs b/crates/biome_project/src/node_js_project/package_json.rs
index 603db54cb96a..5bddaab507ac 100644
--- a/crates/biome_project/src/node_js_project/package_json.rs
+++ b/crates/biome_project/src/node_js_project/package_json.rs
@@ -28,7 +28,7 @@ impl Manifest for PackageJson {
     }
 }
 
-#[derive(Debug, Default)]
+#[derive(Debug, Default, biome_deserialize_macros::Deserializable)]
 pub struct Dependencies(FxHashMap);
 
 #[derive(Debug)]
@@ -107,20 +107,6 @@ impl DeserializationVisitor for PackageJsonVisitor {
     }
 }
 
-impl Deserializable for Dependencies {
-    fn deserialize(
-        value: &impl DeserializableValue,
-        name: &str,
-        diagnostics: &mut Vec,
-    ) -> Option {
-        Some(Dependencies(Deserializable::deserialize(
-            value,
-            name,
-            diagnostics,
-        )?))
-    }
-}
-
 impl Deserializable for Version {
     fn deserialize(
         value: &impl DeserializableValue,
diff --git a/crates/biome_service/Cargo.toml b/crates/biome_service/Cargo.toml
index 1c47b9db6a5a..e24c7ed50c64 100644
--- a/crates/biome_service/Cargo.toml
+++ b/crates/biome_service/Cargo.toml
@@ -41,15 +41,14 @@ biome_rowan              = { workspace = true, features = ["serde"] }
 biome_text_edit          = { workspace = true }
 bpaf                     = { workspace = true }
 dashmap                  = { workspace = true }
-
-ignore      = { workspace = true }
-indexmap    = { workspace = true, features = ["serde"] }
-lazy_static = { workspace = true }
-rustc-hash  = { workspace = true }
-schemars    = { workspace = true, features = ["indexmap1"], optional = true }
-serde       = { workspace = true, features = ["derive"] }
-serde_json  = { workspace = true, features = ["raw_value"] }
-tracing     = { workspace = true, features = ["attributes", "log"] }
+ignore                   = { workspace = true }
+indexmap                 = { workspace = true, features = ["serde"] }
+lazy_static              = { workspace = true }
+rustc-hash               = { workspace = true }
+schemars                 = { workspace = true, features = ["indexmap1"], optional = true }
+serde                    = { workspace = true, features = ["derive"] }
+serde_json               = { workspace = true, features = ["raw_value"] }
+tracing                  = { workspace = true, features = ["attributes", "log"] }
 
 [features]
 schema = [
diff --git a/crates/biome_service/src/configuration/css.rs b/crates/biome_service/src/configuration/css.rs
index 31f4d17f9600..5bb11132d11d 100644
--- a/crates/biome_service/src/configuration/css.rs
+++ b/crates/biome_service/src/configuration/css.rs
@@ -1,11 +1,13 @@
 use crate::configuration::{deserialize_line_width, serialize_line_width, PlainIndentStyle};
-use biome_deserialize_macros::{Merge, NoneState};
+use biome_deserialize_macros::{Deserializable, Merge};
 use biome_formatter::{LineEnding, LineWidth, QuoteStyle};
 use bpaf::Bpaf;
 use serde::{Deserialize, Serialize};
 
 /// Options applied to CSS files
-#[derive(Bpaf, Clone, Default, Debug, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(
+    Bpaf, Clone, Default, Debug, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(default, deny_unknown_fields)]
 pub struct CssConfiguration {
@@ -21,7 +23,9 @@ pub struct CssConfiguration {
 }
 
 /// Options that changes how the CSS parser behaves
-#[derive(Bpaf, Clone, Default, Debug, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(
+    Bpaf, Clone, Default, Debug, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(rename_all = "camelCase", default, deny_unknown_fields)]
 pub struct CssParser {
@@ -31,7 +35,9 @@ pub struct CssParser {
     pub allow_wrong_line_comments: Option,
 }
 
-#[derive(Bpaf, Clone, Default, Debug, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(
+    Bpaf, Clone, Default, Debug, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(rename_all = "camelCase", default, deny_unknown_fields)]
 pub struct CssFormatter {
@@ -53,6 +59,7 @@ pub struct CssFormatter {
     /// The size of the indentation applied to CSS (and its super languages) files. Default to 2.
     #[serde(skip_serializing_if = "Option::is_none")]
     #[bpaf(long("css-formatter-indent-size"), argument("NUMBER"), optional)]
+    #[deserializable(deprecated(use_instead = "css.formatter.indentWidth"))]
     pub indent_size: Option,
 
     /// The type of line ending applied to CSS (and its super languages) files.
diff --git a/crates/biome_service/src/configuration/formatter.rs b/crates/biome_service/src/configuration/formatter.rs
index 0bb57d053b30..b7480295791d 100644
--- a/crates/biome_service/src/configuration/formatter.rs
+++ b/crates/biome_service/src/configuration/formatter.rs
@@ -2,7 +2,7 @@ use crate::configuration::overrides::OverrideFormatterConfiguration;
 use crate::settings::{to_matcher, FormatSettings};
 use crate::{Matcher, WorkspaceError};
 use biome_deserialize::StringSet;
-use biome_deserialize_macros::{Merge, NoneState};
+use biome_deserialize_macros::{Deserializable, Merge, NoneState};
 use biome_formatter::{IndentStyle, LineEnding, LineWidth};
 use bpaf::Bpaf;
 use serde::{Deserialize, Serialize};
@@ -10,8 +10,11 @@ use std::path::PathBuf;
 use std::str::FromStr;
 
 /// Generic options applied to all files
-#[derive(Bpaf, Clone, Debug, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(
+    Bpaf, Clone, Debug, Deserialize, Deserializable, Eq, Merge, NoneState, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
+#[deserializable(from_none)]
 #[serde(rename_all = "camelCase", default, deny_unknown_fields)]
 pub struct FormatterConfiguration {
     // if `false`, it disables the feature. `true` by default
@@ -30,6 +33,7 @@ pub struct FormatterConfiguration {
 
     /// The size of the indentation, 2 by default (deprecated, use `indent-width`)
     #[serde(skip_serializing_if = "Option::is_none")]
+    #[deserializable(deprecated(use_instead = "formatter.indentWidth"))]
     #[bpaf(long("indent-size"), argument("NUMBER"), optional)]
     pub indent_size: Option,
 
@@ -177,7 +181,9 @@ where
     s.serialize_u16(line_width.unwrap_or_default().get())
 }
 
-#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Merge, PartialEq, Serialize)]
+#[derive(
+    Clone, Copy, Debug, Default, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(rename_all = "camelCase")]
 pub enum PlainIndentStyle {
diff --git a/crates/biome_service/src/configuration/javascript/formatter.rs b/crates/biome_service/src/configuration/javascript/formatter.rs
index 04a8ce5549b4..e8887c6ff2fd 100644
--- a/crates/biome_service/src/configuration/javascript/formatter.rs
+++ b/crates/biome_service/src/configuration/javascript/formatter.rs
@@ -1,6 +1,6 @@
 use crate::configuration::PlainIndentStyle;
 use crate::configuration::{deserialize_line_width, serialize_line_width};
-use biome_deserialize_macros::{Merge, NoneState};
+use biome_deserialize_macros::{Deserializable, Merge, NoneState};
 use biome_formatter::{LineEnding, LineWidth, QuoteStyle};
 use biome_js_formatter::context::trailing_comma::TrailingComma;
 use biome_js_formatter::context::{ArrowParentheses, QuoteProperties, Semicolons};
@@ -8,7 +8,19 @@ use bpaf::Bpaf;
 use serde::{Deserialize, Serialize};
 
 /// Formatting options specific to the JavaScript files
-#[derive(Default, Debug, Deserialize, Merge, NoneState, Serialize, Eq, PartialEq, Clone, Bpaf)]
+#[derive(
+    Default,
+    Debug,
+    Deserialize,
+    Deserializable,
+    Merge,
+    NoneState,
+    Serialize,
+    Eq,
+    PartialEq,
+    Clone,
+    Bpaf,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(rename_all = "camelCase", default, deny_unknown_fields)]
 pub struct JavascriptFormatter {
@@ -57,6 +69,7 @@ pub struct JavascriptFormatter {
 
     /// The size of the indentation applied to JavaScript (and its super languages) files. Default to 2.
     #[serde(skip_serializing_if = "Option::is_none")]
+    #[deserializable(deprecated(use_instead = "javascript.formatter.indentWidth"))]
     #[bpaf(long("javascript-formatter-indent-size"), argument("NUMBER"), optional)]
     pub indent_size: Option,
 
diff --git a/crates/biome_service/src/configuration/javascript/mod.rs b/crates/biome_service/src/configuration/javascript/mod.rs
index 9e7902f53594..fb0634a6c9fb 100644
--- a/crates/biome_service/src/configuration/javascript/mod.rs
+++ b/crates/biome_service/src/configuration/javascript/mod.rs
@@ -1,13 +1,15 @@
 mod formatter;
 
-pub use crate::configuration::javascript::formatter::{javascript_formatter, JavascriptFormatter};
 use biome_deserialize::StringSet;
-use biome_deserialize_macros::{Merge, NoneState};
+use biome_deserialize_macros::{Deserializable, Merge};
 use bpaf::Bpaf;
+pub use formatter::{javascript_formatter, JavascriptFormatter};
 use serde::{Deserialize, Serialize};
 
 /// A set of options applied to the JavaScript files
-#[derive(Bpaf, Clone, Default, Debug, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(
+    Bpaf, Clone, Default, Debug, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(default, deny_unknown_fields)]
 pub struct JavascriptConfiguration {
@@ -42,13 +44,17 @@ impl JavascriptConfiguration {
     }
 }
 
-#[derive(Bpaf, Clone, Debug, Default, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(
+    Bpaf, Clone, Debug, Default, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(default, deny_unknown_fields)]
 pub struct JavascriptOrganizeImports {}
 
 /// Options that changes how the JavaScript parser behaves
-#[derive(Bpaf, Clone, Debug, Default, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(
+    Bpaf, Clone, Debug, Default, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(rename_all = "camelCase", default, deny_unknown_fields)]
 pub struct JavascriptParser {
diff --git a/crates/biome_service/src/configuration/json.rs b/crates/biome_service/src/configuration/json.rs
index 3374df3b1857..7f6d0a7207bb 100644
--- a/crates/biome_service/src/configuration/json.rs
+++ b/crates/biome_service/src/configuration/json.rs
@@ -1,11 +1,13 @@
 use crate::configuration::{deserialize_line_width, serialize_line_width, PlainIndentStyle};
-use biome_deserialize_macros::{Merge, NoneState};
+use biome_deserialize_macros::{Deserializable, Merge};
 use biome_formatter::{LineEnding, LineWidth};
 use bpaf::Bpaf;
 use serde::{Deserialize, Serialize};
 
 /// Options applied to JSON files
-#[derive(Bpaf, Clone, Debug, Default, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(
+    Bpaf, Clone, Debug, Default, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(default, deny_unknown_fields)]
 pub struct JsonConfiguration {
@@ -21,7 +23,9 @@ pub struct JsonConfiguration {
 }
 
 /// Options that changes how the JSON parser behaves
-#[derive(Bpaf, Clone, Debug, Default, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(
+    Bpaf, Clone, Debug, Default, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(rename_all = "camelCase", default, deny_unknown_fields)]
 pub struct JsonParser {
@@ -35,7 +39,9 @@ pub struct JsonParser {
     pub allow_trailing_commas: Option,
 }
 
-#[derive(Bpaf, Clone, Debug, Default, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(
+    Bpaf, Clone, Debug, Default, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
 #[serde(rename_all = "camelCase", default, deny_unknown_fields)]
 pub struct JsonFormatter {
@@ -57,6 +63,7 @@ pub struct JsonFormatter {
     /// The size of the indentation applied to JSON (and its super languages) files. Default to 2.
     #[serde(skip_serializing_if = "Option::is_none")]
     #[bpaf(long("json-formatter-indent-size"), argument("NUMBER"), optional)]
+    #[deserializable(deprecated(use_instead = "json.formatter.indentWidth"))]
     pub indent_size: Option,
 
     /// The type of line ending applied to JSON (and its super languages) files.
diff --git a/crates/biome_service/src/configuration/linter/mod.rs b/crates/biome_service/src/configuration/linter/mod.rs
index da40ec4b1ad5..6aad86a37733 100644
--- a/crates/biome_service/src/configuration/linter/mod.rs
+++ b/crates/biome_service/src/configuration/linter/mod.rs
@@ -5,8 +5,10 @@ pub use crate::configuration::linter::rules::Rules;
 use crate::configuration::overrides::OverrideLinterConfiguration;
 use crate::settings::{to_matcher, LinterSettings};
 use crate::{Matcher, WorkspaceError};
-use biome_deserialize::{Merge, StringSet};
-use biome_deserialize_macros::{Merge, NoneState};
+use biome_deserialize::{
+    DeserializableValue, DeserializationDiagnostic, Merge, StringSet, VisitableType,
+};
+use biome_deserialize_macros::{Deserializable, Merge, NoneState};
 use biome_diagnostics::Severity;
 use biome_js_analyze::options::PossibleOptions;
 use bpaf::Bpaf;
@@ -17,8 +19,11 @@ use serde::{Deserialize, Serialize};
 use std::path::PathBuf;
 use std::str::FromStr;
 
-#[derive(Debug, Deserialize, Merge, NoneState, Serialize, Clone, Bpaf, Eq, PartialEq)]
+#[derive(
+    Bpaf, Clone, Debug, Deserialize, Deserializable, Eq, Merge, NoneState, PartialEq, Serialize,
+)]
 #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
+#[deserializable(from_none)]
 #[serde(rename_all = "camelCase", default, deny_unknown_fields)]
 pub struct LinterConfiguration {
     /// if `false`, it disables the feature and the linter won't be executed. `true` by default
@@ -96,6 +101,22 @@ pub enum RuleConfiguration {
     WithOptions(Box),
 }
 
+impl biome_deserialize::Deserializable for RuleConfiguration {
+    fn deserialize(
+        value: &impl DeserializableValue,
+        rule_name: &str,
+        diagnostics: &mut Vec,
+    ) -> Option {
+        if value.is_type(VisitableType::STR) {
+            biome_deserialize::Deserializable::deserialize(value, rule_name, diagnostics)
+                .map(Self::Plain)
+        } else {
+            biome_deserialize::Deserializable::deserialize(value, rule_name, diagnostics)
+                .map(|rule| Self::WithOptions(Box::new(rule)))
+        }
+    }
+}
+
 impl FromStr for RuleConfiguration {
     type Err = String;
 
@@ -188,7 +209,7 @@ impl From<&RulePlainConfiguration> for Severity {
     }
 }
 
-#[derive(Default, Deserialize, Serialize, Debug, Eq, PartialEq, Clone)]
+#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schema", derive(JsonSchema))]
 #[serde(rename_all = "camelCase")]
 pub enum RulePlainConfiguration {
@@ -211,11 +232,13 @@ impl FromStr for RulePlainConfiguration {
     }
 }
 
-#[derive(Default, Deserialize, Serialize, Debug, Eq, PartialEq, Clone)]
+#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, PartialEq, Serialize)]
 #[cfg_attr(feature = "schema", derive(JsonSchema))]
 #[serde(rename_all = "camelCase", deny_unknown_fields)]
 pub struct RuleWithOptions {
     pub level: RulePlainConfiguration,
+
+    #[deserializable(passthrough_name)]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub options: Option,
 }
diff --git a/crates/biome_service/src/configuration/linter/rules.rs b/crates/biome_service/src/configuration/linter/rules.rs
index e889aab88256..660f3e449672 100644
--- a/crates/biome_service/src/configuration/linter/rules.rs
+++ b/crates/biome_service/src/configuration/linter/rules.rs
@@ -2,13 +2,17 @@
 
 use crate::RuleConfiguration;
 use biome_analyze::RuleFilter;
-use biome_deserialize_macros::{Merge, NoneState};
+use biome_console::markup;
+use biome_deserialize::{DeserializableValidator, DeserializationDiagnostic};
+use biome_deserialize_macros::{Deserializable, Merge, NoneState};
 use biome_diagnostics::{Category, Severity};
+use biome_rowan::TextRange;
 use indexmap::IndexSet;
 #[cfg(feature = "schema")]
 use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, Deserialize, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[derive(Clone, Debug, Deserialize, Deserializable, Eq, Merge, NoneState, PartialEq, Serialize)]
+#[deserializable(from_none, with_validator)]
 #[cfg_attr(feature = "schema", derive(JsonSchema))]
 #[serde(rename_all = "camelCase", deny_unknown_fields)]
 pub struct Rules {
@@ -18,20 +22,28 @@ pub struct Rules {
     #[doc = r" It enables ALL rules. The rules that belong to `nursery` won't be enabled."]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub all: Option,
+    #[deserializable(rename = "a11y")]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub a11y: Option,
+    #[deserializable(rename = "complexity")]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub complexity: Option,
+    #[deserializable(rename = "correctness")]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub correctness: Option,
+    #[deserializable(rename = "nursery")]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub nursery: Option,
+    #[deserializable(rename = "performance")]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub performance: Option,
+    #[deserializable(rename = "security")]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub security: Option,
+    #[deserializable(rename = "style")]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub style: Option