forked from realm/SwiftLint
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add rule to prevent use of JSONDecoder.decode(_:from:) (#4)
We recently added some error logging inside `Decodable.decode(_:)` which has already proven very useful. We want to enforce its usage everywhere so we can get as much coverage as possible. on our error logging. To that end, we need to warn against using `JSONDecoder.decode(_:from:)`.
- Loading branch information
Showing
5 changed files
with
87 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
Source/SwiftLintBuiltInRules/Rules/Whatnot/JSONDecodingRule.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import SwiftLintCore | ||
import SwiftSyntax | ||
|
||
@SwiftSyntaxRule(foldExpressions: true) | ||
struct JSONDecodingRule: Rule { | ||
var configuration = SeverityConfiguration<Self>(.warning) | ||
|
||
static let description = RuleDescription( | ||
identifier: "json_decoding", | ||
name: "JSON Decoding", | ||
description: "Don't use JSONDecoder.decode directly", | ||
kind: .lint, | ||
nonTriggeringExamples: [ | ||
Example(""" | ||
T.decode(data) | ||
"""), | ||
Example(""" | ||
let decoder = JSONDecoder() | ||
MyType.decode(data, using: decoder) | ||
"""), | ||
Example(""" | ||
MyType.decode(data, using: JSONDecoder().snakeCase()) | ||
"""), | ||
Example(""" | ||
let container = try decoder.container(keyedBy: CodingKeys.self) | ||
let myType = try container.decode(MyType.self, forKey: .myType) | ||
"""), | ||
Example(""" | ||
let container = try decoder.singleValueContainer().decode(MyType.self) | ||
""") | ||
], | ||
triggeringExamples: [ | ||
Example(""" | ||
JSONDecoder().↓decode(MyType.self, from: data) | ||
"""), | ||
Example(""" | ||
let decoder = JSONDecoder() | ||
decoder.↓decode(MyType.self, from: data) | ||
"""), | ||
Example(""" | ||
JSONDecoder().snakeCase().↓decode(Self.self, from: data) | ||
""") | ||
] | ||
) | ||
} | ||
|
||
private extension JSONDecodingRule { | ||
final class Visitor: ViolationsSyntaxVisitor<ConfigurationType> { | ||
override func visitPost(_ node: FunctionCallExprSyntax) { | ||
guard let member = node.calledExpression.as(MemberAccessExprSyntax.self), | ||
member.declName.baseName.text == "decode", | ||
let argument = node.arguments.first?.expression.as(MemberAccessExprSyntax.self), | ||
let modelName = argument.base?.description, | ||
argument.declName.baseName.text == "self", | ||
let fromArgument = node.arguments.first(where: { $0.label?.text == "from" }) | ||
else { return } | ||
|
||
violations.append(reason( | ||
modelName: modelName, | ||
dataName: fromArgument.expression.description, | ||
position: member.declName.positionAfterSkippingLeadingTrivia | ||
)) | ||
} | ||
|
||
func reason(modelName: String, dataName: String, position: AbsolutePosition) -> ReasonedRuleViolation { | ||
.init( | ||
position: position, | ||
reason: """ | ||
Use `\(modelName).decode(\(dataName))` instead. It will automatically trigger \ | ||
error logs if the decoding fails | ||
""", | ||
severity: .warning | ||
) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters