Skip to content

Commit 5c8cb03

Browse files
committed
moving most of the code into a framework
1 parent edbca5c commit 5c8cb03

25 files changed

+212
-178
lines changed

Package.swift

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,42 @@ import PackageDescription
33

44
let package = Package(
55
name: "stringray",
6+
products: [
7+
.executable(
8+
name: "stringray",
9+
targets: ["stringray"]
10+
),
11+
.library(
12+
name: "RayGun",
13+
targets: ["RayGun"]
14+
)
15+
],
616
dependencies: [
717
.package(url: "https://github.com/jpsim/Yams.git", from: "1.0.1"),
818
.package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.5.0"),
919
.package(url: "https://github.com/g-Off/XcodeProject.git", from: "0.4.0"),
10-
.package(url: "https://github.com/g-Off/CommandRegistry.git", .branch("master"))
20+
.package(url: "https://github.com/g-Off/CommandRegistry.git", .branch("master")),
21+
.package(url: "https://github.com/apple/swift-package-manager.git", from: "0.3.0")
1122
],
1223
targets: [
1324
.target(
1425
name: "stringray",
1526
dependencies: [
27+
"CommandRegistry",
28+
"RayGun",
29+
"SwiftyTextTable"
30+
]
31+
),
32+
.target(
33+
name: "RayGun",
34+
dependencies: [
35+
"Utility",
1636
"Yams",
17-
"SwiftyTextTable",
18-
"XcodeProject",
19-
"CommandRegistry"
37+
"XcodeProject"
2038
]
2139
),
2240
.testTarget(
2341
name: "stringrayTests",
24-
dependencies: ["stringray"]),
42+
dependencies: ["RayGun"]),
2543
]
2644
)

Sources/RayGun/Exports.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//
2+
// Exports.swift
3+
// RayGun
4+
//
5+
// Created by Geoffrey Foster on 2019-02-01.
6+
//
7+
8+
@_exported import Basic
9+
@_exported import SwiftyTextTable
10+
@_exported import Utility
11+
@_exported import XcodeProject

Sources/stringray/Extensions/URL+Extensions.swift renamed to Sources/RayGun/Extensions/URL+Extensions.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
import Foundation
99

