mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #85026 from bnbarham/user-doc-cleanup
Cleanup user docs
This commit is contained in:
@@ -44,6 +44,7 @@ GROUP(ActorIsolatedCall, "actor-isolated-call")
|
||||
GROUP(AlwaysAvailableDomain, "always-available-domain")
|
||||
GROUP(AvailabilityUnrecognizedName, "availability-unrecognized-name")
|
||||
GROUP(ClangDeclarationImport, "clang-declaration-import")
|
||||
GROUP(CompilationCaching, "compilation-caching")
|
||||
GROUP(ConformanceIsolation, "conformance-isolation")
|
||||
GROUP(DeprecatedDeclaration, "deprecated-declaration")
|
||||
GROUP(DynamicCallable, "dynamic-callable-requirements")
|
||||
@@ -52,6 +53,7 @@ GROUP(ErrorInFutureSwiftVersion, "error-in-future-swift-version")
|
||||
GROUP(ExclusivityViolation, "exclusivity-violation")
|
||||
GROUP(ExistentialAny, "existential-any")
|
||||
GROUP(ExistentialMemberAccess, "existential-member-access-limitations")
|
||||
GROUP(ExistentialType, "existential-type")
|
||||
GROUP(ImplementationOnlyDeprecated, "implementation-only-deprecated")
|
||||
GROUP(IsolatedConformances, "isolated-conformances")
|
||||
GROUP(MemberImportVisibility, "member-import-visibility")
|
||||
@@ -63,12 +65,16 @@ GROUP(MutableGlobalVariable, "mutable-global-variable")
|
||||
GROUP(NominalTypes, "nominal-types")
|
||||
GROUP(NonisolatedNonsendingByDefault, "nonisolated-nonsending-by-default")
|
||||
GROUP(OpaqueTypeInference, "opaque-type-inference")
|
||||
GROUP(PerformanceHints, "performance-hints")
|
||||
GROUP(PreconcurrencyImport, "preconcurrency-import")
|
||||
GROUP(PropertyWrappers, "property-wrapper-requirements")
|
||||
GROUP(ProtocolTypeNonConformance, "protocol-type-non-conformance")
|
||||
GROUP(RegionIsolation, "region-isolation")
|
||||
GROUP(ResultBuilderMethods, "result-builder-methods")
|
||||
GROUP(ReturnTypeImplicitCopy, "return-type-implicit-copy")
|
||||
GROUP(SendableClosureCaptures, "sendable-closure-captures")
|
||||
GROUP(SendableMetatypes, "sendable-metatypes")
|
||||
GROUP(SendingClosureRisksDataRace, "sending-closure-risks-data-race")
|
||||
GROUP(SendingRisksDataRace, "sending-risks-data-race")
|
||||
GROUP(StrictLanguageFeatures, "strict-language-features")
|
||||
GROUP(StrictMemorySafety, "strict-memory-safety")
|
||||
@@ -76,14 +82,13 @@ GROUP(StringInterpolationConformance, "string-interpolation-conformance")
|
||||
GROUP(TemporaryPointers, "temporary-pointers")
|
||||
GROUP(TrailingClosureMatching, "trailing-closure-matching")
|
||||
GROUP(UnknownWarningGroup, "unknown-warning-group")
|
||||
GROUP(CompilationCaching, "compilation-caching")
|
||||
GROUP(WeakMutability, "weak-mutability")
|
||||
|
||||
GROUP(PerformanceHints, "performance-hints")
|
||||
GROUP(ReturnTypeImplicitCopy, "return-type-implicit-copy")
|
||||
GROUP_LINK(PerformanceHints, ReturnTypeImplicitCopy)
|
||||
GROUP(ExistentialType, "existential-type")
|
||||
GROUP_LINK(PerformanceHints, ExistentialType)
|
||||
GROUP_LINK(PerformanceHints, ReturnTypeImplicitCopy)
|
||||
|
||||
GROUP_LINK(RegionIsolation, SendingClosureRisksDataRace)
|
||||
GROUP_LINK(RegionIsolation, SendingRisksDataRace)
|
||||
|
||||
#define UNDEFINE_DIAGNOSTIC_GROUPS_MACROS
|
||||
#include "swift/AST/DefineDiagnosticGroupsMacros.h"
|
||||
|
||||
@@ -1075,7 +1075,7 @@ NOTE(regionbasedisolation_typed_tns_passed_to_sending, none,
|
||||
"causing races inbetween %0 uses and uses reachable from the callee",
|
||||
(StringRef, Type))
|
||||
|
||||
ERROR(regionbasedisolation_typed_tns_passed_sending_closure, none,
|
||||
GROUPED_ERROR(regionbasedisolation_typed_tns_passed_sending_closure, SendingClosureRisksDataRace, none,
|
||||
"passing closure as a 'sending' parameter risks causing data races between %0 and concurrent execution of the closure",
|
||||
(StringRef))
|
||||
NOTE(regionbasedisolation_typed_tns_passed_to_sending_closure_helper_have_value, none,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Calling an actor-isolated method from a synchronous nonisolated context
|
||||
# Calling an actor-isolated method from a synchronous nonisolated context (ActorIsolatedCall)
|
||||
|
||||
## Overview
|
||||
|
||||
Accessing actor-isolated state from outside the actor can cause data races in your program. Resolve this error by calling actor-isolated functions on the actor.
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Protocol conformances crossing into actor-isolated code
|
||||
# Protocol conformances crossing into actor-isolated code (ConformanceIsolation)
|
||||
|
||||
## Overview
|
||||
|
||||
Protocol conformances crossing into actor-isolated code can cause data races in your program. Resolve this error by ensuring access to isolated state is always done within the actor.
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# Diagnostic descriptions
|
||||
|
||||
<!-- This file is auto-generated via `swift swift/utils/generate-doc-index.swift` -->
|
||||
|
||||
Detailed explanations for various compiler diagnostics.
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
Swift diagnostics are classified into errors and warnings. Warnings can only be silenced in an
|
||||
intentional manner, e.g., adding `_ =` for an unused function result.
|
||||
|
||||
Some diagnostics have more detailed explanations available. These include a `[#Name]` inline and
|
||||
reference to this documentation at the end of the compiler output on the command line, or is
|
||||
presented specially within your IDE of choice. See below for the full list of these notes.
|
||||
|
||||
|
||||
## Topics
|
||||
|
||||
- <doc:dynamic-callable-requirements>
|
||||
- <doc:trailing-closure-matching>
|
||||
- <doc:actor-isolated-call>
|
||||
- <doc:sendable-closure-captures>
|
||||
- <doc:string-interpolation-conformance>
|
||||
- <doc:isolated-conformances>
|
||||
- <doc:error-in-future-swift-version>
|
||||
- <doc:module-not-testable>
|
||||
- <doc:multiple-inheritance>
|
||||
- <doc:nominal-types>
|
||||
- <doc:property-wrapper-requirements>
|
||||
- <doc:protocol-type-non-conformance>
|
||||
- <doc:exclusivity-violation>
|
||||
- <doc:conformance-isolation>
|
||||
- <doc:result-builder-methods>
|
||||
- <doc:sendable-metatypes>
|
||||
- <doc:sending-closure-risks-data-race>
|
||||
- <doc:sending-risks-data-race>
|
||||
- <doc:temporary-pointers>
|
||||
- <doc:opaque-type-inference>
|
||||
- <doc:mutable-global-variable>
|
||||
- <doc:existential-member-access-limitations>
|
||||
- <doc:performance-hints>
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
<!-- This file is auto-generated via `swift swift/utils/generate-doc-index.swift` -->
|
||||
|
||||
Diagnostic groups allow controlling the behavior of warnings in a more precise manner.
|
||||
Detailed explanations for various compiler diagnostics.
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
Diagnostic groups collect some number of diagnostics together under a common group name. This allows
|
||||
for extra documentation to help explain relevant language concepts, as well as the ability to
|
||||
control the behavior of warnings in a more precise manner:
|
||||
control the behavior of warnings in a more precise manner (when that group contains warnings):
|
||||
- `-Werror <group>` - upgrades warnings in the specified group to errors
|
||||
- `-Wwarning <group>` - indicates that warnings in the specified group should remain warnings, even
|
||||
if they were previously upgraded to errors
|
||||
@@ -24,18 +24,59 @@ Or upgrade all warnings except deprecated declaration to errors:
|
||||
-warnings-as-errors -Wwarning DeprecatedDeclaration
|
||||
```
|
||||
|
||||
|
||||
## Topics
|
||||
|
||||
## Groups with warnings
|
||||
- <doc:always-available-domain>
|
||||
- <doc:trailing-closure-matching>
|
||||
- <doc:compilation-caching>
|
||||
- <doc:string-interpolation-conformance>
|
||||
- <doc:deprecated-declaration>
|
||||
- <doc:implementation-only-deprecated>
|
||||
- <doc:embedded-restrictions>
|
||||
- <doc:preconcurrency-import>
|
||||
- <doc:clang-declaration-import>
|
||||
- <doc:missing-module-on-known-paths>
|
||||
- <doc:isolated-conformances>
|
||||
- <doc:error-in-future-swift-version>
|
||||
- <doc:module-version-missing>
|
||||
- <doc:result-builder-methods>
|
||||
- <doc:strict-language-features>
|
||||
- <doc:strict-memory-safety>
|
||||
- <doc:unknown-warning-group>
|
||||
|
||||
|
||||
## Topics
|
||||
- <doc:dynamic-callable-requirements>
|
||||
- <doc:always-available-domain>
|
||||
- <doc:trailing-closure-matching>
|
||||
- <doc:actor-isolated-call>
|
||||
- <doc:sendable-closure-captures>
|
||||
- <doc:compilation-caching>
|
||||
- <doc:string-interpolation-conformance>
|
||||
- <doc:deprecated-declaration>
|
||||
- <doc:implementation-only-deprecated>
|
||||
- <doc:embedded-restrictions>
|
||||
- <doc:preconcurrency-import>
|
||||
- <doc:clang-declaration-import>
|
||||
- <doc:isolated-conformances>
|
||||
- <doc:error-in-future-swift-version>
|
||||
- <doc:missing-module-on-known-paths>
|
||||
- <doc:module-version-missing>
|
||||
- <doc:module-not-testable>
|
||||
- <doc:multiple-inheritance>
|
||||
- <doc:nominal-types>
|
||||
- <doc:exclusivity-violation>
|
||||
- <doc:performance-hints>
|
||||
- <doc:property-wrapper-requirements>
|
||||
- <doc:conformance-isolation>
|
||||
- <doc:protocol-type-non-conformance>
|
||||
- <doc:result-builder-methods>
|
||||
- <doc:sendable-metatypes>
|
||||
- <doc:sending-closure-risks-data-race>
|
||||
- <doc:sending-risks-data-race>
|
||||
- <doc:strict-language-features>
|
||||
- <doc:strict-memory-safety>
|
||||
- <doc:temporary-pointers>
|
||||
- <doc:opaque-type-inference>
|
||||
- <doc:unknown-warning-group>
|
||||
- <doc:availability-unrecognized-name>
|
||||
- <doc:mutable-global-variable>
|
||||
- <doc:existential-member-access-limitations>
|
||||
|
||||
@@ -9,6 +9,5 @@ Documentation on diagnostics emitted by the compiler and settings that control t
|
||||
|
||||
## Topics
|
||||
|
||||
- <doc:diagnostic-descriptions>
|
||||
- <doc:diagnostic-groups>
|
||||
- <doc:upcoming-language-features>
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# @dynamicCallable Implementation Requirements
|
||||
# @dynamicCallable implementation requirements (DynamicCallable)
|
||||
|
||||
## Overview
|
||||
|
||||
If a type is marked with the `@dynamicCallable` attribute, it must provide a valid implementation of `dynamicallyCall(withArguments:)`, `dynamicallyCall(withKeywordArguments:)`, or both. If it fails to do so, an error will be reported at compile-time. Note that an implementation of `dynamicallyCall(withKeywordArguments:)` is required to support calls with keyword arguments.
|
||||
|
||||
To be considered valid, an implementation of `dynamicallyCall(withArguments:)` must:
|
||||
@@ -10,4 +13,8 @@ To be considered valid, an implementation of `dynamicallyCall(withKeywordArgumen
|
||||
- Be an instance method. `static` or `class` implementations are not allowed.
|
||||
- Have an argument type which conforms to the `ExpressibleByDictionaryLiteral` protocol. This can be `Dictionary`, `KeyValuePairs` (which may be used to support duplicated keyword arguments), or some other conforming type.
|
||||
- The `Key` associated type of the argument type must conform to the `ExpressibleByStringLiteral` protocol. This type is used to represent the dynamic argument keywords.
|
||||
- The `Value` associated type of the argument type and the return type of `dynamicallyCall(withKeywordArguments:)` may be any valid types.
|
||||
- The `Value` associated type of the argument type and the return type of `dynamicallyCall(withKeywordArguments:)` may be any valid types.
|
||||
|
||||
## See also
|
||||
|
||||
- [SE-0216](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0216-dynamic-callable.md)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Language mode and tools version
|
||||
# Language mode and tools version (ErrorInFutureSwiftVersion)
|
||||
|
||||
## Overview
|
||||
|
||||
Swift language mode and Swift compiler tools version are distinct concepts. One compiler version can support multiple language modes.
|
||||
|
||||
@@ -7,6 +9,6 @@ There are two related kinds of "Swift version" that are distinct:
|
||||
* Swift tools version: the version number of the compiler itself. For example, the Swift 5.6 compiler was introduced in March 2022.
|
||||
* Swift language mode version: the language mode version with which we are providing source compatibility. For example, the Swift 5 language mode is the most current language mode version supported by Swift tools version 5.10.
|
||||
|
||||
The Swift tools support multiple Swift language modes. All Swift tools versions between 5.0 and 5.10 support three Swift language modes: 4, 4.2, and 5. The Swift 6.0 compiler supports four Swift language modes: 4, 4.2, 5, and 6. Swift language modes are opt-in; when you use a tools version that supports a new language mode, your code will not build with the new language mode until you set that language mode in your build settings with `-swift-version X`.
|
||||
The Swift tools support multiple Swift language modes. All Swift tools versions between 5.0 and 5.10 support three Swift language modes: 4, 4.2, and 5. The Swift 6.0 compiler supports four Swift language modes: 4, 4.2, 5, and 6. Swift language modes are opt-in; when you use a tools version that supports a new language mode, your code will not build with the new language mode until you set that language mode in your build settings with `-language-mode X`.
|
||||
|
||||
A warning suffixed with `this is an error in the Swift 6 language mode` means that once you migrate to that language mode in your code, the warning will be promoted to an error. These warnings primarily come from enabling upcoming features that are enabled by default in that language mode version, but errors may also be staged in as warnings until the next language mode to maintain source compatibility when fixing compiler bugs.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Overlapping accesses, but operation requires exclusive access
|
||||
# Overlapping accesses, but operation requires exclusive access (ExclusivityViolation)
|
||||
|
||||
## Overview
|
||||
|
||||
Swift requires exclusive access to a variable in order to modify that variable. An error is reported if a program attempts to access a variable while it is already in the process of being accessed via another name. These issues can often be resolved by making a local copy of a variable before modifying it.
|
||||
|
||||
@@ -58,4 +60,10 @@ var toAppend = numbers
|
||||
numbers.append(removingFrom: &toAppend)
|
||||
```
|
||||
|
||||
Exclusivity checks play an important role in enforcing memory safety and enabling compiler optimizations. To learn more, see [Swift 5 Exclusivity Enforcement](https://www.swift.org/blog/swift-5-exclusivity/) on the Swift.org blog.
|
||||
Exclusivity checks play an important role in enforcing memory safety and enabling compiler optimizations. See the Swift.org [blog][exclusivity-enforcement] to learn more.
|
||||
|
||||
## See Also
|
||||
|
||||
- [Swift 5 exclusivity enforcement][exclusivity-enforcement]
|
||||
|
||||
[exclusivity-enforcement]: https://www.swift.org/blog/swift-5-exclusivity/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Using Protocol Members with References to `Self` or `Self`-rooted Associated Types
|
||||
# Using protocol members with references to `Self` or `Self`-rooted associated types (ExistentialMemberAccess)
|
||||
|
||||
Protocol requirements and protocol extension members may be accessed via a conformance constraint on a generic parameter, an opaque result type, or via the protocol type itself:
|
||||
|
||||
@@ -51,4 +51,16 @@ func duplicateShape(_ shape: Shape) -> Shape {
|
||||
}
|
||||
```
|
||||
|
||||
Most use cases involving usage of protocol members that fall under the above restriction can instead be supported by constrained generics, opaque result types, or manual type-erasing wrappers. To learn more, see the sections on [protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html), [generics](https://docs.swift.org/swift-book/LanguageGuide/Generics.html), and [opaque types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html) in the Language Guide. For a better understanding of existential types in particular, and an in-depth exploration of the relationships among these built-in abstraction models, we recommend reading the [design document for improving the UI of the generics model](https://forums.swift.org/t/improving-the-ui-of-generics/22814).
|
||||
Most use cases involving usage of protocol members that fall under the above restriction can instead be supported by constrained generics, opaque result types, or manual type-erasing wrappers. To learn more, see the sections on [protocols], [generics], and [opaque types][opaque-types] in the Language Guide. For a better understanding of existential types in particular, and an in-depth exploration of the relationships among these built-in abstraction models, we recommend reading [design document for improving the UI of the generics model][improving-generics-ui].
|
||||
|
||||
## See Also
|
||||
|
||||
- [Generics][generics]
|
||||
- [Improving the UI of generics][improving-generics-ui]
|
||||
- [Opaque Types][opaque-types]
|
||||
- [Protocols][protocols]
|
||||
|
||||
[generics]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/generics
|
||||
[improving-generics-ui]: https://forums.swift.org/t/improving-the-ui-of-generics/22814
|
||||
[opaque-types]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/opaquetypes
|
||||
[protocols]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
|
||||
Warnings that identify `import` declarations with the `@_implementationOnly` attribute.
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
When applied to `import` declarations, the compiler-internal attribute `@_implementationOnly` attempts prevents declarations from the imported module from being exposed in the ABI or public interface of the dependent module. This attribute became deprecated when support for access levels on `import` declarations was introduced with [SE-0409].
|
||||
|
||||
One reason `@_implementationOnly import` is deprecated is that it is unsafe when used in modules that are built _without_ [library evolution] enabled. For example, suppose the following code were part of a library named `Foo`:
|
||||
One reason `@_implementationOnly import` is deprecated is that it is unsafe when used in modules that are built _without_ [library evolution][library-evolution] enabled. For example, suppose the following code were part of a library named `Foo`:
|
||||
|
||||
```swift
|
||||
// Library `Foo`
|
||||
@@ -19,5 +20,10 @@ public struct Bar {
|
||||
|
||||
If `Foo` is not compiled with library evolution, then the memory layout of values of `Bar` must be known at compile time in clients of `Foo`. However, the `@_implementationOnly import` of `ImplementationDetail` prevents clients from being able to look up `Baz` which is a type that contributes to the layout of `Foo`. As a result, the layout of `Foo` will be miscalculated resulting in undefined behavior.
|
||||
|
||||
## See Also
|
||||
|
||||
- [SE-0409: Access level on imports][SE-0409]
|
||||
- [Library evolution][library-evolution]
|
||||
|
||||
[SE-0409]: https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md
|
||||
[library evolution]: https://www.swift.org/blog/library-evolution/
|
||||
[library-evolution]: https://www.swift.org/blog/library-evolution/
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Isolated conformances
|
||||
# Isolated conformances (IsolatedConformances)
|
||||
|
||||
## Overview
|
||||
|
||||
Using an isolated conformance from outside the actor can cause data races in your program. Resolve these errors by only using isolated conformances within the actor.
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Module not testable
|
||||
# Module not testable (ModuleNotTestable)
|
||||
|
||||
## Overview
|
||||
|
||||
Modules imported using `@testable import` must have been compiled using the `-enable-testing` compiler flag.
|
||||
|
||||
`@testable import` allows clients of a module to access `internal` API when writing tests. A `@testable import` will report an error if the imported module was not compiled with the `-enable-testing` compiler flag. Use of `-enable-testing` is recommended only in debug builds or other builds not intended for production use.
|
||||
`@testable import` allows clients of a module to access `internal` API when writing tests. A `@testable import` will report an error if the imported module was not compiled with the `-enable-testing` compiler flag. Use of `-enable-testing` is recommended only in debug builds or other builds not intended for production use.
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
# Multiple Inheritance
|
||||
# Multiple inheritance (MultipleInheritance)
|
||||
|
||||
## Overview
|
||||
|
||||
In some programming languages, a class can inherit the interface of multiple base classes. Known as multiple inheritance, this feature can add significant complexity to the language and is unsupported in Swift. Instead, Swift allows composition of interfaces using protocols.
|
||||
|
||||
Consider the following example:
|
||||
|
||||
```swift
|
||||
protocol Utensil {
|
||||
protocol Utensil {
|
||||
var name: String { get }
|
||||
}
|
||||
}
|
||||
|
||||
protocol ServingUtensil: Utensil {
|
||||
func serve()
|
||||
}
|
||||
}
|
||||
|
||||
extension ServingUtensil {
|
||||
func serve() { /* Default implementation. */ }
|
||||
@@ -32,6 +34,16 @@ struct Ladle: ServingUtensil, Spoon { /* ... */ }
|
||||
|
||||
Swift protocols can declare interfaces that must be implemented by each conforming type (like abstract class members in other programming languages such as C# or Java), and they can also provide overridable default implementations for those requirements in protocol extensions.
|
||||
|
||||
When class inheritance and protocol conformances are used together, subclasses inherit protocol conformances from base classes, introducing additional complexity. For example, the default implementation of a protocol requirement not overridden in the conforming base class also cannot be overridden in any subclass ([#42725](https://github.com/apple/swift/issues/42725)).
|
||||
When class inheritance and protocol conformances are used together, subclasses inherit protocol conformances from base classes, introducing additional complexity. For example, the default implementation of a protocol requirement not overridden in the conforming base class also cannot be overridden in any subclass ([#42725]).
|
||||
|
||||
To learn more about defining and adopting protocols, see the [Protocols](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html) section in _The Swift Programming Language_. To learn more about class inheritance, see the [Inheritance](https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html) section in _The Swift Programming Language_.
|
||||
To learn more about defining and adopting protocols, see the [Protocols][protocols] section in _The Swift Programming Language_. To learn more about class inheritance, see the [Inheritance][inheritance] section in _The Swift Programming Language_.
|
||||
|
||||
## See Also
|
||||
|
||||
- [GitHub issue #42725][#42725]
|
||||
- [Inheritance][inheritance]
|
||||
- [Protocols][protocols]
|
||||
|
||||
[#42725]: https://github.com/apple/swift/issues/42725
|
||||
[inheritance]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/inheritance
|
||||
[protocols]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# Unsafe mutable global and static variables
|
||||
# Unsafe mutable global and static variables (MutableGlobalVariable)
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
Mutable global and static variables that can be accessed from anywhere can cause data races in your program. Resolve this error by making the state immutable or protecting it with a global actor.
|
||||
|
||||
@@ -46,7 +49,7 @@ This code is also diagnosed under complete concurrency checking. Even though the
|
||||
```swift
|
||||
class MyModel {
|
||||
@MainActor
|
||||
static let shared = MyModel()
|
||||
static let shared = MyModel()
|
||||
}
|
||||
```
|
||||
|
||||
@@ -57,4 +60,4 @@ Alternatively, isolate the `MyModel` class to the main actor, which will also ma
|
||||
class MyModel {
|
||||
static let shared = MyModel()
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Nominal Types
|
||||
# Nominal types (NominalTypes)
|
||||
|
||||
## Overview
|
||||
|
||||
In Swift, a type is considered a nominal type if it has been explicitly named by a declaration somewhere in code. Examples of nominal types include classes, structures and enumerations. Nominal types are an important concept in Swift because they may conform to protocols, be extended, and have values created using the initializer syntax `MyType()`.
|
||||
|
||||
@@ -6,4 +8,10 @@ In contrast, non-nominal types do not have these capabilities. Many are obtained
|
||||
|
||||
Since a protocol is named by a declaration in code, it may conform to (in other words, refine) other protocols and it may be extended. However, when written as the type of a constant or variable such as `let value: MyProtocol`, the name refers to a distinct, non-nominal existential type that provides a "box" for a value of any concrete type that conforms to the protocol. The existential type itself does not conform to any protocols and cannot be extended, and a value cannot be created using the initializer syntax `MyProtocol()`.
|
||||
|
||||
For more on using existential types, see [Protocols as Types](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID275) in _The Swift Programming Language_.
|
||||
For more on using existential types, see [Protocols as Types][protocols-as-types] in _The Swift Programming Language_.
|
||||
|
||||
## See Also
|
||||
|
||||
- [Protocols as Types][protocols-as-types]
|
||||
|
||||
[protocols-as-types]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols#Protocols-as-Types
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Underlying Type Inference for Opaque Result Types
|
||||
# Underlying type inference for opaque result types (OpaqueTypeInference)
|
||||
|
||||
## Overview
|
||||
|
||||
Opaque result types are a useful tool for abstracting the return type of a function or subscript, or type of a property. Although the concrete underlying type of an opaque type is hidden from clients, it is still inferred by the compiler, which enforces certain usage requirements:
|
||||
|
||||
@@ -64,5 +66,10 @@ func bar(_ x: Int) -> some Equatable { // OK, the underlying type can be inferre
|
||||
}
|
||||
```
|
||||
|
||||
To learn more about opaque result types, see the [Opaque Types](https://docs.swift.org/swift-book/LanguageGuide/OpaqueTypes.html) section of _The Swift Programming Language_.
|
||||
To learn more about opaque result types, see the [Opaque Types][opaque-types] section of _The Swift Programming Language_.
|
||||
|
||||
## See Also
|
||||
|
||||
- [Opaque Types][opaque-types]
|
||||
|
||||
[opaque-types]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/opaquetypes
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Swift Performance Hint: Function returning Array or Dictionary type
|
||||
# Performance hints (PerformanceHints)
|
||||
|
||||
- TODO: Docs
|
||||
## Overview
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Property Wrapper Implementation Requirements
|
||||
# Property wrapper implementation requirements (PropertyWrappers)
|
||||
|
||||
## Overview
|
||||
|
||||
If a type is marked with the `@propertyWrapper` attribute, it must meet certain requirements to be a valid property wrapper.
|
||||
|
||||
First, all property wrapper types must have a property named `wrappedValue`. This property cannot be static and must have the same access level as the property wrapper type. If the property wrapper provides a `projectedValue` property, it is subject to the same requirements.
|
||||
|
||||
Second, none of a property wrapper's initializers may be failable. Additionally, if a property wrapper initializer has a `wrappedValue` parameter, the type of that parameter must either be the same as the type of the `wrappedValue` property or an `@autoclosure` of that type.
|
||||
Second, none of a property wrapper's initializers may be failable. Additionally, if a property wrapper initializer has a `wrappedValue` parameter, the type of that parameter must either be the same as the type of the `wrappedValue` property or an `@autoclosure` of that type.
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# Protocol Types Cannot Conform to Protocols
|
||||
# Protocol types cannot conform to protocols (ProtocolTypeNonConformance)
|
||||
|
||||
## Overview
|
||||
|
||||
In Swift, a protocol that does not have `Self` or associated type requirements can be used as a type. You can use a variable or constant of a protocol type, also called an __existential type__, to hold a value of any conforming type:
|
||||
|
||||
```swift
|
||||
```swift
|
||||
protocol Animal {
|
||||
func makeNoise()
|
||||
static var species: String { get }
|
||||
@@ -89,4 +91,10 @@ struct Habitat {
|
||||
}
|
||||
```
|
||||
|
||||
For more on using existential types, see [Protocols as Types](https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID275) in _The Swift Programming Language_.
|
||||
For more on using existential types, see [Protocols as Types][protocols-as-types] in _The Swift Programming Language_.
|
||||
|
||||
## See Also
|
||||
|
||||
- [Protocols as Types][protocols-as-types]
|
||||
|
||||
[protocols-as-types]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols#Protocols-as-Types
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Result Builder Methods
|
||||
# Result builder methods (ResultBuilderMethods)
|
||||
|
||||
## Overview
|
||||
|
||||
To be useful as a result builder, a result builder type must provide a
|
||||
sufficient subset of function-building methods that enable the transformation of
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Captures in a `@Sendable` closure
|
||||
# Captures in a `@Sendable` closure (SendableClosureCaptures)
|
||||
|
||||
## Overview
|
||||
|
||||
`@Sendable` closures can be called multiple times concurrently, so any captured values must also be safe to access concurrently. To prevent data races, the compiler prevents capturing mutable values in a `@Sendable` closure.
|
||||
|
||||
@@ -12,7 +14,7 @@ func callConcurrently(
|
||||
func capture() {
|
||||
var result = 0
|
||||
result += 1
|
||||
|
||||
|
||||
callConcurrently {
|
||||
print(result)
|
||||
}
|
||||
@@ -53,7 +55,7 @@ If the type of the capture is `Sendable` and the closure only needs the value of
|
||||
func capture() {
|
||||
var result = 0
|
||||
result += 1
|
||||
|
||||
|
||||
callConcurrently { [result] in
|
||||
print(result)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Sendable metatypes
|
||||
# Sendable metatypes (SendableMetatypes)
|
||||
|
||||
## Overview
|
||||
|
||||
Types that are shared in concurrent code generally need to conform to `Sendable`. The same is true in generic code when sharing parameters of a generic parameter `T`. For example, the given code will produce an error under strict concurrency checking
|
||||
|
||||
@@ -59,4 +61,4 @@ func test(c: C) {
|
||||
|
||||
```
|
||||
|
||||
The conformance of `C` to `P` can only be used on the main actor, so it cannot be provided to `doSomethingStatic`, which calls the conformance from a different concurrent task.
|
||||
The conformance of `C` to `P` can only be used on the main actor, so it cannot be provided to `doSomethingStatic`, which calls the conformance from a different concurrent task.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Sending closure risks causing data races
|
||||
# Sending closure risks causing data races (SendingClosureRisksDataRace)
|
||||
|
||||
## Overview
|
||||
|
||||
Sharing mutable state between concurrent tasks can cause data races in your program. Resolve this error by only accessing mutable state in one task at a time.
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# Sending value risks causing data races
|
||||
# Sending value risks causing data races (SendingRisksDataRace)
|
||||
|
||||
## Overview
|
||||
|
||||
Sharing mutable state between concurrent tasks can cause data races in your program. Resolve this error by only accessing mutable state in one task at a time.
|
||||
|
||||
@@ -9,7 +11,7 @@ For example, if a value can be accessed from the main actor, it's invalid to sen
|
||||
```swift
|
||||
class Person {
|
||||
var name: String = ""
|
||||
|
||||
|
||||
func printNameConcurrently() async {
|
||||
print(name)
|
||||
}
|
||||
@@ -36,7 +38,7 @@ The most common fix is to change the `async` method to run on the caller's actor
|
||||
```swift
|
||||
class Person {
|
||||
var name: String = ""
|
||||
|
||||
|
||||
nonisolated(nonsending)
|
||||
func printNameConcurrently() async {
|
||||
print(name)
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# Conforming to `StringInterpolationProtocol`
|
||||
# Conforming to `StringInterpolationProtocol` (StringInterpolationConformance)
|
||||
|
||||
## Overview
|
||||
|
||||
A type conforming to `ExpressibleByStringInterpolation` uses a helper type called `StringInterpolation` to perform its interpolation. Many types can use `DefaultStringInterpolation`, which implements `String`'s interpolation behavior. Types can also implement custom behavior by providing their own type conforming to `StringInterpolationProtocol`.
|
||||
|
||||
In addition to its formal requirements, `init(literalCapacity:interpolationCount:)` and `appendLiteral(_:)`, `StringInterpolationProtocol` has an additional, informal requirement, `appendInterpolation`. String interpolations using `\()` syntax are translated into calls to matching `appendInterpolation` methods.
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# Temporary Pointers
|
||||
# Temporary pointers (TemporaryPointers)
|
||||
|
||||
## Overview
|
||||
|
||||
A temporary, or ephemeral, pointer in Swift is a pointer which is introduced by an implicit function argument conversion and is only valid for the lifetime of the function call it appears in. There are a few ways to create a temporary pointer:
|
||||
|
||||
- Using an inout-to-pointer conversion by passing an argument with `&`:
|
||||
@@ -61,4 +64,3 @@ let ptr = withUnsafePointer(to: &x) { $0 }
|
||||
This code is invalid because the pointer to `x` is only valid until `withUnsafePointer` returns, but it escapes the closure when it is returned and assigned to `ptr`.
|
||||
|
||||
To learn more about correctly using unsafe pointer APIs, see the Swift standard library documentation of `UnsafePointer` and related types.
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
# Argument Matching for Trailing Closures
|
||||
# Argument matching for trailing closures (TrailingClosureMatching)
|
||||
|
||||
## Overview
|
||||
|
||||
Where trailing closures are used to pass one or more arguments to a function, the argument label for the first trailing closure is always omitted:
|
||||
|
||||
```swift
|
||||
func animate(
|
||||
withDuration duration: Double,
|
||||
animations: () -> Void,
|
||||
withDuration duration: Double,
|
||||
animations: () -> Void,
|
||||
completion: (() -> Void)? = nil
|
||||
) { /* ... */ }
|
||||
|
||||
@@ -40,8 +42,8 @@ When scanning forwards to match an unlabeled trailing closure argument, the comp
|
||||
|
||||
```swift
|
||||
func animate(
|
||||
withDuration duration: Double = 1.0,
|
||||
animations: () -> Void,
|
||||
withDuration duration: Double = 1.0,
|
||||
animations: () -> Void,
|
||||
completion: (() -> Void)? = nil
|
||||
) { /* ... */ }
|
||||
|
||||
@@ -60,7 +62,7 @@ animate {
|
||||
|
||||
For source compatibility in Swift 5, the compiler will attempt to apply *both* the new forward scanning rule and the old backward scanning rule when it encounters a function call with a single trailing closure. If the forward and backward scans produce *different valid* matches of arguments to parameters, the compiler will prefer the result of the backward scanning rule and produce a warning. To silence this warning, rewrite the function call to label the argument explicitly without using trailing closure syntax.
|
||||
|
||||
## Structural Resemblance to a Function Type
|
||||
## Structural resemblance to a function type
|
||||
|
||||
A parameter structurally resembles a function type if both of the following are true:
|
||||
|
||||
@@ -73,7 +75,7 @@ The adjusted type of the parameter is the parameter's type as it appears in the
|
||||
2. If the parameter is variadic, look at the base element type.
|
||||
3. Remove all outer "optional" types.
|
||||
|
||||
## Heuristic for Skipping Parameters
|
||||
## Heuristic for skipping parameters
|
||||
|
||||
To maintain source compatibility, the forward scanning rule applies an additional heuristic when matching trailing closure arguments. If:
|
||||
|
||||
@@ -107,4 +109,7 @@ showAlert(message: "Hello, World!") {
|
||||
}
|
||||
```
|
||||
|
||||
To learn more about argument matching for trailing closures, see [Swift Evolution Proposal SE-0286](https://github.com/apple/swift-evolution/blob/master/proposals/0286-forward-scan-trailing-closures.md).
|
||||
## See Also
|
||||
|
||||
- [SE-0279: Multiple trailing closures](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0279-multiple-trailing-closures.md)
|
||||
- [SE-0286: Forward-scan matching for trailing closures](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0286-forward-scan-trailing-closures.md)
|
||||
|
||||
@@ -16,9 +16,7 @@ Some upcoming features have an additional "migration" mode, where the compiler w
|
||||
with fix-its to help migrate to that mode. This can be enabled with `-enable-upcoming-feature
|
||||
<feature>:migrate`.
|
||||
|
||||
|
||||
## Topics
|
||||
|
||||
- <doc:existential-any>
|
||||
- <doc:member-import-visibility>
|
||||
- <doc:nonisolated-nonsending-by-default>
|
||||
|
||||
@@ -5,50 +5,26 @@ import Foundation
|
||||
let usage = """
|
||||
./\(CommandLine.arguments[0]) <swift-source-directory> [output-directory]
|
||||
|
||||
Generates index files for diagnostics notes, groups, and upcoming features.
|
||||
Generates index files for diagnostics groups and upcoming features.
|
||||
"""
|
||||
|
||||
let docsDir = "userdocs/diagnostics"
|
||||
let topLevelFileName = "diagnostics.md"
|
||||
|
||||
let notesDocFileName = "diagnostic-descriptions.md"
|
||||
let notesHeader = """
|
||||
# Diagnostic descriptions
|
||||
let groupsDocFileName = "diagnostic-groups.md"
|
||||
let groupsHeader = """
|
||||
# Diagnostic groups
|
||||
|
||||
<!-- This file is auto-generated via `swift swift/utils/generate-doc-index.swift` -->
|
||||
|
||||
Detailed explanations for various compiler diagnostics.
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
Swift diagnostics are classified into errors and warnings. Warnings can only be silenced in an
|
||||
intentional manner, e.g., adding `_ =` for an unused function result.
|
||||
|
||||
Some diagnostics have more detailed explanations available. These include a `[#Name]` inline and
|
||||
reference to this documentation at the end of the compiler output on the command line, or is
|
||||
presented specially within your IDE of choice. See below for the full list of these notes.
|
||||
|
||||
|
||||
## Topics
|
||||
|
||||
|
||||
"""
|
||||
|
||||
let groupsDocFileName = "diagnostic-groups.md"
|
||||
let groupsHeader = """
|
||||
# Diagnostic groups
|
||||
|
||||
<!-- This file is auto-generated via `swift swift/utils/generate-doc-index.swift` -->
|
||||
|
||||
Diagnostic groups allow controlling the behavior of warnings in a more precise manner.
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
Diagnostic groups collect some number of diagnostics together under a common group name. This allows
|
||||
for extra documentation to help explain relevant language concepts, as well as the ability to
|
||||
control the behavior of warnings in a more precise manner:
|
||||
control the behavior of warnings in a more precise manner (when that group contains warnings):
|
||||
- `-Werror <group>` - upgrades warnings in the specified group to errors
|
||||
- `-Wwarning <group>` - indicates that warnings in the specified group should remain warnings, even
|
||||
if they were previously upgraded to errors
|
||||
@@ -62,11 +38,6 @@ Or upgrade all warnings except deprecated declaration to errors:
|
||||
```sh
|
||||
-warnings-as-errors -Wwarning DeprecatedDeclaration
|
||||
```
|
||||
|
||||
|
||||
## Topics
|
||||
|
||||
|
||||
"""
|
||||
|
||||
let featuresDocFileName = "upcoming-language-features.md"
|
||||
@@ -88,18 +59,17 @@ enabled on the command line with `-enable-upcoming-feature <feature>`.
|
||||
Some upcoming features have an additional "migration" mode, where the compiler will emit warnings
|
||||
with fix-its to help migrate to that mode. This can be enabled with `-enable-upcoming-feature
|
||||
<feature>:migrate`.
|
||||
|
||||
|
||||
## Topics
|
||||
|
||||
|
||||
"""
|
||||
|
||||
let groupsFileName = "include/swift/AST/DiagnosticGroups.def"
|
||||
let groupRegex = /GROUP\(([a-zA-Z]+), ".+"\)/
|
||||
let topicsHeader = "\n\n## Topics\n"
|
||||
|
||||
let featuresFileName = "include/swift/Basic/Features.def"
|
||||
let featuresRegex = /UPCOMING_FEATURE\(([a-zA-Z]+), .+\)/
|
||||
let swiftIncludeDir = "include/swift"
|
||||
|
||||
let groupsFileName = "\(swiftIncludeDir)/AST/DiagnosticGroups.def"
|
||||
let groupRegex = /GROUP\((?<name>[a-zA-Z]+), "(?<file>.+)"\)/
|
||||
|
||||
let featuresFileName = "\(swiftIncludeDir)/Basic/Features.def"
|
||||
let featuresRegex = /UPCOMING_FEATURE\((?<name>[a-zA-Z]+), .+\)/
|
||||
|
||||
let nameRegex = /# .+ \((?<name>[a-zA-Z]+)\)/
|
||||
|
||||
@@ -117,122 +87,185 @@ if !args.isEmpty {
|
||||
outputDir = "\(swiftSourceDir)/\(docsDir)"
|
||||
}
|
||||
|
||||
let generator = GenerateUserDocs(swiftSourceDir: swiftSourceDir, outputDir: outputDir)
|
||||
do {
|
||||
try generator.generateIndex()
|
||||
try generateIndex()
|
||||
} catch {
|
||||
print("error: \(error)")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
struct GenerateUserDocs {
|
||||
let swiftSourceDir: String
|
||||
let outputDir: String
|
||||
func generateIndex() throws {
|
||||
let groupsHandle = try createIndex(name: groupsDocFileName, header: groupsHeader)
|
||||
defer { try? groupsHandle.close() }
|
||||
|
||||
func generateIndex() throws {
|
||||
let notesHandle = try createIndex(name: notesDocFileName, header: notesHeader)
|
||||
defer { try? notesHandle.close() }
|
||||
let featuresHandle = try createIndex(name: featuresDocFileName, header: featuresHeader)
|
||||
defer { try? featuresHandle.close() }
|
||||
|
||||
let groupsHandle = try createIndex(name: groupsDocFileName, header: groupsHeader)
|
||||
defer { try? groupsHandle.close() }
|
||||
let groupsWithWarnings = try groupNamesWithWarnings()
|
||||
let docs = try retrieveDocs(groupsWithWarnings).sorted { a, b in
|
||||
return a.title < b.title
|
||||
}
|
||||
|
||||
let featuresHandle = try createIndex(name: featuresDocFileName, header: featuresHeader)
|
||||
defer { try? featuresHandle.close() }
|
||||
try groupsHandle.write(contentsOf: "\n\n## Groups with warnings\n".data(using: .utf8)!)
|
||||
for doc in docs where doc.kind == .groupWithWarnings {
|
||||
let ref = "- <doc:\(doc.name.dropLast(3))>\n"
|
||||
try groupsHandle.write(contentsOf: ref.data(using: .utf8)!)
|
||||
}
|
||||
|
||||
let docs = try retrieveDocs().sorted { a, b in
|
||||
return a.title < b.title
|
||||
try groupsHandle.write(contentsOf: topicsHeader.data(using: .utf8)!)
|
||||
try featuresHandle.write(contentsOf: topicsHeader.data(using: .utf8)!)
|
||||
|
||||
for doc in docs {
|
||||
let handle: FileHandle
|
||||
switch doc.kind {
|
||||
case .group, .groupWithWarnings:
|
||||
handle = groupsHandle
|
||||
case .feature:
|
||||
handle = featuresHandle
|
||||
}
|
||||
|
||||
for doc in docs {
|
||||
let handle: FileHandle
|
||||
switch doc.kind {
|
||||
case .note:
|
||||
handle = notesHandle
|
||||
case .group:
|
||||
handle = groupsHandle
|
||||
case .feature:
|
||||
handle = featuresHandle
|
||||
let ref = "- <doc:\(doc.name.dropLast(3))>\n"
|
||||
try handle.write(contentsOf: ref.data(using: .utf8)!)
|
||||
}
|
||||
}
|
||||
|
||||
func createIndex(name: String, header: String) throws -> FileHandle {
|
||||
let path = "\(outputDir)/\(name)"
|
||||
|
||||
if FileManager.default.fileExists(atPath: path) {
|
||||
try FileManager.default.removeItem(atPath: path)
|
||||
}
|
||||
FileManager.default.createFile(atPath: path, contents: nil)
|
||||
|
||||
let handle = try FileHandle(forWritingTo: URL(filePath: path))
|
||||
try handle.write(contentsOf: header.data(using: .utf8)!)
|
||||
return handle
|
||||
}
|
||||
|
||||
func retrieveDocs(_ groupsWithWarnings: Set<String>) throws -> [UserDoc] {
|
||||
let groups = Dictionary(try matches(in: "\(swiftSourceDir)/\(groupsFileName)", with: groupRegex) {
|
||||
(file: String($0.file), name: String($0.name))
|
||||
}, uniquingKeysWith: { a, b in a })
|
||||
let features = Set(try matches(in: "\(swiftSourceDir)/\(featuresFileName)", with: featuresRegex) {
|
||||
String($0.1)
|
||||
})
|
||||
|
||||
var docs: [UserDoc] = []
|
||||
|
||||
let files = try FileManager.default.contentsOfDirectory(atPath: "\(swiftSourceDir)/\(docsDir)")
|
||||
for name in files {
|
||||
if !name.hasSuffix(".md")
|
||||
|| name.hasSuffix(topLevelFileName)
|
||||
|| name.hasSuffix(groupsDocFileName)
|
||||
|| name.hasSuffix(featuresDocFileName) {
|
||||
continue
|
||||
}
|
||||
|
||||
guard let groupName = groups[String(name.dropLast(3))] else {
|
||||
throw GenerationError.unknownGroup(file: name)
|
||||
}
|
||||
|
||||
let path = try String(contentsOfFile: "\(swiftSourceDir)/\(docsDir)/\(name)", encoding: .utf8)
|
||||
guard let match = try? nameRegex.prefixMatch(in: path) else {
|
||||
throw GenerationError.missingGroup(name: groupName, file: name)
|
||||
}
|
||||
|
||||
let titleGroupName = String(match.name)
|
||||
if groupName != titleGroupName {
|
||||
throw GenerationError.incorrectGroup(defsName: groupName, titleName: titleGroupName, file: name)
|
||||
}
|
||||
|
||||
let kind: UserDoc.Kind
|
||||
if features.contains(groupName) {
|
||||
kind = .feature
|
||||
} else if groupsWithWarnings.contains(groupName) {
|
||||
kind = .groupWithWarnings
|
||||
} else {
|
||||
kind = .group
|
||||
}
|
||||
|
||||
docs.append(UserDoc(name: name, title: String(match.0), kind: kind))
|
||||
}
|
||||
|
||||
return docs
|
||||
}
|
||||
|
||||
func groupNamesWithWarnings() throws -> Set<String> {
|
||||
let includePath = "\(swiftSourceDir)/\(swiftIncludeDir)"
|
||||
let defPaths = try FileManager.default.subpathsOfDirectory(atPath: includePath)
|
||||
.compactMap { subpath in
|
||||
if subpath.hasSuffix(".def") {
|
||||
return "\(includePath)/\(subpath)"
|
||||
}
|
||||
|
||||
let ref = "- <doc:\(doc.name.dropLast(3))>\n"
|
||||
try handle.write(contentsOf: ref.data(using: .utf8)!)
|
||||
return nil
|
||||
}
|
||||
|
||||
enum WarningGroupState {
|
||||
case outside, inside, name
|
||||
}
|
||||
|
||||
func createIndex(name: String, header: String) throws -> FileHandle {
|
||||
let path = "\(outputDir)/\(name)"
|
||||
var groups: Set<String> = []
|
||||
for path in defPaths {
|
||||
let file = try String(contentsOfFile: path, encoding: .utf8)
|
||||
|
||||
if FileManager.default.fileExists(atPath: path) {
|
||||
try FileManager.default.removeItem(atPath: path)
|
||||
}
|
||||
FileManager.default.createFile(atPath: path, contents: nil)
|
||||
|
||||
let handle = try FileHandle(forWritingTo: URL(filePath: path))
|
||||
try handle.write(contentsOf: header.data(using: .utf8)!)
|
||||
return handle
|
||||
}
|
||||
|
||||
func matches(in fileName: String, with regex: Regex<(Substring, Substring)>) throws -> Set<String> {
|
||||
let file = try String(contentsOfFile: "\(swiftSourceDir)/\(fileName)", encoding: .utf8)
|
||||
|
||||
var matches: Set<String> = []
|
||||
var state = WarningGroupState.outside
|
||||
for line in file.components(separatedBy: .newlines) {
|
||||
if let match = try? regex.firstMatch(in: line) {
|
||||
matches.insert(String(match.1))
|
||||
}
|
||||
}
|
||||
var line = Substring(line)
|
||||
|
||||
return matches
|
||||
}
|
||||
|
||||
func retrieveDocs() throws -> [UserDoc] {
|
||||
let groups = try matches(in: groupsFileName, with: groupRegex)
|
||||
let features = try matches(in: featuresFileName, with: featuresRegex)
|
||||
|
||||
var docs: [UserDoc] = []
|
||||
|
||||
let files = try FileManager.default.contentsOfDirectory(atPath: "\(swiftSourceDir)/\(docsDir)")
|
||||
for name in files {
|
||||
if !name.hasSuffix(".md")
|
||||
|| name.hasSuffix(topLevelFileName)
|
||||
|| name.hasSuffix(notesDocFileName)
|
||||
|| name.hasSuffix(groupsDocFileName)
|
||||
|| name.hasSuffix(featuresDocFileName) {
|
||||
continue
|
||||
}
|
||||
|
||||
let file = try String(contentsOfFile: "\(swiftSourceDir)/\(docsDir)/\(name)", encoding: .utf8)
|
||||
|
||||
if let match = try? nameRegex.prefixMatch(in: file) {
|
||||
let groupName = String(match.name)
|
||||
|
||||
let kind: UserDoc.Kind
|
||||
if features.contains(groupName) {
|
||||
kind = .feature
|
||||
} else if groups.contains(groupName) {
|
||||
kind = .group
|
||||
} else {
|
||||
kind = .note
|
||||
switch state {
|
||||
case .outside:
|
||||
if !line.hasPrefix("GROUPED_WARNING") {
|
||||
continue
|
||||
}
|
||||
|
||||
docs.append(UserDoc(name: name, title: String(match.0), kind: kind))
|
||||
} else {
|
||||
if let newlineIndex = file.firstIndex(of: "\n") {
|
||||
docs.append(UserDoc(name: name, title: String(file[..<newlineIndex]), kind: .note))
|
||||
} else {
|
||||
docs.append(UserDoc(name: name, title: file, kind: .note))
|
||||
state = .inside
|
||||
fallthrough
|
||||
|
||||
case .inside:
|
||||
guard let index = line.firstIndex(of: ",") else {
|
||||
continue
|
||||
}
|
||||
line = line[index...].dropFirst()
|
||||
|
||||
state = .name
|
||||
fallthrough
|
||||
|
||||
case .name:
|
||||
if let index = line.firstIndex(of: ",") {
|
||||
line = line[..<index]
|
||||
}
|
||||
line = line.trimmingPrefix { $0.isWhitespace }
|
||||
|
||||
if line.isEmpty {
|
||||
continue
|
||||
}
|
||||
|
||||
groups.insert(String(line))
|
||||
state = .outside
|
||||
}
|
||||
}
|
||||
|
||||
return docs
|
||||
}
|
||||
|
||||
return groups
|
||||
}
|
||||
|
||||
func matches<R, E>(in path: String, with regex: Regex<R>, _ transform: (Regex<R>.Match) -> E) throws -> [E] {
|
||||
let file = try String(contentsOfFile: path, encoding: .utf8)
|
||||
|
||||
var matches = [E]()
|
||||
for line in file.components(separatedBy: .newlines) {
|
||||
if let match = try? regex.firstMatch(in: line) {
|
||||
matches.append(transform(match))
|
||||
}
|
||||
}
|
||||
|
||||
return matches
|
||||
}
|
||||
|
||||
struct UserDoc {
|
||||
enum Kind {
|
||||
case note
|
||||
case group
|
||||
case groupWithWarnings
|
||||
case feature
|
||||
}
|
||||
|
||||
@@ -240,3 +273,20 @@ struct UserDoc {
|
||||
let title: String
|
||||
let kind: Kind
|
||||
}
|
||||
|
||||
enum GenerationError: CustomStringConvertible, Error {
|
||||
case incorrectGroup(defsName: String, titleName: String, file: String)
|
||||
case missingGroup(name:String, file: String)
|
||||
case unknownGroup(file: String)
|
||||
|
||||
var description: String {
|
||||
switch self {
|
||||
case .incorrectGroup(let defsName, let titleName, let file):
|
||||
return "The title in '\(file)' contains the name '\(titleName)', but it should be '\(defsName)' as per 'DiagnosticGroups.def'"
|
||||
case .missingGroup(let name, let file):
|
||||
return "The title in '\(file)' does not end with a group name, add ' (\(name))' to the end of the title"
|
||||
case .unknownGroup(let file):
|
||||
return "'\(file)' has no corresponding listing in 'DiagnosticGroups.def'"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user