Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Source/SwiftLintBuiltInRules/Models/BuiltInRules.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public let builtInRules: [any Rule.Type] = [
ClosureSpacingRule.self,
CollectionAlignmentRule.self,
ColonRule.self,
CombineFlatMapRule.self,
CommaInheritanceRule.self,
CommaRule.self,
CommentSpacingRule.self,
Expand Down
58 changes: 58 additions & 0 deletions Source/SwiftLintBuiltInRules/Rules/Lint/CombineFlatMapRule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import SwiftSyntax

@SwiftSyntaxRule
struct CombineFlatMapRule: Rule {
var configuration = SeverityConfiguration<Self>(.warning)

static let description = RuleDescription(
identifier: "combine_flatmap",
name: "Combine FlatMap",
description: "Avoid using Combine's flatMap operator.",
kind: .lint,
nonTriggeringExamples: [
Example("[1, 2, 3].flatMap { $0 }"),
Example("array.flatMap { $0 }"),
Example("Combine.map { $0 }")
],
triggeringExamples: [
Example("Combine.flatMap { $0 }"),
Example("let transform = Combine.flatMap")
]
)
}

private extension CombineFlatMapRule {
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
override func visitPost(_ node: FunctionCallExprSyntax) {
guard let memberAccess = node.calledExpression.as(MemberAccessExprSyntax.self),
memberAccess.isCombineFlatMap else {
return
}

violations.append(node.positionAfterSkippingLeadingTrivia)
}

override func visitPost(_ node: MemberAccessExprSyntax) {
guard node.isCombineFlatMap else {
return
}

if let parent = node.parent?.as(FunctionCallExprSyntax.self),
parent.calledExpression.id == node.id {
return
}

violations.append(node.positionAfterSkippingLeadingTrivia)
}
}
}

private extension MemberAccessExprSyntax {
var isCombineFlatMap: Bool {
guard declName.baseName.text == "flatMap" else {
return false
}

return base?.as(DeclReferenceExprSyntax.self)?.baseName.text == "Combine"
}
}
12 changes: 6 additions & 6 deletions Tests/GeneratedTests/GeneratedTests_01.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,12 @@ final class ColonRuleGeneratedTests: SwiftLintTestCase {
}
}

final class CombineFlatMapRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(CombineFlatMapRule.description)
}
}

final class CommaInheritanceRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(CommaInheritanceRule.description)
Expand Down Expand Up @@ -150,9 +156,3 @@ final class ComputedAccessorsOrderRuleGeneratedTests: SwiftLintTestCase {
verifyRule(ComputedAccessorsOrderRule.description)
}
}

final class ConditionalReturnsOnNewlineRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(ConditionalReturnsOnNewlineRule.description)
}
}
12 changes: 6 additions & 6 deletions Tests/GeneratedTests/GeneratedTests_02.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
@testable import SwiftLintCore
import TestHelpers

final class ConditionalReturnsOnNewlineRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(ConditionalReturnsOnNewlineRule.description)
}
}

final class ContainsOverFilterCountRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(ContainsOverFilterCountRule.description)
Expand Down Expand Up @@ -150,9 +156,3 @@ final class EmptyCountRuleGeneratedTests: SwiftLintTestCase {
verifyRule(EmptyCountRule.description)
}
}

final class EmptyEnumArgumentsRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(EmptyEnumArgumentsRule.description)
}
}
12 changes: 6 additions & 6 deletions Tests/GeneratedTests/GeneratedTests_03.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
@testable import SwiftLintCore
import TestHelpers

final class EmptyEnumArgumentsRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(EmptyEnumArgumentsRule.description)
}
}

final class EmptyParametersRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(EmptyParametersRule.description)
Expand Down Expand Up @@ -150,9 +156,3 @@ final class ForWhereRuleGeneratedTests: SwiftLintTestCase {
verifyRule(ForWhereRule.description)
}
}

final class ForceCastRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(ForceCastRule.description)
}
}
12 changes: 6 additions & 6 deletions Tests/GeneratedTests/GeneratedTests_04.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
@testable import SwiftLintCore
import TestHelpers

