Skip to content

Unify #if handling and fix top-level #if regression#5

Draft
fummicc1 wants to merge 1 commit into
masterfrom
feature/unify-ifconfig-blocks
Draft

Unify #if handling and fix top-level #if regression#5
fummicc1 wants to merge 1 commit into
masterfrom
feature/unify-ifconfig-blocks

Conversation

@fummicc1

Copy link
Copy Markdown
Owner

Summary

Conditional compilation (#if/#elseif/#else) was modeled twice in mockolo:
IfMacroModel for member-level blocks and ConditionalImportBlock for imports,
with the directive-emitting switch duplicated between IfMacroTemplate and
ImportsHandler.

A side effect of that split (from uber#328) is a regression: EntityVisitor
treated every non-fileMacro top-level #if as import-only and returned
.skipChildren, so protocols/classes declared inside a top-level #if were
never discovered
and no mock was generated.

What this does

  • Unify the structure — add a generic ConditionalBlock<Leaf> and move
    directive emission to IfClauseType.directiveLine(indent:) /
    endIfLine(indent:), deleting the two duplicated switches.
  • IfMacroModel becomes a thin wrapper over ConditionalBlock<(String, Model)>
    (member-level #if output is byte-identical).
  • Imports use ConditionalBlock<ImportContent> (the old
    ConditionalImportBlock is removed).
  • Fix the regression — a top-level #if is parsed into a
    TopLevelConditionalLeaf union (import / entity / nested). Declarations
    are discovered and tagged with their clause; they flow through normal
    resolution (so members — including nested member-level #if — are fully
    generated), and a new renderConditionalBlocks re-wraps each generated mock in
    the original #if/#elseif/#else directives.

Why not SwiftIfConfig

SwiftIfConfig (BuildConfiguration / removingInactive / ActiveSyntaxVisitor)
resolves the active branch for a known configuration and discards inactive
ones. Mock generation must preserve every branch so the generated file
compiles under any configuration, so the raw IfConfigDeclSyntax.clauses
traversal remains the correct tool here.

Tests

  • All 160 existing tests stay green — member-level and import #if behavior is
    unchanged.
  • New TestConditionalCompilation covers: a protocol inside a top-level #if;
    #if/#elseif/#else each declaring a protocol; a mixed import + declaration
    in one #if; nested top-level #if; and a class with members (incl. a
    member-level #if) inside a top-level #if
    .

Notes

Targets the same regression as uber#346, but takes the unify-the-model route rather
than tagging entities onto the import block.

https://claude.ai/code/session_018WBhuzn7RkfYMWKA9gYF14

Conditional compilation (#if/#elseif/#else) was modeled twice -- IfMacroModel
for member-level blocks and ConditionalImportBlock for imports -- with the
directive-emitting switch duplicated between IfMacroTemplate and ImportsHandler.
A side effect of that split (introduced in uber#328) is a regression: EntityVisitor
treated every non-fileMacro top-level #if as import-only and returned
.skipChildren, so protocols/classes declared inside a top-level #if were never
discovered and no mock was generated.

This unifies the structure and fixes the regression:

- Add a generic ConditionalBlock<Leaf> and centralize directive emission on
  IfClauseType.directiveLine(indent:)/endIfLine(indent:), removing the two
  duplicated switches.
- Reshape IfMacroModel as a thin wrapper over ConditionalBlock<(String, Model)>;
  member-level #if output is byte-identical.
- Replace ConditionalImportBlock with ConditionalBlock<ImportContent>.
- Parse a top-level #if into a TopLevelConditionalLeaf union (import / entity /
  nested), discovering declarations and tagging them with their clause. Entities
  flow through normal resolution (so their members -- including nested
  member-level #if -- are fully generated), and renderConditionalBlocks re-wraps
  each generated mock in the original #if/#elseif/#else directives.

SwiftIfConfig is intentionally not used: it resolves the active branch for a
known configuration, whereas mock generation must preserve every branch.

Tests: all 160 existing tests stay green (member-level and import #if behavior
unchanged); adds TestConditionalCompilation covering top-level #if protocols,
#if/#elseif/#else, mixed import+declaration, nested #if, and class members
(incl. a member-level #if) inside a top-level #if.

Claude-Session: https://claude.ai/code/session_018WBhuzn7RkfYMWKA9gYF14
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