Skip to content

Commit b6512fa

Browse files
committed
Fix indentation of attributes
1 parent 7423f68 commit b6512fa

File tree

4 files changed

+127
-58
lines changed

4 files changed

+127
-58
lines changed

swift-mode-indent.el

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -509,31 +509,14 @@
509509
swift-mode:statement-parent-tokens
510510
swift-mode:multiline-statement-offset))
511511

512-
;; After attributes at the beginning of a statement, without arguments
513-
((and
514-
(string-prefix-p "@" previous-text)
515-
(memq (save-excursion
516-
(goto-char (swift-mode:token:start previous-token))
517-
(swift-mode:token:type (swift-mode:backward-token)))
518-
swift-mode:statement-parent-tokens))
519-
;; Aligns with the attribute.
520-
(goto-char (swift-mode:token:start previous-token))
521-
(swift-mode:align-with-next-token (swift-mode:backward-token)))
522-
523-
;; After attributes at the beginning of a statement, with arguments
524-
((and
525-
(eq previous-type '\))
526-
(save-excursion
527-
(backward-list)
528-
(and
529-
(string-prefix-p
530-
"@"
531-
(swift-mode:token:text (swift-mode:backward-token)))
532-
(memq (swift-mode:token:type (swift-mode:backward-token))
533-
swift-mode:statement-parent-tokens))))
534-
(backward-list)
535-
(swift-mode:backward-token)
536-
(swift-mode:align-with-next-token (swift-mode:backward-token)))
512+
;; After attributes
513+
((eq previous-type 'attribute)
514+
(goto-char (swift-mode:token:end previous-token))
515+
(swift-mode:backward-token-or-list)
516+
(swift-mode:calculate-indent-of-expression
517+
swift-mode:multiline-statement-offset
518+
0
519+
t))
537520

538521
;; Otherwise, it is continuation of the previous line
539522
(t
@@ -597,20 +580,41 @@ on the previous line."
597580
(defun swift-mode:calculate-indent-of-expression
598581
(&optional
599582
offset
600-
bol-offset)
583+
bol-offset
584+
after-attributes)
601585
"Return start column of the current expressions plus offset.
602586
603587
the cursor is assumed to be on the previous line.
604588
605589
OFFSET is the offset. If it is omitted, assumed to be 0.
606-
If scanning stops at eol, align with the next token with BOL-OFFSET."
590+
If scanning stops at eol, align with the next token with BOL-OFFSET.
591+
If AFTER-ATTRIBUTES is nil, skip lines with only attributes at the start of
592+
the expression."
607593
(save-excursion
608594
(let* ((pos (point))
609595
(parent-of-previous-line
610-
(progn (swift-mode:goto-non-comment-bol-with-same-nesting-level)
611-
(swift-mode:backward-token)))
612-
(parent (progn (goto-char pos)
613-
(swift-mode:find-parent-of-expression))))
596+
(save-excursion
597+
(swift-mode:goto-non-comment-bol-with-same-nesting-level)
598+
(swift-mode:backward-token)))
599+
(parent (swift-mode:find-parent-of-expression)))
600+
601+
(when (not after-attributes)
602+
(goto-char (swift-mode:token:end parent))
603+
(swift-mode:forward-attributes)
604+
(swift-mode:goto-non-comment-bol-with-same-nesting-level)
605+
(when (< (point) (swift-mode:token:end parent))
606+
(goto-char (swift-mode:token:end parent)))
607+
(setq parent (swift-mode:backward-token)))
608+
609+
;; When indenting a token after an attribute at the start of the
610+
;; expression, aligns with it.
611+
(when (and after-attributes
612+
(save-excursion
613+
(goto-char (swift-mode:token:end parent))
614+
(eq (swift-mode:token:type (swift-mode:forward-token))
615+
'attribute)))
616+
(setq offset 0))
617+
614618
(if (<= (swift-mode:token:start parent-of-previous-line)
615619
(swift-mode:token:start parent))
616620
;; let x =
@@ -629,6 +633,23 @@ If scanning stops at eol, align with the next token with BOL-OFFSET."
629633
(swift-mode:align-with-next-token parent-of-previous-line
630634
bol-offset)))))
631635

636+
(defun swift-mode:forward-attributes ()
637+
"Skip forward comments, whitespaces, and attributes."
638+
(while
639+
(not
640+
(eq (point)
641+
(progn
642+
(forward-comment (point-max))
643+
(when (eq (char-after) ?@)
644+
(forward-symbol 1)
645+
(forward-comment (point-max))
646+
(when (eq (char-after) ?\()
647+
(condition-case nil
648+
(forward-list)
649+
(scan-error nil))))
650+
(point))))))
651+
652+
632653
(defun swift-mode:calculate-indent-after-open-curly-brace (offset)
633654
"Return indentation after open curly braces.
634655

swift-mode-lexer.el

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
;; - prefix-operator (including try, try?, and try!)
7171
;; - postfix-operator
7272
;; - binary-operator (including as, as?, as!, is, =, ., and ->)
73+
;; - attribute (e.g. @objc, @abc(def))
7374
;; - identifier (including keywords, numbers, implicit parameters, and unknown tokens)
7475
;; - [
7576
;; - ]
@@ -283,17 +284,7 @@
283284
t)
284285

285286
;; Supress implicit semicolon after attributes.
286-
((string-prefix-p "@" (swift-mode:token:text previous-token))
287-
nil)
288-
289-
;; Supress implicit semicolon after attributes with arguments.
290-
((and
291-
(eq (swift-mode:token:type previous-token) '\))
292-
(save-excursion
293-
(backward-list)
294-
(string-prefix-p
295-
"@"
296-
(swift-mode:token:text (swift-mode:backward-token-simple)))))
287+
((eq (swift-mode:token:type previous-token) 'attribute)
297288
nil)
298289

299290
;; Inserts implicit semicolon before keywords that behave like method
@@ -341,10 +332,6 @@
341332
(swift-mode:forward-token-simple)))
342333
"<")))
343334

344-
;; Inserts implicit semicolon before attributes unless other condtions
345-
;; met.
346-
((string-prefix-p "@" (swift-mode:token:text previous-token)) t)
347-
348335
;; Inserts implicit semicolon before open square bracket.
349336
;;
350337
;; Open square bracket for array indexing cannot appear at the start of a
@@ -571,7 +558,6 @@ type `out-of-buffer'"
571558
"in"
572559
(swift-mode:token:start token)
573560
(swift-mode:token:end token))))
574-
575561
token)))))
576562

577563
(defun swift-mode:forward-token-simple ()
@@ -651,6 +637,24 @@ type `out-of-buffer'"
651637
pos-after-comment
652638
(point))))
653639

640+
;; Attribute
641+
((eq (char-after) ?@)
642+
(let ((pos-after-comment (point)))
643+
(forward-symbol 1)
644+
(let ((pos (point)))
645+
(forward-comment (point-max))
646+
(if (eq (char-after) ?\()
647+
(condition-case nil
648+
(progn
649+
(forward-list 1))
650+
(scan-error (goto-char pos)))
651+
(goto-char pos)))
652+
(swift-mode:token
653+
'attribute
654+
(buffer-substring-no-properties pos-after-comment (point))
655+
pos-after-comment
656+
(point))))
657+
654658
;; Other tokens including identifers, implicit parameters, keywords, and
655659
;; numbers
656660
(t
@@ -752,6 +756,23 @@ type `out-of-buffer'."
752756
((bobp)
753757
(swift-mode:token 'outside-of-buffer "" (point) (point)))
754758

759+
;; Attribute or close-parenthesis
760+
((eq (char-before) ?\))
761+
(let ((pos-before-comment (point)))
762+
(condition-case nil
763+
(progn
764+
(backward-list)
765+
(forward-comment (- (point)))
766+
(forward-symbol -1)
767+
(unless (eq (char-after) ?@)
768+
(goto-char (1- pos-before-comment))))
769+
(scan-error (goto-char (1- pos-before-comment))))
770+
(swift-mode:token
771+
(if (eq (char-after) ?@) 'attribute '\))
772+
(buffer-substring-no-properties (point) pos-before-comment)
773+
(point)
774+
pos-before-comment)))
775+
755776
;; Separators and parentheses
756777
((memq (char-before) '(?, ?\; ?\{ ?\} ?\[ ?\] ?\( ?\) ?:))
757778
(backward-char)
@@ -867,6 +888,11 @@ type `out-of-buffer'."
867888
text
868889
(point)
869890
(+ (point) (length text))))
891+
((string-prefix-p "@" text)
892+
(swift-mode:token 'attribute
893+
text
894+
(point)
895+
(+ (point) (length text))))
870896
(t
871897
(swift-mode:token 'identifier
872898
text

test/swift-files/declarations.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,25 @@ fileprivate
341341
func foo()
342342
}
343343

344+
345+
@A
346+
@B
347+
struct A {
348+
func foo() {
349+
}
350+
func foo() {
351+
}
352+
}
353+
354+
@A(a)
355+
@B(b)
356+
struct A {
357+
func foo() {
358+
}
359+
func foo() {
360+
}
361+
}
362+
344363
// Protocol declarations
345364

346365
protocol Foo {

test/swift-files/types.swift

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,41 +51,44 @@ let foo: @A A
5151
= abc
5252

5353
let foo: @A
54-
A = abc
54+
A =
55+
abc
5556

5657
let foo:
5758
@A
58-
A = abc
59+
A =
60+
abc
5961

6062
let foo
6163
:@A
62-
A = abc
64+
A =
65+
abc
6366

6467
class Foo:
6568
@A
66-
A // swift-mode:test:known-bug
67-
.A, // swift-mode:test:known-bug
69+
A
70+
.A,
6871
B {
6972
}
7073

7174
class Foo
7275
: @A
73-
A // swift-mode:test:known-bug
74-
.A, // swift-mode:test:known-bug
76+
A
77+
.A,
7578
B {
7679
}
7780

7881
class Foo: @A
79-
A // swift-mode:test:known-bug
80-
.A // swift-mode:test:known-bug
82+
A
83+
.A
8184
, B
8285
{
8386
}
8487

8588
class Foo
8689
: @A
87-
A // swift-mode:test:known-bug
88-
.A // swift-mode:test:known-bug
90+
A
91+
.A
8992
, B
9093
{
9194
}

0 commit comments

Comments
 (0)