Skip to content

Commit

Permalink
Merge pull request #11 from g-Off/swift-5
Browse files Browse the repository at this point in the history
Swift 5
  • Loading branch information
g-Off authored Jun 12, 2019
2 parents edbca5c + fe55e69 commit 3189d89
Show file tree
Hide file tree
Showing 34 changed files with 315 additions and 256 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/.build
/Packages
/*.xcodeproj
.swiftpm
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM swift:4.2.1
COPY Package.swift ./Package.swift
COPY Sources ./Sources
COPY Tests ./Tests
RUN swift test --configuration debug
44 changes: 0 additions & 44 deletions Makefile

This file was deleted.

1 change: 0 additions & 1 deletion Overrides.xcconfig

This file was deleted.

12 changes: 6 additions & 6 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,26 @@
"repositoryURL": "https://github.com/scottrhoyt/SwiftyTextTable.git",
"state": {
"branch": null,
"revision": "7b8661865f0d9590a4b7c146237fecd99f3d8406",
"version": "0.8.2"
"revision": "c6df6cf533d120716bff38f8ff9885e1ce2a4ac3",
"version": "0.9.0"
}
},
{
"package": "XcodeProject",
"repositoryURL": "https://github.com/g-Off/XcodeProject.git",
"state": {
"branch": null,
"revision": "a1e12a8659684039258b79761c65abb9ec98fc94",
"version": "0.4.0"
"revision": "f5095a860de4cd1f0e635957bed7c4b80392dac8",
"version": "0.5.0"
}
},
{
"package": "Yams",
"repositoryURL": "https://github.com/jpsim/Yams.git",
"state": {
"branch": null,
"revision": "26ab35f50ea891e8edefcc9d975db2f6b67e1d68",
"version": "1.0.1"
"revision": "b08dba4bcea978bf1ad37703a384097d3efce5af",
"version": "1.0.2"
}
}
]
Expand Down
33 changes: 27 additions & 6 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
// swift-tools-version:4.2
// swift-tools-version:5.0
import PackageDescription

let package = Package(
name: "stringray",
platforms: [
.macOS(.v10_14)
],
products: [
.executable(
name: "stringray",
targets: ["stringray"]
),
.library(
name: "RayGun",
targets: ["RayGun"]
)
],
dependencies: [
.package(url: "https://github.com/jpsim/Yams.git", from: "1.0.1"),
.package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.5.0"),
.package(url: "https://github.com/g-Off/XcodeProject.git", from: "0.4.0"),
.package(url: "https://github.com/g-Off/CommandRegistry.git", .branch("master"))
.package(url: "https://github.com/g-Off/XcodeProject.git", from: "0.5.0-alpha.3"),
.package(url: "https://github.com/g-Off/CommandRegistry.git", from: "0.1.0"),
.package(url: "https://github.com/apple/swift-package-manager.git", from: "0.3.0")
],
targets: [
.target(
name: "stringray",
dependencies: [
"Yams",
"CommandRegistry",
"RayGun",
"SwiftyTextTable",
"XcodeProject",
"CommandRegistry"
"Utility",
"Yams",
]
),
.target(
name: "RayGun",
dependencies: [
]
),
.testTarget(
name: "stringrayTests",
dependencies: ["stringray"]),
dependencies: ["RayGun"]),
]
)
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

import Foundation

extension URL {
var tableName: String? {
extension Foundation.URL {
public var tableName: String? {
var url = self
if ["strings", "stringsdict"].contains(url.pathExtension) {
url.deletePathExtension()
Expand All @@ -17,7 +17,7 @@ extension URL {
return nil
}

var locale: Locale? {
public var locale: Locale? {
var url = self
if ["strings", "stringsdict"].contains(url.pathExtension) {
url.deleteLastPathComponent()
Expand All @@ -29,7 +29,7 @@ extension URL {
return nil
}

var resourceDirectory: URL {
public var resourceDirectory: Foundation.URL {
var dir = self
if dir.pathExtension == "strings" || dir.pathExtension == "stringsdict" {
dir.deleteLastPathComponent()
Expand All @@ -40,38 +40,38 @@ extension URL {
return dir
}

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

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

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

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

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

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

private func fileURL(tableName: String, locale: Locale, ext: String, create: Bool) throws -> URL {
private func fileURL(tableName: String, locale: Locale, ext: String, create: Bool) throws -> Foundation.URL {
let lprojURL = appendingPathComponent("\(locale.identifier).lproj", isDirectory: true)
if create {
try FileManager.default.createDirectory(at: lprojURL, withIntermediateDirectories: true, attributes: nil)
Expand Down
56 changes: 56 additions & 0 deletions Sources/RayGun/Lint Rules/LintRule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//
// LintRule.swift
// stringray
//
// Created by Geoffrey Foster on 2018-11-07.
//

import Foundation

public protocol LintRule {
var info: RuleInfo { get }
func scan(table: StringsTable, url: Foundation.URL, config: Linter.Config.Rule?) throws -> [LintRuleViolation]
}

public struct RuleInfo {
public let identifier: String
public let name: String
public let description: String
public let severity: Severity
}

public enum Severity: String, CustomStringConvertible, Decodable {
case warning
case error

public var description: String {
return rawValue
}
}

public struct LintRuleViolation {
public struct Location: CustomStringConvertible {
public let file: Foundation.URL
public let line: Int?

public var description: String {
var path = file.lastPathComponent
if let line = line {
path.append(":\(line)")
}
return path
}
}

public let locale: Locale
public let location: Location
public let severity: Severity
public let reason: String

public init(locale: Locale, location: Location, severity: Severity, reason: String) {
self.locale = locale
self.location = location
self.severity = severity
self.reason = reason
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
//

import Foundation
import Yams

struct Linter {
struct Config: Decodable {
struct Rule: Decodable {
public struct Linter {
public struct Config: Decodable {
public struct Rule: Decodable {
let severity: Severity
}
let included: [String]
Expand All @@ -23,57 +22,54 @@ struct Linter {
case rules
}

init() {
public init() {
self.included = []
self.excluded = []
self.rules = [:]
}

init(url: URL) throws {
let string = try String(contentsOf: url, encoding: .utf8)
self = try YAMLDecoder().decode(Config.self, from: string, userInfo: [:])
}

init(from decoder: Decoder) throws {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.included = try container.decodeIfPresent([String].self, forKey: .included) ?? []
self.excluded = try container.decodeIfPresent([String].self, forKey: .excluded) ?? []
self.rules = try container.decodeIfPresent([String: Rule].self, forKey: .rules) ?? [:]
}
}

static let fileName = ".stringray.yml"
public static let fileName = ".stringray.yml"

static let allRules: [LintRule] = [
public static let allRules: [LintRule] = [
MissingLocalizationLintRule(),
OrphanedLocalizationLintRule(),
MissingPlaceholderLintRule()
MissingPlaceholderLintRule(),
MissingCommentLintRule()
]

struct Error: LocalizedError {
var violations: [LintRuleViolation]
init(_ violations: [LintRuleViolation]) {
public struct Error: LocalizedError {
public private(set) var violations: [LintRuleViolation]

public init(_ violations: [LintRuleViolation]) {
self.violations = violations
}

var errorDescription: String? {
public var errorDescription: String? {
let errorCount = violations.filter { $0.severity == .error }.count
let warningCount = violations.filter { $0.severity == .warning }.count
return "Encountered \(errorCount) errors and \(warningCount) warnings."
}
}

let rules: [LintRule]
public let rules: [LintRule]
private let reporter: Reporter
private let config: Config

init(rules: [LintRule] = Linter.allRules, reporter: Reporter = ConsoleReporter(), config: Config = Config()) {
public init(rules: [LintRule] = Linter.allRules, reporter: Reporter, config: Config = Config()) {
self.rules = rules
self.reporter = reporter
self.config = config
}

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

let includedRules = Set(config.included)
Expand All @@ -93,7 +89,7 @@ struct Linter {
}
}

func report(on table: StringsTable, url: URL) throws {
public func report(on table: StringsTable, url: Foundation.URL) throws {
let violations = try run(on: table, url: url)
var outputStream = LinterOutputStream(fileHandle: FileHandle.standardOutput)
reporter.generateReport(for: violations, to: &outputStream)
Expand Down
25 changes: 25 additions & 0 deletions Sources/RayGun/Lint Rules/MissingCommentLintRule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// MissingCommentLintRule.swift
// RayGun
//
// Created by Geoffrey Foster on 2019-06-02.
//

import Foundation

struct MissingCommentLintRule: LintRule {
let info: RuleInfo = RuleInfo(identifier: "missing_comment", name: "Missing Comment", description: "", severity: .error)

func scan(table: StringsTable, url: Foundation.URL, config: Linter.Config.Rule?) throws -> [LintRuleViolation] {
var violations: [LintRuleViolation] = []
let file = Foundation.URL(fileURLWithPath: "\(table.base.identifier).lproj/\(table.name).strings", relativeTo: url)
for entry in table.baseEntries where entry.comment == nil {
let line = entry.location?.line
let location = LintRuleViolation.Location(file: file, line: line)
let reason = "Mismatched placeholders \(entry.key)"
let violation = LintRuleViolation(locale: table.base, location: location, severity: config?.severity ?? info.severity, reason: reason)
violations.append(violation)
}
return violations
}
}
Loading

0 comments on commit 3189d89

Please sign in to comment.