Skip to content

Add access modifiers to generated imports#883

Open
arpit-garg-1995 wants to merge 3 commits into
apple:mainfrom
arpit-garg-1995:fix/777-import-access-modifiers
Open

Add access modifiers to generated imports#883
arpit-garg-1995 wants to merge 3 commits into
apple:mainfrom
arpit-garg-1995:fix/777-import-access-modifiers

Conversation

@arpit-garg-1995
Copy link
Copy Markdown

@arpit-garg-1995 arpit-garg-1995 commented Mar 20, 2026

### Motivation

Starting in Swift 6.0, users can enable the InternalImportsByDefault upcoming feature flag, which makes all imports internal by default. However, when users generate code and specify an accessModifier of package or public in their swift-openapi-generator configuration, the generated code fails to build. This occurs because the generated public/package declarations are trying to expose types from modules that are only imported internally. We need a way to cascade the appropriate access modifiers down to the imports so the generated code compiles successfully under Swift 6.0.

Modifications

Modified TextBasedRenderer.swift to propagate the configured accessModifier when generating import statements.

  • When the accessModifier is either .public or .package, the generator now wraps the import statement in an #if compiler(>=6.0) conditional compilation block.
  • Inside the Swift 6.0+ block, the access modifier is explicitly prepended to the import statement (e.g., public import Foo).
  • An #else branch is provided to output the plain import statement (e.g., import Foo) for older compilers, thereby ensuring backward compatibility without requiring additional feature flags.
  • Preserved existing attributes (like @preconcurrency and @_spi) so they are correctly attached regardless of the compiler version.

Result

After these changes, code generated with an access modifier of public or package will compile successfully in Swift 6.0 when the InternalImportsByDefault flag is enabled. The imports will correctly match the access level of the generated code, preventing module visibility mismatch errors, while seamlessly supporting developers on older Swift versions.

Test Plan

  • Unit Testing: Added extensive unit tests in Test_TextBasedRenderer.swift (testImportsWithAccessModifiers) to verify that import statements correctly render the #if compiler(>=6.0) blocks when .public and .package modifiers are supplied.
  • Attribute Preservation: Added test coverage to ensure that complex imports (combining @preconcurrency, @_spi, and specific struct imports like struct Foundation.URL) render their attributes correctly in both the #if and #else branches.
  • Manual Qualification: To manually test, generate an OpenAPI client using accessModifier: public in the openapi-generator-config.yaml, and build the resulting Swift package using the Swift 6 compiler with the InternalImportsByDefault feature flag enabled to ensure no build warnings or errors are thrown.
  • Testing with Act: Passed local medium act pull_request workflow

Copy link
Copy Markdown
Collaborator

@simonjbeaumont simonjbeaumont left a comment

Choose a reason for hiding this comment

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

Thanks for taking the time to open the PR.

I'm sympathetic to the problem and open to a solution here. But I think this has been solved at the wrong layer.

The PR currently does this at the concrete implementation of a renderer and just unilaterally updates all imports to use a given access modifier.

This needs to be done in the types that conform to FileTranslator, e.g. see ClientFileTranslator, which is where the structured Swift representation is determined. You'll see there how access modifiers are used to generate the declarations in the file and where the import statements are defined.

This allows for two things, which we'll need before we can land this PR:

  • Other renderer implementations that may come in the future will get consistent behaviour because we removed the layering violation.
  • We can treat the imports used for the generated API differently from the additionalImports.

@arpit-garg-1995 arpit-garg-1995 force-pushed the fix/777-import-access-modifiers branch from d4b05f7 to 7d9b310 Compare April 27, 2026 14:58
@arpit-garg-1995
Copy link
Copy Markdown
Author

arpit-garg-1995 commented Apr 27, 2026

Support access modifiers on generated imports

Motivation

With the introduction of Swift 6.0's InternalImportsByDefault flag, generated declarations need a way to re-export the symbols they depend on. Supporting the configured access modifier on imports ensures they remain visible to consumers of the generated code when necessary.

Modifications

  • Add accessModifier property to ImportDescription.
  • Update TextBasedRenderer to conditionally render public and package access modifiers on imports.
  • Introduce importDescriptions(adding:) in FileTranslator to automatically propagate the configured access modifier to both built-in and additional imports.
  • Adopt the new import generation logic in ClientFileTranslator, ServerFileTranslator, and TypesFileTranslator.
  • Add unit tests in Test_TextBasedRenderer to verify the correct rendering of imports with different access modifiers, attributes, and OS conditions.

Result

Generated Swift files can now properly emit public import or package import statements when compiled with Swift 6.0 and above, based on the provided configuration.

Test Plan

Unit tests added in Test_TextBasedRenderer.
Testing with Act: Passed local medium act pull_request workflow

@simonjbeaumont
Copy link
Copy Markdown
Collaborator

@arpit-garg-1995 just a heads up that this package only supports Swift 6.1+ now so you don't need to do anything special in the generator to handle older compilers.

Support access modifiers on generated imports

### Motivation

With the introduction of Swift 6.0's `InternalImportsByDefault` flag, generated declarations need a way to re-export the symbols they depend on. Supporting the configured access modifier on imports ensures they remain visible to consumers of the generated code when necessary.

### Modifications

- Add `accessModifier` property to `ImportDescription`.
- Update `TextBasedRenderer` to conditionally render `public` and `package` access modifiers on imports, wrapped within an `#if compiler(>=6.0)` block to maintain compatibility with older compilers.
- Introduce `importDescriptions(adding:)` in `FileTranslator` to automatically propagate the configured access modifier to both built-in and additional imports.
- Adopt the new import generation logic in `ClientFileTranslator`, `ServerFileTranslator`, and `TypesFileTranslator`.
- Add unit tests in `Test_TextBasedRenderer` to verify the correct rendering of imports with different access modifiers, attributes, and OS conditions.

### Result

Generated Swift files can now properly emit `public import` or `package import` statements when compiled with Swift `6.0` and above, based on the provided configuration.

### Test Plan

Unit tests added in `Test_TextBasedRenderer`.
@arpit-garg-1995
Copy link
Copy Markdown
Author

Addressed the latest feedback in this commit.

Modifications

  • Removed the compiler-version conditional around the generated code path.
  • Dropped the special handling for older Swift compilers now that the package only supports Swift 6.1+.

Result

This simplifies the generator logic and aligns it with the package’s current Swift version support.

Test Plan

  • Ran swift test.
  • Testing with Act: Passed local medium act pull_request workflow

@swift-server-bot test this please

@simonjbeaumont simonjbeaumont added the 🆕 semver/minor Adds new public API. label May 5, 2026
@simonjbeaumont
Copy link
Copy Markdown
Collaborator

  • Ran swift test.
  • Testing with Act: Passed local medium act pull_request workflow

Are you sure you got the tests passing locally? They're failing for every Swift version and platform in CI.

@swift-server-bot test this please

Just FYI — this does nothing.

@arpit-garg-1995
Copy link
Copy Markdown
Author

Let me check and confirm. Will update soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🆕 semver/minor Adds new public API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants