Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/zadr/swift-module-diff
SwiftSyntax-based command line tool to analyze and compare Swift module interface through .swiftinterface files
https://github.com/zadr/swift-module-diff
swift xcode
Last synced: 22 days ago
JSON representation
SwiftSyntax-based command line tool to analyze and compare Swift module interface through .swiftinterface files
- Host: GitHub
- URL: https://github.com/zadr/swift-module-diff
- Owner: zadr
- License: mit
- Created: 2023-06-19T05:02:08.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-01-01T02:30:08.000Z (10 months ago)
- Last Synced: 2024-01-01T11:30:11.615Z (10 months ago)
- Topics: swift, xcode
- Language: Swift
- Homepage: https://github.com/zadr/swift-module-diff
- Size: 287 KB
- Stars: 5
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
### swift-module-diff
#### What should this do
Given a pair of Xcode apps (such as Xcode.app and Xcode-beta.app):
1. Scan through known SDKs (iOS, macOS, watchOS, tvOS, visionOS)
2. Compile a list of supported architectures and `swiftinterface` files for each architecture
3. For each `swiftinterface` file, parse it with [SwiftSyntax](https://github.com/apple/swift-syntax)
4. Repeat for the other copy of Xcode
5. Compare the two results, noting what frameworks are introduced, along with modifications to types, and members (additions, deprecations, etc)
6. Output some basic HTML to see all the frameworks with modifications on one page
7. Be able to click into a framework to see all modifications to types, and members (additions, deprecations, etc)#### Things Left To Do
Swift is a big and evolving language, so it is likely that edge-cases are broken, or lesser-used features are missing. This tool is still under development, and some known gaps are:- [ ] default values in function parameters
- [ ] tracking headerdoc changesAnd there are some other features that could be nice to have, such as:
- [ ] Using a DSL to generate HTML
- [ ] Making HTML output more readable, such as by:
- Selectively hiding attributes, or parameters of attributes (i.e. macOS @availability parameter isn't helpful on iOS API diff)
- [ ] Making HTML interactable, such as by linking to more docs, or adding an option to expand all details with one click
- [ ] Filtering output by platform, architecture, or framework
- [ ] Extending CLI to expose diffing swiftmodule directories outside of Xcode.app bundles#### But Why?
Having everything that changed one one page can be niceIf more information than base additions / deprecations / removals is needed, official documentation is always available
#### Inspiration
Code Workshop's [`objc-diff`](http://codeworkshop.net/objc-diff/)#### Notes on development
As a hypothetical, consider adding support for a new `magic` keyword that can appear before `func` declarations in `class` contexts.Starting with a new `Magic.swiftmodule` containing the following:
```
class C {
magic func x(y: Int = 1) -> Int { 0 }
}
```Running with `--single-file` flag set: `swift-module-diff --single-file=/path/to/Magic.swiftmodule` will parse a single file.
From there, breakpoints make for a quick way to the AST. For example, in `FunctionTracker.visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind`,
running `vo node` will produce something that looks like this:```
(lldb) vo node
(SwiftSyntax.FunctionDeclSyntax) node = FunctionDeclSyntax
├─attributes: AttributeListSyntax
├─modifiers: DeclModifierListSyntax
│ ╰─[0]: DeclModifierSyntax
│ ╰─name: keyword(SwiftSyntax.Keyword.magic)
├─funcKeyword: keyword(SwiftSyntax.Keyword.func)
├─name: identifier("x")
├─signature: FunctionSignatureSyntax
│ ├─parameterClause: FunctionParameterClauseSyntax
│ │ ├─leftParen: leftParen
│ │ ├─parameters: FunctionParameterListSyntax
│ │ │ ╰─[0]: FunctionParameterSyntax
│ │ │ ├─attributes: AttributeListSyntax
│ │ │ ├─modifiers: DeclModifierListSyntax
│ │ │ ├─firstName: identifier("y")
│ │ │ ├─colon: colon
│ │ │ ├─type: IdentifierTypeSyntax
│ │ │ │ ╰─name: identifier("Int")
│ │ │ ╰─defaultValue: InitializerClauseSyntax
│ │ │ ├─equal: equal
│ │ │ ╰─value: IntegerLiteralExprSyntax
│ │ │ ╰─literal: integerLiteral("1")
│ │ ╰─rightParen: rightParen
│ ╰─returnClause: ReturnClauseSyntax
│ ├─arrow: arrow
│ ╰─type: IdentifierTypeSyntax
│ ╰─name: identifier("Int")
╰─body: CodeBlockSyntax
├─leftBrace: leftBrace
├─statements: CodeBlockItemListSyntax
│ ╰─[0]: CodeBlockItemSyntax
│ ╰─item: IntegerLiteralExprSyntax
│ ╰─literal: integerLiteral("0")
╰─rightBrace: rightBrace
```which shows that `magic` is a declaration modifier.
`swift-module-diff` tracks member types (functions, vars, typealiases, and so on) with the `Member` type, and `Member` includes a `Decorator` enum with results stored in a `decorators` set.
All together, the results will look something like [this](https://github.com/zadr/swift-module-diff/commit/85bf1fb3fdbeb5982900264dac0ba4ed722976fc) commit that added support for tracking `optional` conformances of members within protocols.