Fix lint issues.

This commit is contained in:
Brent Simmons 2025-01-25 10:20:34 -08:00
parent 29e17b8654
commit 7e4fac6cae
15 changed files with 71 additions and 78 deletions

View File

@ -30,7 +30,7 @@ disabled_rules:
excluded: excluded:
- Modules/Secrets/Sources/Secrets/SecretKey.swift - Modules/Secrets/Sources/Secrets/SecretKey.swift
- Modules/Account/Tests/AccountTests/Feedly/ - Modules/Account/Tests/
- Modules/Account/Sources/Account/Feedly/ - Modules/Account/Sources/Account/Feedly/
- Widget/Resources/Localized.swift - Widget/Resources/Localized.swift
- Shared/Extensions/NSAttributedString+NetNewsWire.swift - Shared/Extensions/NSAttributedString+NetNewsWire.swift

View File

@ -11,7 +11,7 @@ import Articles
import RSWeb import RSWeb
import Secrets import Secrets
protocol AccountDelegate { protocol AccountDelegate: AnyObject {
var behaviors: AccountBehaviors { get } var behaviors: AccountBehaviors { get }

View File

@ -20,7 +20,7 @@ class FeedFinder {
if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), urlComponents.host == "micro.blog" { if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), urlComponents.host == "micro.blog" {
urlComponents.path = "\(urlComponents.path).json" urlComponents.path = "\(urlComponents.path).json"
if let newURLString = urlComponents.url?.absoluteString { if let newURLString = urlComponents.url?.absoluteString {
let microblogFeedSpecifier = FeedSpecifier(title: nil, urlString: newURLString, source: .HTMLLink, orderFound: 1) let microblogFeedSpecifier = FeedSpecifier(title: nil, urlString: newURLString, source: .htmlLink, orderFound: 1)
completion(.success(Set([microblogFeedSpecifier]))) completion(.success(Set([microblogFeedSpecifier])))
} }
} else { } else {
@ -45,7 +45,7 @@ class FeedFinder {
} }
if FeedFinder.isFeed(data) { if FeedFinder.isFeed(data) {
let feedSpecifier = FeedSpecifier(title: nil, urlString: url.absoluteString, source: .UserEntered, orderFound: 1) let feedSpecifier = FeedSpecifier(title: nil, urlString: url.absoluteString, source: .userEntered, orderFound: 1)
completion(.success(Set([feedSpecifier]))) completion(.success(Set([feedSpecifier])))
return return
} }
@ -86,7 +86,7 @@ private extension FeedFinder {
var didFindFeedInHTMLHead = false var didFindFeedInHTMLHead = false
for oneFeedSpecifier in possibleFeedSpecifiers { for oneFeedSpecifier in possibleFeedSpecifiers {
if oneFeedSpecifier.source == .HTMLHead { if oneFeedSpecifier.source == .htmlHead {
addFeedSpecifier(oneFeedSpecifier, feedSpecifiers: &feedSpecifiers) addFeedSpecifier(oneFeedSpecifier, feedSpecifiers: &feedSpecifiers)
didFindFeedInHTMLHead = true didFindFeedInHTMLHead = true
} else { } else {
@ -116,11 +116,11 @@ private extension FeedFinder {
// Its also fairly common for /index.xml to work. // Its also fairly common for /index.xml to work.
if let url = URL(string: urlString) { if let url = URL(string: urlString) {
let feedURL = url.appendingPathComponent("feed", isDirectory: true) let feedURL = url.appendingPathComponent("feed", isDirectory: true)
let wordpressFeedSpecifier = FeedSpecifier(title: nil, urlString: feedURL.absoluteString, source: .HTMLLink, orderFound: 1) let wordpressFeedSpecifier = FeedSpecifier(title: nil, urlString: feedURL.absoluteString, source: .htmlLink, orderFound: 1)
feedSpecifiers.insert(wordpressFeedSpecifier) feedSpecifiers.insert(wordpressFeedSpecifier)
let indexXMLURL = url.appendingPathComponent("index.xml", isDirectory: false) let indexXMLURL = url.appendingPathComponent("index.xml", isDirectory: false)
let indexXMLFeedSpecifier = FeedSpecifier(title: nil, urlString: indexXMLURL.absoluteString, source: .HTMLLink, orderFound: 1) let indexXMLFeedSpecifier = FeedSpecifier(title: nil, urlString: indexXMLURL.absoluteString, source: .htmlLink, orderFound: 1)
feedSpecifiers.insert(indexXMLFeedSpecifier) feedSpecifiers.insert(indexXMLFeedSpecifier)
} }
} }

View File

@ -11,7 +11,7 @@ import Foundation
struct FeedSpecifier: Hashable { struct FeedSpecifier: Hashable {
enum Source: Int { enum Source: Int {
case UserEntered = 0, HTMLHead, HTMLLink case userEntered = 0, htmlHead, htmlLink
func equalToOrBetterThan(_ otherSource: Source) -> Bool { func equalToOrBetterThan(_ otherSource: Source) -> Bool {
return self.rawValue <= otherSource.rawValue return self.rawValue <= otherSource.rawValue
@ -64,39 +64,39 @@ private extension FeedSpecifier {
func calculatedScore() -> Int { func calculatedScore() -> Int {
var score = 0 var score = 0
if source == .UserEntered { if source == .userEntered {
return 1000 return 1000
} else if source == .HTMLHead { } else if source == .htmlHead {
score = score + 50 score += 50
} }
score = score - ((orderFound - 1) * 5) score -= (orderFound - 1) * 5
if urlString.caseInsensitiveContains("comments") { if urlString.caseInsensitiveContains("comments") {
score = score - 10 score -= 10
} }
if urlString.caseInsensitiveContains("podcast") { if urlString.caseInsensitiveContains("podcast") {
score = score - 10 score -= 10
} }
if urlString.caseInsensitiveContains("rss") { if urlString.caseInsensitiveContains("rss") {
score = score + 5 score += 5
} }
if urlString.hasSuffix("/feed/") { if urlString.hasSuffix("/feed/") {
score = score + 5 score += 5
} }
if urlString.hasSuffix("/feed") { if urlString.hasSuffix("/feed") {
score = score + 4 score += 4
} }
if urlString.caseInsensitiveContains("json") { if urlString.caseInsensitiveContains("json") {
score = score + 6 score += 6
} }
if let title = title { if let title = title {
if title.caseInsensitiveContains("comments") { if title.caseInsensitiveContains("comments") {
score = score - 10 score -= 10
} }
if title.caseInsensitiveContains("json") { if title.caseInsensitiveContains("json") {
score = score + 1 score += 1
} }
} }

View File

@ -26,8 +26,8 @@ class HTMLFeedFinder {
if let feedLinks = metadata.feedLinks { if let feedLinks = metadata.feedLinks {
for oneFeedLink in feedLinks { for oneFeedLink in feedLinks {
if let oneURLString = oneFeedLink.urlString?.normalizedURL { if let oneURLString = oneFeedLink.urlString?.normalizedURL {
orderFound = orderFound + 1 orderFound += 1
let oneFeedSpecifier = FeedSpecifier(title: oneFeedLink.title, urlString: oneURLString, source: .HTMLHead, orderFound: orderFound) let oneFeedSpecifier = FeedSpecifier(title: oneFeedLink.title, urlString: oneURLString, source: .htmlHead, orderFound: orderFound)
addFeedSpecifier(oneFeedSpecifier) addFeedSpecifier(oneFeedSpecifier)
} }
} }
@ -36,8 +36,8 @@ class HTMLFeedFinder {
let bodyLinks = HTMLLinkParser.htmlLinks(with: parserData) let bodyLinks = HTMLLinkParser.htmlLinks(with: parserData)
for oneBodyLink in bodyLinks { for oneBodyLink in bodyLinks {
if linkMightBeFeed(oneBodyLink), let normalizedURL = oneBodyLink.urlString?.normalizedURL { if linkMightBeFeed(oneBodyLink), let normalizedURL = oneBodyLink.urlString?.normalizedURL {
orderFound = orderFound + 1 orderFound += 1
let oneFeedSpecifier = FeedSpecifier(title: oneBodyLink.text, urlString: normalizedURL, source: .HTMLLink, orderFound: orderFound) let oneFeedSpecifier = FeedSpecifier(title: oneBodyLink.text, urlString: normalizedURL, source: .htmlLink, orderFound: orderFound)
addFeedSpecifier(oneFeedSpecifier) addFeedSpecifier(oneFeedSpecifier)
} }
} }

View File

@ -486,6 +486,7 @@ final class FeedbinAPICaller: NSObject {
} }
// swiftlint:disable:next large_tuple
func retrieveEntries(completion: @escaping (Result<([FeedbinEntry]?, String?, Date?, Int?), Error>) -> Void) { func retrieveEntries(completion: @escaping (Result<([FeedbinEntry]?, String?, Date?, Int?), Error>) -> Void) {
// If this is an initial sync, go and grab the previous 3 months of entries. If not, use the last // If this is an initial sync, go and grab the previous 3 months of entries. If not, use the last

View File

@ -938,9 +938,7 @@ private extension FeedbinAccountDelegate {
return d return d
} }
func sendArticleStatuses(_ statuses: [SyncStatus], func sendArticleStatuses(_ statuses: [SyncStatus], apiCall: ([Int], @escaping (Result<Void, Error>) -> Void) -> Void, completion: @escaping ((Result<Void, Error>) -> Void)) {
apiCall: ([Int], @escaping (Result<Void, Error>) -> Void) -> Void,
completion: @escaping ((Result<Void, Error>) -> Void)) {
guard !statuses.isEmpty else { guard !statuses.isEmpty else {
completion(.success(())) completion(.success(()))
@ -1011,8 +1009,8 @@ private extension FeedbinAccountDelegate {
var orderFound = 0 var orderFound = 0
let feedSpecifiers: [FeedSpecifier] = choices.map { choice in let feedSpecifiers: [FeedSpecifier] = choices.map { choice in
let source = url == choice.url ? FeedSpecifier.Source.UserEntered : FeedSpecifier.Source.HTMLLink let source = url == choice.url ? FeedSpecifier.Source.userEntered : FeedSpecifier.Source.htmlLink
orderFound = orderFound + 1 orderFound += 1
let specifier = FeedSpecifier(title: choice.name, urlString: choice.url, source: source, orderFound: orderFound) let specifier = FeedSpecifier(title: choice.name, urlString: choice.url, source: source, orderFound: orderFound)
return specifier return specifier
} }

View File

@ -14,13 +14,13 @@ import Articles
import ArticlesDatabase import ArticlesDatabase
import os import os
protocol LocalAccountRefresherDelegate { protocol LocalAccountRefresherDelegate: AnyObject {
func localAccountRefresher(_ refresher: LocalAccountRefresher, articleChanges: ArticleChanges) func localAccountRefresher(_ refresher: LocalAccountRefresher, articleChanges: ArticleChanges)
} }
final class LocalAccountRefresher { final class LocalAccountRefresher {
var delegate: LocalAccountRefresherDelegate? weak var delegate: LocalAccountRefresherDelegate?
var downloadProgress: DownloadProgress { var downloadProgress: DownloadProgress {
downloadSession.downloadProgress downloadSession.downloadProgress
} }

View File

@ -22,9 +22,9 @@ public extension URLRequest {
switch credentials.type { switch credentials.type {
case .basic: case .basic:
let data = "\(credentials.username):\(credentials.secret)".data(using: .utf8) let data = Data("\(credentials.username):\(credentials.secret)".utf8)
let base64 = data?.base64EncodedString() let base64 = data.base64EncodedString()
let auth = "Basic \(base64 ?? "")" let auth = "Basic \(base64)"
setValue(auth, forHTTPHeaderField: HTTPRequestHeader.authorization) setValue(auth, forHTTPHeaderField: HTTPRequestHeader.authorization)
case .newsBlurBasic: case .newsBlurBasic:
setValue("application/x-www-form-urlencoded", forHTTPHeaderField: HTTPRequestHeader.contentType) setValue("application/x-www-form-urlencoded", forHTTPHeaderField: HTTPRequestHeader.contentType)
@ -75,7 +75,5 @@ public extension URLRequest {
if let etag = conditionalGet.etag { if let etag = conditionalGet.etag {
setValue(etag, forHTTPHeaderField: HTTPRequestHeader.ifNoneMatch) setValue(etag, forHTTPHeaderField: HTTPRequestHeader.ifNoneMatch)
} }
} }
} }

View File

@ -55,7 +55,7 @@ public struct JSONFeedParser {
throw FeedParserError(.invalidJSON) throw FeedParserError(.invalidJSON)
} }
guard let version = d[Key.version] as? String, let _ = version.range(of: JSONFeedParser.jsonFeedVersionMarker) else { guard let version = d[Key.version] as? String, version.range(of: JSONFeedParser.jsonFeedVersionMarker) != nil else {
throw FeedParserError(.jsonFeedVersionNotFound) throw FeedParserError(.jsonFeedVersionNotFound)
} }
guard let itemsArray = d[Key.items] as? JSONArray else { guard let itemsArray = d[Key.items] as? JSONArray else {

View File

@ -108,7 +108,7 @@ public extension DatabaseTable {
func containsColumn(_ columnName: String, in database: FMDatabase) -> Bool { func containsColumn(_ columnName: String, in database: FMDatabase) -> Bool {
if let resultSet = database.executeQuery("select * from \(name) limit 1;", withArgumentsIn: nil) { if let resultSet = database.executeQuery("select * from \(name) limit 1;", withArgumentsIn: nil) {
if let columnMap = resultSet.columnNameToIndexMap { if let columnMap = resultSet.columnNameToIndexMap {
if let _ = columnMap[columnName.lowercased()] { if columnMap[columnName.lowercased()] != nil {
return true return true
} }
} }

View File

@ -67,7 +67,7 @@ public extension DatabaseRelatedObjectsTable {
// Objects in cache must already exist in database. Filter them out. // Objects in cache must already exist in database. Filter them out.
let objectsToSave = objects.filter { (object) -> Bool in let objectsToSave = objects.filter { (object) -> Bool in
if let _ = cache[object.databaseID] { if cache[object.databaseID] != nil {
return false return false
} }
return true return true

View File

@ -59,26 +59,26 @@ public final class DownloadProgress {
public func addToNumberOfTasks(_ n: Int) { public func addToNumberOfTasks(_ n: Int) {
assert(Thread.isMainThread) assert(Thread.isMainThread)
numberOfTasks = numberOfTasks + n numberOfTasks += n
} }
public func addToNumberOfTasksAndRemaining(_ n: Int) { public func addToNumberOfTasksAndRemaining(_ n: Int) {
assert(Thread.isMainThread) assert(Thread.isMainThread)
numberOfTasks = numberOfTasks + n numberOfTasks += n
numberRemaining = numberRemaining + n numberRemaining += n
} }
public func completeTask() { public func completeTask() {
assert(Thread.isMainThread) assert(Thread.isMainThread)
if numberRemaining > 0 { if numberRemaining > 0 {
numberRemaining = numberRemaining - 1 numberRemaining -= 1
} }
} }
public func completeTasks(_ tasks: Int) { public func completeTasks(_ tasks: Int) {
assert(Thread.isMainThread) assert(Thread.isMainThread)
if numberRemaining >= tasks { if numberRemaining >= tasks {
numberRemaining = numberRemaining - tasks numberRemaining -= tasks
} }
} }

View File

@ -12,7 +12,7 @@ import os
// Create a DownloadSessionDelegate, then create a DownloadSession. // Create a DownloadSessionDelegate, then create a DownloadSession.
// To download things: call download with a set of URLs. DownloadSession will call the various delegate methods. // To download things: call download with a set of URLs. DownloadSession will call the various delegate methods.
public protocol DownloadSessionDelegate { public protocol DownloadSessionDelegate: AnyObject {
func downloadSession(_ downloadSession: DownloadSession, conditionalGetInfoFor: URL) -> HTTPConditionalGetInfo? func downloadSession(_ downloadSession: DownloadSession, conditionalGetInfoFor: URL) -> HTTPConditionalGetInfo?
func downloadSession(_ downloadSession: DownloadSession, downloadDidComplete: URL, response: URLResponse?, data: Data, error: NSError?) func downloadSession(_ downloadSession: DownloadSession, downloadDidComplete: URL, response: URLResponse?, data: Data, error: NSError?)
@ -246,7 +246,7 @@ private extension DownloadSession {
updateDownloadProgress() updateDownloadProgress()
} }
func urlStringIsBlackListedRedirect(_ urlString: String) -> Bool { func urlStringIsDisallowedRedirect(_ urlString: String) -> Bool {
// Hotels and similar often do permanent redirects. We can catch some of those. // Hotels and similar often do permanent redirects. We can catch some of those.
@ -263,7 +263,7 @@ private extension DownloadSession {
} }
func cacheRedirect(_ oldURL: URL, _ newURL: URL) { func cacheRedirect(_ oldURL: URL, _ newURL: URL) {
if urlStringIsBlackListedRedirect(newURL.absoluteString) { if urlStringIsDisallowedRedirect(newURL.absoluteString) {
return return
} }
redirectCache[oldURL] = newURL redirectCache[oldURL] = newURL

View File

@ -86,17 +86,13 @@ public class Reachability {
fileprivate let reachabilitySerialQueue: DispatchQueue fileprivate let reachabilitySerialQueue: DispatchQueue
fileprivate(set) var flags: SCNetworkReachabilityFlags? fileprivate(set) var flags: SCNetworkReachabilityFlags?
required public init(reachabilityRef: SCNetworkReachability, required public init(reachabilityRef: SCNetworkReachability, queueQoS: DispatchQoS = .default, targetQueue: DispatchQueue? = nil) {
queueQoS: DispatchQoS = .default,
targetQueue: DispatchQueue? = nil) {
self.allowsCellularConnection = true self.allowsCellularConnection = true
self.reachabilityRef = reachabilityRef self.reachabilityRef = reachabilityRef
self.reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability", qos: queueQoS, target: targetQueue) self.reachabilitySerialQueue = DispatchQueue(label: "uk.co.ashleymills.reachability", qos: queueQoS, target: targetQueue)
} }
public convenience init(hostname: String, public convenience init(hostname: String, queueQoS: DispatchQoS = .default, targetQueue: DispatchQueue? = nil) throws {
queueQoS: DispatchQoS = .default,
targetQueue: DispatchQueue? = nil) throws {
guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else { guard let ref = SCNetworkReachabilityCreateWithName(nil, hostname) else {
throw ReachabilityError.failedToCreateWithHostname(hostname, SCError()) throw ReachabilityError.failedToCreateWithHostname(hostname, SCError())
} }
@ -192,16 +188,16 @@ extension SCNetworkReachabilityFlags {
} }
var description: String { var description: String {
let W = isOnWWANFlagSet ? "W" : "-" let onWWANFlagSet = isOnWWANFlagSet ? "W" : "-"
let R = isReachableFlagSet ? "R" : "-" let reachableFlagSet = isReachableFlagSet ? "R" : "-"
let c = isConnectionRequiredFlagSet ? "c" : "-" let connectionRequiredFlagSet = isConnectionRequiredFlagSet ? "c" : "-"
let t = isTransientConnectionFlagSet ? "t" : "-" let transientConnectionFlagSet = isTransientConnectionFlagSet ? "t" : "-"
let i = isInterventionRequiredFlagSet ? "i" : "-" let interventionRequiredFlagSet = isInterventionRequiredFlagSet ? "i" : "-"
let C = isConnectionOnTrafficFlagSet ? "C" : "-" let connectionOnTrafficFlagSet = isConnectionOnTrafficFlagSet ? "C" : "-"
let D = isConnectionOnDemandFlagSet ? "D" : "-" let connectionOnDemandFlagSet = isConnectionOnDemandFlagSet ? "D" : "-"
let l = isLocalAddressFlagSet ? "l" : "-" let localAddressFlagSet = isLocalAddressFlagSet ? "l" : "-"
let d = isDirectFlagSet ? "d" : "-" let directFlagSet = isDirectFlagSet ? "d" : "-"
return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)" return "\(onWWANFlagSet)\(reachableFlagSet) \(connectionRequiredFlagSet)\(transientConnectionFlagSet)\(interventionRequiredFlagSet)\(connectionOnTrafficFlagSet)\(connectionOnDemandFlagSet)\(localAddressFlagSet)\(directFlagSet)"
} }
} }