mirror of
https://github.com/realm/SwiftLint.git
synced 2026-06-06 20:18:40 +00:00
FunctionBodyLengthRule
This commit is contained in:
@@ -50,52 +50,13 @@ extension File {
|
||||
violations.extend(self.validateTypeName(kind, dict: subDict))
|
||||
violations.extend(self.validateVariableName(kind, dict: subDict))
|
||||
violations.extend(TypeBodyLengthRule.validateFile(self, kind: kind, dictionary: subDict))
|
||||
violations.extend(self.validateFunctionBodyLength(kind, dict: subDict))
|
||||
violations.extend(FunctionBodyLengthRule.validateFile(self, kind: kind, dictionary: subDict))
|
||||
violations.extend(self.validateNesting(kind, dict: subDict))
|
||||
}
|
||||
return violations
|
||||
}
|
||||
}
|
||||
|
||||
func validateFunctionBodyLength(kind: SwiftDeclarationKind, dict: XPCDictionary) ->
|
||||
[StyleViolation] {
|
||||
let functionKinds: [SwiftDeclarationKind] = [
|
||||
.FunctionAccessorAddress,
|
||||
.FunctionAccessorDidset,
|
||||
.FunctionAccessorGetter,
|
||||
.FunctionAccessorMutableaddress,
|
||||
.FunctionAccessorSetter,
|
||||
.FunctionAccessorWillset,
|
||||
.FunctionConstructor,
|
||||
.FunctionDestructor,
|
||||
.FunctionFree,
|
||||
.FunctionMethodClass,
|
||||
.FunctionMethodInstance,
|
||||
.FunctionMethodStatic,
|
||||
.FunctionOperator,
|
||||
.FunctionSubscript
|
||||
]
|
||||
if !contains(functionKinds, kind) {
|
||||
return []
|
||||
}
|
||||
var violations = [StyleViolation]()
|
||||
if let offset = flatMap(dict["key.offset"] as? Int64, { Int($0) }),
|
||||
let bodyOffset = flatMap(dict["key.bodyoffset"] as? Int64, { Int($0) }),
|
||||
let bodyLength = flatMap(dict["key.bodylength"] as? Int64, { Int($0) }) {
|
||||
let location = Location(file: self, offset: offset)
|
||||
let startLine = self.contents.lineAndCharacterForByteOffset(bodyOffset)
|
||||
let endLine = self.contents.lineAndCharacterForByteOffset(bodyOffset + bodyLength)
|
||||
if let startLine = startLine?.line, let endLine = endLine?.line
|
||||
where endLine - startLine > 40 {
|
||||
violations.append(StyleViolation(type: .Length,
|
||||
location: location,
|
||||
reason: "Function body should be span 40 lines or less: currently spans " +
|
||||
"\(endLine - startLine) lines"))
|
||||
}
|
||||
}
|
||||
return violations
|
||||
}
|
||||
|
||||
func validateTypeName(kind: SwiftDeclarationKind, dict: XPCDictionary) -> [StyleViolation] {
|
||||
let typeKinds: [SwiftDeclarationKind] = [
|
||||
.Class,
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// FunctionBodyLengthRule.swift
|
||||
// SwiftLint
|
||||
//
|
||||
// Created by JP Simard on 5/18/15.
|
||||
// Copyright (c) 2015 Realm. All rights reserved.
|
||||
//
|
||||
|
||||
import SourceKittenFramework
|
||||
import SwiftXPC
|
||||
|
||||
struct FunctionBodyLengthRule: Rule {
|
||||
static let identifier = "function_body_length"
|
||||
static let parameters = [
|
||||
RuleParameter(severity: .VeryLow, value: 40),
|
||||
RuleParameter(severity: .Low, value: 50),
|
||||
RuleParameter(severity: .Medium, value: 75),
|
||||
RuleParameter(severity: .High, value: 100),
|
||||
RuleParameter(severity: .VeryHigh, value: 200)
|
||||
]
|
||||
|
||||
static func validateFile(file: File) -> [StyleViolation] {
|
||||
return self.validateFile(file, dictionary: Structure(file: file).dictionary)
|
||||
}
|
||||
|
||||
static func validateFile(file: File, dictionary: XPCDictionary) -> [StyleViolation] {
|
||||
return (dictionary["key.substructure"] as? XPCArray ?? []).flatMap { subItem in
|
||||
var violations = [StyleViolation]()
|
||||
if let subDict = subItem as? XPCDictionary,
|
||||
let kindString = subDict["key.kind"] as? String,
|
||||
let kind = flatMap(kindString, { SwiftDeclarationKind(rawValue: $0) }) {
|
||||
violations.extend(self.validateFile(file, dictionary: subDict))
|
||||
violations.extend(self.validateFile(file, kind: kind, dictionary: subDict))
|
||||
}
|
||||
return violations
|
||||
}
|
||||
}
|
||||
|
||||
static func validateFile(file: File,
|
||||
kind: SwiftDeclarationKind,
|
||||
dictionary: XPCDictionary) -> [StyleViolation] {
|
||||
let functionKinds: [SwiftDeclarationKind] = [
|
||||
.FunctionAccessorAddress,
|
||||
.FunctionAccessorDidset,
|
||||
.FunctionAccessorGetter,
|
||||
.FunctionAccessorMutableaddress,
|
||||
.FunctionAccessorSetter,
|
||||
.FunctionAccessorWillset,
|
||||
.FunctionConstructor,
|
||||
.FunctionDestructor,
|
||||
.FunctionFree,
|
||||
.FunctionMethodClass,
|
||||
.FunctionMethodInstance,
|
||||
.FunctionMethodStatic,
|
||||
.FunctionOperator,
|
||||
.FunctionSubscript
|
||||
]
|
||||
if !contains(functionKinds, kind) {
|
||||
return []
|
||||
}
|
||||
var violations = [StyleViolation]()
|
||||
if let offset = flatMap(dictionary["key.offset"] as? Int64, { Int($0) }),
|
||||
let bodyOffset = flatMap(dictionary["key.bodyoffset"] as? Int64, { Int($0) }),
|
||||
let bodyLength = flatMap(dictionary["key.bodylength"] as? Int64, { Int($0) }) {
|
||||
let location = Location(file: file, offset: offset)
|
||||
let startLine = file.contents.lineAndCharacterForByteOffset(bodyOffset)
|
||||
let endLine = file.contents.lineAndCharacterForByteOffset(bodyOffset + bodyLength)
|
||||
for parameter in reverse(parameters) {
|
||||
if let startLine = startLine?.line, let endLine = endLine?.line
|
||||
where endLine - startLine > parameter.value {
|
||||
violations.append(StyleViolation(type: .Length,
|
||||
location: location,
|
||||
severity: parameter.severity,
|
||||
reason: "Function body should be span 40 lines or less: currently spans " +
|
||||
"\(endLine - startLine) lines"))
|
||||
}
|
||||
}
|
||||
}
|
||||
return violations
|
||||
}
|
||||
}
|
||||
@@ -123,6 +123,7 @@ class LinterTests: XCTestCase {
|
||||
"}\n"
|
||||
XCTAssertEqual(violations(longerFunctionBody), [StyleViolation(type: .Length,
|
||||
location: Location(file: nil, line: 1),
|
||||
severity: .VeryLow,
|
||||
reason: "Function body should be span 40 lines or less: currently spans 41 lines")])
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
E88DEA8A1B0992B300A66CB0 /* FileLengthRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA891B0992B300A66CB0 /* FileLengthRule.swift */; };
|
||||
E88DEA8C1B0999A000A66CB0 /* ASTRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA8B1B0999A000A66CB0 /* ASTRule.swift */; };
|
||||
E88DEA8E1B0999CD00A66CB0 /* TypeBodyLengthRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA8D1B0999CD00A66CB0 /* TypeBodyLengthRule.swift */; };
|
||||
E88DEA901B099A3100A66CB0 /* FunctionBodyLengthRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = E88DEA8F1B099A3100A66CB0 /* FunctionBodyLengthRule.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 */; };
|
||||
@@ -146,6 +147,7 @@
|
||||
E88DEA891B0992B300A66CB0 /* FileLengthRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileLengthRule.swift; sourceTree = "<group>"; };
|
||||
E88DEA8B1B0999A000A66CB0 /* ASTRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASTRule.swift; sourceTree = "<group>"; };
|
||||
E88DEA8D1B0999CD00A66CB0 /* TypeBodyLengthRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeBodyLengthRule.swift; sourceTree = "<group>"; };
|
||||
E88DEA8F1B099A3100A66CB0 /* FunctionBodyLengthRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FunctionBodyLengthRule.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; };
|
||||
@@ -361,6 +363,7 @@
|
||||
E88DEA871B09924C00A66CB0 /* TrailingNewlineRule.swift */,
|
||||
E88DEA891B0992B300A66CB0 /* FileLengthRule.swift */,
|
||||
E88DEA8D1B0999CD00A66CB0 /* TypeBodyLengthRule.swift */,
|
||||
E88DEA8F1B099A3100A66CB0 /* FunctionBodyLengthRule.swift */,
|
||||
);
|
||||
path = Rules;
|
||||
sourceTree = "<group>";
|
||||
@@ -528,6 +531,7 @@
|
||||
E88DEA711B09847500A66CB0 /* ViolationSeverity.swift in Sources */,
|
||||
E88DEA8C1B0999A000A66CB0 /* ASTRule.swift in Sources */,
|
||||
E88DEA821B0990A700A66CB0 /* TodoRule.swift in Sources */,
|
||||
E88DEA901B099A3100A66CB0 /* FunctionBodyLengthRule.swift in Sources */,
|
||||
E88DEA6B1B0983FE00A66CB0 /* StyleViolation.swift in Sources */,
|
||||
E88DEA7E1B098F2A00A66CB0 /* LeadingWhitespaceRule.swift in Sources */,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user