Skip to content

Commit

Permalink
Add SwiftLint rules to project
Browse files Browse the repository at this point in the history
SwiftLint will ensure consistent rules such as public types using the
appropriate prefix, valid identifier names, etc.

Co-authored-by: Grant Neufeld <activist@gmail.com>
  • Loading branch information
alicerunsonfedora and grantneufeld committed Jan 18, 2025
1 parent 39fc510 commit 5f66f17
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 93 deletions.
45 changes: 45 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
included:
- Sources

allow_zero_lintable_files: false
strict: false
lenient: false
check_for_updates: true
force_cast: warning
force_try:
severity: warning
line_length: 120
type_body_length:
- 300
- 400
file_length:
warning: 500
error: 1200

type_name:
min_length: 3
max_length:
warning: 40
error: 50
excluded: iPhone
allowed_symbols: ["_"]
identifier_name:
min_length:
error: 2
excluded:
- x
- y
- up
- id
- URL
- GlobalAPIKey
custom_rules:
pk_header:
name: "Consistent PuzzleKit Header"
regex: "(public|open) (final +)?(class|enum|struct|protocol) ([^P].|.[^K])"
capture_group: 4
match_kinds:
- identifier
message: "Public-facing types must be prefixed with 'PK'."
severity: warning
reporter: "xcode"
11 changes: 10 additions & 1 deletion Package.resolved
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "6230822fda4d48a6effa9ee9a66ef003d919801cc84bb804a93e1bcc9b6817c8",
"originHash" : "46446cc224ca4a72f5f8b34e6bd41077e94aa39f86e3cda5ed4c903db2f7f13f",
"pins" : [
{
"identity" : "swift-docc-plugin",
Expand All @@ -18,6 +18,15 @@
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
"version" : "1.0.0"
}
},
{
"identity" : "swiftlintplugins",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SimplyDanny/SwiftLintPlugins",
"state" : {
"revision" : "7a3d77f3dd9f91d5cea138e52c20cfceabf352de",
"version" : "0.58.2"
}
}
],
"version" : 3
Expand Down
4 changes: 3 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/apple/swift-docc-plugin.git", from: "1.0.0"),
.package(url: "https://github.com/SimplyDanny/SwiftLintPlugins", from: "0.58.2"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "PuzzleKit"),
name: "PuzzleKit",
plugins: [.plugin(name: "SwiftLintBuildToolPlugin", package: "SwiftLintPlugins")]),
.testTarget(
name: "PuzzleKitTests",
dependencies: ["PuzzleKit"]
Expand Down
4 changes: 2 additions & 2 deletions Sources/PuzzleKit/Generic/PKFloodFillable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extension PKGrid where Self: PKFloodFillable {
var stack = [origin]
var visited = Set<PKGridCoordinate>()
var region = Set<PKGridCoordinate>()
var criterion: Criteria? = nil
var criterion: Criteria?

while !stack.isEmpty {
guard let top = stack.popLast(), let tile = self.tile(at: top) else {
Expand Down Expand Up @@ -69,7 +69,7 @@ extension PKGrid where Self: PKFloodFillable {
stack.append(down)
}
}

return region
}
}
5 changes: 2 additions & 3 deletions Sources/PuzzleKit/Generic/PKGridCoordinate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public struct PKGridCoordinate: Hashable, Equatable, Sendable {
}

// - MARK: Neighbor Coordinates (Non-nullable/Coalescing)

/// Retrieves the coordinate above.
public func above() -> Self {
return .init(x: self.x, y: max(1, self.y - 1))
Expand Down Expand Up @@ -99,7 +99,6 @@ public struct PKGridCoordinate: Hashable, Equatable, Sendable {
return .init(x: max(1, self.x - 1), y: self.y)
}


/// Returns the coordinate below, or nil if the expected coordinate reaches out of bounds.
/// - Parameter maximum: The maximum coordinate on the Y axis.
public func below(stoppingAt maximum: Int? = nil) -> Self? {
Expand Down Expand Up @@ -140,7 +139,7 @@ public extension PKGridCoordinate {
}

/// Subtracts a scalar integer value from a grid coordinate.
static func - (lhs:PKGridCoordinate, rhs: Int) -> PKGridCoordinate {
static func - (lhs: PKGridCoordinate, rhs: Int) -> PKGridCoordinate {
.init(x: rhs - lhs.x, y: rhs - lhs.y)
}
}
6 changes: 4 additions & 2 deletions Sources/PuzzleKit/Generic/PKGridRegion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public struct PKGridRegion: Hashable, Equatable, Identifiable {
}

/// Returns an array of coordinates that describe the shape of the region, relative to an origin coordinate.
/// - Parameter origin: The origin tile to reference. If none is provided, the first tile in the region will be used.
/// - Parameter origin: The origin tile to reference. If none is provided, the first tile in the region will be
/// used.
public func shape(relativeTo origin: PKGridCoordinate? = nil) -> [PKGridCoordinate] {
guard let realOrigin = origin ?? coordinates.first else { return [] }
return coordinates.map { $0 - realOrigin }
Expand All @@ -54,7 +55,8 @@ public extension PKGridRegion {
/// - Parameter origin: The origin tile to start flood-filling from.
/// - Parameter grid: The grid to flood-fill into.
/// - Parameter id: The region's unique identifier.
init<Grid>(floodFillingFrom origin: PKGridCoordinate, in grid: Grid, identifiedBy id: Int) where Grid: PKGrid & PKFloodFillable {
init<Grid>(floodFillingFrom origin: PKGridCoordinate, in grid: Grid, identifiedBy id: Int)
where Grid: PKGrid & PKFloodFillable {
let region = grid.findFloodFilledRegion(startingAt: origin)
coordinates = Array(region)
self.id = id
Expand Down
2 changes: 1 addition & 1 deletion Sources/PuzzleKit/Generic/StringExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extension String {
let idx = self.index(self.startIndex, offsetBy: offset)
return self[idx]
}

init?(charCode: UInt32) {
guard let scalar = UnicodeScalar(charCode) else { return nil }
let char = Character(scalar)
Expand Down
21 changes: 12 additions & 9 deletions Sources/PuzzleKit/Taiji/PKTaijiDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

enum PKTaijiDecoder {
typealias DecodeError = PKTaijiPuzzleDecoderError
struct Constants: Sendable {
static let digits: String = "1234567890"
static let upperAlphabet: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Expand Down Expand Up @@ -38,7 +39,8 @@ enum PKTaijiDecoder {
case error(PKTaijiPuzzleDecoderError)
}

static func decode(from source: String) throws(PKTaijiPuzzleDecoderError) -> (Int, [PKTaijiTile], PKTaijiMechanics) {
// swiftlint:disable:next function_body_length cyclomatic_complexity large_tuple
static func decode(from source: String) throws(DecodeError) -> (Int, [PKTaijiTile], PKTaijiMechanics) {
var tiles = [PKTaijiTile]()
var mechanics: PKTaijiMechanics = []
var boardWidth = 0
Expand All @@ -52,7 +54,7 @@ enum PKTaijiDecoder {
case let (char, .initial) where Constants.digits.contains(char),
let (char, .getWidth) where Constants.digits.contains(char):
if state == .initial { state = .getWidth }
widthString = widthString + String(char)
widthString += String(char)
case (":", .getWidth):
guard let convertedNumber = Int(widthString) else {
throw .invalidBoardWidth
Expand All @@ -62,7 +64,8 @@ enum PKTaijiDecoder {
case (Constants.fillEmpty, .scanForTile):
state = .prefillArray(invisible: false)

// NOTE: Check for the changes here, because doing so after skipping the attributes is too much to handle.
// NOTE: Check for the changes here, because doing so after skipping the attributes is too much to
// handle.
if let lastTile = tiles.last, lastTile.state != .normal, lastTile.filled {
filledSymbolicTile = false
}
Expand Down Expand Up @@ -93,7 +96,7 @@ enum PKTaijiDecoder {
value = abs(9 - value)
}
var tile = PKTaijiTile.symbolic(.dot(value: value, additive: additive))
if let (extendedAttrs, readChars) = Self.getExtendedAttributes(after: charIndex, in: source) {
if let (extendedAttrs, readChars) = Self.getAttributes(after: charIndex, in: source) {
tile = tile.applying(attributes: extendedAttrs)
state = .readExtendedAttributes
extendedAttrsChars = readChars
Expand All @@ -109,7 +112,7 @@ enum PKTaijiDecoder {
}
let value = Constants.flowers.distance(to: index)
var tile = PKTaijiTile.symbolic(.flower(petals: value))
if let (extendedAttrs, readChars) = Self.getExtendedAttributes(after: charIndex, in: source) {
if let (extendedAttrs, readChars) = Self.getAttributes(after: charIndex, in: source) {
tile = tile.applying(attributes: extendedAttrs)
state = .readExtendedAttributes
extendedAttrsChars = readChars
Expand All @@ -121,7 +124,7 @@ enum PKTaijiDecoder {
}
case (Constants.diamond, .scanForTile):
var tile = PKTaijiTile.symbolic(.diamond)
if let (extendedAttrs, readChars) = Self.getExtendedAttributes(after: charIndex, in: source) {
if let (extendedAttrs, readChars) = Self.getAttributes(after: charIndex, in: source) {
tile = tile.applying(attributes: extendedAttrs)
state = .readExtendedAttributes
extendedAttrsChars = readChars
Expand All @@ -133,7 +136,7 @@ enum PKTaijiDecoder {
mechanics.insert(.diamond)
case (Constants.dash, .scanForTile), (Constants.slash, .scanForTile):
var tile = PKTaijiTile.symbolic(.slashdash(rotates: character == Constants.slash))
if let (extendedAttrs, readChars) = Self.getExtendedAttributes(after: charIndex, in: source) {
if let (extendedAttrs, readChars) = Self.getAttributes(after: charIndex, in: source) {
tile = tile.applying(attributes: extendedAttrs)
state = .readExtendedAttributes
extendedAttrsChars = readChars
Expand Down Expand Up @@ -180,7 +183,7 @@ enum PKTaijiDecoder {
}
}

private static func getExtendedAttributes(after index: Int, in source: String) -> (PKTaijiExtendedAttributes, Int)? {
private static func getAttributes(after index: Int, in source: String) -> (PKTaijiExtendedAttributes, Int)? {
var color: PKTaijiSymbolColor?
var readChars = 0
var (filled, state) = (false, PKTaijiTileState.normal)
Expand All @@ -190,7 +193,7 @@ enum PKTaijiDecoder {
if Constants.colors.contains(colorCharacter) {
color = Constants.colorMap[colorCharacter] ?? .black
readChars += 1

let attribCharacter = source[source.index(after: strIndex)]
if Constants.specialDigits.contains(attribCharacter) {
readChars += 1
Expand Down
24 changes: 13 additions & 11 deletions Sources/PuzzleKit/Taiji/PKTaijiEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension PKTaijiTile {
}
tileCode += String(character)

let color = Constants.colorMap.first { (key: Character, value: PKTaijiSymbolColor) in
let color = Constants.colorMap.first { (_: Character, value: PKTaijiSymbolColor) in
value == self.color
}?.key
if let color {
Expand All @@ -35,36 +35,38 @@ extension PKTaijiTile {
}
}
}
tileCode += getBackgroundState()
return tileCode
}

private func getBackgroundState() -> String {
var stateAttribute = "0"
switch (self.state) {
switch self.state {
case .invisible:
stateAttribute = "8"
case .fixed:
stateAttribute = self.filled ? "6" : "4"
case .normal:
stateAttribute = self.filled ? "2" : "0"
}
tileCode += stateAttribute

return tileCode
return stateAttribute
}
}

enum PKTaijiEncoder {
typealias Constants = PKTaijiDecoder.Constants

static func encode(_ puzzle: PKTaijiPuzzle) -> String {
let prefix = "\(puzzle.width):"
var encodedString = puzzle.tiles.map { $0.encode() }.reduce("", +)

// NOTE: Reverse the contents of the range, because we want to go top-down instead of bottom-up.
for i in (2...26).reversed() {
guard let character = String(charCode: 64 + i) else { continue }
for charIdx in (2...26).reversed() {
guard let character = String(charCode: 64 + charIdx) else { continue }

encodedString = encodedString
.replacingOccurrences(of: String(repeating: "0", count: i), with: "+" + character)
.replacingOccurrences(of: String(repeating: "8", count: i), with: "-" + character)
.replacingOccurrences(of: String(repeating: "0", count: charIdx), with: "+" + character)
.replacingOccurrences(of: String(repeating: "8", count: charIdx), with: "-" + character)
}

return prefix + encodedString
Expand Down
14 changes: 7 additions & 7 deletions Sources/PuzzleKit/Taiji/PKTaijiPuzzle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -175,20 +175,20 @@ extension PKTaijiPuzzle: PKGridStretchable {
var copy = self
copy.width += 1

for i in 1...self.height {
let index = i * self.width
for row in 1...self.height {
let index = row * self.width
copy.tiles.insert(.empty(), at: index + 1)
}

return copy
}

public func appendingRow() -> PKTaijiPuzzle {
var copy = self
copy.tiles += Array(repeating: .empty(), count: width)
return copy
}

public func removingLastColumn() -> PKTaijiPuzzle {
var copy = self
copy.width -= 1
Expand All @@ -203,10 +203,10 @@ extension PKTaijiPuzzle: PKGridStretchable {
copy.tiles.append(tile)
column += 1
}

return copy
}

public func removingLastRow() -> PKTaijiPuzzle {
var copy = self
copy.tiles.removeLast(copy.width)
Expand Down
Loading

0 comments on commit 5f66f17

Please sign in to comment.