-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement the
PascalCase
rule. (#90)
Co-authored-by: Andrew Frantz <andrew.frantz@stjude.org>
- Loading branch information
1 parent
066d6bd
commit 03a3ac3
Showing
9 changed files
with
140 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
//! A lint rule that ensures structs are defined with pascal case names. | ||
use convert_case::Boundary; | ||
use convert_case::Case; | ||
use convert_case::Converter; | ||
use wdl_ast::v1::StructDefinition; | ||
use wdl_ast::v1::Visitor; | ||
use wdl_ast::AstToken; | ||
use wdl_ast::Diagnostic; | ||
use wdl_ast::Diagnostics; | ||
use wdl_ast::Span; | ||
use wdl_ast::VisitReason; | ||
|
||
use super::Rule; | ||
use crate::Tag; | ||
use crate::TagSet; | ||
|
||
/// The identifier for the pascal case rule. | ||
const ID: &str = "PascalCase"; | ||
|
||
/// Creates a "use pascal case" diagnostic. | ||
fn use_pascal_case(name: &str, properly_cased_name: &str, span: Span) -> Diagnostic { | ||
Diagnostic::warning(format!("struct name `{name}` is not PascalCase")) | ||
.with_rule(ID) | ||
.with_label("this name must be PascalCase", span) | ||
.with_fix(format!("replace `{name}` with `{properly_cased_name}`")) | ||
} | ||
|
||
/// Detects structs defined without a pascal case name. | ||
#[derive(Debug, Clone, Copy)] | ||
pub struct PascalCaseRule; | ||
|
||
impl Rule for PascalCaseRule { | ||
fn id(&self) -> &'static str { | ||
ID | ||
} | ||
|
||
fn description(&self) -> &'static str { | ||
"Ensures that structs are defined with PascalCase names." | ||
} | ||
|
||
fn explanation(&self) -> &'static str { | ||
"Struct names should be in PascalCase. Maintaining a consistent naming convention makes \ | ||
the code easier to read and understand." | ||
} | ||
|
||
fn tags(&self) -> TagSet { | ||
TagSet::new(&[Tag::Naming, Tag::Style, Tag::Clarity]) | ||
} | ||
|
||
fn visitor(&self) -> Box<dyn Visitor<State = Diagnostics>> { | ||
Box::new(PascalCaseVisitor) | ||
} | ||
} | ||
|
||
/// Checks if the given name is pascal case, and if not adds a warning to the | ||
/// diagnostics. | ||
fn check_name(name: &str, span: Span, diagnostics: &mut Diagnostics) { | ||
let converter = Converter::new() | ||
.remove_boundaries(&[Boundary::DigitLower, Boundary::LowerDigit]) | ||
.to_case(Case::Pascal); | ||
let properly_cased_name = converter.convert(name); | ||
if name != properly_cased_name { | ||
diagnostics.add(use_pascal_case(name, &properly_cased_name, span)); | ||
} | ||
} | ||
|
||
/// Implements the visitor for the pascal case rule. | ||
struct PascalCaseVisitor; | ||
|
||
impl Visitor for PascalCaseVisitor { | ||
type State = Diagnostics; | ||
|
||
fn struct_definition( | ||
&mut self, | ||
state: &mut Self::State, | ||
reason: VisitReason, | ||
def: &StructDefinition, | ||
) { | ||
if reason == VisitReason::Exit { | ||
return; | ||
} | ||
|
||
let name = def.name(); | ||
check_name(name.as_str(), name.span(), state); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
warning[PascalCase]: struct name `this_is_a_bad_name` is not PascalCase | ||
┌─ tests/lints/pascal-case/source.wdl:5:8 | ||
│ | ||
5 │ struct this_is_a_bad_name { | ||
│ ^^^^^^^^^^^^^^^^^^ this name must be PascalCase | ||
│ | ||
= fix: replace `this_is_a_bad_name` with `ThisIsABadName` | ||
|
||
warning[PascalCase]: struct name `thisIsAlsoABadName` is not PascalCase | ||
┌─ tests/lints/pascal-case/source.wdl:9:8 | ||
│ | ||
9 │ struct thisIsAlsoABadName { | ||
│ ^^^^^^^^^^^^^^^^^^ this name must be PascalCase | ||
│ | ||
= fix: replace `thisIsAlsoABadName` with `ThisIsAlsoABadName` | ||
|
||
warning[PascalCase]: struct name `This_Is_Bad_Too` is not PascalCase | ||
┌─ tests/lints/pascal-case/source.wdl:13:8 | ||
│ | ||
13 │ struct This_Is_Bad_Too { | ||
│ ^^^^^^^^^^^^^^^ this name must be PascalCase | ||
│ | ||
= fix: replace `This_Is_Bad_Too` with `ThisIsBadToo` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
## This is a test of ensuring struct names are PascalCase. | ||
version 1.1 | ||
|
||
struct this_is_a_bad_name { | ||
Int x | ||
} | ||
|
||
struct thisIsAlsoABadName { | ||
Int x | ||
} | ||
|
||
struct This_Is_Bad_Too { | ||
Int x | ||
} | ||
|
||
struct ThisNameIsAGoodOne { | ||
Int x | ||
} |