Skip to content

Commit 94274ef

Browse files
chore(lint): Add swiftlint (#4259)
* chore(lint): Add swiftlint * add swift lint and fix package scripts * fix swift lint
1 parent 8c88ac7 commit 94274ef

8 files changed

+185
-26
lines changed

.swiftlint.yml

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# We have to narrow down the included files to avoid minutes long lint runs due to node_modules
2+
included:
3+
- 'samples/react-native/ios/**'
4+
- 'packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/**'
5+
- 'packages/core/ios/**'
6+
- 'performance-tests/TestAppPlain/ios/**'
7+
- 'performance-tests/TestAppSentry/ios/**'
8+
9+
excluded:
10+
- 'samples/react-native/ios/Pods'
11+
- 'samples/react-native/ios/build'
12+
- 'performance-tests/TestAppPlain/ios/Pods'
13+
- 'performance-tests/TestAppPlain/ios/build'
14+
- 'performance-tests/TestAppSentry/ios/Pods'
15+
- 'performance-tests/TestAppSentry/ios/build'
16+
17+
only_rules:
18+
- class_delegate_protocol
19+
- closing_brace
20+
- closure_end_indentation
21+
- closure_parameter_position
22+
- closure_spacing
23+
- colon
24+
- comma
25+
- compiler_protocol_init
26+
- control_statement
27+
- custom_rules
28+
- cyclomatic_complexity
29+
- dynamic_inline
30+
- empty_parameters
31+
- empty_parentheses_with_trailing_closure
32+
- explicit_init
33+
- file_length
34+
- first_where
35+
- force_cast
36+
- force_try
37+
- force_unwrapping
38+
- function_body_length
39+
- generic_type_name
40+
- implicit_getter
41+
- large_tuple
42+
- leading_whitespace
43+
- legacy_cggeometry_functions
44+
- legacy_constant
45+
- legacy_constructor
46+
- legacy_nsgeometry_functions
47+
- line_length
48+
- mark
49+
- nimble_operator
50+
- number_separator
51+
- opening_brace
52+
- operator_usage_whitespace
53+
- operator_whitespace
54+
- overridden_super_call
55+
- private_outlet
56+
- private_unit_test
57+
- prohibited_super_call
58+
- redundant_nil_coalescing
59+
- redundant_optional_initialization
60+
- redundant_string_enum_value
61+
- redundant_void_return
62+
- return_arrow_whitespace
63+
- shorthand_operator
64+
- sorted_imports
65+
- statement_position
66+
- syntactic_sugar
67+
- todo
68+
- trailing_comma
69+
- trailing_newline
70+
- trailing_semicolon
71+
- type_body_length
72+
- type_name
73+
- unused_closure_parameter
74+
- unused_enumerated
75+
- unused_optional_binding
76+
- valid_ibinspectable
77+
- identifier_name
78+
- vertical_parameter_alignment
79+
- vertical_whitespace
80+
- void_return
81+
- weak_delegate
82+
- yoda_condition
83+
84+
identifier_name:
85+
allowed_symbols:
86+
- i
87+
- _
88+
min_length:
89+
- 1
90+
max_length:
91+
warning: 50
92+
error: 50
93+
94+
line_length:
95+
- 1000
96+
type_name:
97+
min_length:
98+
- 2
99+
- 1
100+
max_length:
101+
warning: 50
102+
error: 50
103+
large_tuple:
104+
- 3

package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,26 @@
77
"clean": "lerna run clean",
88
"circularDepCheck": "lerna run circularDepCheck",
99
"test": "lerna run test",
10-
"fix": "run-s fix:lerna fix:android fix:clang",
10+
"fix": "run-s fix:lerna fix:android fix:clang fix:swift",
1111
"fix:lerna": "lerna run fix",
1212
"fix:android": "run-s 'java:format fix' java:pmd",
1313
"fix:clang": "run-s 'clang:format fix'",
14-
"lint": "run-s lint:lerna lint:android lint:clang",
14+
"fix:swift": "run-s 'swift:lint fix'",
15+
"lint": "run-s lint:lerna lint:android lint:clang lint:swift",
1516
"lint:lerna": "lerna run lint",
1617
"lint:android": "run-s 'java:format lint' java:pmd",
1718
"lint:clang": "run-s 'clang:format lint'",
19+
"lint:swift": "run-s 'swift:lint lint'",
1820
"java:format": "./scripts/google-java-format.sh",
1921
"java:pmd": "./scripts/pmd.sh",
2022
"clang:format": "./scripts/clang-format.sh",
23+
"swift:lint": "./scripts/swiftlint.sh",
2124
"run-ios": "cd samples/react-native && yarn react-native run-ios",
2225
"run-android": "cd samples/react-native && yarn react-native run-android",
2326
"set-version-samples": "lerna run set-version"
2427
},
2528
"devDependencies": {
29+
"@expo/swiftlint": "^0.57.1",
2630
"@sentry/cli": "2.38.2",
2731
"clang-format": "^1.8.0",
2832
"downlevel-dts": "^0.11.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
parent_config: ../../../.swiftlint.yml
2+
3+
disabled_rules:
4+
- force_cast
5+
- force_try
6+
- force_unwrapping
7+
- function_body_length
8+
- identifier_name
9+
- large_tuple
10+
- type_body_length
11+
- weak_delegate

packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryBreadcrumbTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import XCTest
21
import Sentry
2+
import XCTest
33

44
class RNSentryBreadcrumbTests: XCTestCase {
55

packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryReplayBreadcrumbConverterTests.swift

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import XCTest
21
import Sentry
2+
import XCTest
33

44
final class RNSentryReplayBreadcrumbConverterTests: XCTestCase {
55

@@ -12,7 +12,7 @@ final class RNSentryReplayBreadcrumbConverterTests: XCTestCase {
1212
testBreadcrumb.category = "navigation"
1313
testBreadcrumb.data = [
1414
"from": "HomeScreen",
15-
"to": "ProfileScreen",
15+
"to": "ProfileScreen"
1616
]
1717
let actual = converter.convert(from: testBreadcrumb)
1818

@@ -36,7 +36,7 @@ final class RNSentryReplayBreadcrumbConverterTests: XCTestCase {
3636
testBreadcrumb.type = "navigation"
3737
testBreadcrumb.category = "navigation"
3838
testBreadcrumb.data = [
39-
"to": "ProfileScreen",
39+
"to": "ProfileScreen"
4040
]
4141
let actual = converter.convert(from: testBreadcrumb)
4242

@@ -48,7 +48,7 @@ final class RNSentryReplayBreadcrumbConverterTests: XCTestCase {
4848
assertRRWebBreadcrumbDefaults(actual: event)
4949
XCTAssertEqual("info", payload["level"] as! String)
5050
XCTAssertEqual("navigation", payload["category"] as! String)
51-
XCTAssertNil(payloadData["from"] ?? nil)
51+
XCTAssertNil(payloadData["from"])
5252
XCTAssertEqual("ProfileScreen", payloadData["to"] as! String)
5353
}
5454

@@ -63,7 +63,7 @@ final class RNSentryReplayBreadcrumbConverterTests: XCTestCase {
6363
XCTAssertNotNil(actual)
6464
let event = actual!.serialize()
6565
let data = event["data"] as! [String: Any?]
66-
let payload = data["payload"] as! [String: Any?];
66+
let payload = data["payload"] as! [String: Any?]
6767
assertRRWebBreadcrumbDefaults(actual: event)
6868
XCTAssertEqual(payload["category"] as! String, "app.foreground")
6969
}
@@ -79,7 +79,7 @@ final class RNSentryReplayBreadcrumbConverterTests: XCTestCase {
7979
XCTAssertNotNil(actual)
8080
let event = actual!.serialize()
8181
let data = event["data"] as! [String: Any?]
82-
let payload = data["payload"] as! [String: Any?];
82+
let payload = data["payload"] as! [String: Any?]
8383
assertRRWebBreadcrumbDefaults(actual: event)
8484
XCTAssertEqual(payload["category"] as! String, "app.background")
8585
}
@@ -132,18 +132,18 @@ final class RNSentryReplayBreadcrumbConverterTests: XCTestCase {
132132

133133
func testTouchMessageReturnsNilOnEmptyArray() throws {
134134
let actual = RNSentryReplayBreadcrumbConverter.getTouchPathMessage(from: [])
135-
XCTAssertEqual(actual, nil);
135+
XCTAssertEqual(actual, nil)
136136
}
137137

138138
func testTouchMessageReturnsNilOnNilArray() throws {
139139
let actual = RNSentryReplayBreadcrumbConverter.getTouchPathMessage(from: nil as [Any]?)
140-
XCTAssertEqual(actual, nil);
140+
XCTAssertEqual(actual, nil)
141141
}
142142

143143
func testTouchMessageReturnsNilOnMissingNameAndLevel() throws {
144144
let testPath: [Any?] = [["element": "element4", "file": "file4"]]
145145
let actual = RNSentryReplayBreadcrumbConverter.getTouchPathMessage(from: testPath as [Any])
146-
XCTAssertEqual(actual, nil);
146+
XCTAssertEqual(actual, nil)
147147
}
148148

149149
func testTouchMessageReturnsMessageOnValidPathExample1() throws {
@@ -153,10 +153,10 @@ final class RNSentryReplayBreadcrumbConverterTests: XCTestCase {
153153
["name": "item2", "label": "label2"],
154154
["name": "item3", "label": "label3", "element": "element3"],
155155
["name": "item4", "label": "label4", "file": "file4"],
156-
["name": "item5", "label": "label5", "element": "element5", "file": "file5"],
156+
["name": "item5", "label": "label5", "element": "element5", "file": "file5"]
157157
]
158158
let actual = RNSentryReplayBreadcrumbConverter.getTouchPathMessage(from: testPath as [Any])
159-
XCTAssertEqual(actual, "label3(element3) > label2 > name1 > label0");
159+
XCTAssertEqual(actual, "label3(element3) > label2 > name1 > label0")
160160
}
161161

162162
func testTouchMessageReturnsMessageOnValidPathExample2() throws {
@@ -166,17 +166,17 @@ final class RNSentryReplayBreadcrumbConverterTests: XCTestCase {
166166
["name": "item4", "label": "label4", "file": "file4"],
167167
["name": "item5", "label": "label5", "element": "element5", "file": "file5"],
168168
["label": "label6"],
169-
["name": "name7"],
169+
["name": "name7"]
170170
]
171171
let actual = RNSentryReplayBreadcrumbConverter.getTouchPathMessage(from: testPath as [Any])
172-
XCTAssertEqual(actual, "label5(element5, file5) > label4(file4) > label3(element3) > label2");
172+
XCTAssertEqual(actual, "label5(element5, file5) > label4(file4) > label3(element3) > label2")
173173
}
174174

175175
private func assertRRWebBreadcrumbDefaults(actual: [String: Any?]) {
176176
let data = actual["data"] as! [String: Any?]
177177
let payload = data["payload"] as! [String: Any?]
178178
XCTAssertEqual("default", payload["type"] as! String)
179-
XCTAssertEqual((payload["timestamp"] as! Double) * 1000.0, Double(actual["timestamp"] as! Int), accuracy: 1.0)
179+
XCTAssertEqual((payload["timestamp"] as! Double) * 1_000.0, Double(actual["timestamp"] as! Int), accuracy: 1.0)
180180
XCTAssertTrue(payload["timestamp"] as! Double > 0.0)
181181
}
182182

packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryReplayOptionsTests.swift

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import XCTest
21
import Sentry
2+
import XCTest
33

44
final class RNSentryReplayOptions: XCTestCase {
55

@@ -26,8 +26,8 @@ final class RNSentryReplayOptions: XCTestCase {
2626
] as NSDictionary).mutableCopy() as! NSMutableDictionary
2727
RNSentryReplay.updateOptions(optionsDict)
2828

29-
let experimental = optionsDict["experimental"] as! [String:Any]
30-
let sessionReplay = experimental["sessionReplay"] as! [String:Any]
29+
let experimental = optionsDict["experimental"] as! [String: Any]
30+
let sessionReplay = experimental["sessionReplay"] as! [String: Any]
3131

3232
assertAllDefaultReplayOptionsAreNotNil(replayOptions: sessionReplay)
3333
}
@@ -41,8 +41,8 @@ final class RNSentryReplayOptions: XCTestCase {
4141
] as NSDictionary).mutableCopy() as! NSMutableDictionary
4242
RNSentryReplay.updateOptions(optionsDict)
4343

44-
let experimental = optionsDict["experimental"] as! [String:Any]
45-
let sessionReplay = experimental["sessionReplay"] as! [String:Any]
44+
let experimental = optionsDict["experimental"] as! [String: Any]
45+
let sessionReplay = experimental["sessionReplay"] as! [String: Any]
4646

4747
assertAllDefaultReplayOptionsAreNotNil(replayOptions: sessionReplay)
4848
}
@@ -57,8 +57,8 @@ final class RNSentryReplayOptions: XCTestCase {
5757
] as NSDictionary).mutableCopy() as! NSMutableDictionary
5858
RNSentryReplay.updateOptions(optionsDict)
5959

60-
let experimental = optionsDict["experimental"] as! [String:Any]
61-
let sessionReplay = experimental["sessionReplay"] as! [String:Any]
60+
let experimental = optionsDict["experimental"] as! [String: Any]
61+
let sessionReplay = experimental["sessionReplay"] as! [String: Any]
6262

6363
assertAllDefaultReplayOptionsAreNotNil(replayOptions: sessionReplay)
6464
}
@@ -105,8 +105,8 @@ final class RNSentryReplayOptions: XCTestCase {
105105

106106
XCTAssertEqual(optionsDict.count, 3)
107107

108-
let experimental = optionsDict["experimental"] as! [String:Any]
109-
let sessionReplay = experimental["sessionReplay"] as! [String:Any]
108+
let experimental = optionsDict["experimental"] as! [String: Any]
109+
let sessionReplay = experimental["sessionReplay"] as! [String: Any]
110110

111111
let maskedViewClasses = sessionReplay["maskedViewClasses"] as! [String]
112112
XCTAssertEqual(maskedViewClasses.count, 1)

scripts/swiftlint.sh

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/bash
2+
3+
set -eo pipefail
4+
5+
# Check if an argument is provided
6+
if [ $# -eq 0 ]; then
7+
echo "Usage: $0 <fix|lint>"
8+
exit 1
9+
fi
10+
11+
# Set the mode based on the first argument
12+
mode=$1
13+
14+
DARWIN_PATH="$(dirname "$0")/../node_modules/@expo/swiftlint/bin/darwin-arm64/swiftlint"
15+
LINUX_PATH="$(dirname "$0")/../node_modules/@expo/swiftlint/bin/linux-x64/swiftlint"
16+
17+
if [[ "$OSTYPE" == "darwin"* ]]; then
18+
CMD="$DARWIN_PATH"
19+
else
20+
CMD="$LINUX_PATH"
21+
fi
22+
23+
if [ "$mode" = "fix" ]; then
24+
$CMD --fix
25+
elif [ "$mode" = "lint" ]; then
26+
$CMD --strict
27+
else
28+
echo "Invalid mode. Use 'fix' or 'lint'."
29+
exit 1
30+
fi

yarn.lock

+10
Original file line numberDiff line numberDiff line change
@@ -3176,6 +3176,15 @@ __metadata:
31763176
languageName: node
31773177
linkType: hard
31783178

3179+
"@expo/swiftlint@npm:^0.57.1":
3180+
version: 0.57.1
3181+
resolution: "@expo/swiftlint@npm:0.57.1"
3182+
dependencies:
3183+
"@expo/spawn-async": ^1.5.0
3184+
checksum: 87f744bb45cc3a4aa2a40424d21995547c138eef4d4918a3990859c9f143acd3ce463ff3f0c421c0b3e95a694abf7d8fcb8c8545dbe00d81767fc461a68c8378
3185+
languageName: node
3186+
linkType: hard
3187+
31793188
"@expo/vector-icons@npm:^14.0.0":
31803189
version: 14.0.2
31813190
resolution: "@expo/vector-icons@npm:14.0.2"
@@ -22891,6 +22900,7 @@ __metadata:
2289122900
version: 0.0.0-use.local
2289222901
resolution: "sentry-react-native@workspace:."
2289322902
dependencies:
22903+
"@expo/swiftlint": ^0.57.1
2289422904
"@sentry/cli": 2.38.2
2289522905
clang-format: ^1.8.0
2289622906
downlevel-dts: ^0.11.0

0 commit comments

Comments
 (0)