Skip to content

chore: add rule helper utilities - #4

Open
nzakas wants to merge 2 commits into
languagefrom
rule-utils
Open

nzakas wants to merge 2 commits into
languagefrom
rule-utils

Conversation

@nzakas

@nzakas nzakas commented Sep 18, 2026 •

Copy link
Copy Markdown
Member

Adds the shared helpers that the rule PRs above this one build on. They're internal (not exported from the package), so this PR uses chore: and stays out of the changelog.

What's included

src/rules/utils.ts:

Helper Purpose
getStaticText(word) The unquoted text of a word made only of literals and quoted literals, or null if it contains an expansion
getCommandName(command) A command's static name, or null (dynamic names like $cmd, or assignment-only statements)
isCommandNamed(statement, name) Whether a statement is a simple command with that name
getExpansions(word, { includeQuoted }) Parameter expansions and command substitutions in a word, optionally including those inside double quotes

They're used by no-useless-echo, no-ls-iteration, no-useless-cat, require-read-r, require-cd-guard, no-variables-in-printf-format, and no-unused-vars.

Testing

13 unit tests in src/rules/utils.spec.ts (154 total); build, lint, and format checks pass.

🤖 Generated with Claude Code


Stack created with GitHub Stacks CLI • Give Feedback 💬

@coderabbitai

coderabbitai Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 35 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 04cacb97-3970-4223-8a51-d5fdabb25a32

📥 Commits

Reviewing files that changed from the base of the PR and between 792a34e and dde227f.

📒 Files selected for processing (2)
  • src/rules/utils.spec.ts
  • src/rules/utils.ts
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@nzakas
nzakas added this pull request to stack #16 September 18, 2026 15:00
@nzakas
nzakas marked this pull request as ready for review September 18, 2026 15:01
@nzakas
nzakas force-pushed the rule-utils branch 2 times, most recently from 3d66b2e to 739e098 Compare September 22, 2026 20:23
@nzakas
nzakas requested a balanced review from Copilot September 28, 2026 18:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Static-text handling and expansion traversal miss valid Bash semantics.

Review effort: Balanced
Findings: 3 Medium severity

Open (3)
What changed in this PR

Adds internal utilities for Bash rule implementations.

Changes:

  • Adds static-word, command-name, and expansion helpers.
  • Adds 13 focused unit tests.
File Description
src/​rules/​utils.ts Implements shared rule helpers.
src/​rules/​utils.spec.ts Tests helper behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/rules/utils.ts Outdated
Comment on lines +40 to +41
case "SingleQuotedString":
return part.value;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch. Went with the conservative option in f81f603: getStaticText() returns null for a $'...' string that contains a backslash, and still returns the text when there are no escapes to decode. Tests added for both, plus getCommandName() on $'e\x63ho'.

Comment thread src/rules/utils.ts
Comment on lines +43 to +44
case "DoubleQuotedString": {
let result = "";

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in f81f603: $"..." strings now return null, with a test.

Comment thread src/rules/utils.ts
Comment on lines +97 to +106
if (
part.type === "ParameterExpansion" ||
part.type === "CommandSubstitution"
) {
if (!quoted || includeQuoted) {
expansions.push(part);
}
} else if (part.type === "DoubleQuotedString") {
visitParts(part.parts, true);
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not changing the behavior here. Every nested expansion sits inside an outer expansion that is already returned, and the helper's only consumer (no-variables-in-printf-format) just asks whether the word contains any expansion, so nothing is missed today. Recursing would also make the result ambiguous for callers that report or fix each returned node, since inner and outer ranges overlap and "quoted" isn't well defined for an operand word. The doc comment did overpromise with "all expansions", so f81f603 rewords it to say nested expansions are not returned and pins that with a test.

nzakas and others added 2 commits October 2, 2026 12:17
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
getStaticText() now returns null for $'...' strings containing escapes
and for locale-translated $"..." strings, whose runtime text can differ
from the source text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants