Skip to content

feat: add lint rule for Bash nounset empty array expansions (#57)#62

Open
olavostauros wants to merge 3 commits into
KnickKnackLabs:mainfrom
olavostauros:feat/bash-empty-array-expansions
Open

feat: add lint rule for Bash nounset empty array expansions (#57)#62
olavostauros wants to merge 3 commits into
KnickKnackLabs:mainfrom
olavostauros:feat/bash-empty-array-expansions

Conversation

@olavostauros

@olavostauros olavostauros commented Jun 23, 2026

Copy link
Copy Markdown

Summary

Adds bash-empty-array-expansions lint rule that flags "${array[@]}" and "${array[*]}" under nounset (set -u), suggesting the Bash-3-safe alternate-value form ${arr[@]+"${arr[@]}"}. macOS Bash 3.2 treats these as unbound variables when the array is empty; Linux Bash 5+ and Homebrew Bash handle them gracefully, creating a silent cross-platform gotcha. ShellCheck does not catch this.

Also collapses decorative 3-line section comment blocks (# ============ Section ============) to single-line headers (# Section) across 9 .bats test files, per KKL convention (AGENTS.md rule #4).

Files changed

File Change
.mise/tasks/lint/bash-empty-array-expansions New rule (~120 lines, text-based ripgrep) — chmod +x
test/lint/bash-empty-array-expansions/bash-empty-array-expansions.bats 15 BATS tests
test/lint/bash-empty-array-expansions/fixtures/ 11 fixture scenarios (clean, dirty, no-nounset, safe-context, ignored, etc.)
.mise/tasks/lint/shellcheck Inline codebase:ignore (guarded usage)
.mise/tasks/lint/github-actions Inline codebase:ignore (guarded usage)
.mise/tasks/lint/mise-settings Inline codebase:ignore (guarded usage)
test/lint/bats-test-task/fixtures/clean/mise.toml Cross-rule fixture ignore
test/lib/shell-files.bats Collapse decorative comment block
test/lint/bats-test-helper/bats-test-helper.bats Collapse 9 decorative comment blocks
test/lint/bats-test-task/bats-test-task.bats Collapse 8 decorative comment blocks
test/lint/gum-table/gum-table.bats Collapse 10 decorative comment blocks
test/lint/mcr-scope/mcr-scope.bats Collapse 6 decorative comment blocks
test/lint/mise-settings/mise-settings.bats Collapse 3 decorative comment blocks
test/lint/or-true/or-true.bats Collapse 11 decorative comment blocks
test/lint/shellcheck/shellcheck.bats Collapse 5 decorative comment blocks
test/migrations/task-pattern/task-pattern.bats Collapse 6 decorative comment blocks
test/pre-commit/pre-commit.bats Collapse 10 decorative comment blocks
test/scan/scan.bats Collapse 5 decorative comment blocks

Validation

  • mise run test233/233 pass (15 new tests at indices 7–21, zero regressions)
  • mise run lint:bash-empty-array-expansions . — self-hosting clean (only test fixtures flagged)
  • mise run lint:shellcheck .mise/tasks/lint/bash-empty-array-expansions — ShellCheck-clean
  • git diff --check — no whitespace errors

Sister issue

This is the array sibling of #48 (bash-empty-argv-forwarding, PR #59). Both share nounset detection logic and the safe-context exclusion pattern.

Closes #57

Adds bash-empty-array-expansions lint rule that flags ${array[@]}
and ${array[*]} under set -u (nounset), suggesting the Bash-3-safe
alternate-value form ${arr[@]+"${arr[@]}"}.

Shares nounset detection pattern with bash-empty-argv-forwarding (KnickKnackLabs#48):
- has_nounset() - detect set -u / set -eu / set -euo pipefail
- is_safe_context() - exclude for loops and local array assignments
- has_safe_form() - exclude already-safe alternate-value forms

Standard text-based ripgrep approach with 11 fixture scenarios and
15 BATS tests. ShellCheck-clean.

Implements KnickKnackLabs#57 (KnickKnackLabs/codebase)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lint Bash nounset empty array expansions

1 participant