-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Traits docs #9048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Traits docs #9048
Conversation
@swift-ci please test |
…ation of traits and wording updates across the API surface
… article to reference traits for using them
@swift-ci please test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking wonderful! Just a few comments for you to check out :)
|
||
Traits, introduced with Swift 6.1, allow packages to offer additional API that may include optional dependencies. | ||
Packages should offer traits to provide API beyond the core of a package. | ||
For example, a package may provide an experimental API, optional API that requires additional dependencies, or functionality that a developer may want to disable in specific circumstances. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
For example, a package may provide an experimental API, optional API that requires additional dependencies, or functionality that a developer may want to disable in specific circumstances. | |
For example, a package may provide an experimental API, an optional API that requires additional dependencies, or functionality that a developer may want to disable in specific circumstances. |
Packages should offer traits to provide API beyond the core of a package. | ||
For example, a package may provide an experimental API, optional API that requires additional dependencies, or functionality that a developer may want to disable in specific circumstances. | ||
If a package offers traits, using that package as a dependency without any declared traits uses the default traits that the package defines. | ||
In the following example dependency declaration, the package uses the default set of traits from the dependency, if any are defined: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Perhaps for clarity here, we should specify that the dependency package (example-package-playingcard) will use its own default traits when being imported into the package that defines it as a dependency if it is declared in this way. I'm not sure how to make that less of a mouthful however :)
] | ||
``` | ||
|
||
To determine what traits a package offers, including its defaults, inspect its `Package.swift` manifest. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: once your other PR #9034 is merged, it would be sweet to also add that you could also invoke swift package show-dependencies
to view the available traits as well! :)
|
||
Define one or more traits to offer default and configurable features for a package. | ||
|
||
Prior to Swift packages prior to Swift 6.1 offered a non-configurable API surface for each version. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo:
Prior to Swift packages prior to Swift 6.1 offered a non-configurable API surface for each version. | |
Swift packages prior to Swift 6.1 offered a non-configurable API surface for each version. |
Constrain the version of a remote dependency when you when you declare the dependency. | ||
The package manager uses git tags interpretted as semantic versions to identify eligible versions of packages. | ||
Constrain the version of a remote dependency when you declare the dependency. | ||
The package manager uses git tags, interpreted as a semantic versions, to identify eligible versions of packages. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo:
The package manager uses git tags, interpreted as a semantic versions, to identify eligible versions of packages. | |
The package manager uses git tags, interpreted as a semantic version, to identify eligible versions of packages. |
/// | ||
/// - Important: Traits must be strictly additive. Enabling a trait **must not** remove API. | ||
/// | ||
/// If your conditional code requires an dependency that you want to enable only when the trait is enabled, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo:
/// If your conditional code requires an dependency that you want to enable only when the trait is enabled, | |
/// If your conditional code requires a dependency that you want to enable only when the trait is enabled, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great. Thanks for working on this @heckj !
/// #if Trait1 | ||
/// // additional imports or APIs that Trait1 enables | ||
/// #endif // Trait1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// #if Trait1 | |
/// // additional imports or APIs that Trait1 enables | |
/// #endif // Trait1 | |
/// #if MyTrait | |
/// // additional imports or APIs that MyTrait enables | |
/// #endif // MyTrait |
|
||
Traits, introduced with Swift 6.1, allow packages to offer additional API that may include optional dependencies. | ||
Packages should offer traits to provide API beyond the core of a package. | ||
For example, a package may provide an experimental API, optional API that requires additional dependencies, or functionality that a developer may want to disable in specific circumstances. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the word disable
is too strong here. There is no way to disable a trait really since across a package graph multiple different packages might enable different traits and we always take the union of all traits.
With Swift 6.1, packages may offer traits, which express a configurable API surface for a package. | ||
|
||
Use traits to enable additional API beyond the core API of the package. | ||
For example, a trait may enable an experimental API, optional extended functionality that requires additional dependencies, or functionality that isn't critical that a developer may want to disable in specific circumstances. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. Maybe we can say
or functionality that isn't critical that a developer may want to enable only in specific circumstances.
Use traits to enable additional API beyond the core API of the package. | ||
For example, a trait may enable an experimental API, optional extended functionality that requires additional dependencies, or functionality that isn't critical that a developer may want to disable in specific circumstances. | ||
|
||
> Note: Traits should always *enable* additional code, never "remove" or disable API when a trait is enabled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "enable additional code" is weird here. Developers are generally free to do whatever they want with traits except remove public API.
Within the package, traits express conditional compilation, and may be used to declare additional dependencies that are enabled when that trait is active. | ||
|
||
Traits are identified by their names, which are name-spaced within the package that hosts them. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC the latest is that traits use be valid Swift identifiers. We can link to the Swift book's grammar section on this.
|
||
The traits enabled by default for the example above is `FeatureA`. | ||
|
||
> Note: Changing the default set of traits for your package should be considered a major semantic version change, as it can potentially remove API surface. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not fully true. It is okay to add more to the default traits just not remove traits from the default.
#### Mutually Exclusive Traits | ||
|
||
The package manifest format doesn't support declaring mutually exclusive traits. | ||
In the rare case that you need to offer mutually exclusive traits, protect that scenario in code: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add an additional line of caution here that this can result in compilation errors when users of the package enable mutually exclusive traits.
Adds documentation for the Swift 6.1 traits feature
Motivation:
Modifications:
Using Dependencies
article to touch on traits and how to consume packages that provide themResult:
Updated content and one additional article in the central documentation for Swift Package Manager that illustrates how to consume and provide packages with traits.