Skip to content

fix(core): don't strip shell/YAML # unless it starts a comment - #1752

Open
serhiizghama wants to merge 5 commits into
yamadashy:mainfrom
serhiizghama:fix/shell-yaml-hash-comment-boundary
Open

fix(core): don't strip shell/YAML # unless it starts a comment#1752
serhiizghama wants to merge 5 commits into
yamadashy:mainfrom
serhiizghama:fix/shell-yaml-hash-comment-boundary

Conversation

@serhiizghama

Copy link
Copy Markdown
Contributor

--remove-comments silently corrupts shell and YAML files. Both are routed to the perl strip profile, which treats every unquoted # as a line comment. But in shell and YAML a # is only a comment at the start of a line or after whitespace — not inside ${name##*/}, $#, or an unquoted URL like a/b#readme.

So a shell script like:

base=${name##*/}
ext=${name#*.}
count=$#

comes out as base=${name, ext=${name, count=$ — the rest of each line is dropped at the first #. Same for YAML: repo: https://github.com/a/b#readme loses #readme. The packed output no longer matches the source, which is exactly what you don't want when feeding it to an LLM.

I replaced the perl routing for .sh, .yaml, and .yml with a small boundary-aware scanner that only cuts at a # when it's at line start or preceded by whitespace, and skips single/double quoted strings (so echo "a # b" and color: "#ff0000" are kept). Real comments — full-line, whitespace-preceded trailing ones, and shebangs — are still stripped, so the existing shell/YAML tests stay green. Added tests for the parameter-expansion, $#, quoted-hash, and URL-fragment cases.

Shell and YAML files were routed through the 'perl' strip profile, which
treats every unquoted # as a comment. That corrupts common syntax such as
${name##*/}, $#, and unquoted URLs like a/b#readme, and drops trailing
content on the first stray #. Strip them with a boundary-aware scanner that
only treats # as a comment at line start or after whitespace, and skips
single/double quoted strings.
@serhiizghama
serhiizghama requested a review from yamadashy as a code owner July 22, 2026 02:13
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 72ad0a0d-96af-4c6e-ac66-31ab33715bf6

📥 Commits

Reviewing files that changed from the base of the PR and between ead41dc and 7cac3c3.

📒 Files selected for processing (2)
  • src/core/file/fileManipulate.ts
  • tests/core/file/fileManipulate.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/core/file/fileManipulate.test.ts
  • src/core/file/fileManipulate.ts

📝 Walkthrough

Walkthrough

Adds boundary-aware # comment stripping for shell and YAML files, preserving hashes in quoted, escaped, parameter-expansion, URL, inline scalar, heredoc, and block scalar contexts while removing actual comments. Tests cover the new shell and YAML behavior.

Changes

Hash comment stripping

Layer / File(s) Summary
Hash comment parser and extension wiring
src/core/file/fileManipulate.ts
Adds HashCommentManipulator with quote, escape, boundary, heredoc, and block-scalar handling, then assigns it to .sh, .yaml, and .yml files.
Shell and YAML edge-case coverage
tests/core/file/fileManipulate.test.ts
Tests preservation of shell parameter expansions and heredocs, YAML scalar hashes and block scalars, while removing genuine comments.

Estimated code review effort: 4 (Complex) | ~40 minutes

Possibly related PRs

Suggested reviewers: yamadashy

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description has a solid summary, but it omits the required checklist section with the npm test and lint items from the template. Add the checklist section and include the npm run test and npm run lint items, while keeping the existing summary.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly reflects the main change: fixing shell/YAML comment stripping for hashes that are not actual comments.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/file/fileManipulate.ts`:
- Around line 55-102: Extend the comment-removal scanner around its existing
quote and `#` handling to track shell heredoc bodies and YAML block-scalar
bodies, preserving every line of those literal sections—including indented or
standalone `#` content—until each construct ends. Apply the boundary rule only
outside these literal-body states, and add regression coverage for quoted
heredocs and YAML `|` block scalars.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6d5dba17-66b6-4409-929e-916c00c9b8d5

📥 Commits

Reviewing files that changed from the base of the PR and between 450ec69 and 67f22d3.

📒 Files selected for processing (2)
  • src/core/file/fileManipulate.ts
  • tests/core/file/fileManipulate.test.ts

Comment thread src/core/file/fileManipulate.ts Outdated
…tripping

The boundary-aware scan treated every line-start `#` as a comment, which
corrupted shell heredocs (cat <<EOF ... EOF) and YAML block scalars
(key: | ...) since their literal bodies can contain lines starting with `#`.
Track these as line/indentation-scoped states so body content is copied
verbatim instead of scanned for comments.
@serhiizghama

Copy link
Copy Markdown
Contributor Author

Good catch — heredocs and block scalars are literal content, the boundary rule shouldn't touch them. Added line/indentation-scoped tracking for both (shell <<EOF...EOF bodies, YAML key: | bodies) so they're copied verbatim instead of scanned for #. Added regression tests for both, verified they fail on the unfixed scanner.

@serhiizghama

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/core/file/fileManipulate.ts (1)

144-153: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Quote-open logic is shell-specific but applied unconditionally to YAML too.

'/" unconditionally flip inSingle/inDouble regardless of position. That's correct for shell (an unescaped quote anywhere outside quotes really does open a string), but wrong for YAML: a plain scalar may contain a literal, unescaped '/" mid-value (e.g. note: it's working # todo) — only a quote as the first character of a value starts a quoted scalar in YAML. With the current logic, the apostrophe in it's flips inSingle = true, and since no closing ' follows on that line, the state persists across subsequent lines (inSingle/inDouble carry over via processed.inSingle/inDouble), silently disabling #-comment stripping for everything until another ' happens to appear. This is a real, unexercised gap — none of the added tests use an apostrophe/contraction value.

🐛 Proposed fix: only treat quotes as YAML value-openers at a value boundary
-      if (char === "'") {
-        inSingle = true;
-        result += char;
-        continue;
-      }
-      if (char === '"') {
-        inDouble = true;
-        result += char;
-        continue;
-      }
+      if (char === "'" || char === '"') {
+        const prev = line[i - 1];
+        const atValueBoundary =
+          i === 0 || prev === ' ' || prev === '\t' || prev === ':' || prev === '-' || prev === ',' || prev === '[' || prev === '{';
+        if (this.language !== 'yaml' || atValueBoundary) {
+          if (char === "'") inSingle = true;
+          else inDouble = true;
+        }
+        result += char;
+        continue;
+      }

Consider adding a regression test for a YAML value containing an apostrophe (e.g. note: it's fine # comment) once fixed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/file/fileManipulate.ts` around lines 144 - 153, Update the quote
handling in the relevant file-scanning/parser function so YAML mode only opens
inSingle or inDouble when the quote is the first character of a value or follows
a YAML value boundary, while preserving the existing unconditional opening
behavior for shell mode. Ensure apostrophes or double quotes inside YAML plain
scalars do not persist quote state across lines, and add a regression test for a
contraction followed by a YAML comment if the surrounding tests support it.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/file/fileManipulate.ts`:
- Around line 48-50: Update YAML_BLOCK_SCALAR_START to require the block scalar
indicator to occur in a valid value position—after a mapping colon,
sequence-item marker, or at the start of the line—while preserving support for
optional chomp and indentation indicators and trailing comments. Ensure bare
scalars such as version: >5 and range: |3 no longer match.
- Around line 76-111: Change the output assembly in the file-processing method
so rtrimLines is applied only to normally processed lines, not heredoc or YAML
block-scalar lines pushed verbatim in the heredocDelimiter and blockScalarIndent
branches. Preserve trailing whitespace for those literal body lines while
retaining existing trimming behavior for ordinary content.

---

Outside diff comments:
In `@src/core/file/fileManipulate.ts`:
- Around line 144-153: Update the quote handling in the relevant
file-scanning/parser function so YAML mode only opens inSingle or inDouble when
the quote is the first character of a value or follows a YAML value boundary,
while preserving the existing unconditional opening behavior for shell mode.
Ensure apostrophes or double quotes inside YAML plain scalars do not persist
quote state across lines, and add a regression test for a contraction followed
by a YAML comment if the surrounding tests support it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 62a39c93-af72-4856-a53d-5e29a07a421e

📥 Commits

Reviewing files that changed from the base of the PR and between 67f22d3 and ead41dc.

📒 Files selected for processing (2)
  • src/core/file/fileManipulate.ts
  • tests/core/file/fileManipulate.test.ts

Comment thread src/core/file/fileManipulate.ts Outdated
Comment thread src/core/file/fileManipulate.ts
…aries

An apostrophe inside a YAML plain scalar (note: it's fine # x) flipped the
single-quote state and swallowed every following # comment until the next quote.
Only open a quoted scalar at a value boundary in YAML, and require the block
scalar |/> indicator to follow a : or - introducer so a plain scalar ending in
| isn't mistaken for one.
@serhiizghama

Copy link
Copy Markdown
Contributor Author

Good catches on the YAML edge cases. Fixed both: quotes now only open a scalar at a value boundary in YAML, so an apostrophe in a plain scalar (note: it's fine # x) no longer flips the quote state and eats the following comments; and the block-scalar regex now requires the |/> to follow a :/- introducer so a plain scalar that merely ends in | isn't treated as a block opener. Added regression tests for both.

Left rtrimLines as-is — it's applied to every language's stripped output, not just shell/YAML, so trailing whitespace in packed content is already normalized project-wide; carving out heredoc/block-scalar bodies would make the behavior inconsistent for a tool whose output is meant for reading, not byte-exact reconstruction.

@serhiizghama

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

1 participant