Skip to content

Provide indent-group feature - #120

Merged
Vladyslav-Kuksiuk merged 4 commits into
masterfrom
improve-indent
Aug 12, 2026
Merged

Provide indent-group feature#120
Vladyslav-Kuksiuk merged 4 commits into
masterfrom
improve-indent

Conversation

@Vladyslav-Kuksiuk

Copy link
Copy Markdown
Collaborator

This PR provides indent-group feature which allows to separate common indents inside one docfragment.

@Vladyslav-Kuksiuk Vladyslav-Kuksiuk self-assigned this Aug 12, 2026
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.30%. Comparing base (242957d) to head (b483380).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #120      +/-   ##
==========================================
+ Coverage   96.19%   96.30%   +0.10%     
==========================================
  Files          43       43              
  Lines        2945     3032      +87     
==========================================
+ Hits         2833     2920      +87     
  Misses         96       96              
  Partials       16       16              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Vladyslav-Kuksiuk
Vladyslav-Kuksiuk marked this pull request as ready for review August 12, 2026 12:56
@Vladyslav-Kuksiuk
Vladyslav-Kuksiuk marked this pull request as draft August 12, 2026 12:57
@Vladyslav-Kuksiuk
Vladyslav-Kuksiuk marked this pull request as ready for review August 12, 2026 13:04
Comment thread fragmentation/lookup.go Outdated
// Returns an error unless the remainder is empty or closes a supported block comment.
func validateDeclarationRemainder(source string, prefix string) error {
remainder := strings.TrimSpace(source)
if remainder == "" || remainder == "*/" || remainder == "-->" {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Rejecting every trailing token is a breaking change, not just indent-group validation.

The old lookup matched names with a greedy "(.*)" and silently ignored whatever followed. Now anything that is not exactly */ or --> aborts fragmentation of the whole file. Markers that worked before this PR and fail after it:

  • comment closers outside the two literals whitelisted here: #} (Twig/Jinja), --}} (Handlebars), %> (JSP/ERB), *) (Pascal/OCaml), #> (PowerShell), ]]>;
  • code or prose after the closer: /* #docfragment "main" */ public void run() {, // #docfragment "main" (see the loop below).

None of the repo's own fixtures hit this, so CI stays green, but users hit it on upgrade with no indent-group in sight, and the failure mode is a hard error for the entire file rather than a skipped marker.

Two ways to keep the typo detection this buys without the collateral damage:

  1. only reject a remainder that is attribute-shaped (something like ^[A-Za-z][A-Za-z_-]*\s*=), and keep ignoring the rest as before; or
  2. keep the strict rule, but hoist the accepted closers into a named list instead of two inline literals, and call the change out in the PR description and in named-fragment.md as deliberate.

Comment thread fragmentation/lookup.go
return nil, err
}

return declaration.names, nil

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

FindDocFragments drops declaration.indentGroup, and it is the only exported way to read an opening marker — both fragmentDeclaration and findDocFragmentDeclaration are unexported.

Two consequences:

  • callers outside the package can parse a marker but cannot see the group it declares, even though the parser now understands it;
  • the parsed group value is asserted nowhere in the unit tests. should find fragment openings with an indentation group (fragmentation_test.go:627) only checks the names, so it would still pass if parseIndentGroup returned the wrong string; the only thing pinning the value is the end-to-end indentation test.

Consider exporting the declaration (e.g. FindDocFragmentDeclaration() (FragmentDeclaration, error)) and keeping FindDocFragments as a thin wrapper over it, so both the public API and the tests can observe the group.

Comment thread fragmentation/lookup.go
// error - when the name is not a valid quoted string.
func consumeQuotedName(source string) (string, string, error) {
quotedName, remainder := consumeQuotedValue(source)
name, err := unquoteName(quotedName)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

unquoteName accepts "", so // #docfragment "" declares a fragment whose name is the empty string. That fragment can never be referenced: fragment="" on an <embed-code> instruction means "whole file" (embedding/parsing/instruction.go:58). The marker lines still vanish from the rendered content, so the typo is silent.

The behavior predates this PR, but the name parsing is being rewritten here, and parseIndentGroup rejects an empty value one function down. The same guard on the name would make the two consistent and turn a silent no-op into a diagnosable error.

Comment thread fragmentation/lookup.go Outdated
if len(line) < fragmentsStart {
return unquotedNames, fmt.Errorf(
"found `%s` prefix without any name", prefix,
declaration, err := parseFragmentDeclaration(line, prefix, false)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lookup is now a pass-through with a single caller (FindEndDocFragments), and prefix always receives FragmentEnd. unparam is enabled in .golangci.yml and reports exactly this shape on unexported functions (prefix always receives FragmentEnd), so this will likely fail the lint job.

The indirection no longer earns its keep either: FindEndDocFragments can call parseFragmentDeclaration(line, FragmentEnd, false) directly. That also retires a doc comment whose prefix example — for example "#docfragment", line 106 — is now unreachable, since start markers go through findDocFragmentDeclaration instead.

Comment thread fragmentation/fragment.go Outdated
@@ -105,17 +111,43 @@ func (f Fragment) text(lines []string, separator string) (string, error) {
// Returns:
// [][]string - selected lines grouped by partition.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Stale after the signature change: the function now returns []partitionText, not [][]string, and each element carries the indentation group as well as the lines.

Comment thread fragmentation/fragment.go Outdated
text := ""
for index, partitionText := range partitionsTexts {
cutIndentLines := indent.CutIndent(partitionText, indentation)
indentation := indentations[partitionText.indentGroup]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The loop variable partitionText on line 91 now shadows the partitionText type introduced at fragment.go:48, so the type name is unusable for the rest of the loop body and the reader meets partitionText.indentGroup (a value) a few lines after partitionText{...} (a type). Renaming the variable to partition, as commonIndentations already does, removes the collision.


Add `indent-group="name"` to an opening `#docfragment` marker. The group name
must be a non-empty quoted string. The matching `#enddocfragment` marker does
not repeat the attribute.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

"does not repeat the attribute" reads as optional, but the parser rejects it outright: #enddocfragment "x" indent-group="y" fails with indent-group is only supported by #docfragment (fragmentation/lookup.go:164).

Worth saying that repeating it is an error. Since this page is now the closest thing to a grammar for the marker, it is also the right place to state the other new rule — nothing may follow the fragment names except an optional indent-group and a */ or --> comment closer.

@Oleg-Melnik Oleg-Melnik left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@Vladyslav-Kuksiuk LGTM with comments to address.

@Vladyslav-Kuksiuk
Vladyslav-Kuksiuk merged commit 719976a into master Aug 12, 2026
5 checks passed
@Vladyslav-Kuksiuk
Vladyslav-Kuksiuk deleted the improve-indent branch August 12, 2026 13:42
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.

2 participants