Skip to content
This repository has been archived by the owner on Jun 1, 2023. It is now read-only.

Show all or none conformances in the declaration #124

Open
sindresorhus opened this issue May 21, 2020 · 7 comments
Open

Show all or none conformances in the declaration #124

sindresorhus opened this issue May 21, 2020 · 7 comments
Labels
design Functionality with a design component question Further information is requested

Comments

@sindresorhus
Copy link

If a type has conformances defined both in the main type declaration and in extensions, swift-doc only shows the ones defined directly in type in the docs declaration.

For example, this type conforms to Hashable and Codable directly in the type, but also conforms to many other things in extensions. However, in swift-docs, it only shows:

Screenshot 2020-05-21 at 17 24 33

Which feels a bit misleading, as it conforms to other types too, which are documented in the "Conforms To" section, but that can easily be missed and confuse users. I don't see why conformances directly on the type are more important than ones defined in extensions.

My recommendation is to either show all conformances or none in the declaration code block.

@mattt
Copy link
Contributor

mattt commented May 23, 2020

I agree that it's confusing when a type's declaration is at odds with its actual inheritance graph. However, I don't see a good way to change the declaration itself to resolve this when we don't know the types in the inheritance list.

  • None: We know that the first type after the colon is a protocol in the case of a structure, but for a class, you don't know if an unknown type is its superclass or a protocol. There's also no way to know in the case of an enumeration; it could be a protocol, or it could be its raw value type (it can be something other than a built-in String / Int types). For me, a class's superclass and an enumeration's raw value type are essential pieces of information, and their absence would be conspicuous.
  • All: Right now, we can't definitively determine all of the protocols that a type conforms to. Even if we could, having that all in the declaration could get overwhelming. And at least speaking personally, I give some thought into which protocols I put in the declaration vs. in an extension, so I'd miss that.

My goal was for the inheritance graph image to be the primary interface for understanding and navigating type relations. Is there anything we could add or change to the UI that could help reconcile this confusion?

@mattt mattt added design Functionality with a design component question Further information is requested labels May 23, 2020
@sindresorhus
Copy link
Author

you don't know if an unknown type is its superclass or a protocol

Is this a permanent limitation or could it be improved in the future?

Any reason SwiftDoc is using swift-syntax and not SourceKit? I assume SourceKit would have such information.

@MaxDesiatov
Copy link
Contributor

MaxDesiatov commented May 24, 2020

Is this a permanent limitation or could it be improved in the future?

Sorry for interjecting, but my understanding is that it requires the AST that swift-doc operates on to be fully annotated by a type checker and have all symbols resolved. You probably could get that by running swift build on the project and looking at the produced index store with something like SwiftIndexStore. That's not very portable though (IndexStore is its own different thing built in a special way), and I didn't find the available documentation for IndexStore to be paricularly good.

Shameless selfish plug, one could also pick up Typology and improve its own type checker, which is written in pure Swift, as opposed to IndexStore's C++. I don't know what is the best way long term, I personally would prefer IndexStore's documentation to be improved and more code in it to be migrated from C++ to Swift. Typology was created primarily as an educational project, but maybe it could help someone to get their feet wet with the whole area of type checking/symbol resolution.

@mattt
Copy link
Contributor

mattt commented May 24, 2020

@sindresorhus

you don't know if an unknown type is its superclass or a protocol

Is this a permanent limitation or could it be improved in the future?

This is a temporary limitation of only using a syntactic parse.

Any reason SwiftDoc is using swift-syntax and not SourceKit? I assume SourceKit would have such information.

A syntactic parse can be performed without compilation, which means it can run up to several orders of magnitude faster. It's not a complete picture, but it's often more than enough to be useful.

We're exploring using IndexStoreDB in #31 to fill in missing context.

@MaxDesiatov

I've also struggled to work with IndexStoreDB. It could be my own lack of understanding, but I ended up forking and adding a few APIs to access the information I needed (USRs by type, queryable by name and source location). That's still a work-in-progress.

We should treat a compiler-generated artifact like an index store as the canonical source of truth for filling in context, but there's still some low-hanging fruit for improving how we do type inference. The current approach is clearly suboptimal. If you think Typology can help here, I'd be very interested to see a proof of concept.

@sindresorhus
Copy link
Author

A syntactic parse can be performed without compilation, which means it can run up to several orders of magnitude faster.

While performance is nice, docs are usually only generated when releasing a new version of a project and is done in a GitHub Action, so whether it takes 1 second or 1 minute, doesn't really matter, at least for me. Having accurate & comprehensive type information and readable docs is much more important.

@MaxDesiatov
Copy link
Contributor

I ended up forking and adding a few APIs to access the information I needed (USRs by type, queryable by name and source location). That's still a work-in-progress.

@mattt is any of that work public? Would you mind sharing it? I hope I could contribute at some point if so.

@mattt
Copy link
Contributor

mattt commented May 24, 2020

@sindresorhus

The overwhelming feedback I've gotten so far is that speed is swift-doc's killer feature. I agree that speed is less of a concern in a CI setting, but I've heard several complaints about the amount of time it takes to build the Docker image in GitHub Actions (to be clear, I want to speed that up, too).

What I'm saying is that it doesn't have to be an either-or. Similar to how Swift has a -Onone and -O, we can satisfy multiple use cases with a composable architecture.

@MaxDesiatov

Here's my fork: https://github.com/SwiftDocOrg/indexstore-db

Here's my WIP / experimentation from a few weeks back:

let libIndexStorePath = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libIndexStore.dylib"
let library = try IndexStoreLibrary(dylibPath: libIndexStorePath)
let storePath = "/Users/mattt/Code/swiftdoc/Hello/.build/debug/index/store"
let databasePath = NSTemporaryDirectory() + "index_\(getpid())"
let db = try! IndexStoreDB(storePath: storePath, databasePath: databasePath, library: library, waitUntilDoneInitializing: true)
//db.pollForUnitChangesAndWait()
//print(db.allSymbolNames())
//print(db.mainFilesContainingFile(path: "/Users/mattt/Code/swiftdoc/SwiftSemantics/Sources/SwiftSemantics/Declaration.swift"))
let symbolNames = db.allSymbolNames()
db.forEachSymbolOccurrence(byKind: .protocol) { occurrence in
// guard occurrence.location.moduleName == "Hello" else { return true }
print("!!!", occurrence.symbol.usr, occurrence.symbol.name)
// for relation in occurrence.relations {
// print("-", relation.roles, relation.symbol)
// }
// print("")
db.forEachSymbolOccurrence(byUSR: occurrence.symbol.usr, roles: [.all]) {
for relation in $0.relations {
print("-", relation.roles, relation.symbol)
}
return true
}
print("")
return true
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
design Functionality with a design component question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants