From 7ec710efa8af89d31cf4870e0326ba861ca61e3c Mon Sep 17 00:00:00 2001 From: Marcelo Fabri Date: Wed, 28 Jun 2017 12:06:21 +0200 Subject: [PATCH] Make vertical_parameter_alignment_on_call more flexible with multiline literal Fixes #1643 --- CHANGELOG.md | 5 ++- ...VerticalParameterAlignmentOnCallRule.swift | 37 +++++++------------ 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bed9e5386d..bcf2092384 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,10 +23,11 @@ [Marcelo Fabri](https://github.com/marcelofabri) [#1635](https://github.com/realm/SwiftLint/issues/1635) -* Make `vertical_parameter_alignment_on_call` more flexible when closures - are used. +* Make `vertical_parameter_alignment_on_call` more flexible when multiline + parameters are used. [Marcelo Fabri](https://github.com/marcelofabri) [#1630](https://github.com/realm/SwiftLint/issues/1630) + [#1643](https://github.com/realm/SwiftLint/issues/1643) ## 0.20.0: Liquid Fabric Softener diff --git a/Source/SwiftLintFramework/Rules/VerticalParameterAlignmentOnCallRule.swift b/Source/SwiftLintFramework/Rules/VerticalParameterAlignmentOnCallRule.swift index 2f64c748eb..1c43c518b0 100644 --- a/Source/SwiftLintFramework/Rules/VerticalParameterAlignmentOnCallRule.swift +++ b/Source/SwiftLintFramework/Rules/VerticalParameterAlignmentOnCallRule.swift @@ -47,7 +47,11 @@ public struct VerticalParameterAlignmentOnCallRule: ASTRule, ConfigurationProvid " completion: { _ in\n" + " baz()\n" + " }\n" + - ")" + ")", + "foo(param1: 1, param2: [\n" + + " 0,\n" + + " 1\n" + + "], param3: 0)" ], triggeringExamples: [ "foo(param1: 1, param2: bar\n" + @@ -80,12 +84,12 @@ public struct VerticalParameterAlignmentOnCallRule: ASTRule, ConfigurationProvid } var visitedLines: Set = [] - var previousArgumentWasMultilineBlock = false + var previousArgumentWasMultiline = false - let violatingOffsets: [Int] = arguments.flatMap { argument in - let closureArgument = isClosure(argument: argument, file: file) + let lastIndex = arguments.count - 1 + let violatingOffsets: [Int] = arguments.enumerated().flatMap { idx, argument in defer { - previousArgumentWasMultilineBlock = closureArgument && isMultiline(argument: argument, file: file) + previousArgumentWasMultiline = isMultiline(argument: argument, file: file) } guard let offset = argument.offset, @@ -101,14 +105,13 @@ public struct VerticalParameterAlignmentOnCallRule: ASTRule, ConfigurationProvid // if this is the first element on a new line after a closure with multiple lines, // we reset the reference position - if previousArgumentWasMultilineBlock && firstVisit { + if previousArgumentWasMultiline && firstVisit { firstArgumentPosition = (line, character) return nil } // never trigger on a trailing closure - if argument.bridge() == arguments.last?.bridge(), closureArgument, - isAlreadyTrailingClosure(dictionary: dictionary, file: file) { + if idx == lastIndex, isTrailingClosure(dictionary: dictionary, file: file) { return nil } @@ -122,19 +125,6 @@ public struct VerticalParameterAlignmentOnCallRule: ASTRule, ConfigurationProvid } } - private func isClosure(argument: [String: SourceKitRepresentable], - file: File) -> Bool { - guard let offset = argument.bodyOffset, - let length = argument.bodyLength, - let range = file.contents.bridge().byteRangeToNSRange(start: offset, length: length), - let match = regex("\\s*\\{").firstMatch(in: file.contents, options: [], range: range)?.range, - match.location == range.location else { - return false - } - - return true - } - private func isMultiline(argument: [String: SourceKitRepresentable], file: File) -> Bool { guard let offset = argument.bodyOffset, let length = argument.bodyLength, @@ -147,10 +137,11 @@ public struct VerticalParameterAlignmentOnCallRule: ASTRule, ConfigurationProvid return endLine > startLine } - private func isAlreadyTrailingClosure(dictionary: [String: SourceKitRepresentable], file: File) -> Bool { + private func isTrailingClosure(dictionary: [String: SourceKitRepresentable], file: File) -> Bool { guard let offset = dictionary.offset, let length = dictionary.length, - let text = file.contents.bridge().substringWithByteRange(start: offset, length: length) else { + case let start = min(offset, offset + length - 1), + let text = file.contents.bridge().substringWithByteRange(start: start, length: length) else { return false }