branch: elpa/swift-mode
commit 29759f529032fff9b88a77318a10b2a1ec8ef5c7
Author: taku0 <[email protected]>
Commit: taku0 <[email protected]>
Fix indentation of generic-parameter-clause
Example:
```
struct Foo<
A: A,
A: A, A: A
> {
}
```
Closes https://github.com/swift-emacs/swift-mode/issues/164.
---
swift-mode-indent.el | 31 +++++-
swift-mode-lexer.el | 41 ++++++++
test/swift-files/indent/declarations.swift | 153 +++++++++++++++++++++++++++++
test/swift-files/indent/types.swift | 2 +-
4 files changed, 221 insertions(+), 6 deletions(-)
diff --git a/swift-mode-indent.el b/swift-mode-indent.el
index dfb59b8..f9b719a 100644
--- a/swift-mode-indent.el
+++ b/swift-mode-indent.el
@@ -316,6 +316,16 @@ declaration and its offset is `swift-mode:basic-offset'."
(backward-list)
(swift-mode:calculate-indent-of-expression 0))
+ ;; Before > as a close angle bracket on the current line
+ ((and next-is-on-current-line
+ (save-excursion
+ (goto-char (swift-mode:token:start next-token))
+ (and (eq (char-after) ?>)
+ (progn (swift-mode:try-backward-generic-parameters)
+ (< (point) (swift-mode:token:start next-token))))))
+ (swift-mode:try-backward-generic-parameters)
+ (swift-mode:calculate-indent-of-expression 0))
+
;; Before end of a interpolated expression on the current line
((and next-is-on-current-line
(eq next-type 'string-chunk-after-interpolated-expression))
@@ -425,8 +435,8 @@ declaration and its offset is `swift-mode:basic-offset'."
(swift-mode:calculate-indent-after-open-curly-brace
swift-mode:basic-offset))
- ;; After ( or [
- ((memq previous-type '(\( \[))
+ ;; After (, [, or < as a open angle bracket
+ ((memq previous-type '(\( \[ <))
(goto-char (swift-mode:token:start previous-token))
(swift-mode:calculate-indent-of-expression
swift-mode:parenthesized-expression-offset
@@ -830,7 +840,7 @@ the expression."
(defun swift-mode:calculate-indent-after-open-curly-brace (offset)
"Return indentation after open curly braces.
-Assuming the cursor is on the open parenthesis.
+Assuming the cursor is on the open brace.
OFFSET is the offset of the contents.
This function is also used for close-curly-brace."
;; If the statement is multiline expression, aligns with the start of
@@ -883,11 +893,22 @@ This function is also used for close-curly-brace."
;; // The body of the for-statement.
;; }
(let ((pos (point))
+ previous-token
next-token
is-declaration-or-control-statement-body)
(if (save-excursion
- (eq (swift-mode:token:type (swift-mode:backward-token))
- 'binary-operator))
+ (setq previous-token (swift-mode:backward-token))
+ (and (eq (swift-mode:token:type previous-token) 'binary-operator)
+ ;; not > as close angle bracket
+ (not
+ (progn
+ (goto-char (swift-mode:token:end previous-token))
+ (and (eq (char-before) ?>)
+ (progn
+ (backward-char)
+ (swift-mode:try-backward-generic-parameters)
+ (< (point)
+ (1- (swift-mode:token:end previous-token)))))))))
;; for x in
;; xs
;; +++ { x in
diff --git a/swift-mode-lexer.el b/swift-mode-lexer.el
index a41d152..11a19b4 100644
--- a/swift-mode-lexer.el
+++ b/swift-mode-lexer.el
@@ -408,6 +408,16 @@ Return nil otherwise."
(memq (swift-mode:token:type previous-token) '({ \( \[))
(memq (swift-mode:token:type next-token) '(} \) \]))
+ ;; Supress implicit semicolon before/after open angle bracket.
+ (and (equal (swift-mode:token:text previous-token) "<")
+ (save-excursion
+ (goto-char (swift-mode:token:start previous-token))
+ (swift-mode:generic-parameter-clause-start-p)))
+ (and (equal (swift-mode:token:text next-token) "<")
+ (save-excursion
+ (goto-char (swift-mode:token:start next-token))
+ (swift-mode:generic-parameter-clause-start-p)))
+
;; Suppress implicit semicolon after/before string chunks inside
;; interpolated expressions.
(eq (swift-mode:token:type previous-token)
@@ -720,6 +730,16 @@ Return nil otherwise."
'(\; { \( \[ "for")))
'{)))
+(defun swift-mode:generic-parameter-clause-start-p ()
+ "Return t if the `<' at the cursor is a start of generic parameters.
+
+Return nil otherwise."
+ (save-excursion
+ (or (member (swift-mode:token:text (swift-mode:backward-token-simple))
+ '("init" "subscript"))
+ (member (swift-mode:token:text (swift-mode:backward-token-simple))
+ '("typealias" "func" "enum" "struct" "class" "init")))))
+
(defun swift-mode:fix-operator-type (token)
"Return new operator token with proper token type.
@@ -819,6 +839,15 @@ type `outside-of-buffer'."
(progn (forward-char) (1- (point)))
(point)))
+ ;; Start of generic-parameter-clause
+ ((and
+ (eq (char-after) ?<)
+ (swift-mode:generic-parameter-clause-start-p))
+ (swift-mode:token '<
+ "<"
+ (progn (forward-char) (1- (point)))
+ (point)))
+
(t
(let ((token (swift-mode:forward-token-simple)))
(setq token (swift-mode:backquote-identifier-if-after-dot token))
@@ -1032,6 +1061,18 @@ type `outside-of-buffer'."
(point)
(1+ (point))))
+ ;; Start of generic-parameter-clause
+ ((and
+ (eq (char-before) ?<)
+ (save-excursion
+ (backward-char)
+ (swift-mode:generic-parameter-clause-start-p)))
+ (backward-char)
+ (swift-mode:token '<
+ "<"
+ (point)
+ (1+ (point))))
+
(t
(let ((token (swift-mode:backward-token-simple)))
(setq token (swift-mode:backquote-identifier-if-after-dot token))
diff --git a/test/swift-files/indent/declarations.swift
b/test/swift-files/indent/declarations.swift
index 5fda5c8..17dc5b3 100644
--- a/test/swift-files/indent/declarations.swift
+++ b/test/swift-files/indent/declarations.swift
@@ -248,6 +248,50 @@ class Foo {
=
C
.D
+
+ typealias Foo<
+ A: A,
+ A: A, A: A
+ > =
+ A
+
+ typealias Foo<
+ A: A,
+ A: A, A: A> =
+ A
+
+ typealias Foo <A: A,
+ A: A, A: A> =
+ A
+
+ typealias Foo <A: A,
+ A: A, A: A
+ > =
+ A
+
+ typealias Foo
+ <
+ A: A,
+ A: A, A: A
+ > =
+ A
+
+ typealias Foo
+ <
+ A: A,
+ A: A, A: A> =
+ A
+
+ typealias Foo
+ <A: A,
+ A: A, A: A> =
+ A
+
+ typealias Foo
+ <A: A,
+ A: A, A: A
+ > =
+ A
}
// Function declarations
@@ -300,6 +344,71 @@ func
foo()
}
+func foo<
+ A: A,
+ A: A, A: A
+> (
+ a: A,
+ a: A
+){
+}
+
+func foo<
+ A: A,
+ A: A, A: A> (
+ a: A,
+ a: A) {
+}
+
+func foo<A: A,
+ A: A, A: A> (a: A,
+ a: A) {
+}
+
+func foo<A: A,
+ A: A, A: A
+> (
+ a: A,
+ a: A
+) {
+}
+
+func foo
+ <
+ A: A,
+ A: A, A: A
+ >
+ (
+ a: A,
+ a: A
+ ){
+}
+
+func foo
+ <
+ A: A,
+ A: A, A: A>
+ (
+ a: A,
+ a: A) {
+}
+
+func foo
+ <A: A,
+ A: A, A: A>
+ (a: A,
+ a: A) {
+}
+
+func foo
+ <A: A,
+ A: A, A: A
+ >
+ (a: A,
+ a: A
+ ) {
+}
+
// Enumeration declarations
fileprivate
@@ -417,6 +526,50 @@ struct A {
}
}
+struct Foo<
+ A: A,
+ A: A, A: A
+> {
+}
+
+struct Foo<
+ A: A,
+ A: A, A: A> {
+}
+
+struct Foo<A: A,
+ A: A, A: A> {
+}
+
+struct Foo<A: A,
+ A: A, A: A
+> {
+}
+
+struct Foo
+ <
+ A: A,
+ A: A, A: A
+ > {
+}
+
+struct Foo
+ <
+ A: A,
+ A: A, A: A> {
+}
+
+struct Foo
+ <A: A,
+ A: A, A: A> {
+}
+
+struct Foo
+ <A: A,
+ A: A, A: A
+ > {
+}
+
// Protocol declarations
protocol Foo {
diff --git a/test/swift-files/indent/types.swift
b/test/swift-files/indent/types.swift
index 331a3c9..c9e0ae3 100644
--- a/test/swift-files/indent/types.swift
+++ b/test/swift-files/indent/types.swift
@@ -282,5 +282,5 @@ let foo: protocol<A<[B]>,
let foo: protocol<
A, // swift-mode:test:known-bug
B
-> // swift-mode:test:known-bug
+>
= a