You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/StandardLibraryProgrammersManual.md
+127-1
Original file line number
Diff line number
Diff line change
@@ -12,10 +12,136 @@ In this document, "stdlib" refers to the core standard library (`stdlib/public/c
12
12
13
13
### Formatting Conventions
14
14
15
-
The stdlib currently has a hard line length limit of 80 characters. To break long lines, please closely follow the indentation conventions you see in the existing codebase. (FIXME: Describe.)
15
+
The Standard Library codebase has some rather strict formatting conventions. While these aren't currently automatically enforced, we still expect these conventions to be followed in every PR, including draft PRs. (PRs are first and foremost intended to be read/reviewed by *people familiar with the stdlib codebase*, and it's crucial that trivial formatting issues don't get in the way of understanding proposed changes.)
16
+
17
+
#### Line Breaking
18
+
19
+
The stdlib currently has a hard line length limit of 80 characters. This allows code to be easily read in environments that don't gracefully handle long lines, including (especially!) code reviews on GitHub.
16
20
17
21
We use two spaces as the unit of indentation. We don't use tabs.
18
22
23
+
To break long lines, please closely follow the indentation conventions you see in the existing codebase. (FIXME: Describe in detail.)
24
+
25
+
Our primary rule is that if we need to break a list (such as arguments, tuple or array/dictionary literals, generic type parameters, etc.), then we always put each item on its own line, indented by +1 unit, even if a series of items would fit on a single line together.
26
+
27
+
The rationale for this is that line breaks tend to put strong visual emphasis on the item that follows them, allowing subsequent items on the same line to be glanced over during review. For example, see how easy it is to accidentally miss `arg2` in the second example below.
The rules typically don't require breaking lines that don't exceed the length limit; but if you find it helps understanding, feel free to do so anyway.
54
+
55
+
```swift
56
+
// OK
57
+
guardlet foo = foo else { returnfalse }
58
+
59
+
// Also OK
60
+
guardlet foo = foo else {
61
+
returnfalse
62
+
}
63
+
```
64
+
65
+
#### Presentation of Type Definitions
66
+
67
+
To ease reading/understanding type declarations, we prefer to define members in the following order:
68
+
69
+
1. Crucial type aliases and nested types, not exceeding a handful of lines in length
70
+
2. Stored properties
71
+
3. Initializers
72
+
4. Any other instance members (methods, calculated properties)
73
+
74
+
Please keep all stored properties together in a single uninterrupted list, followed immediately by the type's most crucial initializer(s). Put these as close to the top of the type declaration as possible -- we don't want to force readers to scroll around to find these core definitions.
75
+
76
+
The main declaration ought to be kept as short as possible -- preferably it should consist of the type's stored properties and a handful of critical initializers, and nothing else.
77
+
Everything else should go in standalone extensions, arranged by logical theme. For example, it's often better to define protocolconformances in dedicated extensions. Think about what order you present these -- put related conformances together, follow some didactic arc, etc. (E.g, conformance definitions for `Equatable`/`Hashable`/`Comparable` should be kept very close to each other, for easy referencing.)
78
+
79
+
It's okay for the core type declaration to forward reference large nested types or static members that are defined in subsequent extensions. It's often a good idea to define these in an extension immediately following the type declaration, but this is not a strict rule. The goal is to make things easy to understand -- if a type is small enough, it may be fine to put every member directly in the `struct`/`class` definition, while it may make sense to break the definition of a huge type into a number of source files.
80
+
81
+
```
82
+
// BAD (a jumbled mess)
83
+
struct Foo: RandomAccessCollection, Hashable{
84
+
var count: Int { ... }
85
+
86
+
structIterator: IteratorProtocol{ /* hundreds of lines */ }
0 commit comments