Skip to content

Commit

Permalink
feat(linter): implement noLowerCaseEnum (#4031)
Browse files Browse the repository at this point in the history
Co-authored-by: Emanuele Stoppa <[email protected]>
  • Loading branch information
eMerzh and ematipico authored Nov 30, 2024
1 parent bdb1620 commit b5e576d
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 9 deletions.
6 changes: 6 additions & 0 deletions crates/biome_analyze/src/rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ pub enum RuleSource {
Eslint(&'static str),
/// Rules from [GraphQL-ESLint](https://github.com/dimaMachina/graphql-eslint)
EslintGraphql(&'static str),
/// Rules from [graphql-schema-linter](https://github.com/cjoudrey/graphql-schema-linter)
EslintGraphqlSchemaLinter(&'static str),
/// Rules from [Eslint Plugin Import](https://github.com/import-js/eslint-plugin-import)
EslintImport(&'static str),
/// Rules from [Eslint Plugin Import Access](https://github.com/uhyo/eslint-plugin-import-access)
Expand Down Expand Up @@ -149,6 +151,7 @@ impl std::fmt::Display for RuleSource {
Self::Clippy(_) => write!(f, "Clippy"),
Self::Eslint(_) => write!(f, "ESLint"),
Self::EslintGraphql(_) => write!(f, "GraphQL-ESLint"),
Self::EslintGraphqlSchemaLinter(_) => write!(f, "graphql-schema-linter"),
Self::EslintImport(_) => write!(f, "eslint-plugin-import"),
Self::EslintImportAccess(_) => write!(f, "eslint-plugin-import-access"),
Self::EslintJest(_) => write!(f, "eslint-plugin-jest"),
Expand Down Expand Up @@ -200,6 +203,7 @@ impl RuleSource {
Self::Clippy(rule_name)
| Self::Eslint(rule_name)
| Self::EslintGraphql(rule_name)
| Self::EslintGraphqlSchemaLinter(rule_name)
| Self::EslintImport(rule_name)
| Self::EslintImportAccess(rule_name)
| Self::EslintJest(rule_name)
Expand All @@ -226,6 +230,7 @@ impl RuleSource {
match self {
Self::Clippy(rule_name) | Self::Eslint(rule_name) => (*rule_name).to_string(),
Self::EslintGraphql(rule_name) => format!("graphql/{rule_name}"),
Self::EslintGraphqlSchemaLinter(rule_name) => format!("graphql/{rule_name}"),
Self::EslintImport(rule_name) => format!("import/{rule_name}"),
Self::EslintImportAccess(rule_name) => format!("import-access/{rule_name}"),
Self::EslintJest(rule_name) => format!("jest/{rule_name}"),
Expand Down Expand Up @@ -253,6 +258,7 @@ impl RuleSource {
Self::Clippy(rule_name) => format!("https://rust-lang.github.io/rust-clippy/master/#/{rule_name}"),
Self::Eslint(rule_name) => format!("https://eslint.org/docs/latest/rules/{rule_name}"),
Self::EslintGraphql(rule_name) => format!("https://the-guild.dev/graphql/eslint/rules/{rule_name}"),
Self::EslintGraphqlSchemaLinter(rule_name) => format!("https://github.com/cjoudrey/graphql-schema-linter?tab=readme-ov-file#{rule_name}"),
Self::EslintImport(rule_name) => format!("https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/{rule_name}.md"),
Self::EslintImportAccess(_) => "https://github.com/uhyo/eslint-plugin-import-access".to_string(),
Self::EslintJest(rule_name) => format!("https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/{rule_name}.md"),
Expand Down
38 changes: 29 additions & 9 deletions crates/biome_configuration/src/analyzer/linter/rules.rs

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

1 change: 1 addition & 0 deletions crates/biome_diagnostics_categories/src/categories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ define_categories! {
"lint/nursery/noInvalidGridAreas": "https://biomejs.dev/linter/rules/use-consistent-grid-areas",
"lint/nursery/noInvalidPositionAtImportRule": "https://biomejs.dev/linter/rules/no-invalid-position-at-import-rule",
"lint/nursery/noIrregularWhitespace": "https://biomejs.dev/linter/rules/no-irregular-whitespace",
"lint/nursery/useNamingConvention": "https://biomejs.dev/linter/rules/use-naming-convention",
"lint/nursery/noMissingGenericFamilyKeyword": "https://biomejs.dev/linter/rules/no-missing-generic-family-keyword",
"lint/nursery/noMissingVarFunction": "https://biomejs.dev/linter/rules/no-missing-var-function",
"lint/nursery/noNestedTernary": "https://biomejs.dev/linter/rules/no-nested-ternary",
Expand Down
2 changes: 2 additions & 0 deletions crates/biome_graphql_analyze/src/lint/nursery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use biome_analyze::declare_lint_group;
pub mod no_duplicated_fields;
pub mod use_deprecated_reason;
pub mod use_named_operation;
pub mod use_naming_convention;

declare_lint_group! {
pub Nursery {
Expand All @@ -13,6 +14,7 @@ declare_lint_group! {
self :: no_duplicated_fields :: NoDuplicatedFields ,
self :: use_deprecated_reason :: UseDeprecatedReason ,
self :: use_named_operation :: UseNamedOperation ,
self :: use_naming_convention :: UseNamingConvention ,
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use biome_analyze::RuleSource;
use biome_analyze::RuleSourceKind;
use biome_analyze::{context::RuleContext, declare_lint_rule, Ast, Rule, RuleDiagnostic};
use biome_console::markup;
use biome_graphql_syntax::GraphqlEnumValueDefinition;
use biome_rowan::AstNode;

declare_lint_rule! {
/// Validates that all enum values are capitalized.
///
/// By convention in GraphQL, enum values are all caps.
///
/// ## Examples
///
/// ### Invalid
///
/// ```graphql,expect_diagnostic
/// enum MyEnum {
/// value
/// }
/// ```
///
/// ### Valid
///
/// ```graphql
/// enum MyEnum {
/// VALUE
/// }
/// ```
///
pub UseNamingConvention {
version: "next",
name: "useNamingConvention",
language: "graphql",
recommended: false,
sources: &[RuleSource::EslintGraphqlSchemaLinter("enum-values-all-caps")],
source_kind: RuleSourceKind::Inspired,
}
}

impl Rule for UseNamingConvention {
type Query = Ast<GraphqlEnumValueDefinition>;
type State = ();
type Signals = Option<Self::State>;
type Options = ();

fn run(ctx: &RuleContext<Self>) -> Option<Self::State> {
let node = ctx.query();
if node.text().chars().any(|c| c.is_lowercase()) {
return Some(());
}

None
}

fn diagnostic(ctx: &RuleContext<Self>, _state: &Self::State) -> Option<RuleDiagnostic> {
//
// Read our guidelines to write great diagnostics:
// https://docs.rs/biome_analyze/latest/biome_analyze/#what-a-rule-should-say-to-the-user
//
Some(
RuleDiagnostic::new(
rule_category!(),
ctx.query().range(),
markup! {
"Enum values should be in all caps."
},
)
.note(markup! {
"Change the enum value to be in all caps."
}),
)
}
}
2 changes: 2 additions & 0 deletions crates/biome_graphql_analyze/src/options.rs

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
enum Status {
Active
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
source: crates/biome_graphql_analyze/tests/spec_tests.rs
expression: invalid.graphql
snapshot_kind: text
---
# Input
```graphql
enum Status {
Active
}
```

# Diagnostics
```
invalid.graphql:2:2 lint/nursery/useNamingConvention ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
! Enum values should be in all caps.
1 │ enum Status {
> 2Active
^^^^^^
3}
4 │
i Change the enum value to be in all caps.
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
enum Status {
ACTIVE
INACTIVE
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
source: crates/biome_graphql_analyze/tests/spec_tests.rs
expression: valid.graphql
---
# Input
```graphql
enum Status {
ACTIVE
INACTIVE
}
```
5 changes: 5 additions & 0 deletions packages/@biomejs/backend-jsonrpc/src/workspace.ts

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

7 changes: 7 additions & 0 deletions packages/@biomejs/biome/configuration_schema.json

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

0 comments on commit b5e576d

Please sign in to comment.