generalized rules and split off LineLengthRule

This commit is contained in:
JP Simard
2015-05-18 05:08:04 +02:00
parent df46421f95
commit 2dbd06d5aa
7 changed files with 107 additions and 16 deletions
+1 -10
View File
@@ -12,15 +12,6 @@ import SwiftXPC
typealias Line = (index: Int, content: String)
extension File {
func lineLengthViolations(lines: [Line]) -> [StyleViolation] {
return lines.filter({ count($0.content) > 100 }).map {
return StyleViolation(type: .Length,
location: Location(file: self.path, line: $0.index),
reason: "Line #\($0.index) should be 100 characters or less: " +
"currently \(count($0.content)) characters")
}
}
func leadingWhitespaceViolations(contents: String) -> [StyleViolation] {
let countOfLeadingWhitespace = contents.countOfLeadingCharactersInSet(
NSCharacterSet.whitespaceAndNewlineCharacterSet()
@@ -323,7 +314,7 @@ extension File {
let lines = contents.lines()
// FIXME: Using '+' to concatenate these arrays would be nicer,
// but slows the compiler to a crawl.
var violations = lineLengthViolations(lines)
var violations = LineLengthRule.validateFile(self)
violations.extend(leadingWhitespaceViolations(contents))
violations.extend(trailingLineWhitespaceViolations(lines))
violations.extend(trailingNewlineViolations(contents))
+18
View File
@@ -0,0 +1,18 @@
//
// Rule.swift
// SwiftLint
//
// Created by JP Simard on 2015-05-16.
// Copyright (c) 2015 Realm. All rights reserved.
//
import SourceKittenFramework
protocol Rule {
typealias ParameterType
static var identifier: String { get }
static var parameters: [RuleParameter<ParameterType>] { get }
static func validateFile(file: File) -> [StyleViolation]
}
@@ -0,0 +1,12 @@
//
// RuleParameter.swift
// SwiftLint
//
// Created by JP Simard on 2015-05-16.
// Copyright (c) 2015 Realm. All rights reserved.
//
struct RuleParameter<T> {
let severity: ViolationSeverity
let value: T
}
@@ -0,0 +1,35 @@
//
// LineLengthRule.swift
// SwiftLint
//
// Created by JP Simard on 2015-05-16.
// Copyright (c) 2015 Realm. All rights reserved.
//
import SourceKittenFramework
struct LineLengthRule: Rule {
static let identifier = "line_length"
static let parameters = [
RuleParameter(severity: .VeryLow, value: 100),
RuleParameter(severity: .Low, value: 120),
RuleParameter(severity: .Medium, value: 150),
RuleParameter(severity: .High, value: 200),
RuleParameter(severity: .VeryHigh, value: 250)
]
static func validateFile(file: File) -> [StyleViolation] {
return compact(file.contents.lines().map { line in
for parameter in reverse(self.parameters) {
if count(line.content) > parameter.value {
return StyleViolation(type: .Length,
location: Location(file: file.path, line: line.index),
severity: parameter.severity,
reason: "Line should be 100 characters or less: currently " +
"\(count(line.content)) characters")
}
}
return nil
})
}
}
@@ -20,7 +20,11 @@ public struct StyleViolation: Printable, Equatable {
}
public init(type: StyleViolationType, location: Location, reason: String? = nil) {
severity = .Low
self.init(type: type, location: location, severity: .Low, reason: reason)
}
public init(type: StyleViolationType, location: Location, severity: ViolationSeverity, reason: String? = nil) {
self.severity = severity
self.type = type
self.location = location
self.reason = reason
@@ -40,5 +44,6 @@ Returns true if `lhs` StyleViolation is equal to `rhs` StyleViolation.
public func ==(lhs: StyleViolation, rhs: StyleViolation) -> Bool {
return lhs.type == rhs.type &&
lhs.location == rhs.location &&
lhs.severity == rhs.severity &&
lhs.reason == rhs.reason
}
@@ -210,11 +210,21 @@ class LinterTests: XCTestCase {
// MARK: String Violations
func testLineLengths() {
let longLine = join("", Array(count: 100, repeatedValue: "/"))
XCTAssertEqual(violations(longLine + "\n"), [])
XCTAssertEqual(violations(longLine + "/\n"), [StyleViolation(type: .Length,
location: Location(file: nil, line: 1),
reason: "Line #1 should be 100 characters or less: currently 101 characters")])
let longLine = join("", Array(count: 100, repeatedValue: "/")) + "\n"
XCTAssertEqual(violations(longLine), [])
let testCases: [(String, Int, ViolationSeverity)] = [
("/", 101, .VeryLow),
(join("", Array(count: 21, repeatedValue: "/")), 121, .Low),
(join("", Array(count: 51, repeatedValue: "/")), 151, .Medium),
(join("", Array(count: 101, repeatedValue: "/")), 201, .High),
(join("", Array(count: 151, repeatedValue: "/")), 251, .VeryHigh)
]
for testCase in testCases {
XCTAssertEqual(violations(testCase.0 + longLine), [StyleViolation(type: .Length,
location: Location(file: nil, line: 1),
severity: testCase.2,
reason: "Line should be 100 characters or less: currently \(testCase.1) characters")])
}
}
func testTrailingNewlineAtEndOfFile() {
+20
View File
@@ -26,6 +26,9 @@
E88DEA711B09847500A66CB0 /* ViolationSeverity.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA701B09847500A66CB0 /* ViolationSeverity.swift */; };
E88DEA731B0984C400A66CB0 /* String+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA721B0984C400A66CB0 /* String+SwiftLint.swift */; };
E88DEA751B09852000A66CB0 /* File+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA741B09852000A66CB0 /* File+SwiftLint.swift */; };
E88DEA771B098D0C00A66CB0 /* Rule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA761B098D0C00A66CB0 /* Rule.swift */; };
E88DEA791B098D4400A66CB0 /* RuleParameter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA781B098D4400A66CB0 /* RuleParameter.swift */; };
E88DEA7C1B098D7D00A66CB0 /* LineLengthRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA7B1B098D7D00A66CB0 /* LineLengthRule.swift */; };
E8AB1A2E1A649F2100452012 /* libclang.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E8AB1A2D1A649F2100452012 /* libclang.dylib */; };
E8BA7E111B07A3EC003E02D0 /* Commandant.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8BA7E101B07A3EC003E02D0 /* Commandant.framework */; };
E8BA7E131B07A3F3003E02D0 /* LlamaKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8BA7E121B07A3F3003E02D0 /* LlamaKit.framework */; };
@@ -122,6 +125,9 @@
E88DEA701B09847500A66CB0 /* ViolationSeverity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViolationSeverity.swift; sourceTree = "<group>"; };
E88DEA721B0984C400A66CB0 /* String+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+SwiftLint.swift"; sourceTree = "<group>"; };
E88DEA741B09852000A66CB0 /* File+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "File+SwiftLint.swift"; sourceTree = "<group>"; };
E88DEA761B098D0C00A66CB0 /* Rule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rule.swift; sourceTree = "<group>"; };
E88DEA781B098D4400A66CB0 /* RuleParameter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RuleParameter.swift; sourceTree = "<group>"; };
E88DEA7B1B098D7D00A66CB0 /* LineLengthRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineLengthRule.swift; sourceTree = "<group>"; };
E8AB1A2D1A649F2100452012 /* libclang.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libclang.dylib; path = Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib; sourceTree = DEVELOPER_DIR; };
E8BA7E101B07A3EC003E02D0 /* Commandant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Commandant.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E8BA7E121B07A3F3003E02D0 /* LlamaKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = LlamaKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -274,7 +280,10 @@
D0D1216E19E87B05005E4BAA /* SwiftLintFramework */ = {
isa = PBXGroup;
children = (
E88DEA7A1B098D7300A66CB0 /* Rules */,
E88DEA741B09852000A66CB0 /* File+SwiftLint.swift */,
E88DEA761B098D0C00A66CB0 /* Rule.swift */,
E88DEA781B098D4400A66CB0 /* RuleParameter.swift */,
E812249B1B04FADC001783D2 /* Linter.swift */,
E88DEA6E1B09843F00A66CB0 /* Location.swift */,
E88DEA721B0984C400A66CB0 /* String+SwiftLint.swift */,
@@ -321,6 +330,14 @@
name = "Supporting Files";
sourceTree = "<group>";
};
E88DEA7A1B098D7300A66CB0 /* Rules */ = {
isa = PBXGroup;
children = (
E88DEA7B1B098D7D00A66CB0 /* LineLengthRule.swift */,
);
path = Rules;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -468,10 +485,13 @@
buildActionMask = 2147483647;
files = (
E812249C1B04FADC001783D2 /* Linter.swift in Sources */,
E88DEA791B098D4400A66CB0 /* RuleParameter.swift in Sources */,
E88DEA731B0984C400A66CB0 /* String+SwiftLint.swift in Sources */,
E88DEA6D1B09842200A66CB0 /* StyleViolationType.swift in Sources */,
E88DEA751B09852000A66CB0 /* File+SwiftLint.swift in Sources */,
E88DEA6F1B09843F00A66CB0 /* Location.swift in Sources */,
E88DEA771B098D0C00A66CB0 /* Rule.swift in Sources */,
E88DEA7C1B098D7D00A66CB0 /* LineLengthRule.swift in Sources */,
E88DEA711B09847500A66CB0 /* ViolationSeverity.swift in Sources */,
E88DEA6B1B0983FE00A66CB0 /* StyleViolation.swift in Sources */,
);