Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

revise: preamble and version stmt lint rules #187

Merged
merged 34 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
56179da
feat: adds exceptable_nodes() to Rule trait
a-frantz Aug 26, 2024
54c86d5
chore: cargo fmt
a-frantz Aug 26, 2024
e669756
revise: upgrade unknown rule to full rule
a-frantz Aug 30, 2024
b0b9c5f
[WIP]
a-frantz Sep 10, 2024
5df7b54
[WIP]
a-frantz Sep 10, 2024
d5d3366
Merge branch 'main' into fix/lint-directives
a-frantz Sep 10, 2024
ad041ab
feat: finish transitioning to exceptable_add in wdl-lint
a-frantz Sep 10, 2024
6f7d6fa
Update Arena.toml
a-frantz Sep 10, 2024
a94d757
feat: MisplacedLintDirective rule
a-frantz Sep 11, 2024
59c741e
Update util.rs
a-frantz Sep 11, 2024
4d304a3
fix: multiple fixes
a-frantz Sep 11, 2024
afc8e31
docs: explanation text
a-frantz Sep 11, 2024
27956f6
chore: update changelogs and fmt
a-frantz Sep 11, 2024
ba00153
[WIP]
a-frantz Sep 13, 2024
bf1ea1d
Merge branch 'main' into revise/preamble
a-frantz Sep 16, 2024
ea25283
chore: finish cleaning merge
a-frantz Sep 16, 2024
ba07927
Merge branch 'main' into revise/preamble
a-frantz Sep 25, 2024
e50d47e
chore: clean up after merge
a-frantz Sep 25, 2024
2aac227
WIP
a-frantz Sep 27, 2024
a2392eb
feat: PrambleCommentAfterVersion rule
a-frantz Sep 27, 2024
0ff136e
[WIP]tests: update wdl-lint tests
a-frantz Sep 30, 2024
1b4351f
fix: downgrade some lint warnings to notes
a-frantz Sep 30, 2024
e0f3d0c
revise: clean up tests
a-frantz Sep 30, 2024
8aaf40a
Update Arena.toml
a-frantz Sep 30, 2024
c43b4c4
Update CHANGELOG.md
a-frantz Sep 30, 2024
7802c28
tests: some more cleaning
a-frantz Sep 30, 2024
4a232f5
chore: remove TODO comments
a-frantz Oct 1, 2024
2b97046
Apply suggestions from code review
a-frantz Oct 1, 2024
a0c541d
Apply review feedback
a-frantz Oct 1, 2024
14f1a31
chore: cargo fmt
a-frantz Oct 1, 2024
bd920dc
fix: simplify logic
a-frantz Oct 1, 2024
0310ae9
fix: simplify logic
a-frantz Oct 1, 2024
7108954
chore: clarify lint message
a-frantz Oct 1, 2024
836554f
Merge branch 'main' into revise/preamble
a-frantz Oct 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,230 changes: 620 additions & 610 deletions Arena.toml

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions wdl-lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ pub fn rules() -> Vec<Box<dyn Rule>> {
Box::<rules::SnakeCaseRule>::default(),
Box::<rules::MissingRuntimeRule>::default(),
Box::<rules::EndingNewlineRule>::default(),
Box::<rules::PreambleWhitespaceRule>::default(),
Box::<rules::PreambleCommentsRule>::default(),
Box::<rules::PreambleFormattingRule>::default(),
Box::<rules::MatchingParameterMetaRule>::default(),
Box::<rules::WhitespaceRule>::default(),
Box::<rules::CommandSectionMixedIndentationRule>::default(),
Expand Down Expand Up @@ -112,7 +111,9 @@ pub fn rules() -> Vec<Box<dyn Rule>> {
Box::<rules::ContainerValue>::default(),
Box::<rules::MissingRequirementsRule>::default(),
Box::<rules::UnknownRule>::default(),
Box::<rules::MisplacedLintDirective>::default(),
Box::<rules::MisplacedLintDirectiveRule>::default(),
Box::<rules::VersionFormattingRule>::default(),
Box::<rules::PreambleCommentAfterVersionRule>::default(),
];

// Ensure all the rule ids are unique and pascal case
Expand Down
10 changes: 6 additions & 4 deletions wdl-lint/src/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ mod missing_runtime;
mod no_curly_commands;
mod nonmatching_output;
mod pascal_case;
mod preamble_comments;
mod preamble_whitespace;
mod preamble_comment_after_version;
mod preamble_formatting;
mod runtime_section_keys;
mod section_order;
mod snake_case;
mod todo;
mod trailing_comma;
mod unknown_rule;
mod version_formatting;
mod whitespace;

pub use blank_lines_between_elements::*;
Expand Down Expand Up @@ -68,12 +69,13 @@ pub use missing_runtime::*;
pub use no_curly_commands::*;
pub use nonmatching_output::*;
pub use pascal_case::*;
pub use preamble_comments::*;
pub use preamble_whitespace::*;
pub use preamble_comment_after_version::*;
pub use preamble_formatting::*;
pub use runtime_section_keys::*;
pub use section_order::*;
pub use snake_case::*;
pub use todo::*;
pub use trailing_comma::*;
pub use unknown_rule::*;
pub use version_formatting::*;
pub use whitespace::*;
6 changes: 3 additions & 3 deletions wdl-lint/src/rules/deprecated_placeholder_option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const ID: &str = "DeprecatedPlaceholderOption";
/// Creates a diagnostic for the use of the deprecated `default` placeholder
/// option.
fn deprecated_default_placeholder_option(span: Span) -> Diagnostic {
Diagnostic::warning(String::from(
Diagnostic::note(String::from(
"use of the deprecated `default` placeholder option",
))
.with_rule(ID)
Expand All @@ -38,7 +38,7 @@ fn deprecated_default_placeholder_option(span: Span) -> Diagnostic {

/// Creates a diagnostic for the use of the deprecated `sep` placeholder option.
fn deprecated_sep_placeholder_option(span: Span) -> Diagnostic {
Diagnostic::warning(String::from(
Diagnostic::note(String::from(
"use of the deprecated `sep` placeholder option",
))
.with_rule(ID)
Expand All @@ -51,7 +51,7 @@ fn deprecated_sep_placeholder_option(span: Span) -> Diagnostic {
/// Creates a diagnostic for the use of the deprecated `true`/`false`
/// placeholder option.
fn deprecated_true_false_placeholder_option(span: Span) -> Diagnostic {
Diagnostic::warning(String::from(
Diagnostic::note(String::from(
"use of the deprecated `true`/`false` placeholder option",
))
.with_rule(ID)
Expand Down
2 changes: 1 addition & 1 deletion wdl-lint/src/rules/double_quotes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const ID: &str = "DoubleQuotes";

/// Creates a "use double quotes" diagnostic.
fn use_double_quotes(span: Span) -> Diagnostic {
Diagnostic::warning("string defined with single quotes")
Diagnostic::note("string defined with single quotes")
.with_rule(ID)
.with_highlight(span)
.with_fix("change the single quotes to double quotes")
Expand Down
4 changes: 2 additions & 2 deletions wdl-lint/src/rules/ending_newline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ const ID: &str = "EndingNewline";

/// Creates a "missing ending newline" diagnostic.
fn missing_ending_newline(span: Span) -> Diagnostic {
Diagnostic::warning("missing newline at the end of the file")
Diagnostic::note("missing newline at the end of the file")
.with_rule(ID)
.with_label("expected a newline to follow this", span)
.with_fix("add an empty line at the end of the file")
}

/// Creates a "multiple ending newline" diagnostic.
fn multiple_ending_newline(span: Span, count: usize) -> Diagnostic {
Diagnostic::warning("multiple empty lines at the end of file")
Diagnostic::note("multiple empty lines at the end of file")
.with_rule(ID)
.with_label(
if count > 1 {
Expand Down
2 changes: 1 addition & 1 deletion wdl-lint/src/rules/input_not_sorted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const ID: &str = "InputSorting";

/// Creates a "input not sorted" diagnostic.
fn input_not_sorted(span: Span, sorted_inputs: String) -> Diagnostic {
Diagnostic::warning("input not sorted")
Diagnostic::note("input not sorted")
.with_rule(ID)
.with_label("input section must be sorted".to_string(), span)
.with_fix(format!("sort input statements as: \n{}", sorted_inputs))
Expand Down
6 changes: 3 additions & 3 deletions wdl-lint/src/rules/misplaced_lint_directive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ pub static RULE_MAP: LazyLock<HashMap<&'static str, Option<&'static [SyntaxKind]

/// Detects unknown rules within lint directives.
#[derive(Default, Debug, Clone, Copy)]
pub struct MisplacedLintDirective;
pub struct MisplacedLintDirectiveRule;

impl Rule for MisplacedLintDirective {
impl Rule for MisplacedLintDirectiveRule {
fn id(&self) -> &'static str {
ID
}
Expand All @@ -91,7 +91,7 @@ impl Rule for MisplacedLintDirective {
}
}

impl Visitor for MisplacedLintDirective {
impl Visitor for MisplacedLintDirectiveRule {
type State = Diagnostics;

fn document(&mut self, _: &mut Self::State, _: VisitReason, _: &Document, _: SupportedVersion) {
Expand Down
2 changes: 1 addition & 1 deletion wdl-lint/src/rules/missing_requirements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const ID: &str = "MissingRequirements";

/// Creates a "deprecated runtime section" diagnostic.
fn deprecated_runtime_section(task: &str, span: Span) -> Diagnostic {
Diagnostic::warning(format!(
Diagnostic::note(format!(
"task `{task}` contains a deprecated `runtime` section"
))
.with_rule(ID)
Expand Down
3 changes: 2 additions & 1 deletion wdl-lint/src/rules/nonmatching_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn extra_output_in_meta(span: Span, name: &str, item_name: &str, ty: &str) -> Di

/// Creates a diagnostic for out-of-order entries.
fn out_of_order(span: Span, output_span: Span, item_name: &str, ty: &str) -> Diagnostic {
Diagnostic::warning(format!(
Diagnostic::note(format!(
"`outputs` section of `meta` for the {ty} `{item_name}` is out of order"
))
.with_rule(ID)
Expand All @@ -76,6 +76,7 @@ fn out_of_order(span: Span, output_span: Span, item_name: &str, ty: &str) -> Dia

/// Creates a diagnostic for non-object `meta.outputs` entries.
fn non_object_meta_outputs(span: Span, item_name: &str, ty: &str) -> Diagnostic {
// TODO: this message is way too long
a-frantz marked this conversation as resolved.
Show resolved Hide resolved
Diagnostic::warning(format!(
"`outputs` key in `meta` section is reserved for an object with keys corresponding to \
declared `output` values. {ty} `{item_name}` has a `meta.outputs` key that is not an \
Expand Down
143 changes: 143 additions & 0 deletions wdl-lint/src/rules/preamble_comment_after_version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//! A lint rule for flagging preamble comments which are outside the preamble.

use wdl_ast::AstToken;
use wdl_ast::Comment;
use wdl_ast::Diagnostic;
use wdl_ast::Diagnostics;
use wdl_ast::Document;
use wdl_ast::Span;
use wdl_ast::SyntaxElement;
use wdl_ast::SyntaxKind;
use wdl_ast::VisitReason;
use wdl_ast::Visitor;

use crate::Rule;
use crate::Tag;
use crate::TagSet;

/// The identifier for the rule.
const ID: &str = "PreambleCommentAfterVersion";

/// Creates a diagnostic for a comment outside the preamble.
fn preamble_comment_outside_preamble(span: Span) -> Diagnostic {
Diagnostic::error("preamble comment after the version statement")
.with_rule(ID)
.with_highlight(span)
}

/// A lint rule for flagging preamble comments which are outside the preamble.
#[derive(Default, Debug, Clone)]
a-frantz marked this conversation as resolved.
Show resolved Hide resolved
pub struct PreambleCommentAfterVersionRule {
/// Exited the preamble.
exited_preamble: bool,
/// The number of comment tokens to skip.
///
/// This is used when consolidating multiple comments into a single
/// diagnositc.
skip_count: usize,
}

impl Rule for PreambleCommentAfterVersionRule {
fn id(&self) -> &'static str {
ID
}

fn description(&self) -> &'static str {
"Ensures that preamble comments are inside the preamble."
}

fn explanation(&self) -> &'static str {
"Preamble comments should be inside the preamble."
}

fn tags(&self) -> TagSet {
TagSet::new(&[Tag::Clarity])
}

fn exceptable_nodes(&self) -> Option<&'static [SyntaxKind]> {
None
}
}

impl Visitor for PreambleCommentAfterVersionRule {
type State = Diagnostics;

fn document(
&mut self,
_: &mut Self::State,
reason: VisitReason,
_: &Document,
_: wdl_ast::SupportedVersion,
) {
if reason == VisitReason::Exit {
return;
}

// Reset the visitor upon document entry.
*self = Default::default();
}

fn version_statement(
&mut self,
_state: &mut Self::State,
reason: VisitReason,
_stmt: &wdl_ast::VersionStatement,
) {
if reason == VisitReason::Exit {
self.exited_preamble = true;
}
}

fn comment(&mut self, state: &mut Self::State, comment: &Comment) {
if !self.exited_preamble {
return;
}

if self.skip_count > 0 {
self.skip_count -= 1;
return;
}

if !comment.as_str().starts_with("## ") {
return;
}

let mut span = comment.span();
let mut current = comment.syntax().next_sibling_or_token();
while let Some(sibling) = current {
match sibling.kind() {
SyntaxKind::Comment => {
self.skip_count += 1;

if !sibling
.as_token()
.expect("expected a token")
.text()
.starts_with("## ")
{
// The sibling comment is valid, so we can break.
break;
}

// Not valid, update the span
span = Span::new(
span.start(),
usize::from(sibling.text_range().end()) - span.start(),
)
}
SyntaxKind::Whitespace => {
// Skip whitespace
}
_ => break,
}

current = sibling.next_sibling_or_token();
}

state.exceptable_add(
preamble_comment_outside_preamble(span),
SyntaxElement::from(comment.syntax().clone()),
&self.exceptable_nodes(),
);
}
}
Loading
Loading