This repository was archived by the owner on Sep 10, 2026. It is now read-only.
Repository navigation
Give the scaffolder's foreign-file edits one whitespace rule - #58
Merged
Merged
Conversation
Three functions append a block to a file `flutter create` produced. Each normalised newlines itself, with two different answers, so the desugaring block got a blank line before it and the other two did not: in a generated project the two Gradle blocks landed flush against each other. `appendBlock` now owns that and nothing else, with the block constants carrying no leading or trailing newline of their own, and the scaffold test pins the separation rather than only the contents. A comment beside the release-signing block claimed it still prepends `import java.util.Properties`. That edit was removed when AGP 9 broke it, so the comment described the one thing the surrounding code exists to avoid. MAINTAINERS.md gains the doctrine these three follow: append never insert, why each block is recognised by a content probe on its own payload, and why FlutterFire's `// START:`/`// END:` markers are deliberately not copied. Those markers are attribution rather than machinery, never read back by flutterfire_cli itself, and an append needs no anchor. The one thing that would earn a marker pair is a block whose content must be found and replaced on a later run, which belongs to an upgrade command that does not exist yet; the section records the shape to use when it does. It also records that configuration values are assigned into declared slots instead, and the JSON-versus-JSONC rule governing how. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
create-eigen-gameowns most of what it writes — four template trees copied whole and token-substituted. Three edits are different: they modify filesflutter createproduced, in a directoryflutterfire configurewill edit next. This gives those three one shared rule and writes down the doctrine behind them.The bug
Each of the three normalised newlines itself, with two different answers:
endsWith("\n") ? "\n" : "\n\n"endsWith("\n") ? "" : "\n"endsWith("\n") ? "" : "\n"Desugaring always left a blank separator line, the other two never did. Since desugaring runs first and leaves a trailing newline, the release-signing block then landed flush against it in every generated project.
appendBlocknow owns the whitespace and nothing else — one blank line before, one newline after, block constants carrying neither — and the scaffold test pins the separation rather than only the contents.Verified by rendering a scaffold against a realistic
flutter createstub and reading the output; the appended blocks are now spaced like Flutter's own.A comment that said the opposite of its code
A comment beside the release-signing block claimed it still prepends
import java.util.Properties. That edit was removed when AGP 9 broke it — the block parseskey.propertieswith the Kotlin stdlib now. The comment described the exact thing the surrounding code exists to avoid, so it is rewritten to record the history without claiming a prepend exists.The doctrine, in MAINTAINERS.md
New section, Editing files the scaffolder does not own:
includes("signingConfigs")would never fire (Flutter's own template already contains it).// START:/// END:markers are deliberately not copied. They are attribution, not machinery: in flutterfire_cli 1.4.1 the two constants appear in ten places and every one is string construction — nothing reads them back. Its idempotency comes fromcontains(_googleServicesPluginClassPath), the same mechanism used here. FlutterFire needs a regex anchor because it must inject into the single permittedplugins { }block; an append needs no anchor, so a marker would add text without adding capability. One shared marker text also means it could not replace selectively even if it read them.includes("releaseKeyProperties")answers "is mine here?" but never "where does mine end?". That arrives with an upgrade command and not before, so the section records the shape to use then: one pair per block, versioned marker text, guarded on exactly one properly nested pair.templates/— those files are wholly owned and rendered whole.wrangler.jsoncandapp-config.json, plus the JSON-versus-JSONC rule: plain JSON is decoded and re-encoded, commented JSONC has its single assignment rewritten in place, and the safety there is the match count rather than the pattern.A companion note lands in eigen-flutter's
firebase_link.dart, where the JSONC half is implemented: eigeninteractive/eigen-flutter#36.Verification
pnpm lintclean ·pnpm -r typecheckclean ·pnpm -r test358 passed.🤖 Generated with Claude Code