jpsim / SourceKitten

An adorable little framework and command line tool for interacting with SourceKit.
MIT License
2.31k stars 226 forks source link

Building an exhaustive list of a class dependencies: missing some information ? #807

Closed jrmybrault closed 9 months ago

jrmybrault commented 9 months ago

Hello 👋 I'm totally new to SourceKitten, so sorry if the question is trivial. What I'm trying to achieve is a Swift script that would output an exhaustive list of a class dependencies, no matter where or how they are declared. I try to make this work with the dummy class definition below:

final class ClassExample {

    private let dependencyA: ProtocolA = ImplementationA.shared

    private let dependencyB: ProtocolB
    private let dependencyC: ProtocolC
    private var dependencyD: ProtocolD?

    init(
        dependencyB: ProtocolB,
        dependencyC: ProtocolC,
        dependencyD: ProtocolD?
    ) {
        self.dependencyB = dependencyB
        self.dependencyC = dependencyC
        self.dependencyD = dependencyD
    }

    convenience init(
        dependencyB: ProtocolB = ImplementationB.shared,
        dependencyC: ProtocolC = ImplementationC()
    ) {
        let dependencyE = ImplementationE()
        let dependencyD = ImplementationD(dependencyE)

        self.init(
            dependencyB: dependencyB,
            dependencyC: dependencyC,
            dependencyD: dependencyD
        )
    }
}

What I would expect to get for this example is:

Using SourceKitten, I was able to load the structure of the file containing the class and get its substructure. From this, I'm able to pull most dependencies, except the ones that are neither injected nor provided through a call expression:

Do I need to build or parse the structure in a particular way to have these "missing" info, like adding some options ? Or maybe is this just not possible at all ?

johnfairh commented 9 months ago

SourceKit doesn't include anything for assignment syntax nodes in its doc structure so those lines you mentioned are not visible. #700, #704.

(Note let dependencyE = ImplementationE() has a function call expression in it, as you say, which does get included.)

Probably best to try and use SwiftSyntax instead which is used by the compiler itself and definitely won't miss stuff out.

jrmybrault commented 9 months ago

Oh I see, I'll have a look at SwiftSyntax then ! Thanks @johnfairh 🙏