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

feat: implement DisallowedDeclarationName rule #343

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

Gyan-max
Copy link

@Gyan-max Gyan-max commented Mar 8, 2025

This pull request adds a new rule to wdl-lint.

  • Rule Name: DisallowedDeclarationNameRule

This rule checks for declaration names that contain their type (like File fileInput) which is considered poor style as it adds unnecessary verbosity and creates redundancy since the type is already declared. The rule identifies declarations like File fileInput, Int my_int, and Array[String] stringArray as problematic.

Before submitting this PR, please make sure:

  • You have added a few sentences describing the PR here.
  • You have added yourself or the appropriate individual as the assignee.
  • You have added at least one relevant code reviewer to the PR.
  • Your code builds clean without any errors or warnings.
  • You have added an entry to the relevant CHANGELOG.md.
  • Your commit messages follow the conventional commit style.

Rule specific checks:

  • You have added the rule as an entry within RULES.md.
  • You have added the rule to the rules() function in wdl-lint/src/lib.rs.
  • You have added a test case in wdl-lint/tests/lints that covers every
    possible diagnostic emitted for the rule within the file where the rule
    is implemented.
  • If you have implemented a new Visitor callback, you have also
    overridden that callback method for the special Validator
    (wdl-ast/src/validation.rs) and LintVisitor
    (wdl-lint/src/visitor.rs) visitors.
  • You have run gauntlet --refresh to ensure that there are no
    unintended changes to the baseline configuration file (Gauntlet.toml).
  • You have run gauntlet --refresh --arena to ensure that all of the
    rules added/removed are now reflected in the baseline configuration file
    (Arena.toml).

Fixes #215

@a-frantz
Copy link
Member

a-frantz commented Mar 8, 2025

follow the PR template please. Re-write your PR description according to https://github.com/stjude-rust-labs/wdl/blob/main/.github/pull_request_template.md?plain=1

@Gyan-max Gyan-max force-pushed the disallowed-declaration-name branch from 6587d56 to 41148c2 Compare March 9, 2025 07:44
@Gyan-max
Copy link
Author

Gyan-max commented Mar 9, 2025

@a-frantz I've addressed all your feedback:

  1. Minimized the diff in lib.rs
  2. Improved the type detection logic to handle various type structures
  3. Updated the diagnostic messages to be more helpful
  4. Fixed the implementation to properly follow the project's coding standards

All tests are now passing. Let me know if you'd like me to make any additional improvements!

@a-frantz
Copy link
Member

a-frantz commented Mar 9, 2025

I think your force push went wrong. I still see the old code I reviewed earlier.

@Gyan-max Gyan-max force-pushed the disallowed-declaration-name branch from beebcb5 to 41148c2 Compare March 9, 2025 16:04
@Gyan-max
Copy link
Author

Gyan-max commented Mar 9, 2025

I think your force push went wrong. I still see the old code I reviewed earlier.

@a-frantz I just force-pushed the updated implementation again. You should now be able to see the changes that address all your feedback. Let me know if you have any further questions or if there are additional improvements needed.

@a-frantz a-frantz assigned a-frantz and Gyan-max and unassigned a-frantz Mar 9, 2025
@a-frantz
Copy link
Member

a-frantz commented Mar 9, 2025

I think your force push went wrong. I still see the old code I reviewed earlier.

@a-frantz I just force-pushed the updated implementation again. You should now be able to see the changes that address all your feedback. Let me know if you have any further questions or if there are additional improvements needed.

still seeing the old code. I think there's something wrong with your git commands. Try again, and then check the "files changed" tab after to make sure your pushes work.

@a-frantz
Copy link
Member

a-frantz commented Mar 9, 2025

Also, your PR description still doesn't have the proper checklist items. Please copy and paste from the template I linked earlier

@Gyan-max Gyan-max force-pushed the disallowed-declaration-name branch from 111492e to 5e3649f Compare March 9, 2025 17:13
@Gyan-max
Copy link
Author

Gyan-max commented Mar 9, 2025

I think your force push went wrong. I still see the old code I reviewed earlier.

@a-frantz I just force-pushed the updated implementation again. You should now be able to see the changes that address all your feedback. Let me know if you have any further questions or if there are additional improvements needed.

still seeing the old code. I think there's something wrong with your git commands. Try again, and then check the "files changed" tab after to make sure your pushes work.

@a-frantz I've made another push with a visible marker comment at the top of the file:

//! FIXING PUSH ISSUE - THIS COMMENT SHOULD BE VISIBLE IN THE PR

Please check the "Files changed" tab to verify that you can now see the updated code. The changes should now include:

  1. Improved diagnostic messages that include both declaration name and type
  2. Better type detection that works case-insensitively
  3. Fixed SyntaxKind values for exceptable_nodes
  4. All tests passing

Let me know if you still can't see the updated code.

@Gyan-max
Copy link
Author

Gyan-max commented Mar 9, 2025

