Skip to content

Commit

Permalink
Add cases with inner types
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulTaykalo committed Mar 2, 2022
1 parent 70d8963 commit c49a844
Showing 1 changed file with 31 additions and 20 deletions.
51 changes: 31 additions & 20 deletions Source/SwiftLintFramework/Rules/Idiomatic/SyntacticSugarRule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ public struct SyntacticSugarRule: SubstitutionCorrectableRule, ConfigurationProv
public var configuration = SeverityConfiguration(.warning)

private var pattern: String {
let types = ["Optional", "ImplicitlyUnwrappedOptional", "Array", "Dictionary"]
let negativeLookBehind = "(?:(?<!\\.)|Swift\\.)"
return negativeLookBehind + "\\b(" + types.joined(separator: "|") + ")\\s*<[^<]*?>"
let types = ["Swift.Optional", "Swift.ImplicitlyUnwrappedOptional", "Swift.Array", "Swift.Dictionary",
"Optional", "ImplicitlyUnwrappedOptional", "Array", "Dictionary"]
let negativeLookBehind = "(?:(?<!\\.))"
return negativeLookBehind + "\\b(" + types.joined(separator: "|") + ")\\s*<[^<]*?(?:<[^<]*?>)?[^<]*?>"
}

public init() {}
Expand Down Expand Up @@ -65,8 +66,8 @@ public struct SyntacticSugarRule: SubstitutionCorrectableRule, ConfigurationProv
Example("func x(a: [Int], b: Int) -> [Int: String]"),
Example("let x = Array<String>.array(of: object)"): Example("let x = [String].array(of: object)"),
Example("let x: Swift.Optional<String>"): Example("let x: String?"),
Example("let x:Dictionary<String, Dictionary<Int, Int>>"): Example("let x:Dictionary<String, [Int: Int]>"),
Example("let x:Dictionary<String, [Int: Int]>"): Example("let x:[String: [Int: Int]]")
Example("let x:Dictionary<String, Dictionary<Int, Int>>"): Example("let x:[String: [Int: Int]]"),
Example("let x:Dictionary<Dictionary<Int, Int>, String>"): Example("let x:[[Int: Int]: String]")
]
)

Expand All @@ -88,43 +89,53 @@ public struct SyntacticSugarRule: SubstitutionCorrectableRule, ConfigurationProv
public func substitution(for violationRange: NSRange, in file: SwiftLintFile) -> (NSRange, String)? {
let contents = file.stringView
let declaration = contents.substring(with: violationRange)
let substitutionResult = substitute(declaration)
return (violationRange, substitutionResult)
}

private func substitute(_ declaration: String) -> String {
let originalRange = NSRange(location: 0, length: declaration.count)
var substitutionResult = declaration
guard
let typeRange = regex(pattern).firstMatch(in: declaration, options: [], range: originalRange)?.range(at: 1)
else {
return (violationRange, substitutionResult)
return declaration
}

let containerType = declaration.bridge().substring(with: typeRange)
let substitutionResult: String
let nsDeclaration = declaration.bridge()
let containerType = nsDeclaration.substring(with: typeRange)
let innerString = nsDeclaration.substring(from: typeRange.upperBound)
let prefix = nsDeclaration.substring(to: typeRange.lowerBound)

let recusiveUpdatedInnerTypes = prefix + containerType + substitute(innerString)

switch containerType {
case "Optional":
let genericType = declaration.bridge().substring(from: typeRange.upperBound)
case "Optional", "Swift.Optional":
let genericType = recusiveUpdatedInnerTypes.bridge().substring(from: typeRange.upperBound)
.replacingOccurrences(of: " ", with: "")
.replacingOccurrences(of: "<", with: "")
.replacingOccurrences(of: ">", with: "")
substitutionResult = "\(genericType)?"
case "ImplicitlyUnwrappedOptional":
let genericType = declaration.bridge().substring(from: typeRange.upperBound)
substitutionResult = "\(prefix)\(genericType)?"
case "ImplicitlyUnwrappedOptional", "Swift.ImplicitlyUnwrappedOptional":
let genericType = recusiveUpdatedInnerTypes.bridge().substring(from: typeRange.upperBound)
.replacingOccurrences(of: " ", with: "")
.replacingOccurrences(of: "<", with: "")
.replacingOccurrences(of: ">", with: "")
substitutionResult = "\(genericType)!"
case "Array":
substitutionResult = declaration.bridge().substring(from: typeRange.upperBound)
substitutionResult = "\(prefix)\(genericType)!"
case "Array", "Swift.Array":
substitutionResult = prefix + recusiveUpdatedInnerTypes.bridge().substring(from: typeRange.upperBound)
.replacingOccurrences(of: "<", with: "[")
.replacingOccurrences(of: ">", with: "]")
case "Dictionary":
substitutionResult = declaration.bridge().substring(from: typeRange.upperBound)
case "Dictionary", "Swift.Dictionary":
substitutionResult = prefix + recusiveUpdatedInnerTypes.bridge().substring(from: typeRange.upperBound)
.replacingOccurrences(of: "<", with: "[")
.replacingOccurrences(of: ">", with: "]")
.replacingOccurrences(of: ",", with: ":")
default:
break
substitutionResult = declaration
}

return (violationRange, substitutionResult)
return substitutionResult
}

private func violationResults(in file: SwiftLintFile) -> [NSTextCheckingResult] {
Expand Down

0 comments on commit c49a844

Please sign in to comment.