mirror of
https://github.com/realm/SwiftLint.git
synced 2026-06-06 20:18:40 +00:00
Implement ParametersListLengthRule
This commit is contained in:
@@ -40,6 +40,7 @@ public let masterRuleList = RuleList( rules: ClosingBraceRule.self,
|
||||
NestingRule.self,
|
||||
OpeningBraceRule.self,
|
||||
OperatorFunctionWhitespaceRule.self,
|
||||
ParametersListLengthRule.self,
|
||||
ReturnArrowWhitespaceRule.self,
|
||||
StatementPositionRule.self,
|
||||
TodoRule.self,
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
//
|
||||
// ParemeterListLengthRule.swift
|
||||
// SwiftLint
|
||||
//
|
||||
// Created by Denis Lebedev on 26/01/2016.
|
||||
// Copyright © 2016 Realm. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SourceKittenFramework
|
||||
|
||||
public struct ParametersListLengthRule: ASTRule, ConfigProviderRule {
|
||||
public var config = SeverityLevelsConfig(warning: 5, error: 8)
|
||||
|
||||
public init() {}
|
||||
|
||||
public static let description = RuleDescription(
|
||||
identifier: "parameters_list_length",
|
||||
name: "Parameter List Length",
|
||||
description: "Length of parameter list should be short.",
|
||||
nonTriggeringExamples: [
|
||||
"func f2(p1: Int, p2: Int) { }",
|
||||
"func f(a: Int, b: Int, c: Int, d: Int, x: Int = 42) {}",
|
||||
"func f(a: [Int], b: Int, c: Int, d: Int, f: Int) -> [Int] {\n" +
|
||||
"let s = a.flatMap { $0 as? [String: Int] } ?? []}}"
|
||||
],
|
||||
triggeringExamples: [
|
||||
"func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int) {}",
|
||||
"func f(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int = 2, g: Int) {}",
|
||||
]
|
||||
)
|
||||
|
||||
public func validateFile(file: File, kind: SwiftDeclarationKind,
|
||||
dictionary: [String: SourceKitRepresentable]) -> [StyleViolation] {
|
||||
if !functionKinds.contains(kind) {
|
||||
return []
|
||||
}
|
||||
|
||||
let nameOffset = Int(dictionary["key.nameoffset"] as? Int64 ?? 0)
|
||||
let length = Int(dictionary["key.namelength"] as? Int64 ?? 0)
|
||||
let substructure = dictionary["key.substructure"] as? [SourceKitRepresentable] ?? []
|
||||
|
||||
let funcDeclarationRange = Range(start: nameOffset, end: nameOffset + length)
|
||||
|
||||
let allParameters = allFunctionParameters(substructure, range: funcDeclarationRange)
|
||||
let defaultParameters = defaultFunctionParameters(file, range: funcDeclarationRange)
|
||||
|
||||
let parametersCount = allParameters - defaultParameters
|
||||
|
||||
for parameter in config.params where parametersCount > parameter.value {
|
||||
let offset = Int(dictionary["key.offset"] as? Int64 ?? 0)
|
||||
return [StyleViolation(ruleDescription: self.dynamicType.description,
|
||||
severity: parameter.severity,
|
||||
location: Location(file: file, characterOffset: offset),
|
||||
reason: "{Parameters list should have \(config.warning) or less parameters: " +
|
||||
"currently it has \(parametersCount)")]
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
private func allFunctionParameters(structure: [SourceKitRepresentable],
|
||||
range: Range<Int>) -> Int {
|
||||
|
||||
var count = 0
|
||||
for e in structure {
|
||||
guard let subDict = e as? [String: SourceKitRepresentable],
|
||||
key = subDict["key.kind"] as? String,
|
||||
offset = subDict["key.offset"] as? Int64 else {
|
||||
continue
|
||||
}
|
||||
|
||||
guard range ~= Int(offset) else {
|
||||
return count
|
||||
}
|
||||
|
||||
if SwiftDeclarationKind(rawValue: key) == .VarParameter {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
||||
|
||||
private func defaultFunctionParameters(file: File, range: Range<Int>) -> Int {
|
||||
let funcDeclaration = file.contents[range]
|
||||
return funcDeclaration.characters.filter { $0 == "=" }.count
|
||||
}
|
||||
|
||||
private let functionKinds: [SwiftDeclarationKind] = [
|
||||
.FunctionAccessorAddress,
|
||||
.FunctionAccessorDidset,
|
||||
.FunctionAccessorGetter,
|
||||
.FunctionAccessorMutableaddress,
|
||||
.FunctionAccessorSetter,
|
||||
.FunctionAccessorWillset,
|
||||
.FunctionConstructor,
|
||||
.FunctionDestructor,
|
||||
.FunctionFree,
|
||||
.FunctionMethodClass,
|
||||
.FunctionMethodInstance,
|
||||
.FunctionMethodStatic,
|
||||
.FunctionOperator,
|
||||
.FunctionSubscript
|
||||
]
|
||||
}
|
||||
@@ -91,6 +91,10 @@ class RulesTests: XCTestCase {
|
||||
verifyRule(OperatorFunctionWhitespaceRule.description)
|
||||
}
|
||||
|
||||
func testParametersListLength() {
|
||||
verifyRule(ParametersListLengthRule.description)
|
||||
}
|
||||
|
||||
func testReturnArrowWhitespace() {
|
||||
verifyRule(ReturnArrowWhitespaceRule.description)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
1F11B3CF1C252F23002E8FA8 /* ClosingBraceRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F11B3CE1C252F23002E8FA8 /* ClosingBraceRule.swift */; };
|
||||
24E17F721B14BB3F008195BE /* File+Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E17F701B1481FF008195BE /* File+Cache.swift */; };
|
||||
2E02005F1C54BF680024D09D /* CyclomaticComplexityRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E02005E1C54BF680024D09D /* CyclomaticComplexityRule.swift */; };
|
||||
2E5761AA1C573B83003271AF /* ParametersListLengthRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E5761A91C573B83003271AF /* ParametersListLengthRule.swift */; };
|
||||
3B0B14541C505D6300BE82F7 /* SeverityConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B0B14531C505D6300BE82F7 /* SeverityConfig.swift */; };
|
||||
3B1150CA1C31FC3F00D83B1E /* Yaml+SwiftLint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B1150C91C31FC3F00D83B1E /* Yaml+SwiftLint.swift */; };
|
||||
3B12C9C11C3209CB000B423F /* test.yml in Resources */ = {isa = PBXBuildFile; fileRef = 3B12C9BF1C3209AC000B423F /* test.yml */; };
|
||||
@@ -164,6 +165,7 @@
|
||||
1F11B3CE1C252F23002E8FA8 /* ClosingBraceRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClosingBraceRule.swift; sourceTree = "<group>"; };
|
||||
24E17F701B1481FF008195BE /* File+Cache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "File+Cache.swift"; sourceTree = "<group>"; };
|
||||
2E02005E1C54BF680024D09D /* CyclomaticComplexityRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CyclomaticComplexityRule.swift; sourceTree = "<group>"; };
|
||||
2E5761A91C573B83003271AF /* ParametersListLengthRule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParametersListLengthRule.swift; sourceTree = "<group>"; };
|
||||
3B0B14531C505D6300BE82F7 /* SeverityConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeverityConfig.swift; sourceTree = "<group>"; };
|
||||
3B1150C91C31FC3F00D83B1E /* Yaml+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Yaml+SwiftLint.swift"; sourceTree = "<group>"; };
|
||||
3B12C9BF1C3209AC000B423F /* test.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = test.yml; sourceTree = "<group>"; };
|
||||
@@ -177,7 +179,6 @@
|
||||
3BB47D821C514E8100AE6A10 /* RegexConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegexConfig.swift; sourceTree = "<group>"; };
|
||||
3BB47D841C51D80000AE6A10 /* NSRegularExpression+SwiftLint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSRegularExpression+SwiftLint.swift"; sourceTree = "<group>"; };
|
||||
3BB47D861C51DE6E00AE6A10 /* CustomRulesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomRulesTests.swift; sourceTree = "<group>"; };
|
||||
3BCC04C51C4EFA52006073C3 /* RuleConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RuleConfig.swift; sourceTree = "<group>"; };
|
||||
3BCC04CC1C4F5694006073C3 /* ConfigurationError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurationError.swift; sourceTree = "<group>"; };
|
||||
3BCC04CF1C4F56D3006073C3 /* SeverityLevelsConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SeverityLevelsConfig.swift; sourceTree = "<group>"; };
|
||||
3BCC04D01C4F56D3006073C3 /* NameConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NameConfig.swift; sourceTree = "<group>"; };
|
||||
@@ -568,6 +569,7 @@
|
||||
E81CDE701C00FEAA00B430F6 /* ValidDocsRule.swift */,
|
||||
E88DEA931B099C0900A66CB0 /* VariableNameRule.swift */,
|
||||
2E02005E1C54BF680024D09D /* CyclomaticComplexityRule.swift */,
|
||||
2E5761A91C573B83003271AF /* ParametersListLengthRule.swift */,
|
||||
);
|
||||
path = Rules;
|
||||
sourceTree = "<group>";
|
||||
@@ -844,6 +846,7 @@
|
||||
3BCC04D11C4F56D3006073C3 /* SeverityLevelsConfig.swift in Sources */,
|
||||
E86396C51BADAC15002C9E88 /* XcodeReporter.swift in Sources */,
|
||||
3B1DF0121C5148140011BCED /* CustomRules.swift in Sources */,
|
||||
2E5761AA1C573B83003271AF /* ParametersListLengthRule.swift in Sources */,
|
||||
E86396C91BADB2B9002C9E88 /* JSONReporter.swift in Sources */,
|
||||
E881985A1BEA96EA00333A11 /* OperatorFunctionWhitespaceRule.swift in Sources */,
|
||||
3BCC04D21C4F56D3006073C3 /* NameConfig.swift in Sources */,
|
||||
|
||||
Reference in New Issue
Block a user