branch: elpa/swift-mode commit b6512fa717c1fd3776e4201e38e653fe3773ce64 Author: taku0 <mxxouy6x3m_git...@tatapa.org> Commit: taku0 <mxxouy6x3m_git...@tatapa.org>
Fix indentation of attributes --- swift-mode-indent.el | 83 +++++++++++++++++++++++-------------- swift-mode-lexer.el | 58 +++++++++++++++++++------- test/swift-files/declarations.swift | 19 +++++++++ test/swift-files/types.swift | 25 ++++++----- 4 files changed, 127 insertions(+), 58 deletions(-) diff --git a/swift-mode-indent.el b/swift-mode-indent.el index 8e7da2c..a821519 100644 --- a/swift-mode-indent.el +++ b/swift-mode-indent.el @@ -509,31 +509,14 @@ swift-mode:statement-parent-tokens swift-mode:multiline-statement-offset)) - ;; After attributes at the beginning of a statement, without arguments - ((and - (string-prefix-p "@" previous-text) - (memq (save-excursion - (goto-char (swift-mode:token:start previous-token)) - (swift-mode:token:type (swift-mode:backward-token))) - swift-mode:statement-parent-tokens)) - ;; Aligns with the attribute. - (goto-char (swift-mode:token:start previous-token)) - (swift-mode:align-with-next-token (swift-mode:backward-token))) - - ;; After attributes at the beginning of a statement, with arguments - ((and - (eq previous-type '\)) - (save-excursion - (backward-list) - (and - (string-prefix-p - "@" - (swift-mode:token:text (swift-mode:backward-token))) - (memq (swift-mode:token:type (swift-mode:backward-token)) - swift-mode:statement-parent-tokens)))) - (backward-list) - (swift-mode:backward-token) - (swift-mode:align-with-next-token (swift-mode:backward-token))) + ;; After attributes + ((eq previous-type 'attribute) + (goto-char (swift-mode:token:end previous-token)) + (swift-mode:backward-token-or-list) + (swift-mode:calculate-indent-of-expression + swift-mode:multiline-statement-offset + 0 + t)) ;; Otherwise, it is continuation of the previous line (t @@ -597,20 +580,41 @@ on the previous line." (defun swift-mode:calculate-indent-of-expression (&optional offset - bol-offset) + bol-offset + after-attributes) "Return start column of the current expressions plus offset. the cursor is assumed to be on the previous line. OFFSET is the offset. If it is omitted, assumed to be 0. -If scanning stops at eol, align with the next token with BOL-OFFSET." +If scanning stops at eol, align with the next token with BOL-OFFSET. +If AFTER-ATTRIBUTES is nil, skip lines with only attributes at the start of +the expression." (save-excursion (let* ((pos (point)) (parent-of-previous-line - (progn (swift-mode:goto-non-comment-bol-with-same-nesting-level) - (swift-mode:backward-token))) - (parent (progn (goto-char pos) - (swift-mode:find-parent-of-expression)))) + (save-excursion + (swift-mode:goto-non-comment-bol-with-same-nesting-level) + (swift-mode:backward-token))) + (parent (swift-mode:find-parent-of-expression))) + + (when (not after-attributes) + (goto-char (swift-mode:token:end parent)) + (swift-mode:forward-attributes) + (swift-mode:goto-non-comment-bol-with-same-nesting-level) + (when (< (point) (swift-mode:token:end parent)) + (goto-char (swift-mode:token:end parent))) + (setq parent (swift-mode:backward-token))) + + ;; When indenting a token after an attribute at the start of the + ;; expression, aligns with it. + (when (and after-attributes + (save-excursion + (goto-char (swift-mode:token:end parent)) + (eq (swift-mode:token:type (swift-mode:forward-token)) + 'attribute))) + (setq offset 0)) + (if (<= (swift-mode:token:start parent-of-previous-line) (swift-mode:token:start parent)) ;; let x = @@ -629,6 +633,23 @@ If scanning stops at eol, align with the next token with BOL-OFFSET." (swift-mode:align-with-next-token parent-of-previous-line bol-offset))))) +(defun swift-mode:forward-attributes () + "Skip forward comments, whitespaces, and attributes." + (while + (not + (eq (point) + (progn + (forward-comment (point-max)) + (when (eq (char-after) ?@) + (forward-symbol 1) + (forward-comment (point-max)) + (when (eq (char-after) ?\() + (condition-case nil + (forward-list) + (scan-error nil)))) + (point)))))) + + (defun swift-mode:calculate-indent-after-open-curly-brace (offset) "Return indentation after open curly braces. diff --git a/swift-mode-lexer.el b/swift-mode-lexer.el index 44a20dc..ee8fccb 100644 --- a/swift-mode-lexer.el +++ b/swift-mode-lexer.el @@ -70,6 +70,7 @@ ;; - prefix-operator (including try, try?, and try!) ;; - postfix-operator ;; - binary-operator (including as, as?, as!, is, =, ., and ->) +;; - attribute (e.g. @objc, @abc(def)) ;; - identifier (including keywords, numbers, implicit parameters, and unknown tokens) ;; - [ ;; - ] @@ -283,17 +284,7 @@ t) ;; Supress implicit semicolon after attributes. - ((string-prefix-p "@" (swift-mode:token:text previous-token)) - nil) - - ;; Supress implicit semicolon after attributes with arguments. - ((and - (eq (swift-mode:token:type previous-token) '\)) - (save-excursion - (backward-list) - (string-prefix-p - "@" - (swift-mode:token:text (swift-mode:backward-token-simple))))) + ((eq (swift-mode:token:type previous-token) 'attribute) nil) ;; Inserts implicit semicolon before keywords that behave like method @@ -341,10 +332,6 @@ (swift-mode:forward-token-simple))) "<"))) - ;; Inserts implicit semicolon before attributes unless other condtions - ;; met. - ((string-prefix-p "@" (swift-mode:token:text previous-token)) t) - ;; Inserts implicit semicolon before open square bracket. ;; ;; Open square bracket for array indexing cannot appear at the start of a @@ -571,7 +558,6 @@ type `out-of-buffer'" "in" (swift-mode:token:start token) (swift-mode:token:end token)))) - token))))) (defun swift-mode:forward-token-simple () @@ -651,6 +637,24 @@ type `out-of-buffer'" pos-after-comment (point)))) + ;; Attribute + ((eq (char-after) ?@) + (let ((pos-after-comment (point))) + (forward-symbol 1) + (let ((pos (point))) + (forward-comment (point-max)) + (if (eq (char-after) ?\() + (condition-case nil + (progn + (forward-list 1)) + (scan-error (goto-char pos))) + (goto-char pos))) + (swift-mode:token + 'attribute + (buffer-substring-no-properties pos-after-comment (point)) + pos-after-comment + (point)))) + ;; Other tokens including identifers, implicit parameters, keywords, and ;; numbers (t @@ -752,6 +756,23 @@ type `out-of-buffer'." ((bobp) (swift-mode:token 'outside-of-buffer "" (point) (point))) + ;; Attribute or close-parenthesis + ((eq (char-before) ?\)) + (let ((pos-before-comment (point))) + (condition-case nil + (progn + (backward-list) + (forward-comment (- (point))) + (forward-symbol -1) + (unless (eq (char-after) ?@) + (goto-char (1- pos-before-comment)))) + (scan-error (goto-char (1- pos-before-comment)))) + (swift-mode:token + (if (eq (char-after) ?@) 'attribute '\)) + (buffer-substring-no-properties (point) pos-before-comment) + (point) + pos-before-comment))) + ;; Separators and parentheses ((memq (char-before) '(?, ?\; ?\{ ?\} ?\[ ?\] ?\( ?\) ?:)) (backward-char) @@ -867,6 +888,11 @@ type `out-of-buffer'." text (point) (+ (point) (length text)))) + ((string-prefix-p "@" text) + (swift-mode:token 'attribute + text + (point) + (+ (point) (length text)))) (t (swift-mode:token 'identifier text diff --git a/test/swift-files/declarations.swift b/test/swift-files/declarations.swift index b11294c..ecb8fcf 100644 --- a/test/swift-files/declarations.swift +++ b/test/swift-files/declarations.swift @@ -341,6 +341,25 @@ fileprivate func foo() } + +@A +@B +struct A { + func foo() { + } + func foo() { + } +} + +@A(a) +@B(b) +struct A { + func foo() { + } + func foo() { + } +} + // Protocol declarations protocol Foo { diff --git a/test/swift-files/types.swift b/test/swift-files/types.swift index af2d4c3..ca3ab48 100644 --- a/test/swift-files/types.swift +++ b/test/swift-files/types.swift @@ -51,41 +51,44 @@ let foo: @A A = abc let foo: @A - A = abc + A = + abc let foo: @A - A = abc + A = + abc let foo :@A - A = abc + A = + abc class Foo: @A - A // swift-mode:test:known-bug - .A, // swift-mode:test:known-bug + A + .A, B { } class Foo : @A - A // swift-mode:test:known-bug - .A, // swift-mode:test:known-bug + A + .A, B { } class Foo: @A - A // swift-mode:test:known-bug - .A // swift-mode:test:known-bug + A + .A , B { } class Foo : @A - A // swift-mode:test:known-bug - .A // swift-mode:test:known-bug + A + .A , B { }