Files
SwiftLint/Source/SwiftLintBuiltInRules/Rules/Lint/NSLocalizedStringRequireBundleRule.swift
Danny Mösch 40bd97038a Support arbitrary configurations in @SwiftSyntaxRule (#5275)
Almost all rules based on SwiftSyntax can be set up now by just adding
`@SwiftSyntaxRule` to the rule struct.
2023-10-16 19:34:43 +02:00

64 lines
2.2 KiB
Swift

import SwiftSyntax
@SwiftSyntaxRule
struct NSLocalizedStringRequireBundleRule: OptInRule {
var configuration = SeverityConfiguration<Self>(.warning)
static let description = RuleDescription(
identifier: "nslocalizedstring_require_bundle",
name: "NSLocalizedString Require Bundle",
description: "Calls to NSLocalizedString should specify the bundle which contains the strings file",
kind: .lint,
nonTriggeringExamples: [
Example("""
NSLocalizedString("someKey", bundle: .main, comment: "test")
"""),
Example("""
NSLocalizedString("someKey", tableName: "a",
bundle: Bundle(for: A.self),
comment: "test")
"""),
Example("""
NSLocalizedString("someKey", tableName: "xyz",
bundle: someBundle, value: "test"
comment: "test")
"""),
Example("""
arbitraryFunctionCall("something")
""")
],
triggeringExamples: [
Example("""
↓NSLocalizedString("someKey", comment: "test")
"""),
Example("""
↓NSLocalizedString("someKey", tableName: "a", comment: "test")
"""),
Example("""
↓NSLocalizedString("someKey", tableName: "xyz",
value: "test", comment: "test")
""")
]
)
}
private extension NSLocalizedStringRequireBundleRule {
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> {
override func visitPost(_ node: FunctionCallExprSyntax) {
if let identifierExpr = node.calledExpression.as(DeclReferenceExprSyntax.self),
identifierExpr.baseName.tokenKind == .identifier("NSLocalizedString"),
!node.arguments.containsArgument(named: "bundle") {
violations.append(node.positionAfterSkippingLeadingTrivia)
}
}
}
}
private extension LabeledExprListSyntax {
func containsArgument(named name: String) -> Bool {
contains { arg in
arg.label?.tokenKind == .identifier(name)
}
}
}