SwiftTypeReader - You can gather type definitions from Swift source code.

Overview

SwiftTypeReader

You can gather type definitions from Swift source code.

Example

            let reader = Reader()

            let source = """
struct S {
    var a: Int?
}
"""
            let result = try reader.read(source: source)

            let s = try XCTUnwrap(result.types[safe: 0]?.struct)
            XCTAssertEqual(s.name, "S")

            XCTAssertEqual(s.storedProperties.count, 1)
            let a = try XCTUnwrap(s.storedProperties[safe: 0])
            XCTAssertEqual(a.name, "a")

            let aType = try XCTUnwrap(a.type?.struct)
            XCTAssertEqual(aType.name, "Optional")
            XCTAssertEqual(aType.genericsArguments.count, 1)

            let aWrappedType = try XCTUnwrap(aType.genericsArguments[safe: 0]?.struct)
            XCTAssertEqual(aWrappedType.name, "Int")

Development

Design consideration

This library doesn't distinguish type descriptor and concrete type. It make implementation simple but ugly especially when generic argument application happens.

Unsupported language features

Class

class C {}

Computed properties

struct S {
    var x: Int { 0 }
    var y: Int {
        get { _y }
        set { _y = newValue }
    }
    var _y: Int = 0
}

Methods

struct S {
    func f() {}
}

Variable without type annotation

struct S {
    var a = 0
}

Function types

struct S {
    var f: () -> Void
}
Comments
  • Reader.readの返り値にはそのreadで読み取ったものを返してほしい

    Reader.readの返り値にはそのreadで読み取ったものを返してほしい

    現在のReader.readModuleを返しているが、これはReaderのプロパティにそのまま生えてるmoduleと同一であり、情報としては嬉しくない。 その1回のreadで読み取った型などのセットを返してあげると、使う側でファイルやディレクトリ単位で読み込まれたものを管理できて便利だと思いました。

    opened by sidepelican 3
  • Swiftコンパイラを参考に大改修する

    Swiftコンパイラを参考に大改修する

    SType は型宣言それ自体と型参照が隠蔽されているので使いづらい。

    Swiftの意味論をうまくコードで表現する設計としては、 本家コンパイラの実装が参考になる。

    最近出版されたSlavaの本 (https://forums.swift.org/t/compiling-swift-generics-part-i/60898) は、 それを学ぶためにとても役に立つ。 この本をガイドにしつつ、コンパイラのソースを読む事で、理解を深める事ができそうだ。

    ある程度深まったら、参考にして大改修する。

    opened by omochi 2
  • Contextの導入

    Contextの導入

    やったこと

    現在 Modules となっている型を変更する。 Readerの出力はContextに影響を与える。

    現在はModulesをweakで保持していて、 それがnilの場合に例外を投げているが、 それがあちこちに伝搬してよくわからないthrowsがはびこっている

    Modulesの生存を管理するのはプログラマ責任で、 動的な入力に依存しないので、 論理バグと考えてクラッシュするように変更する。


    APIの変化

    従来は、指定しない場合 Modules が自動で作られ、Reader.read から返されていた。 これをretainしないと例外が飛んだりした。

    新仕様では、Contextの生成は明示的に必要とした。


    他でやること

    Locationは宣言レベルの構造を規定するので、 ソースコードは必ずモジュールに所属してるため、 必ずモジュールはまず持っている。 これを静的に表現する。

    opened by omochi 1
  • ジェネリックコンテキスト配下の型を表現できない

    ジェネリックコンテキスト配下の型を表現できない

    下記コードにおいて、

    struct G<T> {
      struct A {}
    }
    

    G<X>.AG<Y>.A は型システムにおいて異なる型だが、 現状の設計だと表現できない。

    Location という似たようなコンセプトが導入されているが、 これは記述的な宣言レベルの構造を表す情報なので、型パラメータを取れない。

    例えば上記の場合、 A を表す STypelocation は、 main.G になっているが、型パラメータは持たない。

    一方、TypeSpecifier というコンセプトがある。 これは型参照なのでパスにパラメータを埋められるので、 main.G<X>.A といった表現を持てる。

    しかし、このジェネリックコンテキスト付きのパス情報は SType 自身には付与できない。

    SType には genericArguments プロパティで自身のジェネリック引数を表現するコンセプトがある。 ここで、パラメータ型とコンクリート型は、SType で統合されていて、 パラメータを取る型の状態と、パラメータが埋まった状態を表現できる。

    例えば、 G<GenericParameterType(T)> の状態はパラメータを取る前のジェネリックな型を表現している。 G<StructType(X)> はパラメータを受け取った後の具体化された型を表現している。

    ジェネリックコンテキストの表現は難しいが、 LocationElement.type が型パラメータ引数も表現できるようにしてしまえば一応表せる。

    Location が記述的なコンセプトだったが、 意味的なコンセプトに拡張されることになる。 なにか問題は無いだろうか・・・?

    opened by omochi 1
  • Use original SwiftSyntax

    Use original SwiftSyntax

    Issue

    Xcode 14.0 beta (14A5228q) 及びSwift 5.7でBinarySwiftSyntaxが利用できなくなった。( https://github.com/omochi/BinarySwiftSyntax/issues/5 ) その影響でこのパッケージもビルドできなくなっている。

    Fix

    本家のSwiftSyntaxを使う。

    本家のSwiftSyntaxは最新のリリースから _InternalSwiftSyntaxParser.dylib を同梱するようになり、実行環境のXcodeに依存しなくても良くなった。

    https://github.com/apple/swift-syntax/releases/tag/0.50600.1

    opened by sidepelican 1
  • Search other module's type information

    Search other module's type information

    課題

    TypeResolver が型を探索する際、すでに読み込み済みの他モジュールの型情報を探索してくれない問題を修正します。 具体的には、下記のようなモジュール構成の場合に、main.P.f の返り値である E の型情報が読み取れなくなっています。 E の型名だけは取り出せるのでこれまでは課題が顕現しませんでしたが、 E がenumかどうか、の検証を始めると課題が浮かび上がりました。

    // MyLib モジュール
    public enum E {
       case a
    }
    
    // main モジュール
    import MyLib
    
    protocol P {
       func f() -> E
    }
    

    解決方法

    現状では Swift モジュールだけハードコードで探索されている部分を自身の親 Modules 全体を読み込むように変更します。

    その他

    課題はこれで解決しますが、依然厳密さは足りていない状況で、ファイル単位での import declの有無を検証しないため、本来import文が不足していて読み取れないはずの型を読み取れてしまうことがあります。 現状のSwiftTypeReaderではファイル単位で型定義のスコープを管理する仕組みがないので、これは一旦諦めて Modules に読み込まれたモジュールは全てimportされているという前提ということにしています。

    opened by sidepelican 1
  • Use BinarySwiftSyntax 13.0

    Use BinarySwiftSyntax 13.0

    https://github.com/omochi/SwiftTypeReader/pull/7#discussion_r743528385 への対応です。

    BinarySwiftSyntax側のmainブランチにSwiftSyntax-Xcode13.0が生えてから正しく動作可能になります。 PR: https://github.com/omochi/BinarySwiftSyntax/pull/3

    exclude: ["Resources"]Resourcesディレクトリがそのそも存在しなくて警告が出ていたので削除しました。

    opened by sidepelican 1
  • TypeLocの削除

    TypeLocの削除

    TypeLocはコンパイラ内部で利用されているTypeReprもしくはTypeを保持する型。

    多くの場合にはTypeReprとして機能しているが、 コンパイラ内部ではDeclを動的に構成する際に、 手元の解決済みの型を直接設定する場合に使われている。

    知る限りでは、Protocolの Self 型の conformance protocol として プロトコル自身を設定するところで、 プロトコル型を直接埋め込んでいた。

    しかし、動的に構成可能で、TypeReprで表現できない型は存在しないように思われるので、 そこに型があるならTypeReprで表現して格納できると思う。

    その方がデータ構造がシンプルになり理解しやすいので、 いったん削除してみる。

    opened by omochi 0
  • As cast

    As cast

    asStruct などのキャストプロパティを追加します。

    as? 演算子は、 as? any NominalTypeDecl と書くべきところで as? any NominalType と書いてしまうなどのミスが生じたり、 Xcodeが変換候補を提供しない、式を丸括弧で包む必要がある、などの欠点があります。

    それを補うため、補間によって候補を列挙したり、入力ミスをしない方法を提供します。

    opened by omochi 0
  • DeclとReprの導入

    DeclとReprの導入

    本家Swiftコンパイラを参考にデータ構造を組み替える


    依存値のキャッシュ計算+サイクル検出はc2tsでも必要になったので、 Request Evaluatorを導入する


    ~~コンパイラと違ってレジリエンスは要らないため、 エラー値は導入しない事にする。 不正なコードが入力されて意味解決に問題がある場合、例外で停止する。 Requestの依存があるのでほとんどがthrowsになるだろう。~~

    SwiftTypeReaderのレイヤーだと、不明な型はそのまま通したほうが扱いやすい。 後段のC2TSのレイヤーで、エラーにするとかtypeMapですり替えるとか、 そういう対応がありえる。

    型推論の未解決型変数に unresolved type が使われているので、 type reprの未解決は unknown type に名前を変更する。


    Typeは値型にしてみる。 本家同様にimmutable classにした場合と比べると、 キャッシュのキーに使う場合にハッシュ計算コストがかかってしまう。 逆にimmutable classは生成時にキャッシュを通す必要が生じるが、 依存値を引く時のキャッシュはポインタで済む。


    Declはクラスにしてツリー構造を表現する。 parentへの弱参照も入れる。 こうすることでLocationで無理する必要がなくなる。

    DeclはASTインスタンスであり、 静的なオブジェクトになる。

    Typeは必要に応じてDeclを参照する。 概ねそれ+GenericArg だけのオブジェクトになる事が多いだろう。


    NominalとBoundGenericNominalの区別は入れない。 必要ないと思うんだよな。 シンプルに済ませられる。


    Reprも値型にしてみる。 これこそキャッシュを考えるとclassが望ましいが・・・


    archetypeは導入しない 難しそうなので なくても十分な気がする


    ASTScopeは導入しない Decl treeだけでいけるきがする


    TypeReprも読めない可能性がある。 そういう場合に、そういうフィールドだけ読み飛ばすほうがマシなので、 やはりレジリエンスは必要・・・

    opened by omochi 0
  • Add ImportReader

    Add ImportReader

    需要

    読み取ったソースコードが他モジュールへのimport文を持っていた場合に、コード生成した結果のファイルにも同様のimport文を書きたくなるときがある。

    例:

    • Entityモジュール
    public struct UserID {}
    
    • APIDefinitionモジュール
    import Entity
    
    public protocol FooServiceProtocol {
        func foo() -> UserID
    }
    
    • 生成コード
    // import Entity(ここにimportをいい感じに書けるようにしたい)
    
    struct FooProvider {
        func foo() -> UserID { ... } // compile error! UserID is not found
    }
    

    解決方法

    Module から、そのモジュールがimportしている定義を取得できるようにする

    悩み

    • SwiftTypeReaderは名前的にはTypeを読み取るのが仕事であるため、importDeclを読み込みのは責務を超えている?
      • このような微妙に手が届いてないケースにはコード生成コードがSwiftSyntaxを直接使うべき?
      • あるいは利便性を考慮してSwiftTypeReaderで読めるようにしてあげるべき?
    opened by sidepelican 0
  • extensionの導入

    extensionの導入

    extensionがあると、

    struct GenericID<T> {}
    
    extension GenericID: Codable where T: Codable {}
    

    というパターンが正しく認識できるようになる。 conditional conformanceを解決するのは、 associated typeの解決もある場合、難しすぎるけど・・・

    opened by omochi 0
Releases(2.3.1)
Owner
omochimetaru
omochimetaru
Tutorials from sparrowcode.io website. You can add new, translate or fix typos. Also you can add your apps from App Store for free.

Страницы доступны на sparrowcode.io/en & sparrowcode.io/ru Как добавить свое приложение Добавьте элемент в json /ru/apps/apps.json. Если ваше приложен

Sparrow Code 30 Nov 25, 2022
You can monitor your APIs and websites on your menubar. Gives you status code 🎉 Cool & good

Hope not. Monitor your APIs and websites on your menubar. For macOS. Right now! YyeeeHav!

Steven J. Selcuk 10 Nov 29, 2022
High-quality source code, easy implementation

High-quality source code, easy implementation

T.M 0 Nov 8, 2021
The source code to the civic tech project Öppna Skolplattformen.

Give us a ⭐ if you appreciate what we do! Öppna skolplattformen We are parents who got fed up with Skolplattformen, the City of Stockholm's school adm

Skolplattformen.org 784 Dec 29, 2022
The source code to How to build a news app with react native 📰

Royal News · The source code to How to build a news app with react native article on NimreyCode, medium, and dev.to. Requirements: Android Studio or X

Mohammed Salman 96 Aug 16, 2022
Gett's Design System code generator. Use Zeplin Styleguides as your R&D's Single Source of Truth.

Prism is a Design System code generator developed by the team at Gett ?? . Synchronizing design teams with engineering teams is a huge challenge. As t

Gett 346 Dec 31, 2022
ESP source code for Free Fire (iOS jailbreak)

ESP FreeFire ESP source code for Free Fire (iOS jailbreak, Free Fire version: 1.93.1). This source is for learning purpose only, please do not use it

Huy Nguyen 11 Dec 25, 2022
The iOS pod which can collect profile data to detect code coverage.

CodeCoverageKit Installation CodeCoverageKit is available through CocoaPods.

木子 2 Sep 29, 2021
A zero-code template app that demonstrates how to use TheraForge's APIs and can be used for fast prototyping

TheraForge MagicBox 1.0.0-beta The Open TheraForge (OTF) MagicBox app is a template for creating digital health solutions that help people better mana

TheraForge 0 Dec 23, 2021
Sonic language: Heavily inspired by Swift, but compiles to C so you can use it anywhere.

Sonic Sonic programming language: Heavily inspired by Swift, but compiles to C so you can use it anywhere. Brought to you by Chris Hulbert and Andres

Sonic Language 27 Apr 8, 2022
A Simple way help you drop or drag your source (like UIImage) between different App.

A Simple way help you drop or drag your source (like UIImage) between different App.

逸风 13 Nov 24, 2022
It can help you to prepare yourself for interview 🚀

Note I will keep updating the content table as I am going through, keep connected to stay updated ! Contribution You can contribute here as well, crea

Mohammad Yasir 4 Mar 21, 2022
🌳 Environment – a nicer, type-safe way of working with environment variables in Swift.

?? Environment Welcome to Environment – a nicer, type-safe way of working with environment variables in Swift. Usage Access Environment Variables The

Will Lisac 31 Dec 17, 2022
Type-based input validation.

Ensure Type-based input validation try Ensure<PackageIsCool>(wrappedValue: packages.ensure) Validators A Validator is a type that validates an input.

Build Passed 5 Jan 22, 2022
React Native utility library around image and video files for getting metadata like MIME type, timestamp, duration, and dimensions. Works on iOS and Android using Java and Obj-C, instead of Node 🚀.

Qeepsake React Native File Utils Extracts information from image and video files including MIME type, duration (video), dimensions, and timestamp. The

Qeepsake 12 Oct 19, 2022
MQTagged provides a Tagged structure which helps differentiating between values of the same type.

MQTagged provides a Tagged structure which helps differentiating between values of the same type.

Miquido 2 Jun 29, 2022
Quotes shows you famous quotes to, hopefully, give you enlightment

"Quotes" shows you famous quotes to, hopefully, give you enlightment! You can also save/favorite the quotes that you liked to review later or show to your friends!

Filipe Kunioshi 1 Mar 7, 2022
Start your next Open-Source Swift Framework 📦

SwiftKit enables you to easily generate a cross platform Swift Framework from your command line. It is the best way to start your next Open-Source Swi

Sven Tiigi 821 Dec 28, 2022
A Swift playground that comes pre-loaded with Plot, that can be used to explore the new component API.

PlotPlayground A Swift playground that comes pre-loaded with Plot, so that you can quickly try out the library and its new, SwiftUI-like API for build

John Sundell 48 Jan 5, 2023