Skip to content

Commit e57f50b

Browse files
committed
Add .swift-format and fix lint warnings
1 parent c9e9adb commit e57f50b

36 files changed

+481
-70
lines changed

.github/workflows/VerifyChanges.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,22 @@ on:
88
branches: [ $default-branch ]
99

1010
jobs:
11+
lint:
12+
name: Lint
13+
runs-on: macos-15
14+
if: ${{ github.event_name == 'pull_request' }}
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
- name: Select Xcode 16.4
19+
run: |
20+
sudo xcode-select -s /Applications/Xcode_16.4.0.app
21+
- name: Lint
22+
run: |
23+
Scripts/lint
1124
build-and-test:
1225
name: Build and Test (${{ matrix.platform }})
26+
needs: lint
1327
runs-on: macos-15
1428
strategy:
1529
fail-fast: false

.swift-format

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
"fileScopedDeclarationPrivacy": {
3+
"accessLevel": "private"
4+
},
5+
"indentConditionalCompilationBlocks": false,
6+
"indentSwitchCaseLabels": false,
7+
"indentation": {
8+
"spaces": 4
9+
},
10+
"lineBreakAroundMultilineExpressionChainComponents": false,
11+
"lineBreakBeforeControlFlowKeywords": false,
12+
"lineBreakBeforeEachArgument": false,
13+
"lineBreakBeforeEachGenericRequirement": false,
14+
"lineBreakBetweenDeclarationAttributes": false,
15+
"lineLength": 120,
16+
"maximumBlankLines": 2,
17+
"multiElementCollectionTrailingCommas": true,
18+
"noAssignmentInExpressions": {
19+
"allowedFunctions": []
20+
},
21+
"prioritizeKeepingFunctionOutputTogether": true,
22+
"reflowMultilineStringLiterals": {
23+
"never": {}
24+
},
25+
"respectsExistingLineBreaks": true,
26+
"rules": {
27+
"AllPublicDeclarationsHaveDocumentation": false,
28+
"AlwaysUseLiteralForEmptyCollectionInit": true,
29+
"AlwaysUseLowerCamelCase": true,
30+
"AmbiguousTrailingClosureOverload": true,
31+
"AvoidRetroactiveConformances": false,
32+
"BeginDocumentationCommentWithOneLineSummary": true,
33+
"DoNotUseSemicolons": true,
34+
"DontRepeatTypeInStaticProperties": true,
35+
"FileScopedDeclarationPrivacy": true,
36+
"FullyIndirectEnum": true,
37+
"GroupNumericLiterals": true,
38+
"IdentifiersMustBeASCII": true,
39+
"NeverForceUnwrap": false,
40+
"NeverUseForceTry": false,
41+
"NeverUseImplicitlyUnwrappedOptionals": false,
42+
"NoAccessLevelOnExtensionDeclaration": true,
43+
"NoAssignmentInExpressions": true,
44+
"NoBlockComments": true,
45+
"NoCasesWithOnlyFallthrough": true,
46+
"NoEmptyLinesOpeningClosingBraces": false,
47+
"NoEmptyTrailingClosureParentheses": true,
48+
"NoLabelsInCasePatterns": true,
49+
"NoLeadingUnderscores": false,
50+
"NoParensAroundConditions": true,
51+
"NoPlaygroundLiterals": true,
52+
"NoVoidReturnOnFunctionSignature": true,
53+
"OmitExplicitReturns": false,
54+
"OneCasePerLine": true,
55+
"OneVariableDeclarationPerLine": true,
56+
"OnlyOneTrailingClosureArgument": true,
57+
"OrderedImports": true,
58+
"ReplaceForEachWithForLoop": true,
59+
"ReturnVoidInsteadOfEmptyTuple": true,
60+
"TypeNamesShouldBeCapitalized": true,
61+
"UseEarlyExits": true,
62+
"UseExplicitNilCheckInConditions": true,
63+
"UseLetInEveryBoundCaseVariable": true,
64+
"UseShorthandTypeNames": true,
65+
"UseSingleLinePropertyGetter": true,
66+
"UseSynthesizedInitializer": true,
67+
"UseTripleSlashForDocumentationComments": true,
68+
"UseWhereClausesInForLoops": true,
69+
"ValidateDocumentationComments": false
70+
},
71+
"spacesAroundRangeFormationOperators": true,
72+
"spacesBeforeEndOfLineComments": 4,
73+
"tabWidth": 4,
74+
"version": 1
75+
}

