lolgear
(Dmitry Lobanov)
1
Well, I have a pretty big component.
It has parts that are very similar.
I would like to add documentation to each part, but in this case I have to copy documentation.
I see one possibility: Add protocols.
But!
These protocols are necessary only for documentation and I don't want to expose them to others.
So, this story is all about namespaces for protocols, yes. But I would like to know if it is possible to declare protocol as internal or fileprivate and to make it reachable to some types.
So, possible solution would be:
Protocol.swift
fileprivate protocol DocumentationProtocol {
/// Print current value
func printValue()
}
/// Types Adoption
/// Printer1 and Printer2 are structs or enums
extension Big.Namespace.By.Enums.Printer1: DocumentationProtocol {}
extension Big.Namespace.By.Enums.Printer2: DocumentationProtocol {}
I don't think there is a way to do that. Only SwiftUI seems to do that with the View.body property in internal types (where Body == Never), but I don't think it's a publicly documented feature. Also, in apple frameworks and the Standard Library, identifiers prefixed with _ are automatically hidden, but unlike SwiftUI's body property (in internal types), they can be accessed.
For example, in the String when autocomplete suggests properties and methods:
"myString".
// String self
// Void encode(to: Encoder) throws
// ...
In the above autocomplete list, _guts is omitted.
But this:
"myString"._guts
is perfectly valid.
lolgear
(Dmitry Lobanov)
3
So, Apple forced us to split code into frameworks to use access control to avoid namespace collapse.
I tried to prefix protocol with __MyProtocol, but it appeared in autocomplete, yes.
Unfortunately there is no public markup feature available to library authors to signify that a given identifier should be hidden from autocomplete.
xwu
(Xiaodi Wu)
5
Sure, you can certainly conform public types to internal protocols. Not sure if the documentation itself will also be treated as internal, though.
But taking a step back, if you have several types that share a common API, to the point where even the documentation is shared (so they must have the same semantics as well as syntax), why not expose a public protocol? It seems like your users could write useful generic algorithms with them.
lolgear
(Dmitry Lobanov)
6
No, it is only for internal usage in a team, so, anybody in a team could read it and understand what is going on. Not sure if this code will be changed by someone else.
These parts of component semantically close, yes, and it is so frustrating to copy-paste documentation.
If you structure the project like the following, does it have the effect you want?
Package.swift:
// swift-tools-version:5.2
import PackageDescription
let package = Package(
name: "Library",
products: [
.library(name: "Library", targets: ["Library"]),
],
targets: [
// The main product library.
.target(name: "Library", dependencies: ["Protocol"]),
// The internal protocol; not part of the product.
.target(name: "Protocol", dependencies: []),
// An example client.
.target(name: "Client", dependencies: ["Library"])
]
)
Sources/Protocol/Protocol.swift:
public protocol Protocol {
/// Does something.
func doSomething()
}
Sources/Library/Library.swift:
import Protocol
public struct Conformer: Protocol {
public init() {}
public func doSomething() {}
}
Sources/Client/Client.swift:
import Library
func use() {
let conformer = Conformer()
conformer.doSomething()
// ✓ Compiles.
// ✓ ⌥‐Click displays “Does something.”
let `protocol` = conformer as? Protocol
// ✗ Compiler error: “Use of undeclared type 'Protocol'”
}
lolgear
(Dmitry Lobanov)
8
I don't have enough resources to separate whole project into mini-libraries. Main point is simple solution inside one project, not a separate library for client. Of course, if you have libraries, this question will be solved by access control.