Fix an issue where logs would be printed asynchronously. Fixes #200.

This commit is contained in:
JP Simard
2015-11-17 18:15:13 -08:00
parent 7199e2256f
commit 306a80a00a
6 changed files with 58 additions and 17 deletions
+4
View File
@@ -48,6 +48,10 @@
[Mickael Morier](https://github.com/mmorier)
[#135](https://github.com/realm/SwiftLint/issues/135)
* Fix an issue where logs would be printed asynchronously over each other.
[JP Simard](https://github.com/jpsim)
[#200](https://github.com/realm/SwiftLint/issues/200)
## 0.3.0: Wrinkly Rules
@@ -0,0 +1,34 @@
//
// QueuedPrint.swift
// SwiftLint
//
// Created by JP Simard on 2015-11-17.
// Copyright © 2015 Realm. All rights reserved.
//
import Foundation
private let outputQueue: dispatch_queue_t = {
let queue = dispatch_queue_create("io.realm.swiftlint.outputQueue", DISPATCH_QUEUE_SERIAL)
dispatch_set_target_queue(queue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0))
atexit_b {
dispatch_barrier_sync(queue) {}
}
return queue
}()
/// A thread-safe version of Swift's standard print().
public func queuedPrint<T>(object: T) {
dispatch_async(outputQueue) {
print(object, terminator: "")
}
}
/// A thread-safe, newline-terminated version of fputs(..., stderr).
public func queuedPrintError(string: String) {
dispatch_async(outputQueue) {
fputs(string + "\n", stderr)
}
}
@@ -57,10 +57,10 @@ public struct Configuration {
let invalidRules = disabledRules.filter({ !validRuleIdentifiers.contains($0) })
if !invalidRules.isEmpty {
for invalidRule in invalidRules {
fputs("config error: '\(invalidRule)' is not a valid rule identifier\n", stderr)
queuedPrintError("config error: '\(invalidRule)' is not a valid rule identifier")
}
let listOfValidRuleIdentifiers = validRuleIdentifiers.joinWithSeparator("\n")
fputs("Valid rule identifiers:\n\(listOfValidRuleIdentifiers)\n", stderr)
queuedPrintError("Valid rule identifiers:\n\(listOfValidRuleIdentifiers)")
}
// Validate that rule identifiers aren't listed multiple times
@@ -71,10 +71,9 @@ public struct Configuration {
accu[element] = accu[element]?.successor() ?? 1
return accu
}.filter { $0.1 > 1 }
for duplicateRule in duplicateRules {
fputs("config error: '\(duplicateRule.0)' is listed \(duplicateRule.1) times\n",
stderr)
}
queuedPrintError(duplicateRules.map { rule in
"config error: '\(rule.0)' is listed \(rule.1) times"
}.joinWithSeparator("\n"))
return nil
}
self.disabledRules = validDisabledRules
@@ -111,7 +110,7 @@ public struct Configuration {
let yamlContents = try NSString(contentsOfFile: fullPath,
encoding: NSUTF8StringEncoding) as String
if let _ = Configuration(yaml: yamlContents) {
fputs("Loading configuration from '\(path)'\n", stderr)
queuedPrintError("Loading configuration from '\(path)'")
self.init(yaml: yamlContents)!
return
}
+8 -9
View File
@@ -51,9 +51,9 @@ struct LintCommand: CommandType {
.filter({ !configuration.excluded.flatMap(filesToLintAtPath).contains($0) }) +
configuration.included.flatMap(filesToLintAtPath)
if path.isEmpty {
fputs("Linting Swift files in current working directory\n", stderr)
queuedPrintError("Linting Swift files in current working directory")
} else {
fputs("Linting Swift files at path \(path)\n", stderr)
queuedPrintError("Linting Swift files at path \(path)")
}
let files = filesToLint.flatMap(File.init)
if !files.isEmpty {
@@ -70,7 +70,7 @@ struct LintCommand: CommandType {
for (index, file) in files.enumerate() {
if let path = file.path {
let filename = (path as NSString).lastPathComponent
fputs("Linting '\(filename)' (\(index + 1)/\(files.count))\n", stderr)
queuedPrintError("Linting '\(filename)' (\(index + 1)/\(files.count))")
}
let linter = Linter(file: file, configuration: configuration)
let currentViolations = linter.styleViolations
@@ -79,22 +79,21 @@ struct LintCommand: CommandType {
if reporter.isRealtime {
let report = reporter.generateReport(currentViolations)
if !report.isEmpty {
print(report)
queuedPrint(report)
}
}
}
if !reporter.isRealtime {
print(reporter.generateReport(violations))
queuedPrint(reporter.generateReport(violations))
}
let numberOfSeriousViolations = violations.filter({ $0.severity == .Error }).count
let violationSuffix = (violations.count != 1 ? "s" : "")
let filesSuffix = (files.count != 1 ? "s." : ".")
fputs(
queuedPrintError(
"Done linting!" +
" Found \(violations.count) violation\(violationSuffix)," +
" \(numberOfSeriousViolations) serious" +
" in \(files.count) file\(filesSuffix)\n",
stderr
" in \(files.count) file\(filesSuffix)"
)
if strict && !violations.isEmpty {
return .Failure(CommandantError<()>.CommandError())
@@ -152,7 +151,7 @@ struct LintCommand: CommandType {
case let .Success(path):
return path
case let .Failure(error):
fputs("\(error)\n", stderr)
queuedPrintError(String(error))
return nil
}
}
+2 -1
View File
@@ -7,6 +7,7 @@
//
import Commandant
import SwiftLintFramework
let registry = CommandRegistry<()>()
registry.register(LintCommand())
@@ -15,5 +16,5 @@ registry.register(HelpCommand(registry: registry))
registry.register(RulesCommand())
registry.main(defaultVerb: LintCommand().verb) { error in
fputs("\(error)\n", stderr)
queuedPrintError(String(error))
}
+4
View File
@@ -26,6 +26,7 @@
E812249C1B04FADC001783D2 /* Linter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E812249B1B04FADC001783D2 /* Linter.swift */; };
E816194C1BFBF35D00946723 /* SwiftDeclarationKind+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E816194B1BFBF35D00946723 /* SwiftDeclarationKind+SwiftLint.swift */; };
E816194E1BFBFEAB00946723 /* ForceTryRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E816194D1BFBFEAB00946723 /* ForceTryRule.swift */; };
E81619531BFC162C00946723 /* QueuedPrint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81619521BFC162C00946723 /* QueuedPrint.swift */; };
E832F10B1B17E2F5003F265F /* NSFileManager+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E832F10A1B17E2F5003F265F /* NSFileManager+SwiftLint.swift */; };
E832F10D1B17E725003F265F /* IntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E832F10C1B17E725003F265F /* IntegrationTests.swift */; };
E83A0B351A5D382B0041A60A /* VersionCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E83A0B341A5D382B0041A60A /* VersionCommand.swift */; };
@@ -173,6 +174,7 @@
E812249B1B04FADC001783D2 /* Linter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Linter.swift; sourceTree = "<group>"; };
E816194B1BFBF35D00946723 /* SwiftDeclarationKind+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftDeclarationKind+SwiftLint.swift"; sourceTree = "<group>"; };
E816194D1BFBFEAB00946723 /* ForceTryRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ForceTryRule.swift; sourceTree = "<group>"; };
E81619521BFC162C00946723 /* QueuedPrint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueuedPrint.swift; sourceTree = "<group>"; };
E832F10A1B17E2F5003F265F /* NSFileManager+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSFileManager+SwiftLint.swift"; sourceTree = "<group>"; };
E832F10C1B17E725003F265F /* IntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntegrationTests.swift; sourceTree = "<group>"; };
E83A0B341A5D382B0041A60A /* VersionCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VersionCommand.swift; sourceTree = "<group>"; };
@@ -487,6 +489,7 @@
24E17F701B1481FF008195BE /* File+Cache.swift */,
E88DEA741B09852000A66CB0 /* File+SwiftLint.swift */,
E832F10A1B17E2F5003F265F /* NSFileManager+SwiftLint.swift */,
E81619521BFC162C00946723 /* QueuedPrint.swift */,
E88DEA721B0984C400A66CB0 /* String+SwiftLint.swift */,
E816194B1BFBF35D00946723 /* SwiftDeclarationKind+SwiftLint.swift */,
E87E4A081BFB9CAE00FCFE46 /* SyntaxKind+SwiftLint.swift */,
@@ -688,6 +691,7 @@
E88DEA6F1B09843F00A66CB0 /* Location.swift in Sources */,
E88DEA771B098D0C00A66CB0 /* Rule.swift in Sources */,
CAF900141BED8B17006A371D /* VariableNameMaxLengthRule.swift in Sources */,
E81619531BFC162C00946723 /* QueuedPrint.swift in Sources */,
E87E4A051BFB927C00FCFE46 /* TrailingSemicolonRule.swift in Sources */,
E88198421BEA929F00333A11 /* NestingRule.swift in Sources */,
E881985B1BEA974E00333A11 /* StatementPositionRule.swift in Sources */,