10-
extension URL {
11-
var tableName: String? {
10+
extension Foundation.URL {
11+
public var tableName: String? {
1212
var url = self
1313
if ["strings", "stringsdict"].contains(url.pathExtension) {
1414
url.deletePathExtension()
@@ -17,7 +17,7 @@ extension URL {
1717
return nil
1818
}
1919

20-
var locale: Locale? {
20+
public var locale: Locale? {
2121
var url = self
2222
if ["strings", "stringsdict"].contains(url.pathExtension) {
2323
url.deleteLastPathComponent()
@@ -29,7 +29,7 @@ extension URL {
2929
return nil
3030
}
3131

32-
var resourceDirectory: URL {
32+
public var resourceDirectory: Foundation.URL {
3333
var dir = self
3434
if dir.pathExtension == "strings" || dir.pathExtension == "stringsdict" {
3535
dir.deleteLastPathComponent()
@@ -40,38 +40,38 @@ extension URL {
4040
return dir
4141
}
4242

43-
var lprojURLs: [URL] {
43+
var lprojURLs: [Foundation.URL] {
4444
let directories = try? FileManager.default.contentsOfDirectory(at: self, includingPropertiesForKeys: nil, options: []).filter { (url) -> Bool in
4545
return url.pathExtension == "lproj"
4646
}
4747
return directories ?? []
4848
}
4949

50-
func stringsFiles(tableName: String) -> [URL] {
50+
func stringsFiles(tableName: String) -> [Foundation.URL] {
5151
return files(tableName: tableName, ext: "strings")
5252
}
5353

54-
func stringsDictFiles(tableName: String) -> [URL] {
54+
func stringsDictFiles(tableName: String) -> [Foundation.URL] {
5555
return files(tableName: tableName, ext: "stringsdict")
5656
}
5757

58-
private func files(tableName: String, ext: String) -> [URL] {
58+
private func files(tableName: String, ext: String) -> [Foundation.URL] {
5959
return lprojURLs.compactMap { (lprojURL) in
6060
let url = lprojURL.appendingPathComponent(tableName).appendingPathExtension(ext)
6161
guard let reachable = try? url.checkResourceIsReachable(), reachable == true else { return nil }
6262
return url
6363
}
6464
}
6565

66-
func stringsURL(tableName: String, locale: Locale) throws -> URL {
66+
func stringsURL(tableName: String, locale: Locale) throws -> Foundation.URL {
6767
return try fileURL(tableName: tableName, locale: locale, ext: "strings", create: true)
6868
}
6969

70-
func stringsDictURL(tableName: String, locale: Locale) throws -> URL {
70+
func stringsDictURL(tableName: String, locale: Locale) throws -> Foundation.URL {
7171
return try fileURL(tableName: tableName, locale: locale, ext: "stringsdict", create: true)
7272
}
7373

74-
private func fileURL(tableName: String, locale: Locale, ext: String, create: Bool) throws -> URL {
74+
private func fileURL(tableName: String, locale: Locale, ext: String, create: Bool) throws -> Foundation.URL {
7575
let lprojURL = appendingPathComponent("\(locale.identifier).lproj", isDirectory: true)
7676
if create {
7777
try FileManager.default.createDirectory(at: lprojURL, withIntermediateDirectories: true, attributes: nil)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//
2+
// LintRule.swift
3+
// stringray
4+
//
5+
// Created by Geoffrey Foster on 2018-11-07.
6+
//
7+
8+
import Foundation
9+
10+
public protocol LintRule {
11+
var info: RuleInfo { get }
12+
func scan(table: StringsTable, url: Foundation.URL, config: Linter.Config.Rule?) throws -> [LintRuleViolation]
13+
}
14+
15+
public struct RuleInfo {
16+
public let identifier: String
17+
public let name: String
18+
public let description: String
19+
public let severity: Severity
20+
}
21+
22+
public enum Severity: String, CustomStringConvertible, Decodable {
23+
case warning
24+
case error
25+
26+
public var description: String {
27+
return rawValue
28+
}
29+
}
30+
31+
public struct LintRuleViolation {
32+
public struct Location: CustomStringConvertible {
33+
public let file: Foundation.URL
34+
public let line: Int?
35+
36+
public var description: String {
37+
var path = file.lastPathComponent
38+
if let line = line {
39+
path.append(":\(line)")
40+
}
41+
return path
42+
}
43+
}
44+
45+
public let locale: Locale
46+
public let location: Location
47+
public let severity: Severity
48+
public let reason: String
49+
50+
public init(locale: Locale, location: Location, severity: Severity, reason: String) {
51+
self.locale = locale
52+
self.location = location
53+
self.severity = severity
54+
self.reason = reason
55+
}
56+
}

Sources/stringray/Lint Rules/Linter.swift renamed to Sources/RayGun/Lint Rules/Linter.swift

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import Foundation
99
import Yams
1010

11-
struct Linter {
12-
struct Config: Decodable {
13-
struct Rule: Decodable {
11+
public struct Linter {
12+
public struct Config: Decodable {
13+
public struct Rule: Decodable {
1414
let severity: Severity
1515
}
1616
let included: [String]
@@ -23,57 +23,58 @@ struct Linter {
2323
case rules
2424
}
2525

26-
init() {
26+
public init() {
2727
self.included = []
2828
self.excluded = []
2929
self.rules = [:]
3030
}
3131

32-
init(url: URL) throws {
32+
public init(url: Foundation.URL) throws {
3333
let string = try String(contentsOf: url, encoding: .utf8)
3434
self = try YAMLDecoder().decode(Config.self, from: string, userInfo: [:])
3535
}
3636

37-
init(from decoder: Decoder) throws {
37+
public init(from decoder: Decoder) throws {
3838
let container = try decoder.container(keyedBy: CodingKeys.self)
3939
self.included = try container.decodeIfPresent([String].self, forKey: .included) ?? []
4040
self.excluded = try container.decodeIfPresent([String].self, forKey: .excluded) ?? []
4141
self.rules = try container.decodeIfPresent([String: Rule].self, forKey: .rules) ?? [:]
4242
}
4343
}
4444

45-
static let fileName = ".stringray.yml"
45+
public static let fileName = ".stringray.yml"
4646

47-
static let allRules: [LintRule] = [
47+
public static let allRules: [LintRule] = [
4848
MissingLocalizationLintRule(),
4949
OrphanedLocalizationLintRule(),
5050
MissingPlaceholderLintRule()
5151
]
5252

53-
struct Error: LocalizedError {
54-
var violations: [LintRuleViolation]
55-
init(_ violations: [LintRuleViolation]) {
53+
public struct Error: LocalizedError {
54+
public private(set) var violations: [LintRuleViolation]
55+
56+
public init(_ violations: [LintRuleViolation]) {
5657
self.violations = violations
5758
}
5859

59-
var errorDescription: String? {
60+
public var errorDescription: String? {
6061
let errorCount = violations.filter { $0.severity == .error }.count
6162
let warningCount = violations.filter { $0.severity == .warning }.count
6263
return "Encountered \(errorCount) errors and \(warningCount) warnings."
6364
}
6465
}
6566

66-
let rules: [LintRule]
67+
public let rules: [LintRule]
6768
private let reporter: Reporter
6869
private let config: Config
6970

70-
init(rules: [LintRule] = Linter.allRules, reporter: Reporter = ConsoleReporter(), config: Config = Config()) {
71+
public init(rules: [LintRule] = Linter.allRules, reporter: Reporter, config: Config = Config()) {
7172
self.rules = rules
7273
self.reporter = reporter
7374
self.config = config
7475
}
7576

76-
private func run(on table: StringsTable, url: URL) throws -> [LintRuleViolation] {
77+
private func run(on table: StringsTable, url: Foundation.URL) throws -> [LintRuleViolation] {
7778
var runnableRules = self.rules
7879

7980
let includedRules = Set(config.included)
@@ -93,7 +94,7 @@ struct Linter {
9394
}
9495
}
9596

96-
func report(on table: StringsTable, url: URL) throws {
97+
public func report(on table: StringsTable, url: Foundation.URL) throws {
9798
let violations = try run(on: table, url: url)
9899
var outputStream = LinterOutputStream(fileHandle: FileHandle.standardOutput)
99100
reporter.generateReport(for: violations, to: &outputStream)

Sources/stringray/Lint Rules/MissingLocalizationLintRule.swift renamed to Sources/RayGun/Lint Rules/MissingLocalizationLintRule.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@ import Foundation
1010
struct MissingLocalizationLintRule: LintRule {
1111
let info: RuleInfo = RuleInfo(identifier: "missing_localization", name: "Missing Localization", description: "", severity: .warning)
1212

13-
func scan(table: StringsTable, url: URL, config: Linter.Config.Rule?) throws -> [LintRuleViolation] {
13+
func scan(table: StringsTable, url: Foundation.URL, config: Linter.Config.Rule?) throws -> [LintRuleViolation] {
1414
return scanEntries(table: table, url: url, config: config) + scanDictEntries(table: table, url: url, config: config)
1515
}
1616

17-
private func scanEntries(table: StringsTable, url: URL, config: Linter.Config.Rule?) -> [LintRuleViolation] {
17+
private func scanEntries(table: StringsTable, url: Foundation.URL, config: Linter.Config.Rule?) -> [LintRuleViolation] {
1818
var violations: [LintRuleViolation] = []
1919
var entries = table.entries
2020
entries.removeValue(forKey: table.base)
2121
let baseEntries = table.baseEntries
2222
for entry in entries {
2323
let missingEntries = baseEntries.subtracting(entry.value)
2424
for missingEntry in missingEntries {
25-
let file = URL(fileURLWithPath: "\(entry.key.identifier).lproj/\(table.name).strings", relativeTo: url)
25+
let file = Foundation.URL(fileURLWithPath: "\(entry.key.identifier).lproj/\(table.name).strings", relativeTo: url)
2626
let location = LintRuleViolation.Location(file: file, line: nil)
2727
let reason = "Missing \(missingEntry.key)"
2828
let violation = LintRuleViolation(locale: entry.key, location: location, severity: config?.severity ?? info.severity, reason: reason)
@@ -32,15 +32,15 @@ struct MissingLocalizationLintRule: LintRule {
3232
return violations
3333
}
3434

35-
private func scanDictEntries(table: StringsTable, url: URL, config: Linter.Config.Rule?) -> [LintRuleViolation] {
35+
private func scanDictEntries(table: StringsTable, url: Foundation.URL, config: Linter.Config.Rule?) -> [LintRuleViolation] {
3636
var violations: [LintRuleViolation] = []
3737
var dictEntries = table.dictEntries
3838
dictEntries.removeValue(forKey: table.base)
3939
let baseDictEntries = table.baseDictEntries
4040
for dictEntry in dictEntries {
4141
let missingDictEntries = baseDictEntries.filter { !dictEntry.value.keys.contains($0.key) }
4242
for missingDictEntry in missingDictEntries {
43-
let file = URL(fileURLWithPath: "\(dictEntry.key.identifier).lproj/\(table.name).stringsdict", relativeTo: url)
43+
let file = Foundation.URL(fileURLWithPath: "\(dictEntry.key.identifier).lproj/\(table.name).stringsdict", relativeTo: url)
4444
let location = LintRuleViolation.Location(file: file, line: nil)
4545
let reason = "Missing \(missingDictEntry.key)"
4646
let violation = LintRuleViolation(locale: dictEntry.key, location: location, severity: config?.severity ?? info.severity, reason: reason)

Sources/stringray/Lint Rules/MissingPlaceholderLintRule.swift renamed to Sources/RayGun/Lint Rules/MissingPlaceholderLintRule.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import Foundation
1010
struct MissingPlaceholderLintRule: LintRule {
1111
let info: RuleInfo = RuleInfo(identifier: "missing_placeholder", name: "Missing Placeholder", description: "", severity: .error)
1212

13-
func scan(table: StringsTable, url: URL, config: Linter.Config.Rule?) throws -> [LintRuleViolation] {
13+
func scan(table: StringsTable, url: Foundation.URL, config: Linter.Config.Rule?) throws -> [LintRuleViolation] {
1414
var violations: [LintRuleViolation] = []
1515
var placeholders: [String: [PlaceholderType]] = [:]
1616
try table.baseEntries.forEach {
@@ -20,7 +20,7 @@ struct MissingPlaceholderLintRule: LintRule {
2020
try entry.value.forEach {
2121
let placeholder = try PlaceholderType.orderedPlaceholders(from: $0.value)
2222
if let basePlaceholder = placeholders[$0.key], placeholder != basePlaceholder {
23-
let file = URL(fileURLWithPath: "\(entry.key.identifier).lproj/\(table.name).strings", relativeTo: url)
23+
let file = Foundation.URL(fileURLWithPath: "\(entry.key.identifier).lproj/\(table.name).strings", relativeTo: url)
2424
let line = $0.location?.line
2525
let location = LintRuleViolation.Location(file: file, line: line)
2626
let reason = "Mismatched placeholders \($0.key)"

Sources/stringray/Lint Rules/OrphanedLocalizationLintRule.swift renamed to Sources/RayGun/Lint Rules/OrphanedLocalizationLintRule.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ import Foundation
1010
struct OrphanedLocalizationLintRule: LintRule {
1111
let info: RuleInfo = RuleInfo(identifier: "orphaned_localization", name: "Orphaned Localization", description: "", severity: .warning)
1212

13-
func scan(table: StringsTable, url: URL, config: Linter.Config.Rule?) throws -> [LintRuleViolation] {
13+
func scan(table: StringsTable, url: Foundation.URL, config: Linter.Config.Rule?) throws -> [LintRuleViolation] {
1414
var violations: [LintRuleViolation] = []
1515
var entries = table.entries
1616
entries.removeValue(forKey: table.base)
1717
let baseEntries = table.baseEntries
1818
for entry in entries {
1919
let orphanedEntries = entry.value.subtracting(baseEntries)
2020
for orphanedEntry in orphanedEntries {
21-
let file = URL(fileURLWithPath: "\(entry.key.identifier).lproj/\(table.name).strings", relativeTo: url)
21+
let file = Foundation.URL(fileURLWithPath: "\(entry.key.identifier).lproj/\(table.name).strings", relativeTo: url)
2222
guard let line = orphanedEntry.location?.line else { continue }
2323
let location = LintRuleViolation.Location(file: file, line: line)
2424
let reason = "Orphaned \(orphanedEntry.key)"

Sources/stringray/Reporters/Reporter.swift renamed to Sources/RayGun/Reporters/Reporter.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77

88
import Foundation
99

10-
protocol Reporter {
10+
public protocol Reporter {
1111
func generateReport<Target: TextOutputStream>(for violations: [LintRuleViolation], to outputStream: inout Target)
1212
}

Sources/stringray/Strings Table/Cache/CachedStringsTable.swift renamed to Sources/RayGun/Strings Table/Cache/CachedStringsTable.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ struct CachedStringsTable: Codable {
2929
return stringsTable.dictEntries[locale]
3030
}
3131

32-
func isCacheValid(for locale: Locale, type: LocalizationType, base: URL) -> Bool {
32+
func isCacheValid(for locale: Locale, type: LocalizationType, base: Foundation.URL) -> Bool {
3333
do {
34-
let fileURL: URL
34+
let fileURL: Foundation.URL
3535
switch type {
3636
case .strings:
3737
fileURL = try base.stringsURL(tableName: stringsTable.name, locale: locale)

0 commit comments

Comments
 (0)