@a-frantz I've updated the PR description to use the proper template with checklist items as requested. Also, I've made another push with visible changes to the rule file - you should now be able to see the updated implementation in the "Files changed" tab.

Copy link
Member

@a-frantz a-frantz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe there was some confusion earlier. I see your push worked, but there are still some issues that I highlighted before that weren't resolved. I unresolved the relevant github threads.

@Gyan-max Gyan-max force-pushed the disallowed-declaration-name branch from 326aadf to 87d9332 Compare March 9, 2025 18:47
@Gyan-max
Copy link
Author

Gyan-max commented Mar 9, 2025

@a-frantz I've addressed all your feedback:

  1. Reverted changes to wdl-doc/src/lib.rs - this file now has no changes
  2. Minimized changes to wdl-lint/src/lib.rs - only adding the DisallowedDeclarationNameRule and changing the for loop
  3. Simplified the type checking in disallowed_declaration_name.rs:
    • Removed the redundant common_types array and associated checks
    • Kept the direct type comparison approach

I've pushed all these changes. Please let me know if there's anything else I need to fix.

@Gyan-max Gyan-max force-pushed the disallowed-declaration-name branch from 5e7a53f to 77b3457 Compare March 9, 2025 18:59
@Gyan-max
Copy link
Author

@a-frantz sorry to bother you again
I installed shellcheck on my machine and re-run all the tests. All passed.
and i also updated test outputs so please review it once more and do let me if any further changes are needed.
ThankYou

@claymcleod claymcleod changed the title Implement DisallowedDeclarationName rule feat: implement DisallowedDeclarationName Mar 19, 2025
@claymcleod claymcleod changed the title feat: implement DisallowedDeclarationName feat: implement DisallowedDeclarationName rule Mar 19, 2025
@claymcleod claymcleod added the S-awaiting-review State: awaiting initial or additional review label Mar 19, 2025
@claymcleod
Copy link
Member

@a-frantz, this is ready for rereview.

SyntaxKind::InputSectionNode,
SyntaxKind::OutputSectionNode,
SyntaxKind::BoundDeclNode,
SyntaxKind::UnboundDeclNode,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context: We try to keep each list of "exceptable nodes" minimal, preferring the most specific node when excepting two different nodes would lead to the same behavior.

That being said, this will need to be expanded to include task and workflow definition nodes so that all private declarations of a task or workflow can be "excepted" at once. That would make this list one of our longer lists of exceptable nodes, but each node would cover a different set of declarations.

Please add those two nodes to this list, and then I think we'll have all our bases covered.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

task and workflow definitions still need to be added here

Comment on lines 111 to 112
let name = decl.name();
let name_str = name.as_str();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: these don't get used till line 172, and I prefer to keep declarations close to where they're used. Can you move these down? It reduces the need to scroll up and down looking for where something is used/defined.

@Gyan-max
Copy link
Author

Hi @a-frantz,
Thanks for the feedback! I've addressed all the requested changes:
Added TaskNode and WorkflowNode to the exceptable_nodes list to allow excepting all private declarations of a task or workflow at once.
Moved the declaration of name and name_str variables closer to where they're used in the code to improve readability.
Added Dir as an additional check for the Directory type to catch both naming variants.
Added Int as an additional check for the Integer type, with a comment explaining that Integer is shortened to Int in WDL.
Removed the blank lines within the match statement to make the code more concise as per the style guidelines.
All changes have been committed and pushed. Let me know if there's anything else that needs addressing!

Copy link
Member

@a-frantz a-frantz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you reBLESS the tests and Arena? Or did the latest round of tweaks not result in any changes?

@Gyan-max
Copy link
Author

I've updated the implementation with the suggested improvements:

  1. Fixed the Integer type handling - I'm now checking for "Integer" explicitly (as primitive_type.to_string() already returns "Int").
  2. Implemented a more generic approach for short type names (3 characters or fewer) using word splitting, which covers both "Int" and "Dir" cases.
  3. Made the code cleaner with better comments to explain the rationale and implementation.

This approach avoids hardcoding specific types and should be more maintainable going forward.

@@ -16,6 +16,7 @@ be out of sync with released packages.
| `DeprecatedObject` | Deprecated | Ensures that the deprecated `Object` construct is not used. |
| `DeprecatedPlaceholderOption` | Deprecated | Ensures that the deprecated placeholder options construct is not used. |
| `DescriptionMissing` | Completeness | Ensures that each meta section has a description key. |
| `DisallowedDeclarationName` | Naming | Ensures that declaration names do not have type prefixes or suffixes. |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `DisallowedDeclarationName` | Naming | Ensures that declaration names do not have type prefixes or suffixes. |
| `DisallowedDeclarationName` | Naming | Ensures that declaration names do not have type suffixes. |

Comment on lines 51 to 52
verbose and often redundant. For example, use 'counter' instead of 'counterInt' or \
'is_active' instead of 'isActiveBoolean'."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
verbose and often redundant. For example, use 'counter' instead of 'counterInt' or \
'is_active' instead of 'isActiveBoolean'."
verbose and often redundant. For example, use 'counter' instead of 'counter_int' or \
'is_active' instead of 'is_active_boolean'."

}
}