CLAUDE.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this
4+
repository.
5+
6+
7+
## Development Commands
8+
9+
### Building and Testing
10+
11+
- **Build for testing**: `swift build --package-path . --disable-automatic-resolution`
12+
- **Run tests**: `swift test --package-path . --disable-automatic-resolution`
13+
- **Run tests with code coverage**: Tests are run through the GitHub Actions workflow using
14+
`build_and_test.sh` from DevBuilds
15+
- **Test specific platform**: Use `xcodebuild` with appropriate destination (see
16+
`.github/workflows/VerifyChanges.yaml` for examples)
17+
18+
### Code Formatting and Linting
19+
20+
- **Lint check**: `Scripts/lint` (runs `swift format lint --recursive --strict` from anywhere)
21+
- **Format code**: `swift format --in-place --recursive Sources/ Tests/`
22+
- **Manual lint**: `swift format lint --recursive --strict Sources/ Tests/`
23+
- **Swift format configuration**: Uses `.swift-format` file with 4-space indentation and 120
24+
character line length
25+
26+
### Git Hooks
27+
28+
- **Install git hooks**: `Scripts/install-git-hooks` (installs pre-commit hook that runs lint
29+
check)
30+
- **Pre-commit hook**: Automatically runs `Scripts/lint` before each commit
31+
32+
### Documentation
33+
34+
- **Build documentation**: `swift package generate-documentation`
35+
- **Documentation source**: `Sources/DevTesting/Documentation.docc/`
36+
37+
38+
## Code Architecture
39+
40+
### Core Components
41+
42+
**RandomValueGenerating Protocol**: The central protocol that test suites conform to for generating
43+
repeatable random test data. Uses `SeedableRandomNumberGenerator` and logs seeds for test
44+
reproducibility.
45+
46+
**Three Main Feature Areas**:
47+
48+
1. **Random Value Generation** (`Sources/DevTesting/Random Value Generation/`): Extensions for
49+
generating random values of various types (String, Data, URL, UUID, etc.) with seeded
50+
randomness
51+
2. **Collection Generation** (`Sources/DevTesting/Collection Generation/`): Array extensions for
52+
generating collections of random data
53+
3. **Stubbing** (`Sources/DevTesting/Stubbing/`): `Stub` and `ThrowingStub` classes for mocking
54+
and spying in tests
55+
56+
### Key Design Patterns
57+
58+
- **Seeded Randomness**: All random generation uses `SeedableRandomNumberGenerator` to ensure
59+
test reproducibility
60+
- **Logging Integration**: Random seeds are logged using `os.Logger` (subsystem: "DevTesting",
61+
category: "randomization")
62+
- **Swift Testing Integration**: Designed specifically for Swift Testing framework, not XCTest
63+
- **Type Safety**: Extensive use of Swift 6 features including typed throws and existential
64+
types
65+
66+
### Dependencies
67+
68+
- **Swift Numerics**: Used for `RealModule` in tests
69+
- **Platform Requirements**: iOS 18+, macOS 15+, tvOS 18+, visionOS 2+, watchOS 11+
70+
- **Swift Version**: Requires Swift 6.1 toolchain
71+
72+
### Testing Strategy
73+
74+
- **Test Plans**: Uses `DevTesting.xctestplan` for organized test execution
75+
- **Coverage Target**: Aims for 99%+ test coverage
76+
- **Platform Testing**: Tests run on iOS, macOS, tvOS, and watchOS simulators
77+
- **CI/CD**: GitHub Actions workflow with matrix strategy across platforms
78+
79+
### Documentation Standards
80+
81+
- **Full Documentation**: All public APIs are documented with Swift DocC
82+
- **API Guidelines**: Follows Swift API Design Guidelines
83+
- **Documentation Comments**: Uses triple-slash comments (`///`)
84+
- **Markdown Style**: Follow `Documentation/MarkdownStyleGuide.md` for consistent formatting:
85+
- 100 character line length
86+
- 4-space indented code blocks (no fenced blocks)
87+
- 2-space indented bullet lists with alignment
88+
- Consistent terminology (function vs method, type vs class)
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
# Markdown Style Guide
2+
3+
This document defines the Markdown formatting standards for documentation in the Shopper iOS
4+
codebase.
5+
6+
7+
## General Formatting
8+
9+
### Line Length
10+
11+
Keep all lines under **100 characters**. Break long sentences and paragraphs at natural points
12+
to stay within this limit.
13+
14+
✅ Good:
15+
Faucibus consectetur lacinia nostra eros conubia nibh inceptos hendrerit, ante blandit
16+
vulputate imperdiet amet porttitor torquent mattis.
17+
18+
❌ Bad:
19+
Faucibus consectetur lacinia nostra eros conubia nibh inceptos hendrerit, ante blandit vulputate imperdiet amet porttitor torquent mattis.
20+
21+
22+
### Spacing
23+
24+
Use consistent spacing for visual hierarchy:
25+
26+
- **Between major sections**: 2 blank lines
27+
- **After code blocks**: 1 blank line
28+
- **Before subsections**: 1 blank line
29+
- **After section headers**: 1 blank line
30+
31+
Example:
32+
33+
## Major Section
34+
35+
Content here.
36+
37+
38+
## Another Major Section
39+
40+
### Subsection
41+
42+
Content after subsection header.
43+
44+
code block here
45+
46+
Content after code block.
47+
48+
49+
## Headers
50+
51+
### Structure
52+
53+
Use consistent header hierarchy:
54+
55+
- `#` for document title
56+
- `##` for major sections
57+
- `###` for subsections
58+
- `####` for sub-subsections (use sparingly)
59+
60+
### Numbering
61+
62+
Number subsections when they represent sequential steps or ordered items:
63+
64+
## Usage Patterns
65+
66+
### 1. Basic Setup
67+
### 2. Advanced Configuration
68+
### 3. Verification
69+
70+
71+
## Code Blocks
72+
73+
### Indented Code Blocks
74+
75+
Use **4-space indentation** for all code blocks instead of fenced blocks:
76+
77+
✅ Good:
78+
import DevTesting
79+
80+
final class MockService: ServiceProtocol {
81+
nonisolated(unsafe) var performActionStub: Stub<String, Bool>!
82+
}
83+
84+
❌ Bad:
85+
```swift
86+
import DevTesting
87+
88+
final class MockService: ServiceProtocol {
89+
nonisolated(unsafe) var performActionStub: Stub<String, Bool>!
90+
}
91+
```
92+
93+
94+
## Lists
95+
96+
### Unordered Lists
97+
98+
Use `-` as the bullet character for unordered lists. Place the hyphen 2 spaces from current
99+
indentation level, followed by a space, then your text. When a bullet point spans multiple lines,
100+
align continuation lines with the start of the text (not the hyphen). This ensures all text within a
101+
bullet aligns vertically and makes proper indentation on continuation lines a matter of pressing tab
102+
one or more times.
103+
104+
- Turpis cubilia sit urna dis ultricies consequat massa hendrerit enim natoque.
105+
- Consectetur sapien posuere sit arcu finibus mattis dictumst dis, lectus ipsum in dictum
106+
lobortis bibendum enim, suscipit aliquet nulla porta erat id class purus.
107+
- Scelerisque massa rutrum dapibus placerat aenean tellus arcu cursus.
108+
- Iaculis, cubilia tristique efficitur bibendum urna imperdiet facilisis turpis hac,
109+
platea est habitant auctor quisque nec pulvinar fermentum sociosqu.
110+
- Parturient justo, venenatis nunc lobortis senectus tortor orci elementum consequat.
111+
- In nibh nisl venenatis bibendum neque mattis habitant tempor proin, tincidunt lobortis
112+
vulputate commodo.
113+
114+
Blank lines can be placed between bullets if it aids in readability.
115+
116+
### Ordered Lists
117+
118+
Use standard numbered lists for sequential items. Follow similar indentation rules as for unordered
119+
lists. Note that the `.` characters in the bullets leads to some strange indentation, but this is
120+
unavoidable.
121+
122+
1. Turpis cubilia sit urna dis ultricies consequat massa hendrerit enim natoque.
123+
124+
2. Consectetur sapien posuere sit arcu finibus mattis dictumst dis, lectus ipsum in dictum
125+
lobortis bibendum enim, suscipit aliquet nulla porta erat id class purus.
126+
127+
1. Scelerisque massa rutrum dapibus placerat aenean tellus arcu cursus.
128+
2. Iaculis, cubilia tristique efficitur bibendum urna imperdiet facilisis turpis hac,
129+
platea est habitant auctor quisque nec pulvinar fermentum sociosqu.
130+
3. Parturient justo, venenatis nunc lobortis senectus tortor orci elementum consequat.
131+
132+
4. In nibh nisl venenatis bibendum neque mattis habitant tempor proin, tincidunt lobortis
133+
vulputate commodo.
134+
135+
136+
## Text Formatting
137+
138+
### Bold Text
139+
140+
Use bold for emphasis on key terms:
141+
142+
- **File names**: `Mock[ProtocolName].swift`
143+
- **Type names**: `Mock[ProtocolName]`
144+
145+
### Code Spans
146+
147+
Use backticks for:
148+
149+
- Type names: `Stub<Input, Output>`
150+
- Function names: `performAction(_:)`
151+
- File names: `MockAppServices.swift`
152+
- Keywords: `nonisolated(unsafe)`
153+
154+
### Terminology Consistency
155+
156+
Use consistent terminology throughout documents:
157+
158+
- Prefer "function" over "method" when referring to Swift functions
159+
- Use "type" instead of "class" when referring generically to classes/structs/enums
160+
- Use "property" for stored and computed properties
161+
162+
163+
## File Structure Examples
164+
165+
Use indented text blocks for file structure diagrams:
166+
167+
Tests/
168+
├── Folder 1/
169+
│ └── Folder 2/
170+
│ ├── File1.swift
171+
│ └── File2.swift
172+
└── Folder 3/
173+
└── Folder 4/
174+
├── File3.swift
175+
└── File4.swift
176+
177+
178+
## Links and References
179+
180+
### Internal References
181+
182+
Use relative paths for internal documentation:
183+
184+
See [Test Mock Documentation](TestMocks.md) for details.
185+
186+
### Code References
187+
188+
Reference specific locations using this pattern:
189+
190+
The main implementation is in `Stub.swift:42-68`.

Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ let package = Package(
2020
.library(
2121
name: "DevTesting",
2222
targets: ["DevTesting"]
23-
),
23+
)
2424
],
2525
dependencies: [
26-
.package(url: "https://github.com/apple/swift-numerics", from: "1.0.0"),
26+
.package(url: "https://github.com/apple/swift-numerics", from: "1.0.0")
2727
],
2828
targets: [
2929
.target(

0 commit comments

Comments
 (0)