mirror of
https://github.com/realm/SwiftLint.git
synced 2026-05-07 20:12:49 +00:00
Format code (#6151)
This commit is contained in:
@@ -238,11 +238,11 @@ private extension ExprSyntax {
|
||||
return true
|
||||
}
|
||||
if let expr = self.as(MemberAccessExprSyntax.self),
|
||||
expr.description.split(separator: ".").allSatisfy(\.startsWithUppercase) {
|
||||
expr.description.split(separator: ".").allSatisfy(\.startsWithUppercase) {
|
||||
return true
|
||||
}
|
||||
if let expr = self.as(GenericSpecializationExprSyntax.self)?.expression.as(DeclReferenceExprSyntax.self),
|
||||
expr.baseName.text.startsWithUppercase {
|
||||
expr.baseName.text.startsWithUppercase {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -13,9 +13,9 @@ struct FileNameNoSpaceRule: OptInRule, SourceKitFreeRule {
|
||||
|
||||
func validate(file: SwiftLintFile) -> [StyleViolation] {
|
||||
guard let filePath = file.path,
|
||||
case let fileName = filePath.bridge().lastPathComponent,
|
||||
!configuration.excluded.contains(fileName),
|
||||
fileName.rangeOfCharacter(from: .whitespaces) != nil else {
|
||||
case let fileName = filePath.bridge().lastPathComponent,
|
||||
!configuration.excluded.contains(fileName),
|
||||
fileName.rangeOfCharacter(from: .whitespaces) != nil else {
|
||||
return []
|
||||
}
|
||||
|
||||
|
||||
@@ -24,13 +24,13 @@ struct FileNameRule: OptInRule, SourceKitFreeRule {
|
||||
|
||||
// Process prefix
|
||||
if let match = prefixRegex.firstMatch(in: typeInFileName, options: [], range: typeInFileName.fullNSRange),
|
||||
let range = typeInFileName.nsrangeToIndexRange(match.range) {
|
||||
let range = typeInFileName.nsrangeToIndexRange(match.range) {
|
||||
typeInFileName.removeSubrange(range)
|
||||
}
|
||||
|
||||
// Process suffix
|
||||
if let match = suffixRegex.firstMatch(in: typeInFileName, options: [], range: typeInFileName.fullNSRange),
|
||||
let range = typeInFileName.nsrangeToIndexRange(match.range) {
|
||||
let range = typeInFileName.nsrangeToIndexRange(match.range) {
|
||||
typeInFileName.removeSubrange(range)
|
||||
}
|
||||
|
||||
@@ -38,10 +38,10 @@ struct FileNameRule: OptInRule, SourceKitFreeRule {
|
||||
let allDeclaredTypeNames = TypeNameCollectingVisitor(
|
||||
requireFullyQualifiedNames: configuration.requireFullyQualifiedNames
|
||||
)
|
||||
.walk(tree: file.syntaxTree, handler: \.names)
|
||||
.map {
|
||||
$0.replacingOccurrences(of: ".", with: configuration.nestedTypeSeparator)
|
||||
}
|
||||
.walk(tree: file.syntaxTree, handler: \.names)
|
||||
.map {
|
||||
$0.replacingOccurrences(of: ".", with: configuration.nestedTypeSeparator)
|
||||
}
|
||||
|
||||
guard allDeclaredTypeNames.isNotEmpty, !allDeclaredTypeNames.contains(typeInFileName) else {
|
||||
return []
|
||||
|
||||
@@ -67,7 +67,7 @@ private extension GenericTypeNameRule {
|
||||
)
|
||||
)
|
||||
} else if let caseCheckSeverity = configuration.validatesStartWithLowercase.severity,
|
||||
!String(name[name.startIndex]).isUppercase() {
|
||||
!String(name[name.startIndex]).isUppercase() {
|
||||
violations.append(
|
||||
ReasonedRuleViolation(
|
||||
position: node.positionAfterSkippingLeadingTrivia,
|
||||
|
||||
@@ -62,8 +62,8 @@ private extension ObjectLiteralRule {
|
||||
private func isColorInit(node: FunctionCallExprSyntax, name: String) -> Bool {
|
||||
guard inits(forClasses: ["UIColor", "NSColor"]).contains(name),
|
||||
case let argumentsNames = node.arguments.compactMap(\.label?.text),
|
||||
argumentsNames == ["red", "green", "blue", "alpha"] || argumentsNames == ["white", "alpha"] else {
|
||||
return false
|
||||
argumentsNames == ["red", "green", "blue", "alpha"] || argumentsNames == ["white", "alpha"] else {
|
||||
return false
|
||||
}
|
||||
|
||||
return node.arguments.allSatisfy(\.expression.canBeExpressedAsColorLiteralParams)
|
||||
|
||||
@@ -63,7 +63,7 @@ private extension Syntax {
|
||||
return true
|
||||
}
|
||||
if let variableDecl = self.as(VariableDeclSyntax.self),
|
||||
variableDecl.bindings.allSatisfy({ $0.accessorBlock == nil }) {
|
||||
variableDecl.bindings.allSatisfy({ $0.accessorBlock == nil }) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -93,12 +93,12 @@ private extension AttributeListSyntax {
|
||||
return nil
|
||||
}
|
||||
if parent?.isFunctionOrStoredProperty == true,
|
||||
let parentClassDecl = parent?.parent?.parent?.parent?.parent?.as(ClassDeclSyntax.self),
|
||||
parentClassDecl.attributes.contains(attributeNamed: "objcMembers") {
|
||||
let parentClassDecl = parent?.parent?.parent?.parent?.parent?.as(ClassDeclSyntax.self),
|
||||
parentClassDecl.attributes.contains(attributeNamed: "objcMembers") {
|
||||
return parent?.functionOrVariableModifiers?.containsPrivateOrFileprivate() == true ? nil : objcAttribute
|
||||
}
|
||||
if let parentExtensionDecl = parent?.parent?.parent?.parent?.parent?.as(ExtensionDeclSyntax.self),
|
||||
parentExtensionDecl.attributes.objCAttribute != nil {
|
||||
parentExtensionDecl.attributes.objCAttribute != nil {
|
||||
return objcAttribute
|
||||
}
|
||||
return nil
|
||||
@@ -111,7 +111,7 @@ extension RedundantObjcAttributeRule {
|
||||
let nsCharSet = CharacterSet.whitespacesAndNewlines.bridge()
|
||||
let nsContent = file.contents.bridge()
|
||||
while nsCharSet
|
||||
.characterIsMember(nsContent.character(at: violationRange.upperBound + whitespaceAndNewlineOffset)) {
|
||||
.characterIsMember(nsContent.character(at: violationRange.upperBound + whitespaceAndNewlineOffset)) {
|
||||
whitespaceAndNewlineOffset += 1
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ private extension ReturnClauseSyntax {
|
||||
return false
|
||||
}
|
||||
if let simpleReturnType = type.as(IdentifierTypeSyntax.self) {
|
||||
return simpleReturnType.typeName == "Void"
|
||||
return simpleReturnType.typeName == "Void"
|
||||
}
|
||||
if let tupleReturnType = type.as(TupleTypeSyntax.self) {
|
||||
return tupleReturnType.elements.isEmpty
|
||||
|
||||
@@ -90,7 +90,7 @@ private extension TypeNameRule {
|
||||
)
|
||||
}
|
||||
if let caseCheckSeverity = nameConfiguration.validatesStartWithLowercase.severity,
|
||||
name.first?.isLowercase == true {
|
||||
name.first?.isLowercase == true {
|
||||
return ReasonedRuleViolation(
|
||||
position: identifier.positionAfterSkippingLeadingTrivia,
|
||||
reason: "Type name '\(name)' should start with an uppercase character",
|
||||
|
||||
@@ -50,9 +50,9 @@ struct UnneededBreakInSwitchRule: Rule {
|
||||
],
|
||||
corrections: [
|
||||
embedInSwitch("something()\n ↓break")
|
||||
: embedInSwitch("something()"),
|
||||
: embedInSwitch("something()"),
|
||||
embedInSwitch("something()\n ↓break // line comment")
|
||||
: embedInSwitch("something()\n // line comment"),
|
||||
: embedInSwitch("something()\n // line comment"),
|
||||
embedInSwitch("""
|
||||
something()
|
||||
↓break
|
||||
@@ -60,14 +60,14 @@ struct UnneededBreakInSwitchRule: Rule {
|
||||
block comment
|
||||
*/
|
||||
""")
|
||||
: embedInSwitch("""
|
||||
: embedInSwitch("""
|
||||
something()
|
||||
/*
|
||||
block comment
|
||||
*/
|
||||
"""),
|
||||
embedInSwitch("something()\n ↓break /// doc line comment")
|
||||
: embedInSwitch("something()\n /// doc line comment"),
|
||||
: embedInSwitch("something()\n /// doc line comment"),
|
||||
embedInSwitch("""
|
||||
something()
|
||||
↓break
|
||||
@@ -75,16 +75,16 @@ struct UnneededBreakInSwitchRule: Rule {
|
||||
/// doc block comment
|
||||
///
|
||||
""")
|
||||
: embedInSwitch("""
|
||||
: embedInSwitch("""
|
||||
something()
|
||||
///
|
||||
/// doc block comment
|
||||
///
|
||||
"""),
|
||||
embedInSwitch("something()\n ↓break", case: "default")
|
||||
: embedInSwitch("something()", case: "default"),
|
||||
: embedInSwitch("something()", case: "default"),
|
||||
embedInSwitch("something()\n ↓break", case: "case .foo, .foo2 where condition")
|
||||
: embedInSwitch("something()", case: "case .foo, .foo2 where condition"),
|
||||
: embedInSwitch("something()", case: "case .foo, .foo2 where condition"),
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -243,9 +243,9 @@ private extension FunctionCallExprSyntax {
|
||||
|
||||
var enumeratedPosition: AbsolutePosition? {
|
||||
if let memberAccess = calledExpression.as(MemberAccessExprSyntax.self),
|
||||
memberAccess.base != nil,
|
||||
memberAccess.declName.baseName.text == "enumerated",
|
||||
hasNoArguments {
|
||||
memberAccess.base != nil,
|
||||
memberAccess.declName.baseName.text == "enumerated",
|
||||
hasNoArguments {
|
||||
return memberAccess.declName.positionAfterSkippingLeadingTrivia
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -234,9 +234,9 @@ private extension CodeBlockItemSyntax {
|
||||
}
|
||||
|
||||
private extension FunctionSignatureSyntax {
|
||||
var allowsImplicitReturns: Bool {
|
||||
returnClause?.allowsImplicitReturns ?? false
|
||||
}
|
||||
var allowsImplicitReturns: Bool {
|
||||
returnClause?.allowsImplicitReturns ?? false
|
||||
}
|
||||
}
|
||||
|
||||
private extension SubscriptDeclSyntax {
|
||||
|
||||
@@ -25,7 +25,7 @@ private extension XCTSpecificMatcherRule {
|
||||
reason: "Prefer the specific matcher '\(suggestion)' instead"
|
||||
))
|
||||
} else if configuration.matchers.contains(.oneArgumentAsserts),
|
||||
let suggestion = OneArgXCTAssert.violations(in: node) {
|
||||
let suggestion = OneArgXCTAssert.violations(in: node) {
|
||||
violations.append(ReasonedRuleViolation(
|
||||
position: node.positionAfterSkippingLeadingTrivia,
|
||||
reason: "Prefer the specific matcher '\(suggestion)' instead"
|
||||
|
||||
@@ -139,7 +139,7 @@ private extension FunctionCallExprSyntax {
|
||||
let modifierName = memberAccess.declName.baseName.text
|
||||
|
||||
if funcCall.isDirectAccessibilityModifier(modifierName) ||
|
||||
funcCall.isContainerExemptingModifier(modifierName) {
|
||||
funcCall.isContainerExemptingModifier(modifierName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -187,7 +187,7 @@ private extension FunctionCallExprSyntax {
|
||||
let modifierName = memberAccess.declName.baseName.text
|
||||
|
||||
if funcCall.isDirectAccessibilityModifier(modifierName) ||
|
||||
funcCall.isContainerExemptingModifier(modifierName) {
|
||||
funcCall.isContainerExemptingModifier(modifierName) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -374,7 +374,7 @@ internal struct AccessibilityLabelForImageRuleExamples {
|
||||
}
|
||||
}
|
||||
"""),
|
||||
// MARK: - SwiftSyntax Migration Detection Improvements
|
||||
// MARK: - SwiftSyntax Migration Detection Improvements
|
||||
// These violations would have been missed by the SourceKit implementation
|
||||
// but are now correctly detected by SwiftSyntax
|
||||
Example("""
|
||||
|
||||
@@ -161,8 +161,8 @@ private struct AccessibilityButtonTraitDeterminator {
|
||||
|
||||
// Stop if we reach a new View declaration or similar boundary
|
||||
if currentSyntaxNode.is(StructDeclSyntax.self) ||
|
||||
currentSyntaxNode.is(ClassDeclSyntax.self) ||
|
||||
currentSyntaxNode.is(EnumDeclSyntax.self) {
|
||||
currentSyntaxNode.is(ClassDeclSyntax.self) ||
|
||||
currentSyntaxNode.is(EnumDeclSyntax.self) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ private extension ClosureSignatureSyntax {
|
||||
return list.onlyElement?.name.text
|
||||
}
|
||||
if let clause = parameterClause?.as(ClosureParameterClauseSyntax.self), clause.parameters.count == 1,
|
||||
clause.parameters.first?.secondName == nil {
|
||||
clause.parameters.first?.secondName == nil {
|
||||
return clause.parameters.first?.firstName.text
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -121,7 +121,7 @@ private extension AsyncWithoutAwaitRule {
|
||||
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
if node.bindingSpecifier.tokenKind == .keyword(.let),
|
||||
node.modifiers.contains(keyword: .async) {
|
||||
node.modifiers.contains(keyword: .async) {
|
||||
functionScopes.modifyLast {
|
||||
$0.containsAwait = true
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ struct BlanketDisableCommandRule: Rule, SourceKitFreeRule {
|
||||
"""),
|
||||
Example("// swiftlint:disable all"),
|
||||
].skipWrappingInCommentTests().skipDisableCommandTests()
|
||||
)
|
||||
)
|
||||
|
||||
func validate(file: SwiftLintFile) -> [StyleViolation] {
|
||||
var violations: [StyleViolation] = []
|
||||
|
||||
@@ -42,7 +42,7 @@ private extension CompilerProtocolInitRule {
|
||||
let argumentsNames = arguments.map(\.text)
|
||||
for compilerProtocol in ExpressibleByCompiler.allProtocols {
|
||||
guard compilerProtocol.initCallNames.contains(name),
|
||||
compilerProtocol.match(arguments: argumentsNames) else {
|
||||
compilerProtocol.match(arguments: argumentsNames) else {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -105,12 +105,12 @@ private extension DeploymentTargetRule {
|
||||
violationType: AvailabilityType) -> String? {
|
||||
guard let platform = DeploymentTargetConfiguration.Platform(rawValue: platform.text),
|
||||
let minVersion = platformToConfiguredMinVersion[platform.rawValue] else {
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
guard let version = try? Version(platform: platform, value: versionString),
|
||||
version <= minVersion else {
|
||||
return nil
|
||||
version <= minVersion else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return """
|
||||
|
||||
@@ -220,9 +220,9 @@ private extension SyntaxProtocol {
|
||||
return false
|
||||
}
|
||||
let ifConfigDecl = itemList
|
||||
.parent?.as(IfConfigClauseSyntax.self)?
|
||||
.parent?.as(IfConfigClauseListSyntax.self)?
|
||||
.parent?.as(IfConfigDeclSyntax.self)
|
||||
.parent?.as(IfConfigClauseSyntax.self)?
|
||||
.parent?.as(IfConfigClauseListSyntax.self)?
|
||||
.parent?.as(IfConfigDeclSyntax.self)
|
||||
if let ifConfigDecl {
|
||||
return ifConfigDecl.hasDocComment
|
||||
}
|
||||
@@ -303,19 +303,19 @@ private extension Stack<AccessControlBehavior> {
|
||||
func computeAcl(givenExplicitAcl acl: AccessControlLevel?, evalEffectiveAcl: Bool) -> AccessControlLevel {
|
||||
if let parentBehavior = peek() {
|
||||
switch parentBehavior {
|
||||
case .local:
|
||||
.private
|
||||
case .actor, .class, .struct, .enum:
|
||||
if let acl {
|
||||
acl < parentBehavior.effectiveAcl || !evalEffectiveAcl ? acl : parentBehavior.effectiveAcl
|
||||
} else {
|
||||
parentBehavior.effectiveAcl >= .internal ? .internal : parentBehavior.effectiveAcl
|
||||
}
|
||||
case .protocol:
|
||||
parentBehavior.effectiveAcl
|
||||
case .extension:
|
||||
acl ?? parentBehavior.effectiveAcl
|
||||
}
|
||||
case .local:
|
||||
.private
|
||||
case .actor, .class, .struct, .enum:
|
||||
if let acl {
|
||||
acl < parentBehavior.effectiveAcl || !evalEffectiveAcl ? acl : parentBehavior.effectiveAcl
|
||||
} else {
|
||||
parentBehavior.effectiveAcl >= .internal ? .internal : parentBehavior.effectiveAcl
|
||||
}
|
||||
case .protocol:
|
||||
parentBehavior.effectiveAcl
|
||||
case .extension:
|
||||
acl ?? parentBehavior.effectiveAcl
|
||||
}
|
||||
} else {
|
||||
acl ?? .internal
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ private func isOrphanedDocComment(
|
||||
while let (_, piece) = iterator.next() {
|
||||
switch piece {
|
||||
case .docLineComment, .docBlockComment,
|
||||
.carriageReturns, .carriageReturnLineFeeds, .newlines, .spaces:
|
||||
.carriageReturns, .carriageReturnLineFeeds, .newlines, .spaces:
|
||||
break
|
||||
|
||||
case .lineComment, .blockComment:
|
||||
|
||||
@@ -65,8 +65,8 @@ private extension PrivateSwiftUIStatePropertyRule {
|
||||
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
guard node.parent?.is(MemberBlockItemSyntax.self) == true,
|
||||
swiftUITypeScopes.peek() ?? false,
|
||||
node.containsSwiftUIStateAccessLevelViolation
|
||||
swiftUITypeScopes.peek() ?? false,
|
||||
node.containsSwiftUIStateAccessLevelViolation
|
||||
else {
|
||||
return
|
||||
}
|
||||
@@ -102,8 +102,8 @@ private extension PrivateSwiftUIStatePropertyRule {
|
||||
|
||||
override func visitPost(_ node: Syntax) {
|
||||
if node.is(ClassDeclSyntax.self) ||
|
||||
node.is(StructDeclSyntax.self) ||
|
||||
node.is(ActorDeclSyntax.self) {
|
||||
node.is(StructDeclSyntax.self) ||
|
||||
node.is(ActorDeclSyntax.self) {
|
||||
swiftUITypeScopes.pop()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,12 +44,12 @@ struct QuickDiscouragedCallRule: OptInRule {
|
||||
kind: SwiftExpressionKind,
|
||||
dictionary: SourceKittenDictionary) -> [StyleViolation] {
|
||||
// is it a call to a restricted method?
|
||||
guard
|
||||
kind == .call,
|
||||
let name = dictionary.name,
|
||||
let kindName = QuickCallKind(rawValue: name),
|
||||
QuickCallKind.restrictiveKinds.contains(kindName)
|
||||
else { return [] }
|
||||
guard kind == .call,
|
||||
let name = dictionary.name,
|
||||
let kindName = QuickCallKind(rawValue: name),
|
||||
QuickCallKind.restrictiveKinds.contains(kindName) else {
|
||||
return []
|
||||
}
|
||||
|
||||
return violationOffsets(in: dictionary.enclosedArguments).map {
|
||||
StyleViolation(ruleDescription: Self.description,
|
||||
@@ -73,29 +73,30 @@ struct QuickDiscouragedCallRule: OptInRule {
|
||||
}
|
||||
|
||||
private func toViolationOffsets(dictionary: SourceKittenDictionary) -> [ByteCount] {
|
||||
guard
|
||||
dictionary.kind != nil,
|
||||
let offset = dictionary.offset
|
||||
else { return [] }
|
||||
guard dictionary.kind != nil,
|
||||
let offset = dictionary.offset else {
|
||||
return []
|
||||
}
|
||||
|
||||
if dictionary.expressionKind == .call,
|
||||
let name = dictionary.name, QuickCallKind(rawValue: name) == nil {
|
||||
let name = dictionary.name, QuickCallKind(rawValue: name) == nil {
|
||||
return [offset]
|
||||
}
|
||||
|
||||
guard dictionary.expressionKind != .call else { return [] }
|
||||
guard dictionary.expressionKind != .call else {
|
||||
return []
|
||||
}
|
||||
|
||||
return dictionary.substructure.compactMap(toViolationOffset)
|
||||
}
|
||||
|
||||
private func toViolationOffset(dictionary: SourceKittenDictionary) -> ByteCount? {
|
||||
guard
|
||||
let name = dictionary.name,
|
||||
let offset = dictionary.offset,
|
||||
dictionary.expressionKind == .call,
|
||||
QuickCallKind(rawValue: name) == nil
|
||||
else { return nil }
|
||||
|
||||
guard let name = dictionary.name,
|
||||
let offset = dictionary.offset,
|
||||
dictionary.expressionKind == .call,
|
||||
QuickCallKind(rawValue: name) == nil else {
|
||||
return nil
|
||||
}
|
||||
return offset
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,10 +57,10 @@ private extension TriviaPiece {
|
||||
for todoKeywords: [TodoConfiguration.TodoKeyword]) -> [ReasonedRuleViolation] {
|
||||
switch self {
|
||||
case
|
||||
.blockComment(let comment),
|
||||
.lineComment(let comment),
|
||||
.docBlockComment(let comment),
|
||||
.docLineComment(let comment):
|
||||
.blockComment(let comment),
|
||||
.lineComment(let comment),
|
||||
.docBlockComment(let comment),
|
||||
.docLineComment(let comment):
|
||||
|
||||
// Construct a regex string considering only keywords.
|
||||
let searchKeywords = todoKeywords.map(\.rawValue).joined(separator: "|")
|
||||
|
||||
@@ -52,14 +52,14 @@ struct TypesafeArrayInitRule: AnalyzerRule {
|
||||
|
||||
private static let parentRule = ArrayInitRule()
|
||||
private static let mapTypePatterns = [
|
||||
regex("""
|
||||
\\Q<Self, T where Self : \\E(?:Sequence|Collection)> \
|
||||
\\Q(Self) -> ((Self.Element) throws -> T) throws -> [T]\\E
|
||||
"""),
|
||||
regex("""
|
||||
\\Q<Self, T, E where Self : \\E(?:Sequence|Collection), \
|
||||
\\QE : Error> (Self) -> ((Self.Element) throws(E) -> T) throws(E) -> [T]\\E
|
||||
"""),
|
||||
regex("""
|
||||
\\Q<Self, T where Self : \\E(?:Sequence|Collection)> \
|
||||
\\Q(Self) -> ((Self.Element) throws -> T) throws -> [T]\\E
|
||||
"""),
|
||||
regex("""
|
||||
\\Q<Self, T, E where Self : \\E(?:Sequence|Collection), \
|
||||
\\QE : Error> (Self) -> ((Self.Element) throws(E) -> T) throws(E) -> [T]\\E
|
||||
"""),
|
||||
]
|
||||
|
||||
func validate(file: SwiftLintFile, compilerArguments: [String]) -> [StyleViolation] {
|
||||
|
||||
@@ -96,7 +96,7 @@ private extension OverridableDecl {
|
||||
}
|
||||
|
||||
guard let call = extractFunctionCallSyntax(statement.item),
|
||||
let member = call.calledExpression.as(MemberAccessExprSyntax.self),
|
||||
let member = call.calledExpression.as(MemberAccessExprSyntax.self),
|
||||
member.base?.is(SuperExprSyntax.self) == true,
|
||||
member.declName.baseName.text == name else {
|
||||
return false
|
||||
|
||||
@@ -161,9 +161,9 @@ private extension SwiftLintFile {
|
||||
|
||||
// Skip CodingKeys as they are used for Codable generation
|
||||
if kind == .enum,
|
||||
indexEntity.name == "CodingKeys",
|
||||
case let allRelatedUSRs = indexEntity.traverseEntitiesDepthFirst(traverseBlock: { $1.usr }),
|
||||
allRelatedUSRs.contains("s:s9CodingKeyP") {
|
||||
indexEntity.name == "CodingKeys",
|
||||
case let allRelatedUSRs = indexEntity.traverseEntitiesDepthFirst(traverseBlock: { $1.usr }),
|
||||
allRelatedUSRs.contains("s:s9CodingKeyP") {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -263,8 +263,8 @@ private extension SourceKittenDictionary {
|
||||
|
||||
func propertyAtOffset<T>(_ offset: ByteCount, property: KeyPath<Self, T?>) -> T? {
|
||||
if let nameOffset,
|
||||
nameOffset == offset,
|
||||
let field = self[keyPath: property] {
|
||||
nameOffset == offset,
|
||||
let field = self[keyPath: property] {
|
||||
return field
|
||||
}
|
||||
for child in substructure {
|
||||
|
||||
@@ -179,7 +179,7 @@ private extension SwiftLintFile {
|
||||
if nextIsModuleImport {
|
||||
nextIsModuleImport = false
|
||||
if let importedModule = cursorInfo.moduleName,
|
||||
cursorInfo.kind == "source.lang.swift.ref.module" {
|
||||
cursorInfo.kind == "source.lang.swift.ref.module" {
|
||||
imports.insert(importedModule)
|
||||
continue
|
||||
}
|
||||
@@ -207,7 +207,7 @@ private extension SwiftLintFile {
|
||||
// Operators are omitted in the editor.open request and thus have to be looked up by the indexsource request
|
||||
func operatorImports(arguments: [String], processedTokenOffsets: Set<ByteCount>) -> Set<String> {
|
||||
guard let index = (try? Request.index(file: path!, arguments: arguments).sendIfNotDisabled())
|
||||
.map(SourceKittenDictionary.init) else {
|
||||
.map(SourceKittenDictionary.init) else {
|
||||
Issue.indexingError(path: path, ruleID: UnusedImportRule.identifier).print()
|
||||
return []
|
||||
}
|
||||
@@ -230,7 +230,7 @@ private extension SwiftLintFile {
|
||||
file: path!, offset: ByteCount(offset), arguments: arguments
|
||||
)
|
||||
guard let cursorInfo = (try? cursorInfoRequest.sendIfNotDisabled())
|
||||
.map(SourceKittenDictionary.init) else {
|
||||
.map(SourceKittenDictionary.init) else {
|
||||
Issue.missingCursorInfo(path: path, ruleID: UnusedImportRule.identifier).print()
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ private extension UnusedSetterValueRule {
|
||||
let visitor = NewValueUsageVisitor(variableName: variableName)
|
||||
if !visitor.walk(tree: node, handler: \.isVariableUsed) {
|
||||
if Syntax(node).closestVariableOrSubscript()?.modifiers?.contains(keyword: .override) == true,
|
||||
let body = node.body, body.statements.isEmpty {
|
||||
let body = node.body, body.statements.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -74,8 +74,8 @@ private extension WeakDelegateRule {
|
||||
override func visitPost(_ node: VariableDeclSyntax) {
|
||||
guard node.hasDelegateSuffix,
|
||||
node.weakOrUnownedModifier == nil,
|
||||
!node.hasComputedBody,
|
||||
!node.containsIgnoredAttribute,
|
||||
!node.hasComputedBody,
|
||||
!node.containsIgnoredAttribute,
|
||||
let parent = node.parent,
|
||||
Syntax(parent).enclosingClass() != nil else {
|
||||
return
|
||||
|
||||
@@ -89,9 +89,9 @@ private extension YodaConditionRule {
|
||||
let lhs = children[lhsIdx]
|
||||
if lhs.isLiteral,
|
||||
children.startIndex == lhsIdx || children[children.index(before: lhsIdx)].isLogicalBinaryOperator {
|
||||
// Literal is at the very beginning of the expression or the previous token is an operator with
|
||||
// weaker binding. Thus, the literal is unique on the left-hand side of the comparison operator.
|
||||
violations.append(lhs.positionAfterSkippingLeadingTrivia)
|
||||
// Literal is at the very beginning of the expression or the previous token is an operator with
|
||||
// weaker binding. Thus, the literal is unique on the left-hand side of the comparison operator.
|
||||
violations.append(lhs.positionAfterSkippingLeadingTrivia)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ private extension LineLengthRule {
|
||||
|
||||
// Check if line starts with comment markers
|
||||
if lineContent.hasPrefix("//") || lineContent.hasPrefix("/*") ||
|
||||
(lineContent.hasPrefix("*/") && lineContent.count == 2) {
|
||||
(lineContent.hasPrefix("*/") && lineContent.count == 2) {
|
||||
// Now verify using SwiftSyntax that this line doesn't contain any tokens
|
||||
var hasNonCommentContent = false
|
||||
|
||||
@@ -225,7 +225,7 @@ private final class MultilineStringLiteralVisitor: SyntaxVisitor {
|
||||
|
||||
override func visitPost(_ node: StringLiteralExprSyntax) {
|
||||
guard node.openingQuote.tokenKind == .multilineStringQuote ||
|
||||
(node.openingPounds != nil && node.openingQuote.tokenKind == .stringQuote) else {
|
||||
(node.openingPounds != nil && node.openingQuote.tokenKind == .stringQuote) else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ private func wrapExample(
|
||||
file: StaticString = #filePath,
|
||||
line: UInt = #line) -> Example {
|
||||
Example("\(prefix)\(type) Abc {\n" +
|
||||
repeatElement(template, count: count).joined() + "\(add)}\n", file: file, line: line)
|
||||
repeatElement(template, count: count).joined() + "\(add)}\n", file: file, line: line)
|
||||
}
|
||||
|
||||
@SwiftSyntaxRule
|
||||
@@ -30,7 +30,7 @@ struct TypeBodyLengthRule: Rule {
|
||||
]
|
||||
}),
|
||||
triggeringExamples: ["class", "struct", "enum", "actor"].map({ type in
|
||||
wrapExample(prefix: "↓", type, "let abc = 0\n", 251)
|
||||
wrapExample(prefix: "↓", type, "let abc = 0\n", 251)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ private extension ExprSyntax {
|
||||
return true
|
||||
}
|
||||
if let functionCall = self.as(FunctionCallExprSyntax.self),
|
||||
let calledExpression = functionCall.calledExpression.as(DeclReferenceExprSyntax.self),
|
||||
calledExpression.baseName.text == "NSPredicate" {
|
||||
let calledExpression = functionCall.calledExpression.as(DeclReferenceExprSyntax.self),
|
||||
calledExpression.baseName.text == "NSPredicate" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -52,8 +52,8 @@ private extension ExprSyntax {
|
||||
return true
|
||||
}
|
||||
if let functionCall = self.as(FunctionCallExprSyntax.self),
|
||||
let calledExpression = functionCall.calledExpression.as(DeclReferenceExprSyntax.self),
|
||||
calledExpression.baseName.text == "NSPredicate" {
|
||||
let calledExpression = functionCall.calledExpression.as(DeclReferenceExprSyntax.self),
|
||||
calledExpression.baseName.text == "NSPredicate" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -152,8 +152,8 @@ private extension ExprSyntax {
|
||||
return identifierExpr.isCopyOnWriteType
|
||||
}
|
||||
if let memberAccesExpr = expr.calledExpression.as(MemberAccessExprSyntax.self),
|
||||
memberAccesExpr.declName.baseName.text == "init",
|
||||
let identifierExpr = memberAccesExpr.base?.identifierExpr {
|
||||
memberAccesExpr.declName.baseName.text == "init",
|
||||
let identifierExpr = memberAccesExpr.base?.identifierExpr {
|
||||
return identifierExpr.isCopyOnWriteType
|
||||
}
|
||||
if expr.calledExpression.isCopyOnWriteType {
|
||||
@@ -162,7 +162,7 @@ private extension ExprSyntax {
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var identifierExpr: DeclReferenceExprSyntax? {
|
||||
if let identifierExpr = self.as(DeclReferenceExprSyntax.self) {
|
||||
|
||||
+8
-8
@@ -102,14 +102,14 @@ struct DeploymentTargetConfiguration: SeverityBasedRuleConfiguration {
|
||||
|
||||
var parameterDescription: RuleConfigurationDescription? {
|
||||
let targets = Dictionary(uniqueKeysWithValues: [
|
||||
iOSDeploymentTarget,
|
||||
iOSAppExtensionDeploymentTarget,
|
||||
macOSDeploymentTarget,
|
||||
macOSAppExtensionDeploymentTarget,
|
||||
watchOSDeploymentTarget,
|
||||
watchOSAppExtensionDeploymentTarget,
|
||||
tvOSDeploymentTarget,
|
||||
tvOSAppExtensionDeploymentTarget,
|
||||
iOSDeploymentTarget,
|
||||
iOSAppExtensionDeploymentTarget,
|
||||
macOSDeploymentTarget,
|
||||
macOSAppExtensionDeploymentTarget,
|
||||
watchOSDeploymentTarget,
|
||||
watchOSAppExtensionDeploymentTarget,
|
||||
tvOSDeploymentTarget,
|
||||
tvOSAppExtensionDeploymentTarget,
|
||||
].map { ($0.platform.configurationKey, $0) })
|
||||
severityConfiguration
|
||||
for (platform, target) in targets.sorted(by: { $0.key < $1.key }) {
|
||||
|
||||
+3
-3
@@ -10,9 +10,9 @@ struct TransitiveModuleConfiguration<Parent: Rule>: Equatable, AcceptableByConfi
|
||||
|
||||
init(fromAny configuration: Any, context _: String) throws {
|
||||
guard let configurationDict = configuration as? [String: Any],
|
||||
Set(configurationDict.keys) == ["module", "allowed_transitive_imports"],
|
||||
let importedModule = configurationDict["module"] as? String,
|
||||
let transitivelyImportedModules = configurationDict["allowed_transitive_imports"] as? [String]
|
||||
Set(configurationDict.keys) == ["module", "allowed_transitive_imports"],
|
||||
let importedModule = configurationDict["module"] as? String,
|
||||
let transitivelyImportedModules = configurationDict["allowed_transitive_imports"] as? [String]
|
||||
else {
|
||||
throw Issue.invalidConfiguration(ruleID: Parent.identifier)
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ private extension TokenSyntax {
|
||||
return true
|
||||
}
|
||||
if let previousToken = previousToken(viewMode: .sourceAccurate),
|
||||
case .spaces(1) = Array(previousToken.trailingTrivia).last {
|
||||
case .spaces(1) = Array(previousToken.trailingTrivia).last {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -147,7 +147,7 @@ private extension TokenSyntax {
|
||||
return true
|
||||
}
|
||||
if let nextToken = nextToken(viewMode: .sourceAccurate),
|
||||
case .spaces(1) = nextToken.leadingTrivia.first {
|
||||
case .spaces(1) = nextToken.leadingTrivia.first {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -197,7 +197,7 @@ private extension TokenSyntax {
|
||||
return true
|
||||
}
|
||||
if let nextToken = nextToken(viewMode: .sourceAccurate),
|
||||
allowedKinds.contains(nextToken.tokenKind) {
|
||||
allowedKinds.contains(nextToken.tokenKind) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -26,7 +26,7 @@ private extension CollectionAlignmentRule {
|
||||
override func visitPost(_ node: DictionaryElementListSyntax) {
|
||||
let locations = node.map { element in
|
||||
let position = configuration.alignColons ? element.colon.positionAfterSkippingLeadingTrivia :
|
||||
element.key.positionAfterSkippingLeadingTrivia
|
||||
element.key.positionAfterSkippingLeadingTrivia
|
||||
let location = locationConverter.location(for: position)
|
||||
|
||||
let graphemeColumn: Int
|
||||
|
||||
@@ -3,7 +3,7 @@ import SourceKittenFramework
|
||||
import SwiftSyntax
|
||||
|
||||
struct CommaInheritanceRule: OptInRule, SubstitutionCorrectableRule,
|
||||
SourceKitFreeRule {
|
||||
SourceKitFreeRule {
|
||||
var configuration = SeverityConfiguration<Self>(.warning)
|
||||
|
||||
static let description = RuleDescription(
|
||||
|
||||
@@ -80,7 +80,7 @@ private extension BracedSyntax {
|
||||
}
|
||||
if let closure = `as`(ClosureExprSyntax.self),
|
||||
closure.keyPathInParent == \FunctionCallExprSyntax.trailingClosure {
|
||||
return closure.leftBrace.previousIndentationDecidingToken
|
||||
return closure.leftBrace.previousIndentationDecidingToken
|
||||
}
|
||||
if let closureLabel = parent?.as(MultipleTrailingClosureElementSyntax.self)?.label {
|
||||
return closureLabel.previousIndentationDecidingToken
|
||||
|
||||
@@ -175,7 +175,7 @@ private extension ExprSyntax {
|
||||
return nil
|
||||
}
|
||||
|
||||
private func containsTrailingClosure(_ node: Syntax) -> Bool {
|
||||
private func containsTrailingClosure(_ node: Syntax) -> Bool {
|
||||
switch node.as(SyntaxEnum.self) {
|
||||
case .functionCallExpr(let node):
|
||||
node.trailingClosure != nil || node.calledExpression.is(ClosureExprSyntax.self)
|
||||
|
||||
@@ -119,10 +119,10 @@ private extension StringView {
|
||||
func recursiveByteOffsets(_ dict: [String: Any]) -> [ByteCount] {
|
||||
let cur: [ByteCount]
|
||||
if let line = dict["key.line"] as? Int64,
|
||||
let column = dict["key.column"] as? Int64,
|
||||
let kindString = dict["key.kind"] as? String,
|
||||
kindsToFind.contains(kindString),
|
||||
let offset = byteOffset(forLine: line, bytePosition: column) {
|
||||
let column = dict["key.column"] as? Int64,
|
||||
let kindString = dict["key.kind"] as? String,
|
||||
kindsToFind.contains(kindString),
|
||||
let offset = byteOffset(forLine: line, bytePosition: column) {
|
||||
cur = [offset]
|
||||
} else {
|
||||
cur = []
|
||||
|
||||
@@ -40,9 +40,9 @@ struct LeadingWhitespaceRule: CorrectableRule, SourceKitFreeRule {
|
||||
let whitespaceAndNewline = CharacterSet.whitespacesAndNewlines
|
||||
let spaceCount = file.contents.countOfLeadingCharacters(in: whitespaceAndNewline)
|
||||
guard spaceCount > 0,
|
||||
let firstLineRange = file.lines.first?.range,
|
||||
file.ruleEnabled(violatingRanges: [firstLineRange], for: self).isNotEmpty else {
|
||||
return 0
|
||||
let firstLineRange = file.lines.first?.range,
|
||||
file.ruleEnabled(violatingRanges: [firstLineRange], for: self).isNotEmpty else {
|
||||
return 0
|
||||
}
|
||||
|
||||
let indexEnd = file.contents.index(
|
||||
|
||||
+13
-13
@@ -220,17 +220,17 @@ extension LiteralExpressionEndIndentationRule {
|
||||
|
||||
let contents = file.stringView
|
||||
guard elements.isNotEmpty,
|
||||
let offset = dictionary.offset,
|
||||
let length = dictionary.length,
|
||||
let (startLine, _) = contents.lineAndCharacter(forByteOffset: offset),
|
||||
let firstParamOffset = elements[0].offset,
|
||||
let (firstParamLine, _) = contents.lineAndCharacter(forByteOffset: firstParamOffset),
|
||||
startLine != firstParamLine,
|
||||
let lastParamOffset = elements.last?.offset,
|
||||
let (lastParamLine, _) = contents.lineAndCharacter(forByteOffset: lastParamOffset),
|
||||
case let endOffset = offset + length - 1,
|
||||
let (endLine, endPosition) = contents.lineAndCharacter(forByteOffset: endOffset),
|
||||
lastParamLine != endLine
|
||||
let offset = dictionary.offset,
|
||||
let length = dictionary.length,
|
||||
let (startLine, _) = contents.lineAndCharacter(forByteOffset: offset),
|
||||
let firstParamOffset = elements[0].offset,
|
||||
let (firstParamLine, _) = contents.lineAndCharacter(forByteOffset: firstParamOffset),
|
||||
startLine != firstParamLine,
|
||||
let lastParamOffset = elements.last?.offset,
|
||||
let (lastParamLine, _) = contents.lineAndCharacter(forByteOffset: lastParamOffset),
|
||||
case let endOffset = offset + length - 1,
|
||||
let (endLine, endPosition) = contents.lineAndCharacter(forByteOffset: endOffset),
|
||||
lastParamLine != endLine
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
@@ -239,8 +239,8 @@ extension LiteralExpressionEndIndentationRule {
|
||||
let regex = Self.notWhitespace
|
||||
let actual = endPosition - 1
|
||||
guard let match = regex.firstMatch(in: file.contents, options: [], range: range)?.range,
|
||||
case let expected = match.location - range.location,
|
||||
expected != actual
|
||||
case let expected = match.location - range.location,
|
||||
expected != actual
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -108,10 +108,9 @@ struct MultilineFunctionChainsRule: ASTRule, OptInRule {
|
||||
let ranges = callRanges(file: file, kind: kind, dictionary: dictionary)
|
||||
|
||||
let calls = ranges.compactMap { range -> (dotLine: Int, dotOffset: Int, range: ByteRange)? in
|
||||
guard
|
||||
let offset = callDotOffset(file: file, callRange: range),
|
||||
let line = file.stringView.lineAndCharacter(forCharacterOffset: offset)?.line else {
|
||||
return nil
|
||||
guard let offset = callDotOffset(file: file, callRange: range),
|
||||
let line = file.stringView.lineAndCharacter(forCharacterOffset: offset)?.line else {
|
||||
return nil
|
||||
}
|
||||
return (dotLine: line, dotOffset: offset, range: range)
|
||||
}
|
||||
@@ -133,11 +132,10 @@ struct MultilineFunctionChainsRule: ASTRule, OptInRule {
|
||||
private static let whitespaceDotRegex = regex("\\s*\\.")
|
||||
|
||||
private func callDotOffset(file: SwiftLintFile, callRange: ByteRange) -> Int? {
|
||||
guard
|
||||
let range = file.stringView.byteRangeToNSRange(callRange),
|
||||
case let regex = Self.whitespaceDotRegex,
|
||||
let match = regex.matches(in: file.contents, options: [], range: range).last?.range else {
|
||||
return nil
|
||||
guard let range = file.stringView.byteRangeToNSRange(callRange),
|
||||
case let regex = Self.whitespaceDotRegex,
|
||||
let match = regex.matches(in: file.contents, options: [], range: range).last?.range else {
|
||||
return nil
|
||||
}
|
||||
return match.location + match.length - 1
|
||||
}
|
||||
@@ -145,11 +143,10 @@ struct MultilineFunctionChainsRule: ASTRule, OptInRule {
|
||||
private static let newlineWhitespaceDotRegex = regex("\\n\\s*\\.")
|
||||
|
||||
private func callHasLeadingNewline(file: SwiftLintFile, callRange: ByteRange) -> Bool {
|
||||
guard
|
||||
let range = file.stringView.byteRangeToNSRange(callRange),
|
||||
case let regex = Self.newlineWhitespaceDotRegex,
|
||||
regex.firstMatch(in: file.contents, options: [], range: range) != nil else {
|
||||
return false
|
||||
guard let range = file.stringView.byteRangeToNSRange(callRange),
|
||||
case let regex = Self.newlineWhitespaceDotRegex,
|
||||
regex.firstMatch(in: file.contents, options: [], range: range) != nil else {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -189,17 +186,15 @@ struct MultilineFunctionChainsRule: ASTRule, OptInRule {
|
||||
call: SourceKittenDictionary,
|
||||
parentName: String,
|
||||
parentNameOffset: ByteCount) -> ByteRange? {
|
||||
guard
|
||||
case let contents = file.stringView,
|
||||
let nameOffset = call.nameOffset,
|
||||
parentNameOffset == nameOffset,
|
||||
let nameLength = call.nameLength,
|
||||
let bodyOffset = call.bodyOffset,
|
||||
let bodyLength = call.bodyLength,
|
||||
case let nameByteRange = ByteRange(location: nameOffset, length: nameLength),
|
||||
let name = contents.substringWithByteRange(nameByteRange),
|
||||
parentName.starts(with: name)
|
||||
else {
|
||||
guard case let contents = file.stringView,
|
||||
let nameOffset = call.nameOffset,
|
||||
parentNameOffset == nameOffset,
|
||||
let nameLength = call.nameLength,
|
||||
let bodyOffset = call.bodyOffset,
|
||||
let bodyLength = call.bodyLength,
|
||||
case let nameByteRange = ByteRange(location: nameOffset, length: nameLength),
|
||||
let name = contents.substringWithByteRange(nameByteRange),
|
||||
parentName.starts(with: name) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ private extension MultilineLiteralBracketsRule {
|
||||
firstElement: (some ExprSyntaxProtocol)?,
|
||||
lastElement: (some ExprSyntaxProtocol)?) {
|
||||
guard let firstElement, let lastElement,
|
||||
isMultiline(node) else {
|
||||
isMultiline(node) else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ struct MultilineParametersBracketsRule: OptInRule {
|
||||
|
||||
// find violations at current level
|
||||
if let kind = substructure.declarationKind,
|
||||
SwiftDeclarationKind.functionKinds.contains(kind) {
|
||||
SwiftDeclarationKind.functionKinds.contains(kind) {
|
||||
guard
|
||||
let nameOffset = substructure.nameOffset,
|
||||
let nameLength = substructure.nameLength,
|
||||
|
||||
@@ -104,15 +104,15 @@ private extension NumberSeparatorValidator {
|
||||
func violation(token: TokenSyntax) -> NumberSeparatorViolation? {
|
||||
let content = token.text
|
||||
guard isDecimal(number: content),
|
||||
!isInValidRanges(number: content)
|
||||
!isInValidRanges(number: content)
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let exponential = CharacterSet(charactersIn: "eE")
|
||||
guard case let exponentialComponents = content.components(separatedBy: exponential),
|
||||
let nonExponential = exponentialComponents.first else {
|
||||
return nil
|
||||
let nonExponential = exponentialComponents.first else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let components = nonExponential.components(separatedBy: ".")
|
||||
@@ -124,8 +124,8 @@ private extension NumberSeparatorValidator {
|
||||
}
|
||||
|
||||
guard let integerSubstring = components.first,
|
||||
case let (valid, expected) = isValid(number: integerSubstring, isFraction: false),
|
||||
!valid || !validFraction
|
||||
case let (valid, expected) = isValid(number: integerSubstring, isFraction: false),
|
||||
!valid || !validFraction
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: ActorDeclSyntax) {
|
||||
if configuration.ignoreMultilineTypeHeaders,
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.actorKeyword) {
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.actorKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: ClassDeclSyntax) {
|
||||
if configuration.ignoreMultilineTypeHeaders,
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.classKeyword) {
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.classKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: EnumDeclSyntax) {
|
||||
if configuration.ignoreMultilineTypeHeaders,
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.enumKeyword) {
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.enumKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: ExtensionDeclSyntax) {
|
||||
if configuration.ignoreMultilineTypeHeaders,
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.extensionKeyword) {
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.extensionKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: ProtocolDeclSyntax) {
|
||||
if configuration.ignoreMultilineTypeHeaders,
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.protocolKeyword) {
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.protocolKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: StructDeclSyntax) {
|
||||
if configuration.ignoreMultilineTypeHeaders,
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.structKeyword) {
|
||||
hasMultilinePredecessors(node.memberBlock, keyword: node.structKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: ForStmtSyntax) {
|
||||
if configuration.ignoreMultilineStatementConditions,
|
||||
hasMultilinePredecessors(node.body, keyword: node.forKeyword) {
|
||||
hasMultilinePredecessors(node.body, keyword: node.forKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: IfExprSyntax) {
|
||||
if configuration.ignoreMultilineStatementConditions,
|
||||
hasMultilinePredecessors(node.body, keyword: node.ifKeyword) {
|
||||
hasMultilinePredecessors(node.body, keyword: node.ifKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: WhileStmtSyntax) {
|
||||
if configuration.ignoreMultilineStatementConditions,
|
||||
hasMultilinePredecessors(node.body, keyword: node.whileKeyword) {
|
||||
hasMultilinePredecessors(node.body, keyword: node.whileKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -114,8 +114,8 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: FunctionDeclSyntax) {
|
||||
if let body = node.body,
|
||||
configuration.shouldIgnoreMultilineFunctionSignatures,
|
||||
hasMultilinePredecessors(body, keyword: node.funcKeyword) {
|
||||
configuration.shouldIgnoreMultilineFunctionSignatures,
|
||||
hasMultilinePredecessors(body, keyword: node.funcKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -124,8 +124,8 @@ private extension OpeningBraceRule {
|
||||
|
||||
override func visitPost(_ node: InitializerDeclSyntax) {
|
||||
if let body = node.body,
|
||||
configuration.shouldIgnoreMultilineFunctionSignatures,
|
||||
hasMultilinePredecessors(body, keyword: node.initKeyword) {
|
||||
configuration.shouldIgnoreMultilineFunctionSignatures,
|
||||
hasMultilinePredecessors(body, keyword: node.initKeyword) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -68,9 +68,9 @@ struct OperatorUsageWhitespaceRule: OptInRule, CorrectableRule, SourceKitFreeRul
|
||||
let equalityOperatorRegex = regex("\\s+=\\s")
|
||||
|
||||
guard let match = equalityOperatorRegex.firstMatch(
|
||||
in: matchedString,
|
||||
options: [],
|
||||
range: matchedString.fullNSRange),
|
||||
in: matchedString,
|
||||
options: [],
|
||||
range: matchedString.fullNSRange),
|
||||
match.range == matchedString.fullNSRange
|
||||
else {
|
||||
return false
|
||||
|
||||
@@ -91,8 +91,8 @@ private extension SelfBindingRule {
|
||||
return super.visit(node.with(\.pattern, newPattern))
|
||||
}
|
||||
if node.initializer == nil,
|
||||
identifierPattern.identifier.text == "self",
|
||||
configuration.bindIdentifier != "self" {
|
||||
identifierPattern.identifier.text == "self",
|
||||
configuration.bindIdentifier != "self" {
|
||||
numberOfCorrections += 1
|
||||
let newPattern = PatternSyntax(
|
||||
identifierPattern
|
||||
|
||||
@@ -103,7 +103,7 @@ private extension ShorthandArgumentRule {
|
||||
if complexArguments.contains(argument) {
|
||||
nil
|
||||
} else if locationConverter.location(for: argument.position).line
|
||||
<= startLine + configuration.allowUntilLineAfterOpeningBrace {
|
||||
<= startLine + configuration.allowUntilLineAfterOpeningBrace {
|
||||
nil
|
||||
} else {
|
||||
ReasonedRuleViolation(
|
||||
|
||||
@@ -84,8 +84,9 @@ struct SortedImportsRule: CorrectableRule, OptInRule {
|
||||
let contents = file.stringView
|
||||
let lines = file.lines
|
||||
let importLines: [Line] = importRanges.compactMap { range in
|
||||
guard let line = contents.lineAndCharacter(forCharacterOffset: range.location)?.line
|
||||
else { return nil }
|
||||
guard let line = contents.lineAndCharacter(forCharacterOffset: range.location)?.line else {
|
||||
return nil
|
||||
}
|
||||
return lines[line - 1]
|
||||
}
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ private extension StatementPositionRule {
|
||||
let validator = Self.uncuddledMatchValidator(contents: file.stringView)
|
||||
let filterRanges = Self.uncuddledMatchFilter(contents: file.stringView, syntaxMap: syntaxMap)
|
||||
let validMatches = matches.compactMap(validator).filter(filterRanges)
|
||||
.filter { file.ruleEnabled(violatingRanges: [$0.range], for: self).isNotEmpty }
|
||||
.filter { file.ruleEnabled(violatingRanges: [$0.range], for: self).isNotEmpty }
|
||||
if validMatches.isEmpty {
|
||||
return 0
|
||||
}
|
||||
@@ -195,7 +195,7 @@ private extension StatementPositionRule {
|
||||
var whitespace = contents.bridge().substring(with: range1)
|
||||
let newLines: String
|
||||
if newlineRange.location != NSNotFound {
|
||||
newLines = contents.bridge().substring(with: newlineRange)
|
||||
newLines = contents.bridge().substring(with: newlineRange)
|
||||
} else {
|
||||
newLines = ""
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ private extension TrailingCommaRule {
|
||||
.with(\.expression, lastElement.expression.with(\.trailingTrivia, []))
|
||||
.with(\.trailingComma, .commaToken())
|
||||
.with(\.trailingTrivia, lastElement.expression.trailingTrivia)
|
||||
)
|
||||
)
|
||||
return super.visit(newNode)
|
||||
case (_, true), (nil, false):
|
||||
return super.visit(node)
|
||||
|
||||
@@ -49,7 +49,7 @@ private extension TrailingWhitespaceRule {
|
||||
|
||||
// Apply `ignoresEmptyLines` configuration
|
||||
if configuration.ignoresEmptyLines &&
|
||||
line.trimmingCharacters(in: .whitespaces).isEmpty {
|
||||
line.trimmingCharacters(in: .whitespaces).isEmpty {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ struct VerticalWhitespaceBetweenCasesRule: Rule {
|
||||
let patternRegex = regex(pattern)
|
||||
let substring = file.contents.substring(from: range.location, length: range.length)
|
||||
guard let matchResult = patternRegex.firstMatch(in: substring, options: [], range: substring.fullNSRange),
|
||||
matchResult.numberOfRanges > 1 else {
|
||||
matchResult.numberOfRanges > 1 else {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ public struct SourceKittenDictionary {
|
||||
public var elements: [Self] {
|
||||
let elements = value["key.elements"] as? [any SourceKitRepresentable] ?? []
|
||||
return elements.compactMap { $0 as? [String: any SourceKitRepresentable] }
|
||||
.map(Self.init)
|
||||
.map(Self.init)
|
||||
}
|
||||
|
||||
public var entities: [Self] {
|
||||
|
||||
@@ -22,7 +22,7 @@ public extension Request {
|
||||
// Skip check for ConditionallySourceKitFree rules since we can't determine
|
||||
// at the type level if they're effectively SourceKit-free
|
||||
if ruleType is any SourceKitFreeRule.Type &&
|
||||
!(ruleType is any ConditionallySourceKitFree.Type) {
|
||||
!(ruleType is any ConditionallySourceKitFree.Type) {
|
||||
queuedFatalError("""
|
||||
'\(ruleID)' is a SourceKitFreeRule and should not be making requests to SourceKit.
|
||||
""")
|
||||
|
||||
@@ -55,8 +55,8 @@ public extension String {
|
||||
limitedBy: utf16.endIndex) ?? utf16.endIndex
|
||||
|
||||
guard let fromIndex = Index(from16, within: self),
|
||||
let toIndex = Index(to16, within: self) else {
|
||||
return nil
|
||||
let toIndex = Index(to16, within: self) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fromIndex..<toIndex
|
||||
|
||||
@@ -159,7 +159,7 @@ extension SwiftLintFile {
|
||||
let tokenRange = token.range
|
||||
if line.byteRange.contains(token.offset) ||
|
||||
tokenRange.contains(line.byteRange.location) {
|
||||
results[line.index].append(token)
|
||||
results[line.index].append(token)
|
||||
}
|
||||
let tokenEnd = tokenRange.upperBound
|
||||
let lineEnd = line.byteRange.upperBound
|
||||
|
||||
@@ -66,8 +66,8 @@ public extension ExprSyntax {
|
||||
return functionCall
|
||||
}
|
||||
if let tuple = self.as(TupleExprSyntax.self),
|
||||
let firstElement = tuple.elements.onlyElement,
|
||||
let functionCall = firstElement.expression.as(FunctionCallExprSyntax.self) {
|
||||
let firstElement = tuple.elements.onlyElement,
|
||||
let functionCall = firstElement.expression.as(FunctionCallExprSyntax.self) {
|
||||
return functionCall
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -105,10 +105,9 @@ public struct Baseline: Equatable {
|
||||
var filteredViolations: Set<BaselineViolation> = []
|
||||
|
||||
for (ruleIdentifier, ruleViolations) in violationsByRuleIdentifier {
|
||||
guard
|
||||
let baselineViolations = baselineViolationsByRuleIdentifier[ruleIdentifier],
|
||||
baselineViolations.isNotEmpty else {
|
||||
filteredViolations.formUnion(ruleViolations)
|
||||
guard let baselineViolations = baselineViolationsByRuleIdentifier[ruleIdentifier],
|
||||
baselineViolations.isNotEmpty else {
|
||||
filteredViolations.formUnion(ruleViolations)
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public struct ChildOptionSeverityConfiguration<Parent: Rule>: RuleConfiguration,
|
||||
|
||||
public mutating func apply(configuration: Any) throws {
|
||||
guard let configString = configuration as? String,
|
||||
let optionSeverity = ChildOptionSeverity(rawValue: configString.lowercased()) else {
|
||||
let optionSeverity = ChildOptionSeverity(rawValue: configString.lowercased()) else {
|
||||
throw Issue.invalidConfiguration(ruleID: Parent.identifier)
|
||||
}
|
||||
self.optionSeverity = optionSeverity
|
||||
|
||||
@@ -109,9 +109,9 @@ public struct Command: Equatable {
|
||||
// Store any text after the comment delimiter as the trailingComment.
|
||||
// The addition to currentIndex is to move past the delimiter
|
||||
trailingComment = String(
|
||||
scanner
|
||||
.string[scanner.currentIndex...]
|
||||
.dropFirst(Self.commentDelimiter.count)
|
||||
scanner
|
||||
.string[scanner.currentIndex...]
|
||||
.dropFirst(Self.commentDelimiter.count)
|
||||
)
|
||||
}
|
||||
let ruleTexts = rawRuleTexts.components(separatedBy: .whitespacesAndNewlines).filter {
|
||||
|
||||
@@ -11,7 +11,7 @@ public struct RuleDescription: Equatable, Sendable {
|
||||
/// explanation of the rule's purpose and rationale.
|
||||
public let description: String
|
||||
|
||||
/// A longer explanation of the rule's purpose and rationale. Typically defined as a multiline string, long text
|
||||
/// A longer explanation of the rule's purpose and rationale. Typically defined as a multiline string, long text
|
||||
/// lines should be wrapped. Markdown formatting is supported. Multiline code blocks will be formatted as
|
||||
/// `swift` code unless otherwise specified, and will automatically be indented by four spaces when printed
|
||||
/// to the console.
|
||||
|
||||
@@ -92,7 +92,7 @@ public extension SwiftVersion {
|
||||
try? Request.customRequest(request: params).sendIfNotDisabled()
|
||||
}
|
||||
if let result,
|
||||
let major = result.versionMajor, let minor = result.versionMinor, let patch = result.versionPatch {
|
||||
let major = result.versionMajor, let minor = result.versionMinor, let patch = result.versionPatch {
|
||||
return SwiftVersion(rawValue: "\(major).\(minor).\(patch)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public protocol Rule {
|
||||
/// Create a description of how this rule has been configured to run.
|
||||
///
|
||||
/// - parameter exclusiveOptions: A set of options that should be excluded from the description.
|
||||
///
|
||||
///
|
||||
/// - returns: A description of the rule's configuration.
|
||||
func createConfigurationDescription(exclusiveOptions: Set<String>) -> RuleConfigurationDescription
|
||||
|
||||
@@ -83,17 +83,17 @@ public protocol Rule {
|
||||
/// - ruleID: The name of a rule as used in a disable command.
|
||||
///
|
||||
/// - Returns: A boolean value indicating whether the violation can be disabled by the given ID.
|
||||
func canBeDisabled(violation: StyleViolation, by ruleID: RuleIdentifier) -> Bool
|
||||
func canBeDisabled(violation: StyleViolation, by ruleID: RuleIdentifier) -> Bool
|
||||
|
||||
/// Checks if a the rule is enabled in a given region. A specific rule ID can be provided in case a rule supports
|
||||
/// more than one identifier.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - region: The region to check.
|
||||
/// - ruleID: Rule identifier deviating from the default rule's name.
|
||||
///
|
||||
/// - Returns: A boolean value indicating whether the rule is enabled in the given region.
|
||||
func isEnabled(in region: Region, for ruleID: String) -> Bool
|
||||
/// Checks if a the rule is enabled in a given region. A specific rule ID can be provided in case a rule supports
|
||||
/// more than one identifier.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - region: The region to check.
|
||||
/// - ruleID: Rule identifier deviating from the default rule's name.
|
||||
///
|
||||
/// - Returns: A boolean value indicating whether the rule is enabled in the given region.
|
||||
func isEnabled(in region: Region, for ruleID: String) -> Bool
|
||||
}
|
||||
|
||||
public extension Rule {
|
||||
|
||||
@@ -50,8 +50,8 @@ public struct RegexConfiguration<Parent: Rule>: SeverityBasedRuleConfiguration,
|
||||
executionMode.rawValue,
|
||||
]
|
||||
if let jsonData = try? JSONSerialization.data(withJSONObject: jsonObject),
|
||||
let jsonString = String(data: jsonData, encoding: .utf8) {
|
||||
return jsonString
|
||||
let jsonString = String(data: jsonData, encoding: .utf8) {
|
||||
return jsonString
|
||||
}
|
||||
queuedFatalError("Could not serialize regex configuration for cache")
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ open class CodeBlockVisitor<Configuration: RuleConfiguration>: ViolationsSyntaxV
|
||||
return
|
||||
}
|
||||
if parent.is(FunctionCallExprSyntax.self) || parent.is(MultipleTrailingClosureElementSyntax.self),
|
||||
node.keyPathInParent != \FunctionCallExprSyntax.calledExpression {
|
||||
node.keyPathInParent != \FunctionCallExprSyntax.calledExpression {
|
||||
// Trailing closure
|
||||
collectViolations(for: node)
|
||||
}
|
||||
|
||||
@@ -66,8 +66,8 @@ extension Array where Element == String {
|
||||
let responseFile = String(arg.dropFirst())
|
||||
return (try? String(contentsOf: URL(fileURLWithPath: responseFile, isDirectory: false))).flatMap {
|
||||
$0.trimmingCharacters(in: .newlines)
|
||||
.components(separatedBy: "\n")
|
||||
.expandingResponseFiles
|
||||
.components(separatedBy: "\n")
|
||||
.expandingResponseFiles
|
||||
} ?? [arg]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,8 +273,8 @@ extension Configuration {
|
||||
queuedPrintError("\(options.capitalizedVerb) Swift files \(filesInfo)")
|
||||
}
|
||||
let excludeLintableFilesBy = options.useExcludingByPrefix
|
||||
? Configuration.ExcludeBy.prefix
|
||||
: .paths(excludedPaths: excludedPaths())
|
||||
? Configuration.ExcludeBy.prefix
|
||||
: .paths(excludedPaths: excludedPaths())
|
||||
return options.paths.flatMap {
|
||||
self.lintableFiles(
|
||||
inPath: $0,
|
||||
|
||||
@@ -171,8 +171,8 @@ extension Configuration {
|
||||
) {
|
||||
for key in dict.keys where !validGlobalKeys.contains(key) {
|
||||
guard let identifier = ruleList.identifier(for: key),
|
||||
let ruleType = ruleList.list[identifier] else {
|
||||
continue
|
||||
let ruleType = ruleList.list[identifier] else {
|
||||
continue
|
||||
}
|
||||
|
||||
switch rulesMode {
|
||||
|
||||
@@ -131,7 +131,7 @@ package struct LintOrAnalyzeCommand {
|
||||
Could not change working directory to '\(workingDirectory)'. \
|
||||
Make sure it exists and is accessible.
|
||||
"""
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
try await Signposts.record(name: "LintOrAnalyzeCommand.run") {
|
||||
@@ -236,9 +236,8 @@ package struct LintOrAnalyzeCommand {
|
||||
return try Baseline(fromPath: baselinePath)
|
||||
} catch {
|
||||
Issue.baselineNotReadable(path: baselinePath).print()
|
||||
if
|
||||
(error as? CocoaError)?.code != CocoaError.fileReadNoSuchFile ||
|
||||
options.writeBaseline != options.baseline {
|
||||
if (error as? CocoaError)?.code != CocoaError.fileReadNoSuchFile ||
|
||||
options.writeBaseline != options.baseline {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ struct LintableFilesVisitor {
|
||||
|
||||
private static func loadLogCompilerInvocations(_ path: String) -> [[String]]? {
|
||||
if let data = FileManager.default.contents(atPath: path),
|
||||
let logContents = String(data: data, encoding: .utf8) {
|
||||
let logContents = String(data: data, encoding: .utf8) {
|
||||
if logContents.isEmpty {
|
||||
return nil
|
||||
}
|
||||
@@ -164,7 +164,7 @@ struct LintableFilesVisitor {
|
||||
}
|
||||
|
||||
guard let object = try? JSONSerialization.jsonObject(with: fileContents),
|
||||
let compileDB = object as? [[String: Any]] else {
|
||||
let compileDB = object as? [[String: Any]] else {
|
||||
throw CompileCommandsLoadError.malformedCommands(path)
|
||||
}
|
||||
|
||||
|
||||
@@ -373,7 +373,7 @@ public struct CollectedLinter {
|
||||
private func cachedStyleViolations(benchmark: Bool = false) -> ([StyleViolation], [(id: String, time: Double)])? {
|
||||
let start = Date()
|
||||
guard let cache, let file = file.path,
|
||||
let cachedViolations = cache.violations(forFile: file, configuration: configuration) else {
|
||||
let cachedViolations = cache.violations(forFile: file, configuration: configuration) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -74,9 +74,9 @@ public final class LinterCache {
|
||||
|
||||
internal func violations(forFile file: String, configuration: Configuration) -> [StyleViolation]? {
|
||||
guard let lastModification = fileManager.modificationDate(forFileAtPath: file),
|
||||
let entry = fileCache(cacheDescription: configuration.cacheDescription).entries[file],
|
||||
entry.lastModification == lastModification,
|
||||
entry.swiftVersion == swiftVersion
|
||||
let entry = fileCache(cacheDescription: configuration.cacheDescription).entries[file],
|
||||
entry.lastModification == lastModification,
|
||||
entry.swiftVersion == swiftVersion
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ final class CustomRulesTests: SwiftLintTestCase {
|
||||
]
|
||||
|
||||
let example = Example(
|
||||
"""
|
||||
"""
|
||||
// swiftlint:disable custom1 custom3
|
||||
return 10
|
||||
"""
|
||||
|
||||
@@ -38,7 +38,7 @@ final class GlobTests: SwiftLintTestCase {
|
||||
|
||||
func testNoMatchOneCharacterInBracket() {
|
||||
let files = Glob.resolveGlob(mockPath.stringByAppendingPathComponent("Level[ab].swift"))
|
||||
XCTAssertTrue(files.isEmpty)
|
||||
XCTAssertTrue(files.isEmpty)
|
||||
}
|
||||
|
||||
func testMatchesCharacterInRange() {
|
||||
|
||||
@@ -47,10 +47,10 @@ public let allRuleIdentifiers = Set(RuleRegistry.shared.list.list.keys)
|
||||
public extension Configuration {
|
||||
func applyingConfiguration(from example: Example) -> Configuration {
|
||||
guard let exampleConfiguration = example.configuration,
|
||||
case let .onlyConfiguration(onlyRules) = self.rulesMode,
|
||||
let firstRule = (onlyRules.first { $0 != "superfluous_disable_command" }),
|
||||
case let configDict: [_: any Sendable] = ["only_rules": onlyRules, firstRule: exampleConfiguration],
|
||||
let typedConfiguration = try? Configuration(dict: configDict) else { return self }
|
||||
case let .onlyConfiguration(onlyRules) = self.rulesMode,
|
||||
let firstRule = (onlyRules.first { $0 != "superfluous_disable_command" }),
|
||||
case let configDict: [_: any Sendable] = ["only_rules": onlyRules, firstRule: exampleConfiguration],
|
||||
let typedConfiguration = try? Configuration(dict: configDict) else { return self }
|
||||
return merged(withChild: typedConfiguration, rootDirectory: rootDirectory)
|
||||
}
|
||||
}
|
||||
@@ -156,7 +156,7 @@ private func render(violations: [StyleViolation], in contents: String) -> String
|
||||
var contents = StringView(contents).lines.map(\.content)
|
||||
for violation in violations.sorted(by: { $0.location > $1.location }) {
|
||||
guard let line = violation.location.line,
|
||||
let character = violation.location.character else { continue }
|
||||
let character = violation.location.character else { continue }
|
||||
|
||||
let message = String(repeating: " ", count: character - 1) + "^ " + [
|
||||
"\(violation.severity.rawValue): ",
|
||||
@@ -267,10 +267,10 @@ private func testCorrection(_ correction: (Example, Example),
|
||||
#endif
|
||||
var config = configuration
|
||||
if let correctionConfiguration = correction.0.configuration,
|
||||
case let .onlyConfiguration(onlyRules) = configuration.rulesMode,
|
||||
let ruleToConfigure = (onlyRules.first { $0 != SuperfluousDisableCommandRule.identifier }),
|
||||
case let configDict: [_: any Sendable] = ["only_rules": onlyRules, ruleToConfigure: correctionConfiguration],
|
||||
let typedConfiguration = try? Configuration(dict: configDict) {
|
||||
case let .onlyConfiguration(onlyRules) = configuration.rulesMode,
|
||||
let ruleToConfigure = (onlyRules.first { $0 != SuperfluousDisableCommandRule.identifier }),
|
||||
case let configDict: [_: any Sendable] = ["only_rules": onlyRules, ruleToConfigure: correctionConfiguration],
|
||||
let typedConfiguration = try? Configuration(dict: configDict) {
|
||||
config = configuration.merged(withChild: typedConfiguration, rootDirectory: configuration.rootDirectory)
|
||||
}
|
||||
|
||||
@@ -307,11 +307,11 @@ public extension XCTestCase {
|
||||
}
|
||||
|
||||
guard let config = makeConfig(
|
||||
ruleConfiguration,
|
||||
ruleDescription.identifier,
|
||||
skipDisableCommandTests: skipDisableCommandTests) else {
|
||||
XCTFail("Failed to create configuration", file: (file), line: line)
|
||||
return
|
||||
ruleConfiguration,
|
||||
ruleDescription.identifier,
|
||||
skipDisableCommandTests: skipDisableCommandTests) else {
|
||||
XCTFail("Failed to create configuration", file: (file), line: line)
|
||||
return
|
||||
}
|
||||
|
||||
let disableCommands: [String]
|
||||
|
||||
Reference in New Issue
Block a user