final class ForceCastRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(ForceCastRule.description)
}
}

final class ForceTryRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(ForceTryRule.description)
Expand Down Expand Up @@ -150,9 +156,3 @@ final class LegacyCGGeometryFunctionsRuleGeneratedTests: SwiftLintTestCase {
verifyRule(LegacyCGGeometryFunctionsRule.description)
}
}

final class LegacyConstantRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(LegacyConstantRule.description)
}
}
12 changes: 6 additions & 6 deletions Tests/GeneratedTests/GeneratedTests_05.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
@testable import SwiftLintCore
import TestHelpers

final class LegacyConstantRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(LegacyConstantRule.description)
}
}

final class LegacyConstructorRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(LegacyConstructorRule.description)
Expand Down Expand Up @@ -150,9 +156,3 @@ final class NSLocalizedStringRequireBundleRuleGeneratedTests: SwiftLintTestCase
verifyRule(NSLocalizedStringRequireBundleRule.description)
}
}

final class NSNumberInitAsFunctionReferenceRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(NSNumberInitAsFunctionReferenceRule.description)
}
}
12 changes: 6 additions & 6 deletions Tests/GeneratedTests/GeneratedTests_06.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
@testable import SwiftLintCore
import TestHelpers

final class NSNumberInitAsFunctionReferenceRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(NSNumberInitAsFunctionReferenceRule.description)
}
}

final class NSObjectPreferIsEqualRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(NSObjectPreferIsEqualRule.description)
Expand Down Expand Up @@ -150,9 +156,3 @@ final class PeriodSpacingRuleGeneratedTests: SwiftLintTestCase {
verifyRule(PeriodSpacingRule.description)
}
}

final class PreferAssetSymbolsRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(PreferAssetSymbolsRule.description)
}
}
12 changes: 6 additions & 6 deletions Tests/GeneratedTests/GeneratedTests_07.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
@testable import SwiftLintCore
import TestHelpers

final class PreferAssetSymbolsRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(PreferAssetSymbolsRule.description)
}
}

final class PreferConditionListRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(PreferConditionListRule.description)
Expand Down Expand Up @@ -150,9 +156,3 @@ final class RedundantDiscardableLetRuleGeneratedTests: SwiftLintTestCase {
verifyRule(RedundantDiscardableLetRule.description)
}
}

final class RedundantNilCoalescingRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(RedundantNilCoalescingRule.description)
}
}
12 changes: 6 additions & 6 deletions Tests/GeneratedTests/GeneratedTests_08.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
@testable import SwiftLintCore
import TestHelpers

final class RedundantNilCoalescingRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(RedundantNilCoalescingRule.description)
}
}

final class RedundantObjcAttributeRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(RedundantObjcAttributeRule.description)
Expand Down Expand Up @@ -150,9 +156,3 @@ final class StrictFilePrivateRuleGeneratedTests: SwiftLintTestCase {
verifyRule(StrictFilePrivateRule.description)
}
}

final class StrongIBOutletRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(StrongIBOutletRule.description)
}
}
12 changes: 6 additions & 6 deletions Tests/GeneratedTests/GeneratedTests_09.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
@testable import SwiftLintCore
import TestHelpers

final class StrongIBOutletRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(StrongIBOutletRule.description)
}
}

final class SuperfluousElseRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(SuperfluousElseRule.description)
Expand Down Expand Up @@ -150,9 +156,3 @@ final class UnneededSynthesizedInitializerRuleGeneratedTests: SwiftLintTestCase
verifyRule(UnneededSynthesizedInitializerRule.description)
}
}

final class UnneededThrowsRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(UnneededThrowsRule.description)
}
}
6 changes: 6 additions & 0 deletions Tests/GeneratedTests/GeneratedTests_10.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
@testable import SwiftLintCore
import TestHelpers

final class UnneededThrowsRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(UnneededThrowsRule.description)
}
}

final class UnownedVariableCaptureRuleGeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
verifyRule(UnownedVariableCaptureRule.description)
Expand Down