// Get declaration name after type checking (moving closer to usage)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Get declaration name after type checking (moving closer to usage)

Comment on lines 167 to 168
let name = decl.name();
let name_str = name.as_str();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let name = decl.name();
let name_str = name.as_str();
let name = decl.name().as_str();

Comment on lines 193 to 194
let name_lower = name_str.to_lowercase();
if name_lower.ends_with(&type_lower) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let name_lower = name_str.to_lowercase();
if name_lower.ends_with(&type_lower) {
if name.to_lowercase().ends_with(&type_lower) {

.collect()
}

#[cfg(test)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests you've written here are essentially the same as the tests checked by source.wdl and source.errors, so I think it's ok to just delete all these.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you except DisallowedDeclarationName from this source.wdl to prevent these errors?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please fix all of these

warning[DisallowedDeclarationName]: declaration identifier 'int' ends with type name 'Int'
┌─ tests/lints/disallowed-input-name/source.wdl:24:13
24 │ Int int = 1 # This is OK
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we just delete this line from source.wdl to prevent this diagnostic. It's not a good example anymore

@Gyan-max
Copy link
Author

@a-frantz All done, please review it once and let me know if any further improvement is needed.

@a-frantz
Copy link
Member

@Gyan-max please fix everything reported by CI. But this is really close! Nice work

@Gyan-max
Copy link
Author

@Gyan-max please fix everything reported by CI. But this is really close! Nice work

On it!

@Gyan-max
Copy link
Author

@a-frantz All tests are now passing with both cargo test and cargo clippy, and I've blessed the test baselines using BLESS=1.

@Gyan-max Gyan-max requested a review from a-frantz March 20, 2025 18:26
Copy link
Member

@a-frantz a-frantz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly nits about unhelpful comments. We like to avoid comments that are describing something "obvious", although that is kind of subjective 🤷

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can except NonmatchingOutput and InputSorting, but please correct the rest of the diagnostics reported here that aren't related to the new lint.

SyntaxKind::InputSectionNode,
SyntaxKind::OutputSectionNode,
SyntaxKind::BoundDeclNode,
SyntaxKind::UnboundDeclNode,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

task and workflow definitions still need to be added here

Comment on lines 112 to 117
// Get the declaration name
let binding = decl.name();
let name = binding.text();

// Get the declaration type
let ty = decl.ty();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Get the declaration name
let binding = decl.name();
let name = binding.text();
// Get the declaration type
let ty = decl.ty();
let binding = decl.name();
let name = binding.text();
let ty = decl.ty();

Comment on lines 130 to 133
// Add the primitive type name
type_names.insert(primitive_type.to_string());
// Also check for "Bool"
type_names.insert("Bool".to_string());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Add the primitive type name
type_names.insert(primitive_type.to_string());
// Also check for "Bool"
type_names.insert("Bool".to_string());
type_names.insert(primitive_type.to_string());
type_names.insert("Bool".to_string());

}
}

// Get the element for diagnostic reporting
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Get the element for diagnostic reporting

Decl::Unbound(d) => SyntaxElement::from(d.inner().clone()),
};

// Check if the declaration name ends with one of the type names
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Check if the declaration name ends with one of the type names

// Check if the short type name appears as the last word
if let Some(last_word) = words.last() {
if last_word.to_lowercase() == type_lower {
let diagnostic = decl_identifier_with_type(decl.name().span(), name, type_name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let diagnostic = decl_identifier_with_type(decl.name().span(), name, type_name);
let diagnostic = decl_identifier_with_type(binding.span(), name, type_name);

// Special handling for short type names (3 characters or less)
// These require word-based checks to avoid false positives
if type_lower.len() <= 3 {
// Split the identifier into words
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Split the identifier into words

@Gyan-max
Copy link
Author

@a-frantz I addressed all your feedbacks sorry for unnecessary bother and thankyou for your guidance.

@Gyan-max Gyan-max requested a review from a-frantz March 20, 2025 19:12
Copy link
Member

@a-frantz a-frantz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we maybe want to leave File and String as ignored, but why don't you bless Arena with those enabled and I'll review what comes up, then we can decide what to do with those two types.

#[derive(Debug, Default)]
pub struct DisallowedDeclarationNameRule {
/// Tracks whether we're currently within an input or output declaration section
in_declaration_section: bool,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point of this? It doesn't look like your using it, and I don't think we would care for this rule. Declarations everywhere (inputs, outputs, private decls) should all be handled the same.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this because while running the tests it was showing an error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you share the error? I'm not following

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just give me a minute, I'm running the tests

@Gyan-max Gyan-max requested a review from a-frantz March 20, 2025 19:42
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I think everything ending in string and file can be ignored. Please update the logic to allow those two type suffixes and then rebless everything

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-awaiting-review State: awaiting initial or additional review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New rule: DisallowedDeclarationName
4 participants