[WIP] Work towards SwiftExtract, a reusable Swift analysis module#774
Draft
ktoso wants to merge 13 commits into
Draft
[WIP] Work towards SwiftExtract, a reusable Swift analysis module#774ktoso wants to merge 13 commits into
ktoso wants to merge 13 commits into
Conversation
10143bc to
c4ebf47
Compare
This will take a while to finish up but this introduces a new core foundational module called `SwiftExtract` that allows for analysis of swift code into an analysis result that then source generators -- such as swift-java can use. This is to prepare reuse from other language generators, with a strong well maintianed analysis core that swift-java has spearheaded here. This is a massive "move stuff around" so reviewing everyting might be hard but the long term benefit will be massive.
ac9071e to
e23ae2c
Compare
Introduce SwiftExtractConfiguration protocol (neutral AccessLevelMode / Logger.Level) so SwiftExtract no longer depends on SwiftJavaConfigurationShared; Configuration conforms via JExtractSwiftLib/Configuration+SwiftExtract.swift. Gate operator extraction behind config.extractsOperators (default off -> Java unchanged). Expose ExtractedNominalType.declAttributes / declGroupSyntax. All SwiftExtractTests + JExtractSwiftTests pass.
…zer extraction Two opt-in, language-neutral knobs on `SwiftExtractConfiguration` (both default to the prior behavior, so the Java path is unchanged): - `availableImportModules: Set<String>` — module names treated as importable when resolving `#if canImport(<module>)`. The analyzer wraps its build configuration in an `ImportOverlayBuildConfiguration` so declarations guarded behind `#if canImport(MyModule)` are extracted (e.g. another language code generator may declare its runtime module importable here, even when the static build config doesn't otherwise know about it). - `extractsGenericTypeInitializers: Bool` — extract initializers of generic nominal types even when not specialized. swift-java skips these by default (an open generic isn't directly constructible); other language code generators that specialize generics in a post-analysis pass need the base type's initializers available to clone onto the specialization.
The Foundation/FoundationEssentials known-module source files declared Data, Date, and UUID, but URL was missing — so any user code using URL (e.g. `func getHost(url: URL)`) failed to import with an unresolved-type warning, dropping the function silently. Other consumers of the language-neutral analyzer rely on URL for bridging tests; add it alongside the other Foundation built-ins, declaring just the failable `init(string:)` and `absoluteString` property the language-neutral analyzer needs to resolve uses.
…Modules `DefaultSwiftExtractConfiguration` exposed `extractsOperators` and `availableImportModules` as stored properties with init parameters but omitted `extractsGenericTypeInitializers`, so callers using the default config could not opt into it programmatically and silently fell back to the protocol-extension default of `false`. Add it as a stored property and init parameter alongside the other two. Also add four targeted tests in `AnalysisResultTests` exercising the non-default paths of the two analysis-shaping knobs: - `unspecializedGenericInitializersAreSkippedByDefault` and `extractsGenericTypeInitializersKeepsBaseInitializers` confirm the base `Tank<Fish>` flips between 0 and 2 initializers as the knob toggles. - `canImportGuardedDeclsAreSkippedWhenModuleNotAvailable` and `availableImportModulesActivatesCanImportClause` confirm `#if canImport(MadeUpModule)`-guarded types are extracted only when the module is listed in `availableImportModules`.
The `Resources/dummy.json` placeholder exists only so SwiftPM emits a
`Bundle.module` for the SwiftExtract target — the real
`static-build-config.json` is generated at build time by
`_StaticBuildConfigPlugin`. Note that on the `.process("Resources")`
line so a future reader doesn't try to delete the empty-looking file.
… on tests Three small review-driven cleanups: - `SwiftAnalyzer` doc: drop the parenthetical example in the lead-in and fix "language-neutral" to "output is language-neutral"; drop the "useful for tests / no code generation" sentence on the static `analyze` convenience. - `SwiftExtractConfiguration`: remove the protocol-extension defaults for `extractsOperators` and `extractsGenericTypeInitializers`. Both are semantic decisions about what the analysis layer should do for a given language target; making conformers state their position keeps a new language code generator from silently inheriting the Java-specific defaults. `Configuration` (swift-java) now declares both as `false` explicitly. - `SwiftExtractTests`: drop the `.swiftLanguageMode(.v5)` override; the target compiles and runs cleanly under the package's default Swift 6 mode.
…hared Reviewer asked: "why does swift-java need to map at all, can it not use this exact enum?" — yes, after introducing a small shared target. `SwiftJavaConfigurationShared` is intentionally lightweight (stdlib + Foundation only): it must be symlinked into each plugin's source tree because SwiftPM plugins can't have target dependencies. Pulling SwiftSyntax in via `SwiftExtract` would balloon plugin builds. Instead, introduce a sibling `SwiftExtractConfigurationShared` target that holds nothing but the small `AccessLevelMode` enum. Both `SwiftExtract` and `SwiftJavaConfigurationShared` depend on it; the plugin symlink discipline (`Plugins/PluginsShared/SwiftExtractConfigurationShared`) mirrors the existing `SwiftJavaConfigurationShared` symlink. Effects: - `AccessLevelMode` is the single, shared enum. swift-java's `Configuration` uses it directly via `@_exported import`, retiring `JExtractMinimumAccessLevelMode` and the four-line mapping switch in `Configuration+SwiftExtract.swift` (now an identity passthrough). - `SwiftJavaConfigurationShared/Configuration.swift` guards the import with `#if canImport(SwiftExtractConfigurationShared)` so plugin builds (which inline the file alongside `AccessLevelMode.swift` via symlink rather than as a separate module) still compile. - `AccessLevelMode` gains `@nonexhaustive` (SE-0487, gated with `#if compiler(>=6.2)`) per reviewer request, so adding cases in the future is non-breaking. `Codable` conformance is added so it can replace `JExtractMinimumAccessLevelMode` in the on-disk `Configuration` JSON without changing the wire format. - The CLI's `@Option var minimumInputAccessLevelMode` and the `ExpressibleByArgument` conformance switch over to `AccessLevelMode` accordingly.
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
🚧 🚧 🚧 Early WIP, not worth reviewing yet 🚧 🚧 🚧
This will take a while to finish up but this introduces a new core foundational module called
SwiftExtractthat allows for analysis of swift code into an analysis result that then source generators -- such as swift-java can use.This is to prepare reuse from other language generators, with a strong well maintianed analysis core that swift-java has spearheaded here.
This is a massive "move stuff around" so reviewing everyting might be hard but the long term benefit will be massive.