emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/swift-mode 9471669 304/496: Merge taku0/swift3-mode


From: ELPA Syncer
Subject: [nongnu] elpa/swift-mode 9471669 304/496: Merge taku0/swift3-mode
Date: Sun, 29 Aug 2021 11:33:56 -0400 (EDT)

branch: elpa/swift-mode
commit 9471669b0bc5a72236b434f66a4c6782d807afea
Author: taku0 <mxxouy6x3m_github@tatapa.org>
Commit: taku0 <mxxouy6x3m_github@tatapa.org>

    Merge taku0/swift3-mode
---
 .gitignore                          |    4 +-
 Cask                                |   10 +-
 Makefile                            |  102 +-
 README.md                           |  238 ++--
 swift-mode-beginning-of-defun.el    |  152 +++
 swift-mode-font-lock.el             |  232 ++++
 swift-mode-indent.el                | 1475 ++++++++++++++++++++++
 swift-mode-lexer.el                 |  883 ++++++++++++++
 swift-mode-repl.el                  |  108 ++
 swift-mode.el                       |  860 ++-----------
 test/font-lock-tests.el             |  212 ----
 test/indentation-tests.el           | 2280 -----------------------------------
 test/swift-files/comment.swift      |   35 +
 test/swift-files/declarations.swift |  376 ++++++
 test/swift-files/expressions.swift  |  571 +++++++++
 test/swift-files/identifiers.swift  |   40 +
 test/swift-files/operators.swift    |   70 ++
 test/swift-files/statements.swift   |  805 +++++++++++++
 test/swift-files/types.swift        |  274 +++++
 test/swift-mode-test-indent.el      |  164 +++
 20 files changed, 5492 insertions(+), 3399 deletions(-)

diff --git a/.gitignore b/.gitignore
index bf0d9e6..f613485 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
+*~
 /.cask/
 *.elc
-/swift-mode.elc
 /dist/
+swift-mode-autoloads.el
+swift-mode-pkg.el
diff --git a/Cask b/Cask
index 01fa162..9960ec2 100644
--- a/Cask
+++ b/Cask
@@ -1,12 +1,4 @@
-(source melpa)
 (source gnu)
-(source org)
+(source melpa)
 
 (package-file "swift-mode.el")
-
-(development
- (depends-on "s")
- (depends-on "dash")
- (depends-on "cl-lib")
- (depends-on "flycheck")
- (depends-on "flycheck-cask"))
diff --git a/Makefile b/Makefile
index c0c02fb..9086362 100644
--- a/Makefile
+++ b/Makefile
@@ -1,56 +1,56 @@
-CWD          = $(shell pwd)
-DIST         = $(CWD)/dist
-CASK        ?= cask
-EMACS       ?= emacs
-EMACSFLAGS   = --batch -Q
-VERSION     := $(shell EMACS=$(EMACS) $(CASK) version)
-PKG_DIR     := $(shell EMACS=$(EMACS) $(CASK) package-directory)
-USER_EMACS_D = ~/.emacs.d
-USER_ELPA_D  = $(USER_EMACS_D)/elpa
-
-SRCS         = $(filter-out %-pkg.el, $(wildcard *.el))
-TESTS        = $(filter-out %-pkg.el, $(wildcard test/*.el))
-EL          = $(DIST)/swift-mode-$(VERSION).el
-
-.PHONY: all
-all : deps $(DIST)
-
-.PHONY: deps
-deps : $(PKG_DIR)
-$(PKG_DIR) :
+CASK ?= cask
+EMACS ?= emacs
+VERSION := $(shell EMACS=$(EMACS) $(CASK) version)
+PKG_DIR := $(shell EMACS=$(EMACS) $(CASK) package-directory)
+
+SRC = $(wildcard *.el)
+PACKAGE = dist/swift-mode-$(VERSION).tar
+
+.PHONY: help all deps package install test clean
+
+help:
+## Shows this message.
+# Process this Makefile with following filters
+#
+# - Remove empty line.
+# - Remove lien containing ## no-doc.
+# - Remove after colon if the line is not a comment line.
+# - Replace /^## / to "  ".
+# - Remove other comment lines.
+# - Insert newline before rules.
+       @sed -e '/^\s*$$/d; /^[ .A-Z]/d; /## no-doc/d; s/^\([^#][^:]*\):.*/\1/; 
s/^## /  /; /^#/d; s/^[^ ]/\n&/' Makefile
+
+all: package
+## Builds the package.
+
+$(PKG_DIR): ## no-doc
        $(CASK) install
 
-.PHONY: check
-check : deps
-       $(CASK) exec $(EMACS) $(EMACSFLAGS)  \
-       $(patsubst %,-l % , $(SRCS))\
-       $(patsubst %,-l % , $(TESTS))\
-       -f ert-run-tests-batch-and-exit
+deps: $(PKG_DIR)
+## Installs the dependencies.
 
-.PHONY: install
-install : $(DIST) $(USER_ELPA_D)
-       $(EMACS) $(EMACSFLAGS) -l package \
-       -f package-initialize  --eval '(package-install-file "$(EL)")'
-
-.PHONY: uninstall
-uninstall :
-       rm -rf $(USER_ELPA_D)/swift-mode-*
-
-.PHONY: reinstall
-reinstall : clean uninstall install
-
-.PHONY: clean-all
-clean-all : clean
-       rm -rf $(PKG_DIR)
-
-.PHONY: clean
-clean :
-       $(CASK) clean-elc
-       rm -f *.elc
-       rm -rf $(DIST)
-
-$(DIST) :
+$(PACKAGE): $(SRC) deps ## no-doc
+       rm -rf dist
        $(CASK) package
 
-$(USER_ELPA_D) :
-       mkdir -p $(USER_ELPA_D)
+package: $(PACKAGE)
+## Builds the package.
+
+install: package
+## Installs the package.
+       $(CASK) exec $(EMACS) --batch \
+         -l package \
+         -f package-initialize \
+         --eval '(package-install-file "$(PACKAGE)")'
+
+clean:
+## Cleans the dist directory.
+       rm -rf dist
+
+check: deps
+## Tests the package.
+       $(CASK) exec $(EMACS) --batch -q \
+         --eval "(add-to-list 'load-path \""$(shell realpath .)"\")" \
+         -l swift-mode.el \
+         -l test/swift-mode-test-indent.el \
+         -f swift-mode:run-test:indent
diff --git a/README.md b/README.md
index a195d73..aadda12 100644
--- a/README.md
+++ b/README.md
@@ -1,107 +1,193 @@
 [![License GPL 3][badge-license]][copying]
 [![Build Status][badge-travis]][travis]
 
[![MELPA](https://melpa.org/packages/swift-mode-badge.svg)](https://melpa.org/#/swift-mode)
-[![MELPA 
stable](https://stable.melpa.org/packages/swift-mode-badge.svg)](https://stable.melpa.org/#/swift-mode)
+[![MELPA](https://stable.melpa.org/packages/swift-mode-badge.svg)](https://melpa.org/#/swift-mode)
 
 # swift-mode
 
-## Summary
-
-Major-mode for Apple's [Swift programming language][swift]. Provides:
-
-- syntax highlighting
-- indentation
-- code navigation with [imenu][]
-- automatic syntax checking with [flycheck][] (disabled by default)
-
-This is currently at an early stage of development and there's plenty of work 
to
-do. Check the issue tracker.
-
-A new [swift3-mode](https://github.com/taku0/swift3-mode) is
-under development. It will be merged into `swift-mode` in the near future.
-
-Requires Emacs 24.4 or later.
-
-## Installing
-
-`swift-mode` can be installed using Emacs' built-in package manager or from
-source. You can also install [flycheck][] if you want syntax checking.
-
-### package.el
-
-#### MELPA
+Major-mode for Apple's [Swift programming 
language](https://developer.apple.com/swift/).
+
+## Installation
+
+Install `swift-mode` package from MELPA.
+
+To install without MELPA, download [latest 
release](https://github.com/swift-emacs/swift-mode/releases) and execute `M-x 
package-install-file`.
+
+## Features
+
+- Font Lock
+- Indentation
+
+  ```swift
+  switch foo {
+  case let .P1(x)
+         where
+           x > 0,
+       let .P2(x)
+         where
+           x > 0:
+      bar()
+        .then { x in
+            return baz(x)
+        }
+        .then {(
+                 x,
+                 y
+               ) in
+            return moo(x + y)
+        }
+  }
+
+  // Hanging brace
+  let x = [
+    1,
+    2,
+    3
+  ]
+
+  // Brace on its own line
+  let y =
+    [
+      1,
+      2,
+      3
+    ]
+
+  // Utrecht style
+  let z =
+    [ 1
+    , 2
+    , 3
+    ]
+  ```
+- `forward-sexp`
+- `beginning-of-defun` and `end-of-defun`
+- `indent-new-comment-line`
+- [Imenu](https://www.gnu.org/software/emacs/manual/html_node/emacs/Imenu.html)
+- Running Swift REPL in a buffer (`M-x run-swift`)
+
+This package does not provide flycheck. See 
[flycheck-swift](https://github.com/swift-emacs/flycheck-swift).
+
+## Limitations
+
+Some syntax constructs removed from Swift 3.0 are not supported:
+
+- C-style for-loop: `for var i = 1; i < 10; i++ { }`
+- Multiple assignments in single `if let`:
+  ```swift
+  if let x = x,
+         y = y {
+  }
+  ```
+
+  Use multiple `let` instead:
+  ```swift
+  if let x = x,
+     let y = y {
+  }
+  ```
+
+Indentation may not accurate. For example, `foo(Bar < A, B > (c))` is 
ambiguous. It is indented like either
+```swift
+foo(Bar < A,
+    B > (c)) // Passing two Boolean arguments to foo
+```
+or
+```swift
+foo(Bar < A,
+          B > (c)) // constructing Bar with two type arguments and a value
+```
+The Swift compiler disambiguates this case using tokens after `>`, but those 
tokens may not available in editing time. We use some heuristic for this.
 
-You can install a snapshot version of `swift-mode` from the [MELPA][]
-repository. The version of `swift-mode` there will always be up-to-date, but it
-might be unstable (albeit rarely).
+Another example is difficulty of handling of colons. We have to pair all `?` 
and `:` of conditional operators to decide indentation. This is a future work.
 
-You can add MELPA to the list of `package.el` repositories like this:
+```swift
+switch foo {
+  case let P(x) where x is Foo? ? a ? b : c ?? d : e ? f : g :
+    h ? i?.j() : k()
+}
 
-```el
-(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/";))
+switch foo {
+  case let P(x) where (x is Foo?) ? (a ? b : c ?? d) : (e ? f : g) :
+    h ? i?.j() : k()
+}
 ```
 
-#### MELPA Stable
-
-You can install the last stable version of `swift-mode` from the
-[MELPA Stable][] repository.
+Yet another difficult case is consistency of blocks. We want to indent method 
chains like this:
+```swift
+var x = foo
+  .then { x in
+      aaa
+  }
+  .then { x in
+      aaa
+  }
+```
 
-You can add MELPA Stable to the list of `package.el` repositories like this:
+while we also want to indent if body like this:
 
-```el
-(add-to-list 'package-archives '("melpa-stable" . 
"https://stable.melpa.org/packages/";))
+```swift
+if anotherVeryLongVariableName
+     .veryLongPropertyName {
+    aaa
+}
 ```
 
-***
-
-The package installation is as easy as:
+Then, how should we indent this when the cursor is before `@`?
 
+```swift
+var x = foo
+  .bar {
+    @
 ```
-M-x package-install swift-mode
-```
-
-If you'd like to get on-the-fly syntax checking you should install
-[flycheck][] as well:
 
+This could be
+```swift
+var x = foo
+  .bar {
+    @abc willSet {
+        aaa
+    }
+}
 ```
-M-x package-install flycheck
+or
+```swift
+var x = foo
+  .bar {
+      @abc var x = 1
+      x
+  }
 ```
 
-And enable `flycheck` checker for `swift`:
+Both are syntactically correct code. We cannot handle this case properly. This 
is also a future work.
 
-```
-(add-to-list 'flycheck-checkers 'swift)
-```
+## Hacking
 
-### Manual
+To build the package locally, run `make package`. You need 
[Cask](https://github.com/cask/cask).
 
-You will need `make` and [Cask][] to build the project.
+To install the built package, run `make install`.
 
-```
-cd swift-mode
-make && make install
-```
+To run tests, run `make check`.
 
-This will install `swift-mode` via `package.el` locally.
+For other commands, run `make help`.
 
-You can also install `swift-mode` the old-school way by simply dropping it
-somewhere on your `load-path`.
+## Related projects
 
-```el
-(add-to-list 'load-path "~/emacs.d/vendor")
-(require 'swift-mode)
-```
+- [Official swift-mode.el by 
Apple](https://github.com/apple/swift/blob/master/utils/swift-mode.el) Seems 
still in very early stage for now. We cannot contribute to it due to the 
license incompatibility.
+- [company-sourcekit](https://github.com/nathankot/company-sourcekit) 
Completion for Swift projects via SourceKit with the help of SourceKitten.
+- [flycheck-swift](https://github.com/swift-emacs/flycheck-swift) Flycheck 
extensions for Swift.
 
 ## Contributing
 
-Yes, please do! See [CONTRIBUTING][] for guidelines.
+Yes, please do! See [CONTRIBUTING](./CONTRIBUTING.md) for guidelines.
 
 ## Acknowledgements
 
-The REPL code is based on [js-comint][].
+The REPL code is based on [js-comint](http://js-comint-el.sourceforge.net/).
 
-Thanks to the following users for their contributions:
+Thanks to the following original developer and users for their contributions:
 
+- [@chrisbarrett](https://github.com/chrisbarrett) (Chris Barrett)
 - [@ap4y](https://github.com/ap4y) (Arthur Evstifeev)
 - [@bbatsov](https://github.com/bbatsov) (Bozhidar Batsov)
 - [@ckruse](https://github.com/ckruse) (Christian Kruse)
@@ -110,20 +196,12 @@ Thanks to the following users for their contributions:
 
 You can find a [full list of those people 
here](https://github.com/swift-emacs/swift-mode/graphs/contributors).
 
+Thanks to [@purcell](https://github.com/purcell) (Steve Purcell) for advices 
on the code and arrangement for merging `swift3-mode` and `swift-mode`.
+
 ## License
 
-See [COPYING][]. Copyright (c) 2014-2016 Chris Barrett, Bozhidar Batsov, 
Arthur Evstifeev.
+GPLv3. See [COPYING][] for details. Copyright (C) 2014-2016 taku0, Chris 
Barrett, Bozhidar Batsov, Arthur Evstifeev.
 
 [badge-license]: https://img.shields.io/badge/license-GPL_3-green.svg
-[badge-travis]: https://travis-ci.org/swift-emacs/swift-mode.png?branch=master
 [travis]: https://travis-ci.org/swift-emacs/swift-mode
-[COPYING]: https://github.com/swift-emacs/swift-mode/blob/master/COPYING
-[CONTRIBUTING]: 
https://github.com/swift-emacs/swift-mode/blob/master/CONTRIBUTING.md
-[swift]: https://developer.apple.com/swift/
-[cask]: https://github.com/cask/cask
-[rust-mode]: https://github.com/mozilla/rust/tree/master/src/etc/emacs
-[melpa]: https://melpa.org
-[melpa stable]: https://stable.melpa.org
-[imenu]: http://www.gnu.org/software/emacs/manual/html_node/emacs/Imenu.html
-[flycheck]: http://flycheck.readthedocs.org/en/latest/
-[js-comint]: http://js-comint-el.sourceforge.net/
+[COPYING]: ./COPYING
diff --git a/swift-mode-beginning-of-defun.el b/swift-mode-beginning-of-defun.el
new file mode 100644
index 0000000..c884361
--- /dev/null
+++ b/swift-mode-beginning-of-defun.el
@@ -0,0 +1,152 @@
+;;; swift-mode-beginning-of-defun.el --- Major-mode for Apple's Swift 
programming language, beginning/end-of-defun. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2014-2016 taku0
+
+;; Authors: taku0 (http://github.com/taku0)
+;;
+;; Version: 2.1
+;; Package-Requires: ((emacs "24.4"))
+;; Keywords: languages swift
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; beginning-of-defun and end-of-defun
+
+;;; Code:
+
+(require 'swift-mode-lexer)
+(require 'swift-mode-indent)
+
+(defun swift-mode:beginning-of-defun (&optional arg)
+  "Move backward to the beginning of a defun."
+  (interactive)
+  (setq arg (or arg 1))
+  (let (result
+        pos)
+    (if (<= 0 arg)
+        (while (< 0 arg)
+          (setq result (swift-mode:beginning-of-defun-1
+                        #'swift-mode:backward-token-or-list))
+          (setq arg (1- arg)))
+      (while (< arg 0)
+        (setq pos (point))
+
+        (swift-mode:beginning-of-statement)
+
+        (when (<= (point) pos)
+          (while (not
+                  (memq
+                   (swift-mode:token:type (swift-mode:forward-token-or-list))
+                   '({} outside-of-buffer)))))
+
+        (setq result (swift-mode:beginning-of-defun-1
+                      (lambda ()
+                        (prog1 (swift-mode:forward-token-or-list)
+                          (forward-comment (point-max))))))
+        (setq arg (1+ arg))))
+    result))
+
+(defun swift-mode:beginning-of-defun-1 (next-token-function)
+  (catch 'swift-mode:found-defun
+    (while (not (eq (swift-mode:token:type (funcall next-token-function))
+                    'outside-of-buffer))
+      (when (save-excursion (swift-mode:is-point-before-body-of-defun))
+        (swift-mode:beginning-of-statement)
+        (throw 'swift-mode:found-defun t)))
+    nil))
+
+
+(defun swift-mode:is-point-before-body-of-defun ()
+  (and
+   (= (char-after) ?{)
+   (progn
+     ;; Skips implicit ;
+     (forward-comment (- (point)))
+     (let* ((defun-keywords '("class" "struct" "protocol" "enum" "extension"
+                              "func" "operator" "var" "get" "set" "willSet"
+                              "didSet" "deinit" "subscript"))
+            (previous-token (swift-mode:backward-token-or-list))
+            (previous-type (swift-mode:token:type previous-token))
+            (previous-text (swift-mode:token:text previous-token)))
+       (while (and
+               (not (eq previous-type 'outside-of-buffer))
+               (not (memq previous-type swift-mode:statement-parent-tokens))
+               (not (member previous-text swift-mode:statement-parent-tokens))
+               (not (member previous-text defun-keywords))
+               (not (and (equal previous-text "init")
+                         (save-excursion
+                           ;; Excludes self.init() {}
+                           (not
+                            (equal
+                             (swift-mode:token:text 
(swift-mode:backward-token))
+                             "."))))))
+         (setq previous-token (swift-mode:backward-token-or-list))
+         (setq previous-type (swift-mode:token:type previous-token))
+         (setq previous-text (swift-mode:token:text previous-token)))
+       (unless (bobp)
+         (swift-mode:forward-token-simple))
+       (or (equal previous-text "init")
+           (member previous-text defun-keywords))))))
+
+(defun swift-mode:beginning-of-statement ()
+  "Move backward to the beginning of a statement or some kind of expression.
+
+Intended for internal use."
+  (let ((parent (swift-mode:backward-sexps-until
+                 swift-mode:statement-parent-tokens)))
+    (forward-comment (point-max))
+    (swift-mode:goto-non-comment-bol)
+    (when (< (point) (swift-mode:token:end parent))
+      (goto-char (swift-mode:token:end parent)))
+    (swift-mode:skip-whitespaces)))
+
+
+(defun swift-mode:end-of-defun (&optional arg)
+  "Move forward to the end of a defun."
+  (interactive)
+  (setq arg (or arg 1))
+  (let (result)
+    (if (<= 0 arg)
+        (while (< 0 arg)
+          (setq result (swift-mode:end-of-defun-1
+                        #'swift-mode:forward-token-or-list
+                        ))
+          (setq arg (1- arg)))
+      (while (< arg 0)
+        (setq result (swift-mode:end-of-defun-1
+                      (lambda ()
+                        (prog1 (swift-mode:backward-token-or-list)
+                          (forward-comment (- (point)))))))
+        (setq arg (1+ arg))))
+    result))
+
+(defun swift-mode:end-of-defun-1 (next-token-function)
+  (catch 'swift-mode:found-defun
+    (while (not (eq (swift-mode:token:type (funcall next-token-function))
+                    'outside-of-buffer))
+      (when (and (= (char-before) ?})
+                 (save-excursion
+                   (backward-list)
+                   (swift-mode:is-point-before-body-of-defun)))
+        (throw 'swift-mode:found-defun t)))
+    nil))
+
+
+(provide 'swift-mode-beginning-of-defun)
+
+;;; swift-mode-beginning-of-defun.el ends here
diff --git a/swift-mode-font-lock.el b/swift-mode-font-lock.el
new file mode 100644
index 0000000..dfa9a2a
--- /dev/null
+++ b/swift-mode-font-lock.el
@@ -0,0 +1,232 @@
+;;; swift-mode-font-lock.el --- Major-mode for Apple's Swift programming 
language, Font Locks. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2014-2016 taku0, Chris Barrett, Bozhidar Batsov, Arthur 
Evstifeev
+
+;; Authors: taku0 (http://github.com/taku0)
+;;       Chris Barrett <chris.d.barrett@me.com>
+;;       Bozhidar Batsov <bozhidar@batsov.com>
+;;       Arthur Evstifeev <lod@pisem.net>
+;;
+;; Version: 2.1
+;; Package-Requires: ((emacs "24.4"))
+;; Keywords: languages swift
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Routines for Font Locks
+
+;;; Code:
+
+(defun swift-mode:function-name-pos-p (pos)
+  "Return t if POS is at just before function name."
+  (save-excursion
+    (save-match-data
+      (goto-char pos)
+      (forward-comment (- (point)))
+      (skip-syntax-backward "w_")
+      (looking-at 
"\\<\\(func\\|enum\\|struct\\|class\\|protocol\\|extension\\)\\>"))))
+
+(defun swift-mode:font-lock-match-function-names (limit)
+  "Move the cursor just after a function name or others.
+
+Others includes enum, struct, class, protocol name.
+Set `match-data', and return t if a function name found before position LIMIT.
+Return nil otherwise."
+  (and
+   (re-search-forward "\\<\\(\\sw\\|\\s_\\)+\\>" limit t)
+   (or
+    (swift-mode:function-name-pos-p (match-beginning 0))
+    (swift-mode:font-lock-match-function-names limit))))
+
+(defconst swift-mode:font-lock-keywords
+  '(
+    ;; Attributes
+    "@\\(\\sw\\|\\s_\\)*"
+
+    ;; Constants
+    ("\\<true\\>" . font-lock-constant-face)
+    ("\\<false\\>" . font-lock-constant-face)
+    ("\\<nil\\>" . font-lock-constant-face)
+
+    ;; Keywords
+    ;; 
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID410
+
+    ;; Keywords that begin with a number sign (#)
+    ("#available\\>" . font-lock-preprocessor-face)
+    ("#column\\>" . font-lock-preprocessor-face)
+    ("#elseif\\>" . font-lock-preprocessor-face)
+    ("#else\\>" . font-lock-preprocessor-face)
+    ("#endif\\>" . font-lock-preprocessor-face)
+    ("#file\\>" . font-lock-preprocessor-face)
+    ("#function\\>" . font-lock-preprocessor-face)
+    ("#if\\>" . font-lock-preprocessor-face)
+    ("#line\\>" . font-lock-preprocessor-face)
+    ("#selector\\>" . font-lock-preprocessor-face)
+
+    ;; Keywords used in declarations
+    "\\<associatedtype\\>"
+    "\\<class\\>"
+    "\\<deinit\\>"
+    "\\<enum\\>"
+    "\\<extension\\>"
+    "\\<fileprivate\\>"
+    "\\<func\\>"
+    "\\<import\\>"
+    "\\<init\\>"
+    "\\<inout\\>"
+    "\\<internal\\>"
+    "\\<let\\>"
+    "\\<open\\>"
+    "\\<operator\\>"
+    "\\<private\\>"
+    "\\<protocol\\>"
+    "\\<public\\>"
+    "\\<static\\>"
+    "\\<struct\\>"
+    "\\<subscript\\>"
+    "\\<typealias\\>"
+    "\\<var\\>"
+
+    ;; Keywords used in statements
+    "\\<break\\>"
+    "\\<case\\>"
+    "\\<continue\\>"
+    "\\<default\\>"
+    "\\<defer\\>"
+    "\\<do\\>"
+    "\\<else\\>"
+    "\\<fallthrough\\>"
+    "\\<for\\>"
+    "\\<guard\\>"
+    "\\<if\\>"
+    "\\<in\\>"
+    "\\<repeat\\>"
+    "\\<return\\>"
+    "\\<switch\\>"
+    "\\<where\\>"
+    "\\<while\\>"
+
+    ;; Keywords used in expressions and types (without true, false, and 
keywords begin with a number sign)
+    "\\<as\\>"
+    "\\<catch\\>"
+    "\\<dynamicType\\>"
+    "\\<is\\>"
+    "\\<nil\\>"
+    "\\<rethrows\\>"
+    "\\<super\\>"
+    "\\<self\\>"
+    "\\<Self\\>"
+    "\\<throws\\>"
+    "\\<throw\\>"
+    "\\<try\\>"
+
+    ;; Keywords reserved in particular contexts
+    "\\<Protocol\\>"
+    "\\<Type\\>"
+    "\\<and\\>"
+    "\\<assignment\\>"
+    "\\<associativity\\>"
+    "\\<convenience\\>"
+    "\\<didSet\\>"
+    "\\<dynamic\\>"
+    "\\<final\\>"
+    "\\<get\\>"
+    "\\<higherThan\\>"
+    "\\<indirect\\>"
+    "\\<infix\\>"
+    "\\<lazy\\>"
+    "\\<left\\>"
+    "\\<lowerThan\\>"
+    "\\<mutating\\>"
+    "\\<none\\>"
+    "\\<nonmutating\\>"
+    "\\<optional\\>"
+    "\\<override\\>"
+    "\\<postfix\\>"
+    "\\<precedence\\>"
+    "\\<precedencegroup\\>"
+    "\\<prefix\\>"
+    "\\<required\\>"
+    "\\<right\\>"
+    "\\<set\\>"
+    "\\<unowned\\>"
+    "\\<weak\\>"
+    "\\<willSet\\>"
+
+    ;; Standard library functions
+    ;; 
https://developer.apple.com/library/ios/documentation/Swift/Reference/Swift_StandardLibrary_Functions/index.html#//apple_ref/doc/uid/TP40016052
+    ("\\<abs\\>" . font-lock-builtin-face)
+    ("\\<alignof\\>" . font-lock-builtin-face)
+    ("\\<alignofValue\\>" . font-lock-builtin-face)
+    ("\\<anyGenerator\\>" . font-lock-builtin-face)
+    ("\\<assert\\>" . font-lock-builtin-face)
+    ("\\<assertionFailure\\>" . font-lock-builtin-face)
+    ("\\<debugPrint\\>" . font-lock-builtin-face)
+    ("\\<dump\\>" . font-lock-builtin-face)
+    ("\\<fatalError\\>" . font-lock-builtin-face)
+    ("\\<getVaList\\>" . font-lock-builtin-face)
+    ("\\<isUniquelyReferenced\\>" . font-lock-builtin-face)
+    ("\\<isUniquelyReferencedNonObjC\\>" . font-lock-builtin-face)
+    ("\\<max\\>" . font-lock-builtin-face)
+    ("\\<min\\>" . font-lock-builtin-face)
+    ("\\<numericCast\\>" . font-lock-builtin-face)
+    ("\\<precondition\\>" . font-lock-builtin-face)
+    ("\\<preconditionFailure\\>" . font-lock-builtin-face)
+    ("\\<print\\>" . font-lock-builtin-face)
+    ("\\<readLine\\>" . font-lock-builtin-face)
+    ("\\<sizeof\\>" . font-lock-builtin-face)
+    ("\\<sizeofValue\\>" . font-lock-builtin-face)
+    ("\\<strideof\\>" . font-lock-builtin-face)
+    ("\\<strideofValue\\>" . font-lock-builtin-face)
+    ("\\<swap\\>" . font-lock-builtin-face)
+    ("\\<transcode\\>" . font-lock-builtin-face)
+    ("\\<unsafeAddressOf\\>" . font-lock-builtin-face)
+    ("\\<unsafeBitCast\\>" . font-lock-builtin-face)
+    ("\\<unsafeDowncast\\>" . font-lock-builtin-face)
+    ("\\<unsafeUnwrap\\>" . font-lock-builtin-face)
+    ("\\<withExtendedLifetime\\>" . font-lock-builtin-face)
+    ("\\<withUnsafeMutablePointer\\>" . font-lock-builtin-face)
+    ("\\<withUnsafeMutablePointers\\>" . font-lock-builtin-face)
+    ("\\<withUnsafePointer\\>" . font-lock-builtin-face)
+    ("\\<withUnsafePointers\\>" . font-lock-builtin-face)
+    ("\\<withVaList\\>" . font-lock-builtin-face)
+    ("\\<zip\\>" . font-lock-builtin-face)
+
+    ;; keywords for build configuration statements
+    ("\\<os\\>" . font-lock-builtin-face)
+    ("\\<arch\\>" . font-lock-builtin-face)
+    ("\\<swift\\>" . font-lock-builtin-face)
+    ("\\<OSX\\>" . font-lock-builtin-face)
+    ("\\<iOS\\>" . font-lock-builtin-face)
+    ("\\<watchOS\\>" . font-lock-builtin-face)
+    ("\\<tvOS\\>" . font-lock-builtin-face)
+    ("\\<i386\\>" . font-lock-builtin-face)
+    ("\\<x86_64\\>" . font-lock-builtin-face)
+    ("\\<arm\\>" . font-lock-builtin-face)
+    ("\\<arm64\\>" . font-lock-builtin-face)
+    ("\\<iOSApplicationExtension\\>" . font-lock-builtin-face)
+    ("\\<OSXApplicationExtension\\>" . font-lock-builtin-face)
+
+    (swift-mode:font-lock-match-function-names . font-lock-function-name-face)
+    )
+  "Swift mode keywords for Font Lock.")
+
+
+(provide 'swift-mode-font-lock)
+
+;;; swift-mode-font-lock.el ends here
diff --git a/swift-mode-indent.el b/swift-mode-indent.el
new file mode 100644
index 0000000..0a69525
--- /dev/null
+++ b/swift-mode-indent.el
@@ -0,0 +1,1475 @@
+;;; swift-mode-indent.el --- Major-mode for Apple's Swift programming 
language, indentation. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2014-2016 taku0, Chris Barrett, Bozhidar Batsov, Arthur 
Evstifeev
+
+;; Authors: taku0 (http://github.com/taku0)
+;;       Chris Barrett <chris.d.barrett@me.com>
+;;       Bozhidar Batsov <bozhidar@batsov.com>
+;;       Arthur Evstifeev <lod@pisem.net>
+;;
+;; Version: 2.1
+;; Package-Requires: ((emacs "24.4"))
+;; Keywords: languages swift
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Routines for Indentation
+
+;;; Code:
+
+(require 'swift-mode-lexer)
+
+;;;###autoload
+(defcustom swift-mode:basic-offset 4
+  "Amount of indentation for block contents."
+  :type 'integer
+  :group 'swift
+  :safe 'integerp)
+
+;;;###autoload
+(defcustom swift-mode:parenthesized-expression-offset 2
+  "Amount of indentation inside parentheses and square brackets."
+  :type 'integer
+  :group 'swift
+  :safe 'integerp)
+
+;;;###autoload
+(defcustom swift-mode:multiline-statement-offset 2
+  "Amount of indentation for continuations of expressions."
+  :type 'integer
+  :group 'swift
+  :safe 'integerp)
+
+;;;###autoload
+(defcustom swift-mode:switch-case-offset 0
+  "Amount of indentation for case labels in switch statements."
+  :type 'integer
+  :group 'swift
+  :safe 'integerp)
+
+;;;###autoload
+(defcustom swift-mode:insert-space-after-asterisk-in-comment t
+  "Automatically insert a space after asterisk in comment if non-nil."
+  :type 'boolean
+  :group 'swift
+  :safe 'booleanp)
+
+;;;###autoload
+(defcustom swift-mode:auto-close-multiline-comment t
+  "If non-nil, `indent-new-comment-line' automatically close multiline 
comment."
+  :type 'boolean
+  :group 'swift
+  :safe 'booleanp)
+
+;;;###autoload
+(defcustom swift-mode:fix-comment-close t
+  "Fix \"* /\" in incomplete multiline comment to \"*/\" if non-nil."
+  :type 'boolean
+  :group 'swift
+  :safe 'booleanp)
+
+(defconst swift-mode:statement-parent-tokens
+  '(implicit-\; \; case-: { \( \[ anonymous-function-parameter-in)
+  "Parent tokens for statements.")
+
+(defconst swift-mode:expression-parent-tokens
+  (append swift-mode:statement-parent-tokens
+          '(\, < "where" "if" "guard" "while"))
+  "Parent tokens for expressions.")
+
+(defun swift-mode:indent-line ()
+  (let ((indent (save-excursion (swift-mode:calculate-indent)))
+        (current-indent
+         (save-excursion (back-to-indentation) (current-column))))
+    (if (<= (current-column) current-indent)
+        ;; The cursor is on the left margin. Moving to the new indent.
+        (indent-line-to indent)
+      ;; Keeps current relative position.
+      (save-excursion (indent-line-to indent)))))
+
+(defun swift-mode:calculate-indent ()
+  (back-to-indentation)
+
+  (if (nth 4 (syntax-ppss))
+      ;; If the 4th element of `(syntax-ppss)' is non-nil, the cursor is on
+      ;; the 2nd or following lines of a multiline comment, because:
+      ;;
+      ;; - The 4th element of `(syntax-ppss)' is nil on the comment starter.
+      ;; - We have called `back-to-indentation`.
+      (swift-mode:calculate-indent-of-multiline-comment)
+    (swift-mode:calculate-indent-of-code)))
+
+(defun swift-mode:calculate-indent-of-multiline-comment ()
+  (back-to-indentation)
+  (let ((comment-beginning-position (nth 8 (syntax-ppss))))
+    (forward-line -1)
+    (back-to-indentation)
+    (if (<= (point) comment-beginning-position)
+        ;; The cursor was on the 2nd line of the comment, so aligns with
+        ;; the asterisk of the comment starter.
+        (progn
+          (goto-char comment-beginning-position)
+          (forward-char)
+          (current-column))
+      ;; The cursor was on the 3rd or following lines of the comment, so aligns
+      ;; with a non-empty preceding line.
+      (if (eolp)
+          ;; The cursor is on an empty line, so seeks a non-empty-line.
+          (swift-mode:calculate-indent-of-multiline-comment)
+        (current-column)))))
+
+(defun swift-mode:calculate-indent-of-code ()
+  (back-to-indentation)
+  (let* ((previous-token (save-excursion (swift-mode:backward-token)))
+         (previous-type (swift-mode:token:type previous-token))
+         (previous-text (swift-mode:token:text previous-token))
+         (next-token (save-excursion (swift-mode:forward-token)))
+         (next-type (swift-mode:token:type next-token))
+         (next-text (swift-mode:token:text next-token))
+         (next-is-on-same-line
+          (<= (swift-mode:token:end next-token) (line-end-position))))
+    (cond
+     ;; Beginning of the buffer
+     ((eq previous-type 'outside-of-buffer)
+      0)
+
+     ;; Before } on the same line
+     ((and next-is-on-same-line (eq next-type '}))
+      (goto-char (swift-mode:token:end next-token))
+      (backward-list)
+      (swift-mode:calculate-indent-after-open-curly-brace 0))
+
+     ;; Before ) or ] on the same line
+     ((and next-is-on-same-line (memq next-type '(\) \])))
+      (goto-char (swift-mode:token:end next-token))
+      (backward-list)
+      (swift-mode:calculate-indent-of-expression
+       swift-mode:expression-parent-tokens
+       0
+       ;; Stops scanning at BOL:
+       ;;
+       ;; foo
+       ;;   .bar(
+       ;;     1
+       ;;   )
+       ;;
+       ;; rather than
+       ;;
+       ;; foo
+       ;;   .bar(
+       ;;   1
+       ;; )
+       'any))
+
+     ;; Before , on the same line
+     ((and next-is-on-same-line (eq next-type '\,))
+      (swift-mode:calculate-indent-of-prefix-comma))
+
+     ;; After ,
+     ((eq previous-type '\,)
+      (goto-char (swift-mode:token:start previous-token))
+      (swift-mode:calculate-indent-after-comma))
+
+     ;; Before "in" on the same line
+     ((and next-is-on-same-line (equal next-text "in"))
+      ;; When it is for-in statement, align with the token after "for":
+      ;;
+      ;; for
+      ;;   x
+      ;;   in
+      ;;   foo
+      ;;
+      ;; for x
+      ;;     in
+      ;;     foo
+      ;;
+      ;; When it is anonymous function, align with the token after {:
+      ;;
+      ;; foo {
+      ;;   x
+      ;;   in
+      ;;   ...
+      ;; }
+      ;;
+      ;;
+      ;; foo { x
+      ;;       in
+      ;;  ...
+      ;; }
+      ;;
+      ;; foo { [
+      ;;         weak self
+      ;;       ]
+      ;;       (
+      ;;         x,
+      ;;         y
+      ;;       )
+      ;;       -> Void
+      ;;       in
+      ;;   a
+      ;; }
+      (swift-mode:calculate-indent-of-expression '("for" {)))
+
+     ;; Before "case" or "default" on the same line, for switch statement
+     ((and
+       next-is-on-same-line
+       (member next-text '("case" "default"))
+       (save-excursion
+         (equal (swift-mode:token:text
+                 (swift-mode:backward-sexps-until
+                  '("switch" "enum" "for" "while" "if" "guard")))
+                "switch")))
+      ;; "case" is used for "switch", "enum", "for", "while", "if", and 
"guard".
+      ;; Only switch statement has special indentation rule.
+      ;;
+      ;; switch foo {
+      ;; default:
+      ;;   aaa
+      ;; case A:
+      ;;   aaa
+      ;; case B, C, D:
+      ;;   aaa
+      ;; case E(1, 2, 3, (4, 5)) where aaa,
+      ;;      F(1, 2, 3, (4, 5)) where aaa:
+      ;;   aaa
+      ;; case G: print(1); case H: print(2)
+      ;; case I:
+      ;;   ...
+      ;; }
+      ;;
+      ;; enum Foo {
+      ;;   case A
+      ;;   case B, C, D
+      ;;   indirect
+      ;;     case E(x: Int, y: Int)
+      ;; }
+      ;;
+      ;; enum Foo: Int, A, B {
+      ;;   case A = 1, B = 2
+      ;;   case C = 3
+      ;; }
+      ;;
+      ;; for
+      ;;   case let (x, y) in tuples {
+      ;; }
+      ;; if
+      ;;   case let (x, y) = tuple {
+      ;; }
+      ;; while
+      ;;   case let (x, y) = tuple {
+      ;; }
+      ;;
+      ;; Searches sibling "case" at the beginning of a line. If found, aligns
+      ;; with it.
+      ;;
+      ;; Otherwise, searches "switch" and aligh with it with offset.
+      (let ((parent (swift-mode:backward-sexps-until
+                     '("switch") nil '("case" "default"))))
+        (if (equal (swift-mode:token:text parent) "switch")
+            ;; Inside a switch-statement. Aligns with the "switch"
+            (swift-mode:calculate-indent-of-expression
+             swift-mode:statement-parent-tokens
+             swift-mode:switch-case-offset)
+          ;; Other cases. Aligns with the previous case.
+          (swift-mode:align-with-current-line))))
+
+     ;; Before "where" on the same line
+     ((and next-is-on-same-line (equal next-text "where"))
+      ;; switch {
+      ;; case let P(x)
+      ;;        where
+      ;;          a,
+      ;;      let Q(x)
+      ;;        where
+      ;;          a:
+      ;;   aaa
+      ;; }
+      ;;
+      ;; for case (x, y) in xys
+      ;;            where
+      ;;              aaa {
+      ;; }
+      ;;
+      ;; do {
+      ;; } catch let P(x)
+      ;;           where
+      ;;             aaa
+      ;;
+      ;; func foo<A: AAA,
+      ;;          B: BBB
+      ;;            where
+      ;;              ABC>() {
+      ;; }
+      ;;
+      ;; class Foo<A,
+      ;;           B,
+      ;;           C>: AAA,
+      ;;               BBB,
+      ;;               CCC
+      ;;   where
+      ;;     ABC {
+      ;; }
+      (let ((parent (save-excursion (swift-mode:backward-sexps-until
+                                     (append swift-mode:statement-parent-tokens
+                                             '("case"))))))
+        (swift-mode:calculate-indent-of-expression
+         (append swift-mode:statement-parent-tokens
+                 '(< "case" "catch" "for")
+                 (if (equal (swift-mode:token:text parent) "case") '(\,) '()))
+         swift-mode:multiline-statement-offset)))
+
+     ;; After {
+     ((eq previous-type '{)
+      (goto-char (swift-mode:token:start previous-token))
+      (swift-mode:calculate-indent-after-open-curly-brace
+       swift-mode:basic-offset))
+
+     ;; After ( or [
+     ((memq previous-type '(\( \[))
+      (goto-char (swift-mode:token:start previous-token))
+      (swift-mode:calculate-indent-of-expression
+       swift-mode:expression-parent-tokens
+       swift-mode:parenthesized-expression-offset
+       ;; Stops scanning at BOL:
+       ;;
+       ;; foo
+       ;;   .bar(
+       ;;     1
+       ;;   )
+       ;;
+       ;; rather than
+       ;;
+       ;; foo
+       ;;   .bar(
+       ;;   1
+       ;; )
+       'any
+       nil
+       swift-mode:parenthesized-expression-offset))
+
+     ;; After "where"
+     ((equal previous-text "where")
+      ;; switch {
+      ;; case let P(x) where
+      ;;        A,
+      ;;      let Q(x) where
+      ;;        A:
+      ;;   aaa
+      ;; case let P(x)
+      ;;        where
+      ;;          a,
+      ;;      let Q(x)
+      ;;        where
+      ;;          a:
+      ;;   aaa
+      ;; case let P(x), let Q(x) where
+      ;;                  a
+      ;; }
+      ;;
+      ;; for case let (x, y) in xys where
+      ;;            aaa {
+      ;; }
+      ;;
+      ;; for case let (x, y) in xys
+      ;;            where
+      ;;              aaa {
+      ;; }
+      ;;
+      ;; do {
+      ;; } catch let P(x) where
+      ;;           aaa
+      ;; do {
+      ;; } catch let P(x)
+      ;;           where
+      ;;             aaa
+      ;;
+      ;;
+      ;;
+      ;; func foo<A: AAA,
+      ;;          B: BBB where
+      ;;            ABC>() {
+      ;; }
+      ;;
+      ;; func foo<A: AAA,
+      ;;          B: BBB
+      ;;            where
+      ;;              ABC>() {
+      ;; }
+      ;;
+      ;; class Foo<A,
+      ;;           B,
+      ;;           C> A,
+      ;;              B,
+      ;;              C where
+      ;;   ABC {
+      ;; }
+      ;;
+      ;; class Foo<A,
+      ;;           B,
+      ;;           C>: A,
+      ;;               B,
+      ;;               C
+      ;;   where
+      ;;     ABC {
+      ;; }
+      (goto-char (swift-mode:token:start previous-token))
+      (if (swift-mode:bol-other-than-comments-p)
+          (swift-mode:align-with-current-line
+           swift-mode:multiline-statement-offset)
+        (let ((parent (save-excursion
+                        (swift-mode:backward-sexps-until
+                         (append swift-mode:statement-parent-tokens
+                                 '("case"))))))
+          (swift-mode:calculate-indent-of-expression
+           (append swift-mode:statement-parent-tokens
+                   '(< "case" "catch" "for")
+                   (if (equal (swift-mode:token:text parent) "case") '(\,) 
'()))
+           swift-mode:multiline-statement-offset))))
+
+     ;; After implicit-\; or ;
+     ((memq previous-type '(implicit-\; \;))
+      (goto-char (swift-mode:token:start previous-token))
+      (swift-mode:calculate-indent-of-expression
+       (remove '\; (remove 'implicit-\; swift-mode:statement-parent-tokens))
+       0
+       '(implicit-\; \;)))
+
+     ;; After "in" for anonymous function parameters
+     ((eq previous-type 'anonymous-function-parameter-in)
+      (goto-char (swift-mode:token:start previous-token))
+      (swift-mode:backward-sexps-until '({))
+      (swift-mode:calculate-indent-after-open-curly-brace
+       swift-mode:basic-offset))
+
+     ;; After "in" for "for" statements
+     ((equal previous-text "in")
+      ;; Aligns with "in" if it is at the start of the line:
+      ;;
+      ;; for
+      ;;   x
+      ;;   in
+      ;;   foo
+      ;;
+      ;; for x
+      ;;     in
+      ;;     foo
+      ;;
+      ;; Otherwise, aligns with the next token of the "for".
+      ;;
+      ;; for x in
+      ;;     foo
+      ;;
+      ;; for
+      ;;   x in
+      ;;   foo
+      (goto-char (swift-mode:token:start previous-token))
+      (if (swift-mode:bol-other-than-comments-p)
+          (swift-mode:align-with-current-line)
+        (let ((parent (swift-mode:backward-sexps-until '("for" {))))
+          (swift-mode:align-with-next-token parent))))
+
+     ;; After case ... : or default:
+     ((eq previous-type 'case-:)
+      (goto-char (swift-mode:token:start previous-token))
+      (swift-mode:calculate-indent-of-expression
+       swift-mode:statement-parent-tokens
+       swift-mode:basic-offset))
+
+     ;; Before ; on the same line
+     ((and next-is-on-same-line (eq next-type '\;))
+      (swift-mode:calculate-indent-of-expression
+       (remove '\; (remove 'implicit-\; swift-mode:statement-parent-tokens))
+       0
+       '(implicit-\; \;)))
+
+     ;; After if, guard, while
+     ((member previous-text '("if" "guard" "while"))
+      (swift-mode:calculate-indent-of-expression
+       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)))
+
+     ;; Otherwise, it is continuation of the previous line
+     (t
+      (goto-char (swift-mode:token:end previous-token))
+      (swift-mode:backward-token-or-list)
+      (swift-mode:calculate-indent-of-expression
+       swift-mode:expression-parent-tokens
+       swift-mode:multiline-statement-offset
+       'any)))))
+
+(defun swift-mode:calculate-indent-of-expression
+    (parents
+     &optional
+     offset
+     stop-at-eol-token-types
+     stop-at-bol-token-types
+     bol-offset)
+  "Return start column of the current expressions or statement plus OFFSET.
+
+If OFFSET is omitted, it is assumed to be 0.
+PARENTS is a list of token types that precedes an expression or a statement.
+See `swift-mode:backward-sexps-until' for the details of
+STOP-AT-EOL-TOKEN-TYPES and STOP-AT-BOL-TOKEN-TYPES.
+If scanning stops at STOP-AT-EOL-TOKEN-TYPES, align with the next token with
+BOL-OFFSET.
+If scanning stops at STOP-AT-BOL-TOKEN-TYPES, align with that token with
+BOL-OFFSET.
+If STOP-AT-BOL-TOKEN-TYPES is the symbol `any', the cursor is assumed to be
+on the previous line."
+  (save-excursion
+    (let* ((parent (swift-mode:backward-sexps-until
+                    parents
+                    stop-at-eol-token-types
+                    stop-at-bol-token-types))
+           (parent-end (swift-mode:token:end parent))
+           (stopped-at-parent
+            (or (memq (swift-mode:token:type parent) parents)
+                (member (swift-mode:token:text parent) parents)
+                (eq (swift-mode:token:type parent) 'outside-of-buffer)))
+           (stopped-at-eol
+            (and
+             (not stopped-at-parent)
+             stop-at-eol-token-types
+             (or
+              (eq stop-at-eol-token-types 'any)
+              (memq (swift-mode:token:type parent)
+                    stop-at-eol-token-types)
+              (member (swift-mode:token:text parent)
+                      stop-at-eol-token-types)))))
+      (when (or stopped-at-parent stopped-at-eol)
+        (goto-char parent-end)
+        (forward-comment (point-max)))
+      ;; Now, the cursor is at the first token of the expression.
+
+      (if stopped-at-parent
+          ;; The cursor is at the start of the entire expression.
+          ;; Aligns with the start of the expression with offset.
+          (swift-mode:align-with-next-token parent offset)
+        ;; The cursor is at the middle of the expression.
+        ;; Aligns with this line with bol-offset.
+        (swift-mode:align-with-current-line bol-offset)))))
+
+(defun swift-mode:calculate-indent-after-open-curly-brace (offset)
+  "Return indentation after open curly braces.
+
+Assuming the cursor is on the open parenthesis.
+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
+  ;; the line on which the open brace is:
+  ;;
+  ;; foo()
+  ;;   .then { x in
+  ;;     foo()
+  ;;     foo()
+  ;;   }
+  ;;   .then { x in
+  ;;     foo()
+  ;;     foo()
+  ;;   }
+  ;;
+  ;; rather than
+  ;;
+  ;; foo()
+  ;;   .then { x in
+  ;;     foo()
+  ;;     foo()
+  ;; }
+  ;;   .then { x in
+  ;;     foo()
+  ;;     foo()
+  ;; }
+  ;;
+  ;; Otherwise, aligns with the start of the whole statement:
+  ;;
+  ;; for x in
+  ;;     xs
+  ;;       .foo() {
+  ;; }
+  ;;
+  ;; rather than
+  ;;
+  ;; for x in
+  ;;     xs
+  ;;       .foo() {
+  ;;       }
+  ;;
+  ;; Note that curly brace after binary operator is a part of
+  ;; a multiline expression:
+  ;;
+  ;; for x in
+  ;;     xs
+  ;;     +++ { x in
+  ;;       // this is not the body of the for-statement.
+  ;;     } {
+  ;;   // The body of the for-statement.
+  ;; }
+  (let ((pos (point))
+        next-token
+        is-declaration-or-control-statement-body)
+    (if (save-excursion
+          (eq (swift-mode:token:type (swift-mode:backward-token))
+              'binary-operator))
+        ;; for x in
+        ;;     xs
+        ;;     +++ { x in
+        ;;       // this is not the body of the for statement.
+        ;;     } {
+        ;;   ...
+        ;; }
+        (setq is-declaration-or-control-statement-body nil)
+      (save-excursion
+        (swift-mode:backward-sexps-until swift-mode:statement-parent-tokens)
+        (swift-mode:forward-token)
+        (setq next-token (swift-mode:forward-token-or-list))
+        (while (<= (point) pos)
+          (cond
+           ((member
+             (swift-mode:token:text next-token)
+             '("for" "while" "repeat" "if" "else" "defer" "do" "catch"
+               "get" "set" "willSet" "didSet" "func" "init" "subscript"
+               "enum" "struct" "class" "extension" "prefix" "postfix" "infix"
+               "precedencegroup"))
+            (setq is-declaration-or-control-statement-body t)
+            (goto-char (1+ pos)))
+
+           ((and
+             (equal (swift-mode:token:text next-token) "protocol")
+             (not (equal (swift-mode:token:text
+                          (save-excursion (swift-mode:forward-token)))
+                         "<")))
+            (setq is-declaration-or-control-statement-body t)
+            (goto-char (1+ pos)))
+
+           ((equal (swift-mode:token:text next-token) "var")
+            ;; There are several cases:
+            ;;
+            ;; var foo = bar
+            ;;   .then { x in
+            ;;       x
+            ;;   }
+            ;;   .then { x in
+            ;;       x
+            ;;   }
+            ;;
+            ;; var foo = bar
+            ;;   .baz {
+            ;;     willSet {
+            ;;         ...
+            ;;     }
+            ;; }
+            ;;
+            ;; var foo {
+            ;;     get {
+            ;;         ...
+            ;;     }
+            ;; }
+            ;;
+            ;; Note that the 1st and the 2nd cases cannot be distinguished
+            ;; without inspecting the contents of the block.
+            ;; We indent the 2nd case like the 1st case for now.
+            ;; Future implementation may use more sophisticated logic.
+            (goto-char pos)
+            (setq is-declaration-or-control-statement-body
+                  (equal (swift-mode:token:text
+                          (swift-mode:backward-sexps-until '("var" "=")))
+                         "var"))
+            (goto-char (1+ pos)))
+
+           (t
+            ;; Suppose indenting the A token below.
+            ;;
+            ;; foo {
+            ;;   A
+            ;;
+            ;; This function is called on the open curly brace.
+            ;; If the close curly brace doesn't exist,
+            ;; swift-mode:forward-token-or-list results in
+            ;; "Unbalanced parentheses" error.
+            ;; So if the point is just before the open curly brace,
+            ;; exits immediately.
+            (forward-comment (point-max))
+            (if (< (point) pos)
+                (setq next-token (swift-mode:forward-token-or-list))
+              (goto-char (1+ pos))))))))
+    (swift-mode:calculate-indent-of-expression
+     swift-mode:statement-parent-tokens
+     offset
+     (if is-declaration-or-control-statement-body nil 'any)
+     nil
+     offset)))
+
+(defun swift-mode:calculate-indent-of-prefix-comma ()
+  "Return indentation for prefix comma.
+
+Example:
+
+let x = [ 1
+        , 2
+        , 3
+]
+
+class Foo: A
+         , B
+         , C
+
+case A
+   , B
+   , C
+       :
+
+var x = 1
+  , y = 2
+  , z = 3
+
+This is also known as Utrecht-style in the Haskell community."
+  (let* ((comma-type-and-statement-parent (swift-mode:detect-type-of-comma))
+         (comma-type (nth 0 comma-type-and-statement-parent))
+         (statement-parent (nth 1 comma-type-and-statement-parent)))
+    (if (eq comma-type 'condition-list)
+        (swift-mode:calculate-indent-of-prefix-comma-of-condition-list
+         statement-parent)
+      (let* ((parents (swift-mode:parents-of-comma comma-type))
+             (parent (swift-mode:backward-sexps-until parents
+                                                      nil
+                                                      '(\,)))
+             (parent-end (swift-mode:token:end parent))
+             (stopped-at-parent
+              (or (memq (swift-mode:token:type parent) parents)
+                  (member (swift-mode:token:text parent) parents)
+                  (eq (swift-mode:token:type parent) 'outside-of-buffer))))
+        (if stopped-at-parent
+            (progn
+              ;; Aligns with the end of the parent.
+              (goto-char parent-end)
+              (backward-char)
+              (current-column))
+          ;; Aligns with the previous comma.
+          (swift-mode:align-with-current-line))))))
+
+(defun swift-mode:calculate-indent-of-prefix-comma-of-condition-list
+    (statement-parent)
+  ;; The comma is in a condition-list but not in an enum-case-pattern-list.
+  ;;
+  ;; Example:
+  ;;
+  ;; if case let P(x)
+  ;;       , let Q(x)     // comma for enum-case-pattern-list
+  ;;       , let R(x) = a // comma for enum-case-pattern-list
+  ;;  , let x = x         // comma for condition-list
+  ;;  , foo == bar        // comma for condition-list
+  ;;
+  ;; We scan from beginning of the statement and remembers last anchor token,
+  ;; i.e. "if", "guard", "while", or comma at the beginning of the line.
+  (let ((pos (point))
+        next-token
+        (anchor statement-parent)
+        in-case-pattern-list)
+    (goto-char (swift-mode:token:end statement-parent))
+    (setq next-token (swift-mode:forward-token-or-list))
+    (while (< (point) pos)
+      (cond
+       ((equal (swift-mode:token:text next-token) "case")
+        (setq in-case-pattern-list t))
+
+       ((equal (swift-mode:token:text next-token) "=")
+        (setq in-case-pattern-list nil))
+
+       ((member (swift-mode:token:text next-token) '("if" "guard" "while"))
+        (setq anchor next-token))
+
+       ((and (not in-case-pattern-list)
+             (eq (swift-mode:token:type next-token) '\,)
+             (save-excursion
+               (goto-char (swift-mode:token:start next-token))
+               (swift-mode:bol-other-than-comments-p)))
+        (setq anchor next-token)))
+      (setq next-token (swift-mode:forward-token-or-list)))
+    (if (eq (swift-mode:token:type anchor) '\,)
+        ;; Aligns with the previous comma.
+        (progn
+          (goto-char (swift-mode:token:start anchor))
+          (swift-mode:align-with-current-line))
+      ;; Aligns with the end of the anchor
+      (goto-char (swift-mode:token:end anchor))
+      (backward-char)
+      (current-column))))
+
+(defun swift-mode:calculate-indent-after-comma ()
+  "Return indentation after comma.
+
+Assuming the cursor is on the comma."
+  (let* ((comma-type-and-statement-parent (swift-mode:detect-type-of-comma))
+         (comma-type (nth 0 comma-type-and-statement-parent))
+         (statement-parent (nth 1 comma-type-and-statement-parent)))
+    (if (eq comma-type 'condition-list)
+        (swift-mode:calculate-indent-after-comma-of-condition-list
+         statement-parent)
+      (swift-mode:align-with-next-token
+       (swift-mode:backward-sexps-until
+        (swift-mode:parents-of-comma comma-type)
+        '(\,))))))
+
+(defun swift-mode:calculate-indent-after-comma-of-condition-list
+    (statement-parent)
+  ;; The comma is in a condition-list but not in an enum-case-pattern-list.
+  ;;
+  ;; Example:
+  ;;
+  ;; if
+  ;;   case let P(x),     // comma for enum-case-pattern-list
+  ;;        let Q(x),     // comma for enum-case-pattern-list
+  ;;        let R(x) = a, // comma for condition-list
+  ;;   let x = x,         // comma for condition-list
+  ;;   foo == bar
+  ;;
+  ;; We scan from beginning of the statement and remembers last parent token,
+  ;; i.e. "if", "guard", "while", or comma at the end of the line.
+  (let ((pos (point))
+        next-token
+        (parent statement-parent)
+        in-case-pattern-list)
+    (goto-char (swift-mode:token:end statement-parent))
+    (setq next-token (swift-mode:forward-token-or-list))
+    (while (< (point) pos)
+      (cond
+       ((equal (swift-mode:token:text next-token) "case")
+        (setq in-case-pattern-list t))
+
+       ((equal (swift-mode:token:text next-token) "=")
+        (setq in-case-pattern-list nil))
+
+       ((member (swift-mode:token:text next-token) '("if" "guard" "while"))
+        (setq parent next-token))
+
+       ((and (not in-case-pattern-list)
+             (eq (swift-mode:token:type next-token) '\,)
+             (swift-mode:eol-other-than-comments-p))
+        (setq parent next-token)))
+      (setq next-token (swift-mode:forward-token-or-list)))
+    (swift-mode:align-with-next-token parent)))
+
+(defun swift-mode:detect-type-of-comma ()
+  "Return type of comma token under the cursor.
+
+Comma type is a list where:
+0th element is one of the following:
+
+- tuple-or-array (inside () or [])
+- type-parameters-or-requirements (inside <>)
+- enum-case-pattern-list (e.g. if case P, Q, R = x)
+- condition-list (e.g. if let x = x, let y = y)
+- variable-declarations (e.g. let x = 1, y = 2)
+- switch-case-or-enum-case-item-list (e.g. switch {case P, Q, R: a} or
+  enum {case A, B, C})
+- class-like-declarations (supertypes of class, or where clause after
+  super types)
+
+1st element is the token before the beginning of the statement.
+"
+  ;; Various examples:
+  ;;
+  ;; let x = ( // simple case
+  ;;   1,
+  ;;   2,
+  ;;   3
+  ;; )
+  ;;
+  ;; let x = [ // simple case
+  ;;   1,
+  ;;   2,
+  ;;   3
+  ;; ]
+  ;;
+  ;; let x: Foo<A, B> = a, // "let" is not a part of elements
+  ;;     y: Foo<A, B> = b,
+  ;;     z: Foo<A, B> = c
+  ;;
+  ;; switch foo {
+  ;; case (let x, // "let" is a part of an element
+  ;;       Y,
+  ;;       Z):
+  ;;   aaa
+  ;; }
+  ;;
+  ;; class Foo<A where A: B, // "where" is not a part of elements
+  ;;                   A: C,
+  ;;                   A: D> {
+  ;; }
+  ;;
+  ;; switch foo {
+  ;; case A(x) where p(x), // "case" is not a part of elements
+  ;;      B(x) where p(x), // "where" is a part of an element
+  ;;      C(x) where p(x):
+  ;;   aaa
+  ;; }
+  ;;
+  ;; if // or guard or while
+  ;;   let x = x, // "let" is a part of an element
+  ;;   let y = y,
+  ;;   let z = z,
+  ;;   case P(a, b, c), // "case" is a part of an element of condition-list
+  ;;        Q(a, b, c) = abc, // "case" is not a part of elements of
+  ;;                          // enum-case-pattern-list
+  ;;   case (a, b, c) = abc,
+  ;;   aaa {
+  ;;
+  ;;   bbb
+  ;; }
+  ;;
+  ;; See also SE-0099 and SE-0043:
+  ;; 
https://github.com/apple/swift-evolution/blob/master/proposals/0099-conditionclauses.md
+  ;; 
https://github.com/apple/swift-evolution/blob/master/proposals/0043-declare-variables-in-case-labels-with-multiple-patterns.md
+  ;;
+  ;; class Foo<T>: A,
+  ;;               B,
+  ;;               C
+  ;;   where
+  ;;     T: A,
+  ;;     T: B,
+  ;;     T: C {
+  ;; }
+  ;;
+  ;; extension _ArrayType
+  ;;   where
+  ;;     Generator.Element: A,
+  ;;     Generator.Element: B,
+  ;;     Generator.Element: C {
+  ;; }
+  ;;
+  ;; func foo<T> -> Int
+  ;;   where
+  ;;     T: A,
+  ;;     T: B,
+  ;;     T: C {
+  ;; }
+  ;;
+  ;; enum Foo {
+  ;;   case A(x: Int),
+  ;;        B(y: Int),
+  ;;        C(z: Int)
+  ;;   case D(x: Int)
+  ;;      , E(y: Int)
+  ;;      , F(z: Int)
+  ;; }
+  ;;
+  ;; enum Foo: Int {
+  ;;   case A,
+  ;;        B,
+  ;;        C = 2
+  ;;   case D = 3
+  ;;      , E
+  ;;      , F
+  ;; }
+  (save-excursion
+    (let ((pos (point))
+          (parent (swift-mode:backward-sexps-until
+                   (cons '< swift-mode:statement-parent-tokens))))
+      (cond
+       ((memq (swift-mode:token:type parent) '(\( \[))
+        (list 'tuple-or-array parent))
+
+       ((eq (swift-mode:token:type parent) '<)
+        (list 'type-parameters-or-requirements parent))
+
+       (t
+        (goto-char (swift-mode:token:end parent))
+        (let ((next-token (swift-mode:forward-token-or-list))
+              result)
+          (while (and (<= (point) pos) (not result))
+            (cond
+             ((member (swift-mode:token:text next-token)
+                      '("if" "guard" "while"))
+              ;; Conditions
+              ;;
+              ;; Distinguishes condition-list and enum-case-pattern-list:
+              ;;
+              ;; if
+              ;;   let x = x,
+              ;;   case P(a, b, c),
+              ;;        Q(a, b, c),
+              ;;        R(a, b, c) = abc,
+              ;;   let x = x,
+              ;;   foo == bar,
+              ;;   case (a, b, c) = abc {
+              ;; }
+              (goto-char pos)
+              (if (equal
+                   (swift-mode:token:text (swift-mode:backward-sexps-until
+                                           '("if" "guard" "while" "case" "=")))
+                   "case")
+                  (setq result 'enum-case-pattern-list)
+                (setq result 'condition-list)))
+
+             ((member (swift-mode:token:text next-token)
+                      '("let" "var"))
+              (setq result 'variable-declarations))
+
+             ((equal (swift-mode:token:text next-token)
+                     "case")
+              (setq result 'switch-case-or-enum-case-item-list))
+
+             ((equal (swift-mode:token:text next-token)
+                     "where")
+              (setq result 'type-parameters-or-requirements))
+
+             ((eq (swift-mode:token:type next-token) 'typing-:)
+              (setq result 'class-like-declarations)))
+
+            (setq next-token (swift-mode:forward-token-or-list)))
+          (if (and (> (point) pos) (eq (swift-mode:token:type next-token) '<>))
+              ;; The comma was inside <> but scanner misunderstand < as
+              ;; a binary-operator.
+              (list 'type-parameters-or-requirements parent)
+            (list result parent))))))))
+
+(defun swift-mode:parents-of-comma (comma-type)
+  "Return parent token types of comma token Ffrom COMMA-TYPE."
+  (append
+   swift-mode:statement-parent-tokens
+   (cond
+    ((eq comma-type 'tuple-or-array)
+     '(\( \[))
+
+    ((eq comma-type 'type-parameters-or-requirements)
+     '(< "where"))
+
+    ((eq comma-type 'enum-case-pattern-list)
+     '("case"))
+
+    ((eq comma-type 'variable-declarations)
+     '("let" "var"))
+
+    ((eq comma-type 'switch-case-or-enum-case-item-list)
+     '("case"))
+
+    ((eq comma-type 'class-like-declarations)
+     '(typing-: "where")))))
+
+(defun swift-mode:backward-sexps-until (token-types
+                                        &optional
+                                        stop-at-eol-token-types
+                                        stop-at-bol-token-types)
+  "Backward sexps until a token with one of given token types appears.
+Return the token.
+When this function returns, the cursor is at the start of the token.
+
+TOKEN-TYPES is a list of guard token typess.  This function backs to a token
+with  one of those token types.
+STOP-AT-EOL-TOKEN-TYPES is a list of token types that if we skipped the end of
+a line just after a token with one of given toke typen, the function returns.
+Typically, this is a list of token types that separates list elements
+\(e.g. ',', ';'). If STOP-AT-EOL-TOKEN-TYPES is the symbol `any', it matches
+all tokens.
+STOP-AT-BOL-TOKEN-TYPES is a list of token types that if we hit
+the beginning of a line just before a token with one of given token types,
+the function returns. Typically, this is a list of token types that starts
+list element (e.g. 'case' of switch statement body). If STOP-AT-BOL-TOKEN-TYPES
+is the symbol `any', it matches all tokens."
+  (let*
+      ((parent (swift-mode:backward-token-or-list))
+       (type (swift-mode:token:type parent))
+       (text (swift-mode:token:text parent)))
+    (while (not
+            ;; Stops loop when...
+            (or
+             ;; Hits a guard token.
+             (member type token-types)
+             (member text token-types)
+
+             ;; Beginning of the buffer.
+             (eq type 'outside-of-buffer)
+
+             ;; When this function is called on "," token before position (1),
+             ;; this function stops just before the "," token after "Foo".
+             ;;
+             ;; case Foo,
+             ;;      Bar, Baz, // (1)
+             ;;      AAA
+             (and stop-at-eol-token-types
+                  (save-excursion
+                    (swift-mode:forward-token-or-list)
+                    (forward-comment (- (point)))
+                    (swift-mode:eol-other-than-comments-p))
+                  (or (eq stop-at-eol-token-types 'any)
+                      (member type stop-at-eol-token-types)
+                      (member text stop-at-eol-token-types)))
+
+             ;; When this function is called on "case" token before position
+             ;; (1), this function stops just before "case Bar".
+             ;;
+             ;; switch foo {
+             ;; case Foo:
+             ;;     ...
+             ;; case Bar: case Baz:
+             ;;     ...
+             ;; case AAA: // (1)
+             ;; }
+             (and stop-at-bol-token-types
+                  (and
+                   (or
+                    (eq stop-at-bol-token-types 'any)
+                    (member type stop-at-bol-token-types)
+                    (member text stop-at-bol-token-types))
+                   (swift-mode:bol-other-than-comments-p)))))
+      (setq parent (swift-mode:backward-token-or-list))
+      (setq type (swift-mode:token:type parent))
+      (setq text (swift-mode:token:text parent)))
+    parent))
+
+(defun swift-mode:align-with-next-token (parent &optional offset)
+  (let ((parent-end (swift-mode:token:end parent)))
+    (goto-char parent-end)
+    (forward-comment (point-max))
+    (swift-mode:goto-non-comment-bol)
+    (when (< (point) parent-end)
+      (goto-char parent-end))
+    (swift-mode:skip-whitespaces)
+    (+ (or offset 0) (current-column))))
+
+(defun swift-mode:align-with-current-line (&optional offset)
+  (swift-mode:goto-non-comment-bol)
+  (swift-mode:skip-whitespaces)
+  (+ (or offset 0) (current-column)))
+
+(defun swift-mode:backward-token-or-list ()
+  "Move point to the start position of the previous token or list.
+Return the token skipped."
+  (let* ((previous-token (swift-mode:backward-token))
+         (previous-type (swift-mode:token:type previous-token))
+         (previous-text (swift-mode:token:text previous-token))
+         (previous-start (swift-mode:token:start previous-token))
+         (previous-end (swift-mode:token:end previous-token)))
+    (cond
+     ;; List
+     ((memq previous-type '(} \) \]))
+      (goto-char previous-end)
+      (backward-list)
+      (swift-mode:token
+       (cdr (assoc previous-type '((} . {})
+                                   (\) . \(\))
+                                   (\] . \[\]))))
+       (buffer-substring-no-properties (point) previous-end)
+       (point)
+       previous-end))
+
+     ;; Generic parameter list
+     ((equal previous-text ">")
+      (swift-mode:try-backward-generic-parameters)
+      (if (= (point) previous-start)
+          previous-token
+        (swift-mode:token
+         '<>
+         (buffer-substring-no-properties (point) previous-end)
+         (point)
+         previous-end)))
+
+     ;; Other token
+     (t previous-token))))
+
+(defun swift-mode:forward-token-or-list ()
+  "Move point to the end position of the next token or list.
+Return the token skipped."
+  (let* ((next-token (swift-mode:forward-token))
+         (next-type (swift-mode:token:type next-token))
+         (next-text (swift-mode:token:text next-token))
+         (next-start (swift-mode:token:start next-token))
+         (next-end (swift-mode:token:end next-token)))
+    (cond
+     ;; List
+     ((memq next-type '({ \( \[))
+      (goto-char next-start)
+      (forward-list)
+      (swift-mode:token
+       (cdr (assoc next-type '(({ . {})
+                               (\( . \(\))
+                               (\[ . \[\]))))
+       (buffer-substring-no-properties next-start (point))
+       next-start
+       (point)))
+
+     ;; Generic parameter list
+     ((equal next-text "<")
+      (swift-mode:try-forward-generic-parameters)
+      (if (= (point) next-end)
+          next-token
+        (swift-mode:token
+         '<>
+         (buffer-substring-no-properties next-start (point))
+         next-start
+         (point))))
+
+     ;; Other token
+     (t next-token))))
+
+(defun swift-mode:try-backward-generic-parameters ()
+  "Move point to the start of the generic parameter list.
+
+Keep position if the cursor is not at the end of a generic parameter list.
+
+Assuming the cursor is on the close angle bracket.
+
+It is a Generic parameter list if:
+- it has matching angle brackets, and
+- it does not have tokens that cannot appears in a generic parameter list."
+  (swift-mode:try-skip-generic-parameters
+   #'swift-mode:backward-token-or-list
+   "<" ">"))
+
+(defun swift-mode:try-forward-generic-parameters ()
+  "Move point to the end of the generic parameter list.
+
+Keep position if the cursor is not at the start of a generic parameter list.
+
+Assuming the cursor is after the open angle bracket.
+
+It is a Generic parameter list if:
+- it has matching angle brackets, and
+- it does not have tokens that cannot appears in a generic parameter list."
+  (swift-mode:try-skip-generic-parameters
+   #'swift-mode:forward-token-or-list
+   ">" "<"))
+
+(defconst siwft-mode:tokens-not-in-generic-parameter-list
+  ;; Whitelisting tend to be fragile. So we list tokens that are
+  ;; unlikely to appear in generic parameter lists in the current
+  ;; version and future ones.
+  ;;
+  ;; Example of complex generic parameters:
+  ;; <
+  ;;   A: B,
+  ;;   C: protocol<X, Y>
+  ;;   where
+  ;;     A: @aaa(1 + 2 + 3) D<Int>!,
+  ;;     C == (@aaa(1) inout [E.F]?, G...) throws -> [Int:Int]
+  ;; >
+  ;;
+  ;; We don't need to consider the contents of inner brackets because they are
+  ;; skipped by `swift-mode:backward-token-or-list'.
+  ;;
+  ;; String literals, implicit parameter names, and numbers are also excluded
+  ;; by `swift-mode:try-skip-generic-parameters'.
+  '(outside-of-buffer
+    \;
+    { } \( \) \[ \]
+    "true" "false"
+    "class" "struct" "enum" "extension" "func" "operator"
+    "try" "try?" "try!"
+    "as" "as?" "as!"
+    "is"
+    "in"
+    "init" "deinit" "get" "set" "willSet" "didSet" "subscript"
+    "for" "case" "default" "while" "let" "var" "repeat" "if" "else"
+    "guard" "break" "continue" "fallthrough" "return" "throw" "defer"
+    "do" "catch" "import" "typealias" "associatedtype"))
+
+(defun swift-mode:try-skip-generic-parameters
+    (skip-token-or-list-function matching-bracket-text unmatching-bracket-text)
+  (let ((pos (point))
+        (prohibited-tokens (append
+                            unmatching-bracket-text
+                            siwft-mode:tokens-not-in-generic-parameter-list))
+        (next-token (funcall skip-token-or-list-function)))
+    (while
+        (cond
+         ((or (memq (swift-mode:token:type next-token) prohibited-tokens)
+              (member (swift-mode:token:text next-token) prohibited-tokens)
+              (string-match-p "^[\"$0-9]"
+                              (swift-mode:token:text next-token)))
+          ;; Not a generic parameter list. Returns to the initial position and
+          ;; stops the loop.
+          (goto-char pos)
+          nil)
+
+         ((equal (swift-mode:token:text next-token) matching-bracket-text)
+          ;; Found the matching open angle bracket. Stops the loop.
+          nil)
+
+         ;; Otherwise, keep scanning
+         (t t))
+      (setq next-token (funcall skip-token-or-list-function)))
+    next-token))
+
+(defun swift-mode:bol-other-than-comments-p ()
+  "Return t if there is nothing other than comments in the front of this line.
+
+Return nil otherwise.
+Newlines inside comments are ignored."
+  ;; Foo // ← bol
+  ;; /* */ Foo // ← bol
+  ;; X /* */ Foo // ← not bol
+  ;;
+  ;; /*
+  ;; */ /* */ /*
+  ;; */ Foo // ← bol
+  ;;
+  ;; X /*
+  ;; */ /* */ /*
+  ;; */ Foo // ← not bol
+  ;;
+  ;; X
+  ;; /* */ /*
+  ;; */ Foo // ← bol
+  (save-excursion
+    (let ((pos (point)))
+      (swift-mode:goto-non-comment-bol)
+      (forward-comment (point-max))
+      (<= pos (point)))))
+
+(defun swift-mode:eol-other-than-comments-p ()
+  "Return t if there is nothing other than comments until the end of this line.
+
+Return nil otherwise.
+Newlines inside comments are ignored."
+  (save-excursion
+    (let ((pos (point)))
+      (swift-mode:goto-non-comment-eol)
+      (forward-comment (- (point)))
+      (<= (point) pos))))
+
+(defun swift-mode:bolp ()
+  "Return t if there is nothing in the front of this line.
+
+Return nil otherwise."
+  (save-excursion
+    (skip-syntax-backward " ")
+    (bolp)))
+
+(defun swift-mode:skip-whitespaces ()
+  "Skips forward whitespaces and newlines."
+  (skip-syntax-forward " >"))
+
+(defun swift-mode:incomplete-comment-p ()
+  (and (nth 4 (syntax-ppss))
+       (save-excursion
+         (goto-char (nth 8 (syntax-ppss)))
+         (not (forward-comment 1)))))
+
+(defun swift-mode:indent-new-comment-line (&optional soft)
+  "Break the line at the point and indent the new line.
+
+If the point is inside a comment, continue the comment. If the comment is a
+multiline comment, close the previous comment and start new one if
+`comment-multi-line' is nil."
+  (interactive)
+  (let* ((parser-state (syntax-ppss))
+         (is-inside-comment (nth 4 parser-state))
+         (is-single-line-comment (eq (nth 7 parser-state) 1))
+         (comment-beginning-position (nth 8 parser-state))
+         (space-after-asterisk
+          (if swift-mode:insert-space-after-asterisk-in-comment " " "")))
+    (delete-horizontal-space)
+    (if soft (insert-and-inherit ?\n) (newline 1))
+    (delete-horizontal-space)
+
+    (when is-inside-comment
+      (insert-before-markers-and-inherit
+       (cond
+        (is-single-line-comment
+         "// ")
+
+        (comment-multi-line
+         (save-excursion
+           (beginning-of-line)
+           (forward-char -1)
+           (beginning-of-line)
+           (if (<= (point) comment-beginning-position)
+               ;; The cursor was on the 2nd line of the comment.
+               ;; Uses default prefix.
+               (concat "*" space-after-asterisk)
+             ;; The cursor was on the 3nd or following lines of
+             ;; the comment.
+             ;; Use the prefix of the previous line.
+             (back-to-indentation)
+             (if (looking-at "\\*+")
+                 (concat (match-string-no-properties 0) space-after-asterisk)
+               ""))))
+
+        (t
+         (backward-char)
+         (insert-before-markers-and-inherit " */")
+         (forward-char)
+         (save-excursion
+           (goto-char comment-beginning-position)
+           (looking-at "/\\*+")
+           (concat (match-string-no-properties 0) space-after-asterisk))))))
+    (indent-according-to-mode)
+
+    ;; Closes incomplete multiline comment.
+    (when (and swift-mode:auto-close-multiline-comment
+               (not is-single-line-comment)
+               (swift-mode:incomplete-comment-p))
+      (save-excursion
+        (end-of-line)
+        (if soft (insert-and-inherit ?\n) (newline 1))
+        (insert-before-markers-and-inherit "*/")
+        (indent-according-to-mode)))))
+
+(defun swift-mode:post-self-insert ()
+  (cond
+   ((and
+     (= last-command-event ?*)
+     (nth 4 (syntax-ppss))
+     (save-excursion (backward-char) (skip-syntax-backward " ") (bolp)))
+    (when swift-mode:insert-space-after-asterisk-in-comment
+      (insert-before-markers-and-inherit " "))
+    (indent-according-to-mode))
+   ((and
+     (= last-command-event ?/)
+     swift-mode:fix-comment-close
+     (nth 4 (syntax-ppss))
+     (save-excursion
+       (let ((pos (point)))
+         (beginning-of-line)
+         (and
+          (looking-at "^[      ]*\\*[  ]+/")
+          (eq (match-end 0) pos)
+          (swift-mode:incomplete-comment-p)))))
+    (backward-char)
+    (delete-horizontal-space)
+    (forward-char))))
+
+(provide 'swift-mode-indent)
+
+;;; swift-mode-indent.el ends here
diff --git a/swift-mode-lexer.el b/swift-mode-lexer.el
new file mode 100644
index 0000000..d5c1ed8
--- /dev/null
+++ b/swift-mode-lexer.el
@@ -0,0 +1,883 @@
+;;; swift-mode-lexer.el --- Major-mode for Apple's Swift programming language, 
lexer. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2014-2016 taku0, Chris Barrett, Bozhidar Batsov, Arthur 
Evstifeev
+
+;; Authors: taku0 (http://github.com/taku0)
+;;       Chris Barrett <chris.d.barrett@me.com>
+;;       Bozhidar Batsov <bozhidar@batsov.com>
+;;       Arthur Evstifeev <lod@pisem.net>
+;;
+;; Version: 2.1
+;; Package-Requires: ((emacs "24.4"))
+;; Keywords: languages swift
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Routines for Swift tokens
+
+;; Token is a tuple consists of:
+;;
+;; - Token type
+;; - Token text
+;; - Start position (inclusive)
+;; - End position (exclusive)
+
+;;; Code:
+
+(declare-function swift-mode:backward-sexps-until "swift-mode-indent.el"
+                  (token-types
+                   &optional
+                   stop-at-eol-token-types
+                   stop-at-bol-token-types))
+
+(defun swift-mode:token (type text start end)
+  "Construct and returns a token."
+  (list type text start end))
+
+(defun swift-mode:token:type (token)
+  "Return the type of TOKEN."
+  (nth 0 token))
+
+(defun swift-mode:token:text (token)
+  "Return the text of TOKEN."
+  (nth 1 token))
+
+(defun swift-mode:token:start (token)
+  "Return the start position of TOKEN."
+  (nth 2 token))
+
+(defun swift-mode:token:end (token)
+  "Return the end position of TOKEN."
+  (nth 3 token))
+
+;; Token types is one of the follwing symbols:
+;;
+;; - prefix-operator (including try, try?, and try!)
+;; - postfix-operator
+;; - binary-operator (including as, as?, as!, is, =, ., and ->)
+;; - identifier (including keywords, numbers, implicit parameters, and unknown 
tokens)
+;; - [
+;; - ]
+;; - {
+;; - }
+;; - (
+;; - )
+;; - ,
+;; - ;
+;; - implicit-;
+;; - < (as an angle bracket)
+;; - > (as an angle bracket)
+;; - typing-: (colon for supertype declaration or type declaration of let or 
var)
+;; - case-: (colon for case or default label)
+;; - : (part of conditional operator, key-value separator, label-statement 
separator)
+;; - anonymous-function-parameter-in ("in" after anonymous function parameter)
+;; - outside-of-buffer
+;;
+;; Additionaly, `swift-mode:backward-token-or-list' may return a parenthesized
+;; expression as a token with one of the following types:
+;; - ()
+;; - []
+;; - {}
+;; - <>
+
+;;; Syntax table
+
+(defconst swift-mode:syntax-table
+  (let ((table (make-syntax-table)))
+    ;; Whitespace characters
+    ;; Word constituents
+
+    ;; Symbol constituents
+    (modify-syntax-entry ?_ "_" table)
+    (modify-syntax-entry ?$ "_" table)
+    (modify-syntax-entry ?@ "_" table)
+    (modify-syntax-entry ?# "_" table)
+
+    ;; Punctuation characters
+    ;;
+    ;; Operators
+    ;; 
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID410
+    ;; TODO Unicode operators
+    ;;
+    ;; / and * will be overridden below as comment delimiters
+    (mapc (lambda (c) (modify-syntax-entry c "." table)) "/=-+!*%<>&|^~?.")
+    ;; Separators
+    (mapc (lambda (c) (modify-syntax-entry c "." table)) ",;")
+
+    ;; Parenthesis characters
+    (modify-syntax-entry ?\( "()" table)
+    (modify-syntax-entry ?\) ")(" table)
+    (modify-syntax-entry ?\[ "(]" table)
+    (modify-syntax-entry ?\] ")[" table)
+    (modify-syntax-entry ?{ "(}" table)
+    (modify-syntax-entry ?} "){" table)
+
+    ;; String quotes
+    (modify-syntax-entry ?\" "\"" table)
+    (modify-syntax-entry ?` "\"" table)
+
+    ;; Escape-syntax characters
+    (modify-syntax-entry ?\\ "\\" table)
+
+    ;; Character quotes
+    ;; Paired delimiters
+    ;; Expression prefixes
+
+    ;; Comments
+    (modify-syntax-entry ?/  ". 124b" table)
+    (modify-syntax-entry ?*  ". 23n"  table)
+    (modify-syntax-entry ?\n "> b"    table)
+    (modify-syntax-entry ?\r "> b"    table)
+
+    table))
+
+
+;;; Lexers
+
+(defun swift-mode:implicit-semi-p ()
+  "Return t if the cursor is after the end of a statement."
+  (let
+      ((previous-token (save-excursion
+                         (swift-mode:backquote-identifier-if-after-dot
+                          (swift-mode:backward-token-simple))))
+       (next-token (save-excursion
+                     (swift-mode:backquote-identifier-if-after-dot
+                      (swift-mode:forward-token-simple)))))
+    ;; If the cursor is on the empty line, pretend an identifier is the line.
+    (when (and
+           (< (swift-mode:token:end previous-token) (line-beginning-position))
+           (< (line-end-position) (swift-mode:token:start next-token)))
+      (setq next-token (swift-mode:token 'identifier "" (point) (point))))
+    (cond
+     ((or
+       ;; Supresses implicit semicolon around binary operators and separators.
+       (memq (swift-mode:token:type previous-token)
+             '(binary-operator \; \, :))
+       (memq (swift-mode:token:type next-token)
+             '(binary-operator \; \, :))
+
+       ;; Supresses implicit semicolon after try, try?, and try!.
+       (member (swift-mode:token:text previous-token)
+               '("try" "try?" "try!"))
+
+       ;; Suppress implicit semicolon after open brackets or before close
+       ;; brackets.
+       (memq (swift-mode:token:type previous-token) '({ \( \[))
+       (memq (swift-mode:token:type next-token) '(} \) \]))
+
+       ;; Suppress implicit semicolon around keywords that cannot start or end
+       ;; statements.
+       (member (swift-mode:token:text previous-token)
+               '("inout" "throws" "rethrows" "in" "where"))
+       (member (swift-mode:token:text next-token)
+               '("inout" "throws" "rethrows" "in" "where")))
+      nil)
+
+     ;; Inserts implicit semicolon around #... directives.
+     ;;
+     ;; Note that we cannot split #if line; the following code is not allowed.
+     ;;
+     ;; #if
+     ;;   true
+     ;; #end if
+     ((and
+       (or
+        (string-prefix-p "#" (swift-mode:token:text previous-token))
+        (string-prefix-p "#" (swift-mode:token:text next-token)))
+       (not (member (swift-mode:token:text previous-token)
+                    '("#file" "#line" "column" "#function")))
+       (not (member (swift-mode:token:text next-token)
+                    '("#file" "#line" "column" "#function"))))
+      t)
+
+     ;; Suppress implicit semicolon after modifiers.
+     ((member (swift-mode:token:text previous-token)
+              '("indirect" "convenience" "dynamic" "final" "infix" "lazy"
+                "mutating" "nonmutating" "optional" "override" "postfix"
+                "prefix" "required" "static" "unowned" "weak" "internal"
+                "private" "public" "open" "fileprivate"))
+      nil)
+
+     ;; internal(set) private(set) public(set) open(set) fileprivate(set)
+     ;; unowned(safe) unowned(unsafe)
+     ((and
+       (eq (swift-mode:token:type previous-token) '\))
+       (save-excursion
+         (and
+          (eq (swift-mode:token:type (swift-mode:backward-token-simple)) '\))
+          (member (swift-mode:token:text (swift-mode:backward-token-simple))
+                  '("set" "safe" "unsafe"))
+          (eq (swift-mode:token:type (swift-mode:backward-token-simple)) '\()
+          (member (swift-mode:token:text
+                   (swift-mode:backquote-identifier-if-after-dot
+                    (swift-mode:backward-token-simple)))
+                  '("unowned" "internal" "private" "public" "open"
+                    "fileprivate")))))
+      nil)
+
+     ;; Insert implicit semicolon before modifiers.
+     ;;
+     ;; Preceding mofidiers takes precedence over this.
+     ((member (swift-mode:token:text next-token)
+              '("indirect" "convenience" "dynamic" "final" "infix" "lazy"
+                "mutating" "nonmutating" "optional" "override" "postfix"
+                "prefix" "required" "static" "unowned" "weak" "internal"
+                "private" "public" "open" "fileprivate"))
+      t)
+
+     ;; Inserts implicit semicolon around keywords that forms single keyword
+     ;; statements.
+     ((or
+       (member (swift-mode:token:text previous-token)
+               '("break" "continue" "fallthrough"))
+       (member (swift-mode:token:text next-token)
+               '("break" "continue" "fallthrough")))
+      t)
+
+     ;; Suppress implicit semicolon after keywords that cannot end statements.
+     ((member (swift-mode:token:text previous-token)
+              '("while" "for" "switch" "case" "default" "catch" "if" "guard"
+                "let" "var" "throw" "import" "return"))
+      nil)
+
+     ;; Inserts implicit semicolon before keywords that starts a new
+     ;; statement.
+     ((member (swift-mode:token:text next-token)
+              '("for" "repeat" "switch"  "case" "default" "defer" "do" "if"
+                "guard" "let" "var" "throw" "import" "return"))
+      t)
+
+     ;; Inserts implicit semicolon before `while' unless it is part of
+     ;; `repeat...while'.
+     ((equal (swift-mode:token:text next-token) "while")
+      (save-excursion
+        (not
+         (and
+          (eq (swift-mode:token:type previous-token) '\})
+          (progn
+            (backward-list)
+            (equal (swift-mode:token:text
+                    (swift-mode:backquote-identifier-if-after-dot
+                     (swift-mode:backward-token-simple)))
+                   "repeat"))))))
+
+     ;; Inserts implicit around else
+     ((or
+       (equal (swift-mode:token:text previous-token) "else")
+       (equal (swift-mode:token:text next-token) "else"))
+      t)
+
+     ;; Supress implicit semicolon after attributes.
+     ((string-prefix-p "@" (swift-mode:token:text previous-token)) nil)
+
+     ;; Inserts implicit semicolon before keywords that behave like method
+     ;; names.
+     ((member (swift-mode:token:text next-token)
+              '("get" "set" "willSet" "didSet" "subscript" "init" "deinit"))
+      t)
+
+     ;; Suppress implicit semicolon after keywords that behave like method
+     ;; names.
+     ;;
+     ;; Note that binary operators take precedence over this:
+     ;;
+     ;; self . // not insert semicolon here
+     ;;   init
+     ((member (swift-mode:token:text previous-token)
+              '("set" "willSet" "didSet" "subscript" "init" "deinit"))
+      nil)
+
+     ;; Suppress implicit semicolon after declaration starters.
+     ((member (swift-mode:token:text previous-token)
+              '("class" "struct" "protocol" "enum" "extension" "func"
+                "typealias""associatedtype" "precedencegroup" "operator"))
+      nil)
+
+     ;; Inserts implicit semicolon before declaration starters.
+     ;; Modifiers take precedence over this.
+     ;;
+     ;; Notes that class-requirement is handled by the `:' rule above:
+     ;;
+     ;; protocol Foo: // not insert semicolon here
+     ;;   class
+     ;;
+     ;; `protocol' is handled by the next rule
+     ((member (swift-mode:token:text next-token)
+              '("class" "struct" "enum" "extension" "func" "typealias"
+                "associatedtype" "precedencegroup"))
+      t)
+
+     ;; Inserts implicit semicolon before protocol unless it is followed by <.
+     ((equal "protocol" (swift-mode:token:text next-token))
+      (not (equal (swift-mode:token:text
+                   (save-excursion
+                     (swift-mode:forward-token-simple)
+                     (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
+    ;; line.
+    ;; 
https://github.com/apple/swift/blob/8d4b1cc3c47c7624d57f188d5b227152ccb03163/lib/Parse/ParseExpr.cpp#L1525
+    ;;
+    ;; Note that the following pattern (i.e. after binary-operator) is handled
+    ;; by above case.
+    ;;
+    ;; let x =
+    ;;   [
+    ;;     1
+    ;;   ]
+    ((eq (swift-mode:token:type next-token) '\[) t)
+
+    ;; Inserts implicit semicolon before open parenthesis.
+    ;;
+    ;; Open parenthesis for function arguments cannot appear at the start of a
+    ;; line.
+    ;; 
https://github.com/apple/swift/blob/8d4b1cc3c47c7624d57f188d5b227152ccb03163/lib/Parse/ParseExpr.cpp#L1251
+    ;;
+    ;; Note that the following pattern (i.e. after binary-operator) is handled
+    ;; by above case.
+    ;;
+    ;; let x =
+    ;;   (
+    ;;     1
+    ;;   )
+    ((eq (swift-mode:token:type next-token) '\() t)
+
+    ;; Inserts semicolon before open curly bracket.
+    ;;
+    ;; Open curly bracket may continue the previous line, but we do not indent
+    ;; there. For example, the code below is parsed as `(foo() { x in ... })'
+    ;; by the Swift compiler, but we indent it like `foo(); { x in ... }'.
+    ;;
+    ;; foo()
+    ;; { // does not indent here
+    ;;   x in
+    ;;   ...
+    ;; }
+    ((eq (swift-mode:token:type next-token) '\{) t)
+
+    ;; Otherwise, inserts implicit semicolon.
+    (t t))))
+
+(defun swift-mode:type-colon-p ()
+  "Return t if a colon at the cursor is the colon for type annotation.
+
+That is supertype declaration or type declaration of let or var."
+  (save-excursion
+    (let ((previous-token (swift-mode:backward-token-simple)))
+      ;; class Foo<T>: Bar ← type colon
+      ;; class Foo<T> : Bar ← type colon
+      ;; class Foo<T where T: Bar<[(Int, String)]>> : Bar ← type colon
+      ;; case Foo: ← not a type colon
+      ;; case Foo where foo: ← not a type colon
+      ;; default: ← not a type colon
+      ;; foo ? bar : baz ← not a type colon
+      ;; [
+      ;;   foo: ← not a type colon
+      ;;     bar
+      ;; ]
+      ;; foo(bar, baz: baz) ← not a type colon
+      (or
+       (eq (swift-mode:token:type previous-token) '>)
+       ;; class Foo: ← type colon
+       ;; extension Foo: ← type colon
+       ;; let foo: ← type colon
+       ;; var foo: ← type colon
+       ;; protocol Foo {
+       ;;   typealias Bar: Baz ← type colon
+       ;; }
+       (member (swift-mode:token:text
+                (swift-mode:backquote-identifier-if-after-dot
+                 (swift-mode:backward-token-simple)))
+               '("class" "extension" "enum" "struct" "protocol" "typealias"
+                 "associatedtype" "let" "var"))))))
+
+(defun swift-mode:case-colon-p ()
+  "Return t if a colon at the cursor is the colon for case or default label."
+  (save-excursion
+    (member
+     ;; This function can be confused by conditional operator.
+     ;;
+     ;;
+     ;; switch foo {
+     ;; case let x where x is Foo ?
+     ;;                    a : // This function should return nil but it
+     ;;                       // actually retuns t.
+     ;;                    b: // This function should return t but it
+     ;;                       // actually return nil.
+     ;;   let y = a ? b : c // This function returns nil correctly for this.
+     ;; }
+
+     ;; FIXME: mutual dependency
+     (swift-mode:token:text
+      (swift-mode:backward-sexps-until
+       '(implicit-\; \; { \( \[ "case" "default" 'case-:)))
+     '("case" "default"))))
+
+(defun swift-mode:anonyous-parameter-in-p ()
+  "Return t if a 'in' token at the cursor is for anonymous function 
parameters."
+  (save-excursion
+    (eq
+     ;; FIXME: mutual dependency
+     (swift-mode:token:type (swift-mode:backward-sexps-until
+                             '(\; { \( \[ "for")))
+     '{)))
+
+(defun swift-mode:fix-operator-type (token)
+  "Return new operator token with proper token type."
+  ;; Operator type (i.e. prefix, postfix, infix) is decided from spaces or
+  ;; comments around the operator.
+  ;; 
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID410
+  ;; 
https://github.com/apple/swift-evolution/blob/master/proposals/0037-clarify-comments-and-operators.md
+  (let*
+      ((text (swift-mode:token:text token))
+       (start (swift-mode:token:start token))
+       (end (swift-mode:token:end token))
+       (has-preceding-space (or
+                             (= start (point-min))
+                             (memq (char-syntax (char-before start)) '(?  ?>))
+                             (nth 4 (save-excursion
+                                      (syntax-ppss (1- start))))))
+       (has-following-space (or
+                             (= end (point-max))
+                             (memq (char-syntax (char-after end)) '(?  ?<))
+                             (save-excursion (goto-char end)
+                                             (looking-at "/\\*\\|//"))
+                             (= (char-after end) ?\C-j)))
+       (has-following-dot (eq (char-after end) ?.))
+       (is-declaration (save-excursion
+                         ;; i.e.
+                         ;; func +++(x1: X, x2: X)
+                         ;; or operator declarations.
+                         (goto-char start)
+                         (member
+                          (swift-mode:token:text
+                           (swift-mode:backquote-identifier-if-after-dot
+                            (swift-mode:backward-token-simple)))
+                          '("func" "operator"))))
+       (type
+        (cond
+         (is-declaration 'identifier)
+         ((member text '("try" "try?" "try!")) 'prefix-operator)
+         ((equal text ".") 'binary-operator)
+         ((and has-preceding-space has-following-space) 'binary-operator)
+         (has-preceding-space 'prefix-operator)
+         ((or has-following-space has-following-dot) 'postfix-operator)
+         (t 'binary-operator))))
+    (swift-mode:token type text start end)))
+
+(defun swift-mode:backquote-identifier-if-after-dot (token)
+  "Backquote identifiers including keywords if it is after dot.
+
+See SE-0071:
+https://github.com/apple/swift-evolution/blob/master/proposals/0071-member-keywords.md";
+  (if (and (string-match "^[a-z]" (swift-mode:token:text token))
+           (save-excursion
+             (goto-char (swift-mode:token:start token))
+             (equal (swift-mode:token:text (swift-mode:backward-token-simple))
+                    ".")))
+      (swift-mode:token
+       'identifier
+       (concat "`" (swift-mode:token:text token) "`")
+       (swift-mode:token:start token)
+       (swift-mode:token:end token))
+    token))
+
+(defun swift-mode:forward-token ()
+  "Move point forward to the next position of the end of a token.
+
+Return the token object.  If no more tokens available, return a token with
+type `out-of-buffer'"
+
+  (let ((pos (point)))
+    (forward-comment (point-max))
+    (cond
+     ;; Outside of buffer
+     ((eobp)
+      (swift-mode:token 'outside-of-buffer "" (point) (point)))
+
+     ;; Implicit semicolon
+     ((and (< pos
+              (save-excursion
+                (swift-mode:goto-non-comment-bol)
+                (point)))
+           (save-excursion (goto-char pos) (swift-mode:implicit-semi-p)))
+
+      (swift-mode:token 'implicit-\;
+                        (buffer-substring-no-properties pos (point))
+                        pos
+                        (point)))
+
+     ;; Colon
+     ((eq (char-after) ?:)
+      (swift-mode:token (cond
+                         ((swift-mode:type-colon-p) 'typing-:)
+                         ((swift-mode:case-colon-p) 'case-:)
+                         (t ':))
+                        ":"
+                        (progn (forward-char) (1- (point)))
+                        (point)))
+
+     (t
+      (let ((token (swift-mode:forward-token-simple)))
+        (setq token (swift-mode:backquote-identifier-if-after-dot token))
+
+        (when (and (equal (swift-mode:token:text token) "in")
+                   (save-excursion
+                     (goto-char (swift-mode:token:start token))
+                     (swift-mode:anonyous-parameter-in-p)))
+          (setq token
+                (swift-mode:token
+                 'anonymous-function-parameter-in
+                 "in"
+                 (swift-mode:token:start token)
+                 (swift-mode:token:end token))))
+
+        token)))))
+
+(defun swift-mode:forward-token-simple ()
+  "Like `swift-mode:forward-token' without recursion, and never produces
+`implicit-;' or `type-:'."
+  (forward-comment (point-max))
+  (cond
+   ;; Outside of buffer
+   ((eobp)
+    (swift-mode:token 'outside-of-buffer "" (point) (point)))
+
+   ;; Separators and parentheses
+   ((memq (char-after) '(?, ?\; ?\{ ?\} ?\[ ?\] ?\( ?\) ?:))
+    (forward-char)
+    (swift-mode:token (intern (string (char-before)))
+                      (string (char-before))
+                      (1- (point))
+                      (point)))
+
+   ;; Open angle bracket for type parameters
+   ;;
+   ;; We use a heuristic: spaces are inserted around inequality sign, but not
+   ;; for angle bracket, and a type paramer starts with an upper case
+   ;; character, a square bracket, a parenthesis, or keyword 'protocol'.
+   ((and (eq (char-after) ?<)
+         (looking-at "<\\([[:upper:]\\[[(]\\|protocol\\)"))
+    (forward-char)
+    (swift-mode:token '< "<" (1- (point)) (point)))
+
+   ;; Close angle bracket for type parameters
+   ;;
+   ;; Close angle bracket follows identifier, a square bracket, a parenthesis,
+   ;; or another another bracket (e.g. Foo<Bar<[(Int, String)]>>)
+   ((and (eq (char-after) ?>)
+         (save-excursion
+           ;; You know that regular language can be reversed. Thus you may
+           ;; think that `looking-back' reverse the given regexp and scan
+           ;; chars backwards. Nevertheless, `looking' function does not
+           ;; do that. It just repeats `looking-at' with decrementing start
+           ;; position until it succeeds. The document says that it is not
+           ;; recommended to use. So using `skip-chars-backward',
+           ;; `skip-syntax-backward', and `looking-at' here.
+           (skip-chars-backward "])>")
+           (skip-syntax-backward "w_")
+           (looking-at "[[:upper:]_]")))
+    (forward-char)
+    (swift-mode:token '> ">" (1- (point)) (point)))
+
+   ;; Operator (other than as, try, or is)
+   ;;
+   ;; Operators starts with a dot can contains dots. Other operators cannot
+   ;; contain dots.
+   ;;
+   ;; 
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/dot-operator-head
+   ((looking-at "[-/=+!*%<>&|^~?]+\\|[.][-./=+!*%<>&|^~?]*")
+    (let*
+        ((text (match-string-no-properties 0))
+         (start (match-beginning 0))
+         (end (match-end 0)))
+      (when (string-match ".*/\\*\\|.*//" text)
+        ;; e.g. +++/* */ or +++//
+        (setq end
+              (- end
+                 (- (length text) (- (match-end 0) 2))))
+        (setq text (substring text 0 (- (match-end 0) 2))))
+      (goto-char end)
+      (swift-mode:fix-operator-type
+       (swift-mode:token nil text start end))))
+
+   ;; String and backquoted identifer
+   ((memq (char-after) '(?\" ?`))
+    (let ((pos-after-comment (point)))
+      (goto-char (scan-sexps (point) 1))
+      (swift-mode:token
+       'identifier
+       (buffer-substring-no-properties pos-after-comment (point))
+       pos-after-comment
+       (point))))
+
+   ;; Other tokens including identifers, implicit parameters, keywords, and
+   ;; numbers
+   (t
+    (let*
+        ((pos-after-comment (point))
+         (text
+          (cond
+           ;; Identifers, implicit parameters, keywords, numbers
+           ;;
+           ;; Note: syntax class _ includes #, @, and $.
+           ((memq (char-syntax (char-after)) '(?w ?_))
+            (progn (forward-symbol 1)
+                   (buffer-substring-no-properties pos-after-comment
+                                                   (point))))
+           ;; Unknown character type. Treats as a single-letter token.
+           (t (forward-char) (string (char-before))))))
+      (cond
+       ((member text '("as" "try"))
+        ;; as?, as!, try?, or try!
+        (when (member (char-after) '(?? ?!))
+          (forward-char)
+          (setq text (concat text (list (char-before)))))
+        (swift-mode:token (if (member text '("as" "as?" "as!"))
+                              'binary-operator
+                            'prefix-operator)
+                          text
+                          (- (point) (length text))
+                          (point)))
+       ((equal text "is")
+        (swift-mode:token 'binary-operator
+                          text
+                          (- (point) (length text))
+                          (point)))
+       (t
+        (swift-mode:token 'identifer
+                          text
+                          (- (point) (length text))
+                          (point))))))))
+
+(defun swift-mode:backward-token ()
+  "Move point backward to the previous position of the end of a token.
+
+Return the token object.  If no more tokens available, return a token with
+type `out-of-buffer'."
+
+  (let ((pos (point)))
+    (forward-comment (- (point)))
+    (cond
+     ;; Outside of buffer
+     ((bobp)
+      (swift-mode:token 'outside-of-buffer "" (point) (point)))
+
+     ;; Implicit semicolon
+     ((and (< (save-excursion
+                (swift-mode:goto-non-comment-eol)
+                (point))
+              pos)
+           (save-excursion (goto-char pos) (swift-mode:implicit-semi-p)))
+      (swift-mode:token 'implicit-\;
+                        (buffer-substring-no-properties (point) pos)
+                        (point)
+                        pos))
+
+     ;; Colon
+     ((eq (char-before) ?:)
+      (backward-char)
+      (swift-mode:token (cond
+                         ((swift-mode:type-colon-p) 'typing-:)
+                         ((swift-mode:case-colon-p) 'case-:)
+                         (t ':))
+                        ":"
+                        (point)
+                        (1+ (point))))
+
+     (t
+      (let ((token (swift-mode:backward-token-simple)))
+        (setq token (swift-mode:backquote-identifier-if-after-dot token))
+
+        (when (and (equal (swift-mode:token:text token) "in")
+                   (save-excursion
+                     (goto-char (swift-mode:token:start token))
+                     (swift-mode:anonyous-parameter-in-p)))
+          (setq token
+                (swift-mode:token
+                 'anonymous-function-parameter-in
+                 "in"
+                 (swift-mode:token:start token)
+                 (swift-mode:token:end token))))
+        token)))))
+
+(defun swift-mode:backward-token-simple ()
+  "Like `swift-mode:backward-token' without recursion, and never produces
+`implicit-;' or `type-:'."
+  (forward-comment (- (point)))
+  (cond
+   ;; Outside of buffer
+   ((bobp)
+    (swift-mode:token 'outside-of-buffer "" (point) (point)))
+
+   ;; Separators and parentheses
+   ((memq (char-before) '(?, ?\; ?\{ ?\} ?\[ ?\] ?\( ?\) ?:))
+    (backward-char)
+    (swift-mode:token (intern (string (char-after)))
+                      (string (char-after))
+                      (point)
+                      (1+ (point))))
+
+   ;; >! or >?
+   ((and (memq (char-before) '(?! ??))
+         (eq (char-before (1- (point))) ?>)
+         (save-excursion
+           (backward-char)
+           (eq (swift-mode:token:type (swift-mode:backward-token-simple))
+               '>)))
+    (backward-char)
+    (swift-mode:token (intern (string (char-after)))
+                      (string (char-after))
+                      (point)
+                      (1+ (point))))
+
+   ;; Open angle bracket for type parameters
+   ;;
+   ;; We use a heuristic: spaces are inserted around inequality sign, but not
+   ;; for angle bracket, and a type paramer starts with an upper case
+   ;; character, a square bracket, a parenthesis, or keyword `protocol'.
+   ((and (eq (char-before) ?<)
+         (looking-at "\\([[:upper:]\\[[(]\\|protocol\\)"))
+    (backward-char)
+    (swift-mode:token '< "<" (point) (1+ (point))))
+
+   ;; Close angle bracket for type parameters
+   ;;
+   ;; Close angle bracket follows identifier, a square bracket, a parenthesis,
+   ;; or another another bracket (e.g. Foo<Bar<[(Int, String)]>>)
+   ((and (eq (char-before) ?>)
+         (save-excursion
+           (skip-chars-backward "])>")
+           (skip-syntax-backward "w_")
+           (looking-at "[[:upper:]_]")))
+    (backward-char)
+    (swift-mode:token '> ">" (point) (1+ (point))))
+
+   ;; Operator (other than as, try, or is)
+   ;;
+   ;; Operators which starts with a dot can contain other dots. Other
+   ;; operators cannot contain dots.
+   ;;
+   ;; 
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/swift/grammar/dot-operator-head
+   ((memq (char-before) '(?. ?- ?/ ?= ?+ ?! ?* ?% ?< ?> ?& ?| ?^ ?~ ??))
+    (let ((point-before-comments (point)))
+      (skip-chars-backward "-./=+!*%<>&|^~?")
+      (cond
+       ((save-excursion
+          (forward-symbol -1)
+          (and (looking-at "\\(as\\|try\\)[?!]")
+               (= point-before-comments (match-end 0))))
+        ;; as?, as!, try?, try!
+        t)
+       ((looking-at "[.][-./=+!*%<>&|^~?]*")
+        ;; e.g. 1 .++++.++++...+. 1
+        t)
+       ((and (looking-at "[-/=+!*%<>&|^~?]+")
+             (<= point-before-comments (match-end 0)))
+        ;; e.g. 1 +++++++++ 1
+        t)
+       (t
+        ;; e.g. 1+++++...++++1, that is (1+++++) ...++++ 1
+        (skip-chars-forward "-/=+!*%<>&|^~?")
+        (looking-at "[.][-./=+!*%<>&|^~?]*")))
+      (let*
+          ((start (match-beginning 0))
+           (end (min point-before-comments (match-end 0)))
+           (text (substring (match-string-no-properties 0) 0 (- end start))))
+        (goto-char start)
+        (swift-mode:fix-operator-type
+         (swift-mode:token nil text start end)))))
+
+   ;; String and backquoted identifer
+   ((memq (char-before) '(?\" ?`))
+    (let ((pos-before-comment (point)))
+      (goto-char (scan-sexps (point) -1))
+      (swift-mode:token
+       'identifier
+       (buffer-substring-no-properties (point) pos-before-comment)
+       (point)
+       pos-before-comment)))
+
+   ;; Other tokens including identifers, implicit parameters, keywords, and
+   ;; numbers
+   (t
+    (let*
+        ((pos-before-comment (point))
+         (text
+          (cond
+           ;; Identifers, implicit parameters, keywords, numbers
+           ;;
+           ;; Note: syntax class _ includes #, @, and $.
+           ((memq (char-syntax (char-before)) '(?w ?_))
+            (progn (forward-symbol -1)
+                   (buffer-substring-no-properties (point)
+                                                   pos-before-comment)))
+           ;; Unknown character type. Treats as a single-letter token.
+           (t (backward-char) (string (char-after))))))
+      (cond
+       ((member text '("is" "as"))
+        (swift-mode:token 'binary-operator
+                          text
+                          (point)
+                          (+ (point) (length text))))
+       ((equal text "try")
+        (swift-mode:token 'prefix-operator
+                          text
+                          (point)
+                          (+ (point) (length text))))
+       (t
+        (swift-mode:token 'identifier
+                          text
+                          (point)
+                          (+ (point) (length text)))))))))
+
+(defun swift-mode:goto-non-comment-bol ()
+  "Back to the beginning of line that is not inside a comment."
+  (beginning-of-line)
+  (while (nth 4 (syntax-ppss))
+    ;; The cursor is in a comment. Backs to the beginning of the comment.
+    (goto-char (nth 8 (syntax-ppss)))
+    (beginning-of-line)))
+
+(defun swift-mode:goto-non-comment-eol ()
+  "Proceed to the end of line that is not inside a comment.
+
+If this line ends with a single-line comment, goto just before the comment."
+  (end-of-line)
+  (while (nth 4 (syntax-ppss))
+    ;; The cursor is in a comment.
+    (if (eq (nth 4 (syntax-ppss)) t)
+        ;; This ia a single-line comment
+        ;; Back to the beginning of the comment.
+        (goto-char (nth 8 (syntax-ppss)))
+      ;; This is a multiline comment
+      ;; Proceed to the end of the comment.
+      (goto-char (nth 8 (syntax-ppss)))
+      (forward-comment 1)
+      (end-of-line))))
+
+(provide 'swift-mode-lexer)
+
+;;; swift-mode-lexer.el ends here
diff --git a/swift-mode-repl.el b/swift-mode-repl.el
new file mode 100644
index 0000000..e4198d8
--- /dev/null
+++ b/swift-mode-repl.el
@@ -0,0 +1,108 @@
+;;; swift-mode-repl.el --- Run Apple's Swift processes in Emacs buffers -*- 
lexical-binding: t -*-
+
+;; Copyright (C) 2014-2016 taku0, Chris Barrett, Bozhidar Batsov, Arthur 
Evstifeev
+
+;; Authors: taku0 (http://github.com/taku0)
+;;       Chris Barrett <chris.d.barrett@me.com>
+;;       Bozhidar Batsov <bozhidar@batsov.com>
+;;       Arthur Evstifeev <lod@pisem.net>
+;;
+;; Version: 2.1
+;; Package-Requires: ((emacs "24.4"))
+;; Keywords: languages swift
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Run Apple's Swift processes in Emacs buffers.
+
+;;; Code:
+
+(require 'comint)
+
+(defcustom swift-mode:repl-executable
+  "xcrun swift"
+  "Path to the Swift CLI."
+  :type 'string
+  :group 'swift
+  :safe 'stringp)
+
+(defvar swift-mode:repl-buffer nil
+  "Stores the name of the current swift REPL buffer, or nil.")
+
+;;;###autoload
+(defun swift-mode:run-repl (cmd &optional dont-switch)
+  "Run a Swift REPL process.
+It input and output via buffer `*CMD*' where CMD is replaced with the CMD 
given.
+If there is a process already running in `*CMD*', switch to that buffer.
+With argument CMD allows you to edit the command line (default is value
+of `swift-mode:repl-executable').  This function updates the buffer local
+variable `swift-mode:repl-executable' with the given CMD, so it will be used
+as the default value for the next invocatoin in the current buffer.
+With DONT-SWITCH cursor will stay in current buffer.
+Runs the hook `swift-repl-mode-hook' \(after the `comint-mode-hook' is run).
+\(Type \\[describe-mode] in the process buffer for a list of commands.)"
+
+  (interactive
+   (list (if current-prefix-arg
+             (read-string "Run swift REPL: " swift-mode:repl-executable)
+           swift-mode:repl-executable)))
+  (unless (comint-check-proc (concat "*" cmd "*"))
+    (save-excursion
+      (let ((cmdlist (split-string cmd)))
+        (set-buffer
+         (apply 'make-comint cmd (car cmdlist) nil (cdr cmdlist)))
+        (swift-repl-mode))))
+  (setq-local swift-mode:repl-executable cmd)
+  (setq-local swift-mode:repl-buffer (concat "*" cmd "*"))
+  (setq-default swift-mode:repl-buffer swift-mode:repl-buffer)
+  (unless dont-switch
+    (pop-to-buffer swift-mode:repl-buffer)))
+
+;;;###autoload
+(defalias 'run-swift 'swift-mode:run-repl)
+
+;;;###autoload
+(defun swift-mode:send-region (start end)
+  "Send the current region to the inferior swift process.
+START and END define region within current buffer"
+  (interactive "r")
+  (swift-mode:run-repl swift-mode:repl-executable t)
+  (comint-send-region swift-mode:repl-buffer start end)
+  (comint-send-string swift-mode:repl-buffer "\n"))
+
+;;;###autoload
+(defun swift-mode:send-buffer ()
+  "Send the buffer to the Swift REPL process."
+  (interactive)
+  (swift-mode:send-region (point-min) (point-max)))
+
+(define-derived-mode swift-repl-mode comint-mode "Swift REPL"
+  "Major mode for interacting with Swift REPL.
+
+A REPL can be fired up with M-x swift-mode:run-repl or M-x run-swift.
+
+Customization: Entry to this mode runs the hooks on comint-mode-hook and
+swift-repl-mode-hook (in that order).
+
+You can send text to the REPL process from other buffers containing source.
+    swift-mode:send-region sends the current region to the REPL process,
+    swift-mode:send-buffer sends the current buffer to the REPL process.")
+
+(provide 'swift-mode-repl)
+
+;;; swift-mode-repl.el ends here
diff --git a/swift-mode.el b/swift-mode.el
index 206a8e2..0c02e9b 100644
--- a/swift-mode.el
+++ b/swift-mode.el
@@ -1,13 +1,16 @@
 ;;; swift-mode.el --- Major-mode for Apple's Swift programming language. -*- 
lexical-binding: t -*-
 
-;; Copyright (C) 2014-2016 Chris Barrett, Bozhidar Batsov, Arthur Evstifeev
+;; Copyright (C) 2014-2016 taku0, Chris Barrett, Bozhidar Batsov, Arthur 
Evstifeev
 
-;; Authors: Chris Barrett <chris.d.barrett@me.com>
+;; Authors: taku0 (http://github.com/taku0)
+;;       Chris Barrett <chris.d.barrett@me.com>
 ;;       Bozhidar Batsov <bozhidar@batsov.com>
 ;;       Arthur Evstifeev <lod@pisem.net>
-;; Version: 0.5.0-snapshot
+;;
+;; Version: 2.1
 ;; Package-Requires: ((emacs "24.4"))
 ;; Keywords: languages swift
+;; URL: https://github.com/swift-emacs/swift-mode
 
 ;; This file is not part of GNU Emacs.
 
@@ -30,763 +33,28 @@
 
 ;;; Code:
 
-(require 'rx)
-(require 'comint)
-(require 'cl-lib)
+(require 'swift-mode-lexer)
+(require 'swift-mode-indent)
+(require 'swift-mode-font-lock)
+(require 'swift-mode-beginning-of-defun)
+(require 'swift-mode-repl)
 
+;;;###autoload
 (defgroup swift nil
-  "Configuration for swift-mode."
+  "Major-mode for Apple's Swift programming language."
   :group 'languages
-  :prefix "swift-")
-
-(defcustom swift-indent-offset 4
-  "Defines the indentation offset for Swift code."
-  :group 'swift
-  :type 'integer)
-
-(defcustom swift-indent-switch-case-offset 0
-  "Defines the indentation offset for cases in a switch statement."
-  :group 'swift
-  :type 'integer)
-
-(defcustom swift-indent-multiline-statement-offset 2
-  "Defines the indentation offset for multiline statements."
-  :group 'swift
-  :type 'integer
-  :package-version '(swift-mode "0.3.0"))
-
-(defcustom swift-indent-hanging-comma-offset nil
-  "Defines the indentation offset for hanging comma."
-  :group 'swift
-  :type '(choice (const :tag "Use default relative formatting" nil)
-                 (integer :tag "Custom offset"))
-  :package-version '(swift-mode "0.4.0"))
-
-(defcustom swift-repl-executable
-  "xcrun swift"
-  "Path to the Swift CLI."
-  :group 'swift)
-
-;;; Indentation
-
-(require 'smie)
-
-(defconst swift-smie-grammar
-  (smie-prec2->grammar
-   (smie-merge-prec2s
-    (smie-bnf->prec2
-     '((id)
-       (type (type) (type "<T" types "T>") ("[" type "]"))
-       (types (type) (type "," type))
-
-       (class-decl-exp (id) (id ":" types))
-       (decl-exp (id) (id ":" type))
-       (decl-exps (decl-exp) (decl-exp "," decl-exp))
-
-       (assign-exp (decl-exp) (id "=" exp))
-
-       (decl (decl ";" decl))
-       (decl (let-decl) (var-decl))
-       (let-decl
-        ("let" decl-exp)
-        ("let" decl-exp "=" exp))
-       (var-decl
-        ("var" decl-exp)
-        ("var" decl-exp "=" exp))
-
-       (top-level-sts (top-level-st) (top-level-st ";" top-level-st))
-       (top-level-st
-        ("import" type)
-        (decl)
-        ("ACCESSMOD" "class" class-decl-exp "{" class-level-sts "}")
-        ("ACCESSMOD" "protocol" class-decl-exp "{" protocol-level-sts "}")
-        )
-
-       (class-level-sts (class-level-st) (class-level-st ";" class-level-st))
-       (class-level-st
-        (decl)
-        (func))
-
-       (protocol-level-sts (protocol-level-st) (protocol-level-st ";" 
protocol-level-st))
-       (protocol-level-st
-        (decl)
-        (func-decl))
-
-       (func-body (insts) ("return" exp))
-       (func (func-decl "{" func-body "}"))
-       (func-decl ("DECSPEC" "func" func-header)
-                  (func-decl "->" type))
-       (func-header (id "(" func-params ")"))
-       (func-param (decl-exp) (decl-exp "=" id) ("..."))
-       (func-params (func-param "," func-param))
-
-       (insts (inst) (insts ";" insts))
-       (inst (decl)
-             (exp "=" exp)
-             (in-exp)
-             (dot-exp)
-             (dot-exp "{" closure "}")
-             (method-call)
-             (method-call "{" closure "}")
-             ("enum" decl-exp "{" enum-body "}")
-             ("switch" exp "{" switch-body "}")
-             (if-clause)
-             (guard-statement)
-             ("for" for-head "{" insts "}")
-             ("while" exp "{" insts "}"))
-
-       (dot-exp (id "." id))
-
-       (method-call (dot-exp "(" method-args ")"))
-       (method-args (method-arg) (method-args "," method-args))
-       (method-arg (id "{" closure "}") (exp))
-
-       (exp ("[" decl-exps "]"))
-       (in-exp (id "in" exp))
-       (guard-exp (exp "where" exp))
-
-       (enum-case ("ecase" assign-exp)
-                  ("ecase" "(" type ")"))
-       (enum-cases (enum-case) (enum-case ";" enum-case))
-       (enum-body (enum-cases) (insts))
-
-       (case-exps (exp)
-                  (guard-exp)
-                  (case-exps "," case-exps))
-       (case (case-exps "case-:" insts))
-       (switch-body (case) (case "case" case))
-
-       (for-head (in-exp) (op-exp) (for-head ";" for-head))
-
-       (guard-conditional (exp) (let-decl) (var-decl))
-       (guard-statement ("guard" guard-conditional "elseguard" "{" insts "}"))
-
-       (if-conditional (exp) (let-decl))
-       (if-body ("if" if-conditional "{" insts "}"))
-       (if-clause (if-body)
-                  (if-body "elseif" if-conditional "{" insts "}")
-                  (if-body "else" "{" insts "}"))
-
-       (closure (insts) (exp "in" insts) (exp "->" id "in" insts)))
-     ;; Conflicts
-     '((nonassoc "{") (assoc "in") (assoc ",") (assoc ";") (right "=") (right 
":"))
-     '((assoc "in") (assoc "where"))
-     '((assoc ";") (assoc "ecase"))
-     '((assoc "case")))
-
-    (smie-precs->prec2
-     '(
-       (right "*=" "/=" "%=" "+=" "-=" "<<=" ">>=" "&="
-              "^=" "|=" "&&=" "||=" "=")                       ;; Assignment 
(Right associative, precedence level 90)
-       (right "?" ":")                                         ;; Ternary 
Conditional (Right associative, precedence level 100)
-       (left "||")                                             ;; Disjunctive 
(Left associative, precedence level 110)
-       (left "&&")                                             ;; Conjunctive 
(Left associative, precedence level 120)
-       (right "??")                                            ;; Nil 
Coalescing (Right associativity, precedence level 120)
-       (nonassoc "<" "<=" ">" ">=" "==" "!=" "===" "!==" "~=") ;; Comparative 
(No associativity, precedence level 130)
-       (nonassoc "is" "as" "as!" "as?")                        ;; Cast (No 
associativity, precedence level 132)
-       (nonassoc "..<" "...")                                  ;; Range (No 
associativity, precedence level 135)
-       (left "+" "-" "&+" "&-" "|" "^")                        ;; Additive 
(Left associative, precedence level 140)
-       (left "*" "/" "%" "&*" "&/" "&%" "&")                   ;; 
Multiplicative (Left associative, precedence level 150)
-       (nonassoc "<<" ">>")                                    ;; 
Exponentiative (No associativity, precedence level 160)
-       ))
-    )))
-
-(defun verbose-swift-smie-rules (kind token)
-  (let ((value (swift-smie-rules kind token)))
-    (message "%s '%s'; sibling-p:%s parent:%s hanging:%s == %s" kind token
-             (ignore-errors (smie-rule-sibling-p))
-             (ignore-errors smie--parent)
-             (ignore-errors (smie-rule-hanging-p))
-             value)
-    value))
-
-(defvar swift-smie--operators
-  '("*=" "/=" "%=" "+=" "-=" "<<=" ">>=" "&=" "^=" "|=" "&&=" "||="
-   "<" "<=" ">" ">=" "==" "!=" "===" "!==" "~=" "||" "&&"
-   "is" "as" "as!" "as?" "..<" "..."
-   "+" "-" "&+" "&-" "|" "^"
-   "*" "/" "%" "&*" "&/" "&%" "&"
-   "<<" ">>" "??"))
-
-(defvar swift-smie--operators-regexp
-  (regexp-opt swift-smie--operators))
-
-(defvar swift-smie--decl-specifier-regexp
-  "\\(?1:mutating\\|override\\|static\\|unowned\\|weak\\)")
-
-(defvar swift-smie--access-modifier-regexp
-  (regexp-opt '("private" "public" "internal")))
-
-(defun swift-smie--implicit-semi-p ()
-  (save-excursion
-    (not (or (memq (char-before) '(?\{ ?\[ ?, ?. ?: ?= ?\())
-             ;; Checking for operators form for "?" and "!",
-             ;; they can be a part of the type.
-             ;; Special case: is? and as? are operators.
-             (looking-back "[[:space:]][?!]" (- (point) 2) t)
-             ;; ??, is? and as? are operators
-             (looking-back "[?][?]\\|as[?]\\|is[?]" (- (point) 3) t)
-             ;; "in" operator in closure
-             (looking-back "\\bin" (- (point) 3) t)
-             ;; Characters placed on the second line in multi-line expression
-             (save-excursion
-               (forward-comment (buffer-size))
-               (looking-at "[.?:]"))
-             ;; Operators placed on the second line in multi-line expression
-             ;; Should respect here possible comments strict before the 
linebreak
-             (save-excursion
-               (forward-comment (buffer-size))
-               (looking-at swift-smie--operators-regexp))
-
-             (and (looking-back swift-smie--operators-regexp (- (point) 3) t)
-                  ;; Not a generic type
-                  (not (looking-back "[[:upper:]]>" (- (point) 2) t)))
-             ))))
-
-(defun swift-smie--forward-token-debug ()
-  (let ((token (swift-smie--forward-token)))
-    (unless (equal token "")
-      (cl-assert (equal token
-                     (save-excursion (swift-smie--backward-token))) t))
-    token
-    ))
-
-(defun swift-smie--backward-token-debug ()
-  (let ((token (swift-smie--backward-token)))
-    (unless (equal token "")
-      (cl-assert (equal token
-                     (save-excursion (swift-smie--forward-token))) t))
-      token
-    ))
-
-(defconst swift-smie--lookback-max-lines -2
-  "Max number of lines 'looking-back' allowed to scan.
-In some cases we can't avoid reverse lookup and this operation can be slow.
-We try to constraint those lookups by reasonable number of lines.")
-
-(defun swift-smie--forward-token ()
-  (skip-chars-forward " \t")
-  (cond
-   ((and (looking-at "\n\\|\/\/") (swift-smie--implicit-semi-p))
-    (if (eolp) (forward-char 1) (forward-comment 1))
-    ";")
-   (t
-    (forward-comment (point))
-    (cond
-   ((looking-at "{") (forward-char 1) "{")
-   ((looking-at "}") (forward-char 1) "}")
-
-   ((looking-at ",") (forward-char 1) ",")
-   ((looking-at ":") (forward-char 1)
-    ;; look-back until "case", "default", ":", "{", ";"
-    (if (looking-back "\\(case[\n\t ][^:{;]+\\|default[\n\t ]*\\):")
-        "case-:"
-      ":"))
-
-   ((looking-at "->") (forward-char 2) "->")
-
-   ((looking-at "<") (forward-char 1)
-    (if (looking-at "[[:upper:]]") "<T" "<"))
-
-   ((looking-at ">[?!]?")
-    (goto-char (match-end 0))
-    (if (looking-back "[[:space:]]>" 2 t) ">" "T>"))
-
-   ((looking-at swift-smie--decl-specifier-regexp)
-    (goto-char (match-end 1)) "DECSPEC")
-
-   ((looking-at swift-smie--access-modifier-regexp)
-    (goto-char (match-end 0)) "ACCESSMOD")
-
-   ((looking-at "\\<default\\>")
-    (goto-char (match-end 0)) "case")
-
-   ((looking-at "else if")
-    (goto-char (match-end 0)) "elseif")
-
-   (t (let ((tok (smie-default-forward-token)))
-        (cond
-         ((equal tok "case")
-          (if (looking-at "\\([\n\t ]\\|.\\)+?\\(where.*[,]\\|:\\)")
-              "case"
-            "ecase"))
-         ((equal tok "else")
-          (if (looking-back "\\(guard.*\\)" (line-beginning-position) t)
-              "elseguard"
-            "else"))
-         (t tok))))
-   ))
-   ))
-
-(defun swift-smie--backward-token ()
-  (let ((pos (point)))
-    (forward-comment (- (point)))
-    (cond
-     ((and (> pos (line-end-position))
-           (swift-smie--implicit-semi-p))
-      ";")
-
-     ((eq (char-before) ?\{) (backward-char 1) "{")
-     ((eq (char-before) ?\}) (backward-char 1) "}")
-
-     ((eq (char-before) ?,) (backward-char 1) ",")
-     ((eq (char-before) ?:) (backward-char 1)
-      ;; look-back until "case", "default", ":", "{", ";"
-      (if (looking-back "\\(case[\n\t ][^:{;]+\\|default[\n\t ]*\\)")
-          "case-:"
-        ":"))
-
-     ((looking-back "->" (- (point) 2) t)
-      (goto-char (match-beginning 0)) "->")
-
-     ((eq (char-before) ?<) (backward-char 1)
-      (if (looking-at "<[[:upper:]]") "<T" "<"))
-     ((looking-back ">[?!]?" (- (point) 2) t)
-      (goto-char (match-beginning 0))
-      (if (looking-back "[[:space:]]" 1 t) ">" "T>"))
-
-     ((looking-back (regexp-opt swift-mode--type-decl-keywords) (- (point) 9) 
t)
-      (goto-char (match-beginning 0))
-      (match-string-no-properties 0))
-
-     ((looking-back swift-smie--decl-specifier-regexp (- (point) 8) t)
-      (goto-char (match-beginning 1)) "DECSPEC")
-
-     ((looking-back swift-smie--access-modifier-regexp (- (point) 8) t)
-      (goto-char (match-beginning 0)) "ACCESSMOD")
-
-     ((looking-back "\\<default\\>" (- (point) 9) t)
-      (goto-char (match-beginning 0)) "case")
-
-     ((looking-back "else if" (- (point) 7) t)
-      (goto-char (match-beginning 0)) "elseif")
-
-     (t (let ((tok (smie-default-backward-token)))
-          (cond
-           ((equal tok "case")
-            (if (looking-at "\\([\n\t ]\\|.\\)+?\\(where.*[,]\\|:\\)")
-                "case"
-              "ecase"))
-           ((equal tok "else")
-            (if (looking-back "\\(guard.*\\)" (line-beginning-position) t)
-                "elseguard"
-              "else"))
-           (t tok))))
-     )))
-
-(defun swift-smie-rules (kind token)
-  (pcase (cons kind token)
-    (`(:elem . basic) swift-indent-offset)
-
-    (`(:after . ":") 0)
-    (`(:before . ":")
-     (cond
-      ;; Rule for ternary operator in
-      ;; assignment expression.
-      ((and (smie-rule-parent-p "?") (smie-rule-bolp)) 0)
-      ((smie-rule-parent-p ",") (smie-rule-parent swift-indent-offset))
-      ;; Rule for the class definition.
-      ((smie-rule-parent-p "class") (smie-rule-parent swift-indent-offset))))
-
-    ;; Indentation rules for switch statements
-    (`(:before . "case")
-     (if (smie-rule-parent-p "{")
-         (smie-rule-parent swift-indent-switch-case-offset)))
-    (`(:before . "case-:") (smie-rule-parent swift-indent-offset))
-
-    ;; Apply swift-indent-multiline-statement-offset only if
-    ;; - if is a first token on the line
-    (`(:before . ".")
-     (when (smie-rule-bolp)
-       (if (smie-rule-parent-p "{")
-           (+ swift-indent-offset swift-indent-multiline-statement-offset)
-         swift-indent-multiline-statement-offset)))
-
-    ;; Apply swift-indent-multiline-statement-offset if
-    ;; operator is the last symbol on the line
-    (`(:after . ,(pred (lambda (token)
-                          (member token swift-smie--operators))))
-     (when (and (smie-rule-hanging-p)
-                (not (apply 'smie-rule-parent-p
-                            (append swift-smie--operators '("?" ":" "=")))))
-       swift-indent-multiline-statement-offset
-       ))
-
-    (`(:before . ",")
-     (if (and swift-indent-hanging-comma-offset (smie-rule-parent-p "class" 
"case"))
-         (smie-rule-parent swift-indent-hanging-comma-offset)))
-
-    ;; Disable unnecessary default indentation for
-    ;; "func" and "class" keywords
-    (`(:after . ,(or `"func" `"class")) (smie-rule-parent))
+  :prefix "swift-mode:")
 
-    ;; "in" token in closure
-    (`(:after . "in")
-     (if (smie-rule-parent-p "{")
-         (smie-rule-parent swift-indent-offset)
-       (smie-rule-parent 0)))
-
-    (`(:after . "(")
-     (cond
-      ((smie-rule-parent-p "(") 0)
-      ((and (smie-rule-parent-p "." "func")
-            (not (smie-rule-hanging-p))) 1)
-      (t (smie-rule-parent swift-indent-offset))))
-
-    (`(:before . "(")
-     (cond
-      ((smie-rule-next-p "[") (smie-rule-parent))
-      ;; Custom indentation for method arguments
-      ((smie-rule-parent-p "." "func") (smie-rule-parent))))
-
-    (`(:before . "[")
-     (cond
-      ((smie-rule-prev-p "->") swift-indent-offset)
-      ((smie-rule-parent-p "[") (smie-rule-parent swift-indent-offset))
-      ((smie-rule-parent-p "{") nil)
-      ((smie-rule-parent-p "class-{") nil)
-      (t (smie-rule-parent))))
-    (`(:after . "->") (smie-rule-parent swift-indent-offset))
-    ))
-
-;;; Font lock
-
-(defvar swift-mode--type-decl-keywords
-  '("class" "enum" "protocol" "struct" "typealias"))
-
-(defvar swift-mode--val-decl-keywords
-  '("let" "var"))
-
-(defvar swift-mode--context-variables-keywords
-  '("self" "super"))
-
-(defvar swift-mode--fn-decl-keywords
-  '("deinit" "func" "init"))
-
-(defvar swift-mode--misc-keywords
-  '("import" "static" "subscript" "extension"))
-
-(defvar swift-mode--statement-keywords
-  '("break" "case" "continue" "default" "do" "else" "fallthrough"
-    "if" "in" "for" "return" "switch" "where" "while" "guard"))
-
-(defvar swift-mode--contextual-keywords
-  '("associativity" "didSet" "get" "infix" "inout" "left" "mutating" "none"
-    "nonmutating" "operator" "override" "postfix" "precedence" "prefix" "right"
-    "set" "unowned" "unowned(safe)" "unowned(unsafe)" "weak" "willSet" 
"convenience"
-    "required" "dynamic" "final" "lazy" "optional" "private" "public" 
"internal"))
-
-(defvar swift-mode--attribute-keywords
-  '("class_protocol" "exported" "noreturn"
-    "NSCopying" "NSManaged" "objc" "autoclosure"
-    "available" "noescape" "nonobjc" "NSApplicationMain" "testable" 
"UIApplicationMain" "warn_unused_result" "convention"
-    "IBAction" "IBDesignable" "IBInspectable" "IBOutlet"))
-
-(defvar swift-mode--keywords
-  (append swift-mode--type-decl-keywords
-          swift-mode--val-decl-keywords
-          swift-mode--context-variables-keywords
-          swift-mode--fn-decl-keywords
-          swift-mode--misc-keywords
-          swift-mode--statement-keywords
-          swift-mode--contextual-keywords)
-  "Keywords used in the Swift language.")
-
-(defvar swift-mode--constants
-  '("true" "false" "nil"))
-
-(defvar swift-font-lock-keywords
-  `(
-    ;; Keywords
-    ;;
-    ;; Swift allows reserved words to be used as identifiers when enclosed
-    ;; with backticks, in which case they should be highlighted as
-    ;; identifiers, not keywords.
-    (,(rx-to-string
-       `(and (or bol (not (any "`"))) bow
-             (group (or ,@swift-mode--keywords))
-             eow)
-       t)
-     1 font-lock-keyword-face)
-
-    ;; Attributes
-    ;;
-    ;; Highlight attributes with keyword face
-    (,(rx-to-string
-       `(and "@" bow (or ,@swift-mode--attribute-keywords) eow)
-       t)
-     0 font-lock-keyword-face)
-
-    ;; Types
-    ;;
-    ;; Any token beginning with an uppercase character is highlighted as a
-    ;; type.
-    (,(rx bow upper (* word) eow)
-     0 font-lock-type-face)
-
-    ;; Function names
-    ;;
-    ;; Any token beginning after `func' is highlighted as a function name.
-    (,(rx bow "func" eow (+ space) (group bow (+ word) eow))
-     1 font-lock-function-name-face)
-
-    ;; Value bindings
-    ;;
-    ;; Any token beginning after `let' or `var' is highlighted as an
-    ;; identifier.
-    (,(rx-to-string `(and bow
-                           (or ,@swift-mode--val-decl-keywords)
-                           eow
-                           (+ space)
-                           (? "(")
-                           (group (+ (or (+ (? ?`) word (? ?`)) ?, space)))
-                           (? ")"))
-                     t)
-       1 font-lock-variable-name-face)
-
-    ;; Use high-visibility face for pattern match wildcards.
-    (,(rx (not (any word digit)) (group "_") (or eol (not (any word digit))))
-     1 font-lock-negation-char-face)
-
-    ;; Constants
-    ;;
-    ;; Highlight nil and boolean literals.
-    (,(rx-to-string `(and bow (or ,@swift-mode--constants) eow))
-     0 font-lock-constant-face)
-
-    ;; Attributes
-    ;;
-    ;; Use string face for attribute name.
-    (,(rx (or bol space)(group "@" (+ word)) eow)
-     1 font-lock-string-face)
-
-    ;; Imported modules
-    ;;
-    ;; Highlight the names of imported modules. Use `font-lock-string-face' for
-    ;; consistency with C modes.
-    (,(rx bow "import" eow (+ space) (group (+ word)))
-     1 font-lock-string-face)
-
-    ;; String interpolation
-    ;;
-    ;; Highlight interpolation expression as identifier.
-    (swift-match-interpolation 0 font-lock-variable-name-face t)
-    ))
-
-(defun swift-syntax-propertize-function (start end)
-  "Syntactic keywords for Swift mode."
-  (let (case-fold-search)
-    (goto-char start)
-    (remove-text-properties start end '(swift-interpolation-match-data))
-    (funcall
-     (syntax-propertize-rules
-      ((rx (group "\\(" (* (any alnum " ()+-._/*[]!?<>&~!:|^%")) ")"))
-       (0 (ignore (swift-syntax-propertize-interpolation)))))
-     start end)))
-
-(defun swift-syntax-propertize-interpolation ()
-  (let* ((beg (match-beginning 0))
-         (context (save-excursion (save-match-data (syntax-ppss beg)))))
-    (put-text-property beg (1+ beg) 'swift-interpolation-match-data
-                       (cons (nth 3 context) (match-data)))))
-
-(defun swift-match-interpolation (limit)
-  (let ((pos (next-single-char-property-change (point) 
'swift-interpolation-match-data
-                                               nil limit)))
-    (when (and pos (> pos (point)))
-      (goto-char pos)
-      (let ((value (get-text-property pos 'swift-interpolation-match-data)))
-        (if (eq (car value) ?\")
-            (progn
-              (set-match-data (cdr value))
-              t)
-          (swift-match-interpolation limit))))))
-
-;;; Imenu
-
-(defun swift-mode--mk-regex-for-def (keyword)
-  "Make a regex matching the identifier introduced by KEYWORD."
-  (let ((ident (rx (any word nonascii "_") (* (any word nonascii digit "_")))))
-    (rx-to-string `(and bow ,keyword eow (+ space) (group (regexp ,ident)))
-                  t)))
-
-(defvar swift-mode--imenu-generic-expression
-  (list
-   (list "Functions" (swift-mode--mk-regex-for-def "func") 1)
-   (list "Classes"   (swift-mode--mk-regex-for-def "class") 1)
-   (list "Enums"     (swift-mode--mk-regex-for-def "enum") 1)
-   (list "Protocols" (swift-mode--mk-regex-for-def "protocol") 1)
-   (list "Structs"   (swift-mode--mk-regex-for-def "struct") 1)
-   (list "Constants" (swift-mode--mk-regex-for-def "let") 1)
-   (list "Variables" (swift-mode--mk-regex-for-def "var") 1))
-  "Value for `imenu-generic-expression' in swift-mode.")
-
-;;; Flycheck
-
-(with-eval-after-load 'flycheck
-  (flycheck-def-option-var flycheck-swift-sdk-path nil swift
-     "A path to the targeted SDK"
-     :type '(choice (const :tag "Don't link against sdk" nil)
-                    (string :tag "Targeted SDK path"))
-     :safe #'stringp)
-
-   (flycheck-def-option-var flycheck-swift-linked-sources nil swift
-     "Source files path to link against. Can be glob, i.e. *.swift"
-     :type '(choice (const :tag "Don't use linked sources" nil)
-                    (string :tag "Linked Sources"))
-     :safe #'stringp)
-
-   (flycheck-def-option-var flycheck-swift-framework-search-paths nil swift
-     "A list of framework search paths"
-     :type '(repeat (directory :tag "Include directory"))
-     :safe #'flycheck-string-list-p)
-
-   (flycheck-def-option-var flycheck-swift-cc-include-search-paths nil swift
-     "A list of include file search paths to pass to the Objective C compiler"
-     :type '(repeat (directory :tag "Include directory"))
-     :safe #'flycheck-string-list-p)
-
-   (flycheck-def-option-var flycheck-swift-target "i386-apple-ios8.1" swift
-     "Target used by swift compiler"
-     :type '(choice (const :tag "Don't specify target" nil)
-                    (string :tag "Build target"))
-     :safe #'stringp)
-
-   (flycheck-def-option-var flycheck-swift-import-objc-header nil swift
-     "Objective C header file to import, if any"
-     :type '(choice (const :tag "Don't specify objective C bridging header" 
nil)
-                    (string :tag "Objective C bridging header path"))
-     :safe #'stringp)
-
-   (flycheck-define-checker swift
-     "Flycheck plugin for for Apple's Swift programming language."
-     :command ("swift"
-               "-frontend" "-parse"
-               (option "-sdk" flycheck-swift-sdk-path)
-               (option-list "-F" flycheck-swift-framework-search-paths)
-               ;; Swift compiler will complain about redeclaration
-               ;; if we will include original file along with
-               ;; temporary source file created by flycheck.
-               ;; We also don't want a hidden emacs interlock files.
-               (eval
-                (let (source file)
-                  (when flycheck-swift-linked-sources
-                    (setq source (car (flycheck-substitute-argument 'source 
'swift)))
-                    (setq file (file-name-nondirectory source))
-                    (cl-remove-if-not
-                     #'(lambda (path)
-                         (and
-                          (eq (string-match ".#" path) nil)
-                          (eq (string-match file path) nil)))
-                     (file-expand-wildcards flycheck-swift-linked-sources)))))
-               (option "-target" flycheck-swift-target)
-               (option "-import-objc-header" flycheck-swift-import-objc-header)
-               (eval
-                (cl-mapcan
-                 #'(lambda (path) (list "-Xcc" (concat "-I" path)))
-                 flycheck-swift-cc-include-search-paths))
-               "-primary-file" source)
-     :error-patterns
-     ((error line-start (file-name) ":" line ":" column ": "
-             "error: " (message) line-end)
-      (warning line-start (file-name) ":" line ":" column ": "
-               "warning: " (message) line-end))
-     :modes swift-mode))
-
-;;; REPL
-
-(defvar swift-repl-buffer nil
-  "Stores the name of the current swift REPL buffer, or nil.")
-
-;;;###autoload
-(defun swift-mode-run-repl (cmd &optional dont-switch-p)
-  "Run a REPL process, input and output via buffer `*swift-repl*'.
-If there is a process already running in `*swift-repl*', switch to that buffer.
-With argument CMD allows you to edit the command line (default is value
-of `swift-repl-executable').
-With DONT-SWITCH-P cursor will stay in current buffer.
-Runs the hook `swift-repl-mode-hook' \(after the `comint-mode-hook'
-is run).
-\(Type \\[describe-mode] in the process buffer for a list of commands.)"
-
-  (interactive (list (if current-prefix-arg
-                         (read-string "Run swift REPL: " swift-repl-executable)
-                       swift-repl-executable)))
-  (unless (comint-check-proc "*swift-repl*")
-    (save-excursion (let ((cmdlist (split-string cmd)))
-                      (set-buffer (apply 'make-comint "swift-repl" (car 
cmdlist)
-                                         nil (cdr cmdlist)))
-                      (swift-repl-mode))))
-  (setq swift-repl-executable cmd)
-  (setq swift-repl-buffer "*swift-repl*")
-  (unless dont-switch-p
-    (pop-to-buffer "*swift-repl*")))
-
-(defun swift-mode-send-region (start end)
-  "Send the current region to the inferior swift process.
-START and END define region within current buffer"
-  (interactive "r")
-  (swift-mode-run-repl swift-repl-executable t)
-  (comint-send-region swift-repl-buffer start end)
-  (comint-send-string swift-repl-buffer "\n"))
-
-(defun swift-mode-send-buffer ()
-  "Send the buffer to the Swift REPL process."
-  (interactive)
-  (swift-mode-send-region (point-min) (point-max)))
-
-(define-derived-mode swift-repl-mode comint-mode "Swift REPL"
-  "Major mode for interacting with Swift REPL.
-
-A REPL can be fired up with M-x swift-mode-run-repl.
-
-Customization: Entry to this mode runs the hooks on comint-mode-hook and
-swift-repl-mode-hook (in that order).
-
-You can send text to the REPL process from other buffers containing source.
-    swift-mode-send-region sends the current region to the REPL process,
-    swift-mode-send-buffer sends the current buffer to the REPL process.
-")
-
-;;; Mode definition
-
-(defvar swift-mode-syntax-table
-  (let ((table (make-syntax-table)))
-
-    ;; Operators
-    (dolist (i '(?+ ?- ?* ?/ ?& ?| ?^ ?< ?> ?~))
-      (modify-syntax-entry i "." table))
-
-    ;; Strings
-    (modify-syntax-entry ?\" "\"" table)
-    (modify-syntax-entry ?\\ "\\" table)
-
-    ;; Additional symbols
-    (modify-syntax-entry ?_ "w" table)
-    (modify-syntax-entry ?? "_" table)
-    (modify-syntax-entry ?! "_" table)
-    (modify-syntax-entry ?: "." table)
-
-    ;; Comments
-    (modify-syntax-entry ?/  ". 124b" table)
-    (modify-syntax-entry ?*  ". 23n"  table)
-    (modify-syntax-entry ?\n "> b"    table)
-
-    ;; Parenthesis, braces and brackets
-    (modify-syntax-entry ?\( "()" table)
-    (modify-syntax-entry ?\) ")(" table)
-    (modify-syntax-entry ?\[ "(]" table)
-    (modify-syntax-entry ?\] ")[" table)
-    (modify-syntax-entry ?\{ "(}" table)
-    (modify-syntax-entry ?\} "){" table)
-
-    table))
+;;; Keymap
 
 (defvar swift-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "C-c C-z") 'swift-mode-run-repl)
-    (define-key map (kbd "C-c C-f") 'swift-mode-send-buffer)
-    (define-key map (kbd "C-c C-r") 'swift-mode-send-region)
+    (set-keymap-parent map prog-mode-map)
+    (define-key map (kbd "M-j") #'swift-mode:indent-new-comment-line)
+    (define-key map (kbd "C-M-j") #'swift-mode:indent-new-comment-line)
+    (define-key map (kbd "C-c C-z") 'swift-mode:run-repl)
+    (define-key map (kbd "C-c C-f") 'swift-mode:send-buffer)
+    (define-key map (kbd "C-c C-r") 'swift-mode:send-region)
     (easy-menu-define swift-menu map "Swift Mode menu"
       `("Swift"
         :help "Swift-specific Features"
@@ -797,31 +65,91 @@ You can send text to the REPL process from other buffers 
containing source.
         ["Send region to REPL" swift-mode-send-region
          :help "Send currently selected region to the REPL"]))
     map)
-  "Key map for swift mode.")
+  "Swift mode key map.")
+
+;;; `foward-sexp-function'
+
+(defun swift-mode:forward-sexp (&optional arg)
+  (setq arg (or arg 1))
+  (if (< 0 arg)
+      (while (< 0 arg)
+        (while (eq
+                (swift-mode:token:type (swift-mode:forward-token-or-list))
+                'implicit-\;))
+        (setq arg (1- arg))))
+  (while (< arg 0)
+    (while (eq
+            (swift-mode:token:type (swift-mode:backward-token-or-list))
+            'implicit-\;))
+    (setq arg (1+ arg))))
+
+;; Imenu
+
+(defun swift-mode:mk-regex-for-def (keyword)
+  "Make a regex matching the identifier introduced by KEYWORD."
+  (concat "\\<" (regexp-quote keyword) "\\>"
+          "\\s *"
+          "\\("
+          "\\(?:" "\\sw" "\\|" "\\s_" "\\)" "+"
+          "\\)"))
+
+(defconst swift-mode:imenu-generic-expression
+  (list
+   (list "Functions" (swift-mode:mk-regex-for-def "func") 1)
+   (list "Classes"   (swift-mode:mk-regex-for-def "class") 1)
+   (list "Enums"     (swift-mode:mk-regex-for-def "enum") 1)
+   (list "Protocols" (swift-mode:mk-regex-for-def "protocol") 1)
+   (list "Structs"   (swift-mode:mk-regex-for-def "struct") 1)
+   (list "Extensions"   (swift-mode:mk-regex-for-def "extension") 1)
+   (list "Constants" (swift-mode:mk-regex-for-def "let") 1)
+   (list "Variables" (swift-mode:mk-regex-for-def "var") 1))
+  "Value for `imenu-generic-expression' in `swift-mode'.")
 
 ;;;###autoload
 (define-derived-mode swift-mode prog-mode "Swift"
-  "Major mode for Apple's Swift programming language.
+  "Major mode for editing Swift code.
 
-\\<swift-mode-map>"
+\\{swift-mode-map}"
+  :syntax-table swift-mode:syntax-table
   :group 'swift
-  :syntax-table swift-mode-syntax-table
-  (setq font-lock-defaults '((swift-font-lock-keywords) nil nil))
-  (setq-local syntax-propertize-function #'swift-syntax-propertize-function)
 
-  (setq-local imenu-generic-expression swift-mode--imenu-generic-expression)
+  (setq font-lock-defaults '(swift-mode:font-lock-keywords))
 
   (setq-local comment-start "// ")
   (setq-local comment-end "")
+  ;; ":" is for Playground Rich Comments Markup Syntax:
+  ;; 
https://developer.apple.com/library/prerelease/ios/documentation/Xcode/Reference/xcode_markup_formatting_ref/PlaygroundRichComments.html
+  (setq-local comment-start-skip
+              (concat
+               "\\s *"
+               "\\(?:"
+               ;; Single-line comment
+               "//+" ":?" "\\|"
+               ;; Multi-line comment
+               "/\\*+" ":?" "\\|"
+               ;; Middle of multi-line-comment
+               "\\*+ "
+               "\\)"
+               "\\s *"))
+  (setq-local adaptive-fill-regexp comment-start-skip)
+  (setq-local comment-multi-line t)
+
   (setq-local indent-tabs-mode nil)
+  (setq-local indent-line-function #'swift-mode:indent-line)
+
+  (setq-local forward-sexp-function #'swift-mode:forward-sexp)
+
   (setq-local electric-indent-chars
-              (append '(?. ?, ?: ?\) ?\] ?\}) electric-indent-chars))
-  (smie-setup swift-smie-grammar 'swift-smie-rules ;; 'verbose-swift-smie-rules
-              :forward-token 'swift-smie--forward-token
-              :backward-token 'swift-smie--backward-token))
+              (append "{}()[]:;,." electric-indent-chars))
 
-;;;###autoload
-(add-to-list 'auto-mode-alist '("\\.swift\\'" . swift-mode))
+  (add-hook 'post-self-insert-hook #'swift-mode:post-self-insert nil t)
+
+  (setq-local imenu-generic-expression swift-mode:imenu-generic-expression)
+
+  (setq-local beginning-of-defun-function #'swift-mode:beginning-of-defun)
+  (setq-local end-of-defun-function #'swift-mode:end-of-defun))
+
+;;;###autoload (add-to-list 'auto-mode-alist '("\\.swift\\'" . swift-mode))
 
 (provide 'swift-mode)
 
diff --git a/test/font-lock-tests.el b/test/font-lock-tests.el
deleted file mode 100644
index eff40e3..0000000
--- a/test/font-lock-tests.el
+++ /dev/null
@@ -1,212 +0,0 @@
-;;; font-lock-tests.el --- Tests for font-lock behaviours in swift-mode.  -*- 
lexical-binding: t; -*-
-
-;; Copyright (C) 2014-2016 Chris Barrett
-
-;; Author: Chris Barrett <chris.d.barrett@me.com>
-;; Version: 0.1
-
-;; This file is not part of GNU Emacs.
-
-;; This program is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Tests for font-lock behaviours in swift-mode.
-;;
-;; Uses puppet-mode tests as a reference:
-;; 
https://github.com/lunaryorn/puppet-mode/blob/master/test/puppet-mode-test.el
-
-;;; Code:
-
-
-(require 'swift-mode)
-(require 'ert)
-(require 'cl-lib)
-(require 's nil t)
-(require 'dash nil t)
-
-;;; Test utilities
-
-(defun swift-test--moustache-substring (str)
-  "Propertise STR and extract the portion between moustaches.
-Returns the substring with properties."
-  (with-temp-buffer
-    (insert str)
-    (goto-char (point-min))
-    (let (start end)
-      ;; Remove open-moustache chars and save position.
-      (search-forward "{{")
-      (delete-char -2)
-      (setq start (point))
-      ;; Remove end-moustache chars and save position.
-      (search-forward-regexp (rx (>= 2 "}")))
-      (delete-char -2)
-      (setq end (point))
-      ;; Propertise buffer.
-      (swift-mode)
-      (font-lock-fontify-buffer)
-      (buffer-substring start end))))
-
-(defun swift-test--whole-string-has-face? (str face)
-  "Non-nil if all of STR is propertised with FACE."
-  (with-temp-buffer
-    (insert str)
-    (goto-char (point-min))
-    (let ((points
-           ;; Walk over the string and get the faces at each position.
-           (cl-loop while (not (eobp))
-                    collecting (get-text-property (point) 'face)
-                    do (forward-char 1))))
-
-      (--all? (cond ((null it)  (null face))
-                    ((listp it) (member face it))
-                    (t          (equal face it)))
-              points))))
-
-(defmacro check-face (description face str)
-  "Declare an ert test for font-lock behaviour.
-The test will check that a portion of the buffer is propertised with the
-given face.
-
-DESCRIPTION is a symbol describing the test.
-
-FACE is the face name as an unquoted symbol.  It can also be nil, which
-means the string should not have any face.
-
-STR is the string to test for face propertisation.  The portion of the
-string to be checked is surrounded with moustaches ('{{' and '}}'), as
-below:
-
-   let {{foo}} = y
-
-The whole substring between moustaches must be propertised with FACE or the
-test will fail."
-  (declare (indent 2))
-  (cl-assert (symbolp description))
-  (cl-assert (or (facep face) (null face)))
-  (cl-assert (stringp str))
-  (cl-assert (s-contains? "{{" str))
-  (cl-assert (s-contains? "}}" str))
-  (cl-assert (<= 1 (length (swift-test--moustache-substring str))))
-
-  (let ((test-name (intern (format "font-lock/%s" description))))
-    `(ert-deftest ,test-name ()
-       (let ((substr (swift-test--moustache-substring ,str)))
-         (should (swift-test--whole-string-has-face? substr ,face))))))
-
-;; Provide font locking for easier test editing.
-
-(font-lock-add-keywords
- 'emacs-lisp-mode
- `((,(rx "(" (group "check-face" eow))
-    (1 font-lock-keyword-face))
-   (,(rx "("
-         (group "check-face") (+ space)
-         (group bow (+ (not space)) eow)
-         )
-    (1 font-lock-keyword-face)
-    (2 font-lock-function-name-face))))
-
-;;; Tests
-
-(check-face let/has-keyword-face/1 font-lock-keyword-face "{{let}}")
-(check-face let/has-keyword-face/2 font-lock-keyword-face " {{let}}")
-(check-face let/has-keyword-face/3 font-lock-keyword-face "{{let}} x = y")
-(check-face let-bind/has-variable-face/1 font-lock-variable-name-face "let 
{{x}} = y")
-(check-face let-bind/has-variable-face/2 font-lock-variable-name-face "let 
{{foo}} = y")
-(check-face let-bind/has-variable-face/3 font-lock-variable-name-face "let 
{{x}}: T = y")
-(check-face let-bind/has-variable-face/4 font-lock-variable-name-face "let 
({{foo}}, bar) = y")
-(check-face let-bind/has-variable-face/5 font-lock-variable-name-face "let 
(foo, {{bar}}) = y")
-(check-face let-bind-type-ann/has-type-face/1 font-lock-type-face "let x: 
{{T}} = y")
-(check-face let-bind-type-ann/has-type-face/2 font-lock-type-face "let x: 
{{Type}} = y")
-
-(check-face var/has-keyword-face/1 font-lock-keyword-face "{{var}}")
-(check-face var/has-keyword-face/2 font-lock-keyword-face " {{var}}")
-(check-face var/has-keyword-face/3 font-lock-keyword-face "{{var}} x = y")
-(check-face var-bind/has-variable-face/1 font-lock-variable-name-face "var 
{{x}} = y")
-(check-face var-bind/has-variable-face/2 font-lock-variable-name-face "var 
{{foo}} = y")
-(check-face var-bind/has-variable-face/3 font-lock-variable-name-face "var 
{{x}}: T = y")
-(check-face var-bind-type-ann/has-type-face/1 font-lock-type-face "var x: 
{{T}} = y")
-(check-face var-bind-type-ann/has-type-face/2 font-lock-type-face "var x: 
{{Type}} = y")
-
-(check-face func/has-keyword-face/1 font-lock-keyword-face "{{func}}")
-(check-face func/has-keyword-face/2 font-lock-keyword-face "{{func}} x() {})")
-(check-face func-name/has-function-name-face/1 font-lock-function-name-face 
"func {{x}}")
-(check-face func-name/has-function-name-face/2 font-lock-function-name-face 
"func {{foo}}")
-(check-face func-name/has-function-name-face/3 font-lock-function-name-face 
"func {{foo}}()")
-(check-face func-name/has-function-name-face/4 font-lock-function-name-face 
"func {{foo}}<T>")
-(check-face func-name/has-function-name-face/6 font-lock-function-name-face
-  "func {{foo}}<T>(param: T) -> U {}")
-(check-face func-access-control/has-keyword-face/1 font-lock-keyword-face 
"{{private}} func foo() {}")
-(check-face func-access-control/has-keyword-face/2 font-lock-keyword-face 
"{{public}} func foo() {}")
-(check-face func-access-control/has-keyword-face/3 font-lock-keyword-face 
"{{internal}} func foo() {}")
-
-(check-face func-return-type/has-type-face/1 font-lock-type-face "func foo() 
-> {{U}} {}")
-(check-face func-return-type/arrow-has-default-face/1 nil "func foo() {{->}} U 
{}")
-
-(check-face enum/has-keyword-face/1 font-lock-keyword-face "{{enum}} T")
-(check-face enum/has-keyword-face/2 font-lock-keyword-face "{{enum}} T")
-(check-face enum/type-has-type-face/1 font-lock-type-face "enum {{T}}")
-(check-face enum/type-has-type-face/2 font-lock-type-face "enum {{Type}}")
-(check-face enum/type-has-type-face/3 font-lock-type-face "enum {{T}} {}")
-(check-face enum/type-has-type-face/4 font-lock-type-face "enum {{T}} {\n}")
-(check-face enum/generic-parameter/has-type-face/1 font-lock-type-face "enum 
N<{{T}}>")
-(check-face enum/generic-parameter/has-type-face/2 font-lock-type-face "enum 
Name<{{T}}> {}")
-(check-face enum/generic-parameter/has-type-face/3 font-lock-type-face "enum 
Name <{{T}}> {}")
-(check-face enum/generic-parameter/brackets-have-default-face/1 nil "enum 
N{{<}}T>")
-(check-face enum/generic-parameter/brackets-have-default-face/2 nil "enum 
N<T{{>}}")
-
-(check-face class/has-keyword-face/1 font-lock-keyword-face "{{class}} T")
-(check-face class/has-keyword-face/2 font-lock-keyword-face "{{class}} T")
-(check-face class/type-has-type-face/1 font-lock-type-face "class {{T}}")
-(check-face class/type-has-type-face/2 font-lock-type-face "class {{Type}}")
-(check-face class/type-has-type-face/3 font-lock-type-face "class {{T}} {}")
-(check-face class/type-has-type-face/4 font-lock-type-face "class {{T}} {\n}")
-(check-face class/type-has-type-face/5 font-lock-type-face "class {{T}}: Base")
-
-(check-face class/body-brackets-have-default-face nil "class T {{{}}}")
-
-(check-face class/generic-parameter/has-type-face/1 font-lock-type-face "class 
N<{{T}}>")
-(check-face class/generic-parameter/has-type-face/2 font-lock-type-face "class 
Name<{{T}}> {}")
-(check-face class/generic-parameter/has-type-face/3 font-lock-type-face "class 
Name <{{T}}> {}")
-(check-face class/generic-parameter/brackets-have-default-face/1 nil "class 
N{{<}}T>")
-(check-face class/generic-parameter/brackets-have-default-face/2 nil "class 
N<T{{>}}")
-
-(check-face class/base-type-has-type-face/1 font-lock-type-face "class 
T:{{Base}}")
-(check-face class/base-type-has-type-face/2 font-lock-type-face "class T: 
{{Base}}")
-(check-face class/base-type-has-type-face/3 font-lock-type-face "class T : 
{{Base}}")
-(check-face class/base-type-has-type-face/4 font-lock-type-face "class T<U> : 
{{Base}}")
-(check-face class/base-type-colon-has-default-face/1 nil "class T {{:}} Base")
-
-(check-face string-interpolation/has-variable-face/1 
font-lock-variable-name-face "\"foo {{\\\(bar)}}\"")
-(check-face string-interpolation/has-variable-face/2 
font-lock-variable-name-face "\"{{\\\(bar)}}\"")
-(check-face string-interpolation/has-variable-face/3 
font-lock-variable-name-face "\"\\\(bar\(1\){{\)}}\"")
-(check-face string-interpolation/has-variable-face/4 
font-lock-variable-name-face "\"\\\(bar\(1\){{ + baz\(2\)\)}}\"")
-(check-face string-interpolation/has-variable-face/5 
font-lock-variable-name-face "\"foo {{\\\(bar_baz)}}\"")
-(check-face string-interpolation/has-variable-face/6 
font-lock-variable-name-face "\"foo {{\\\(bar.baz)}}\"")
-(check-face string-interpolation/has-variable-face/7 
font-lock-variable-name-face "\"foo {{\\\(bar[0])}}\"")
-(check-face string-interpolation/has-variable-face/8 
font-lock-variable-name-face "\"foo {{\\\(bar!.baz)}}\"")
-(check-face string-interpolation/has-variable-face/9 
font-lock-variable-name-face "\"foo {{\\\(bar?.baz)}}\"")
-(check-face string-interpolation/after-has-string-face/2 font-lock-string-face 
"\"(foo \\\(bar){{baz}}\")")
-
-(check-face self/has-keyword-face/1 font-lock-keyword-face "{{self}}.foo")
-(check-face super/has-keyword-face/1 font-lock-keyword-face "{{super}}.foo")
-
-(check-face attributes/has-keyword-face/1 font-lock-keyword-face 
"{{@IBAction}} func")
-
-(check-face comments/nested-multiline-comments-has-comments-face/1 
font-lock-comment-face "/*/* text */{{*/}}")
-
-(provide 'font-lock-tests)
-
-;;; font-lock-tests.el ends here
diff --git a/test/indentation-tests.el b/test/indentation-tests.el
deleted file mode 100644
index 6a4c295..0000000
--- a/test/indentation-tests.el
+++ /dev/null
@@ -1,2280 +0,0 @@
-;;; indentation-tests.el --- Test swift-mode indentation behaviour
-
-;; Copyright (C) 2014-2016 Chris Barrett
-
-;; Author: Chris Barrett <chris.d.barrett@me.com>
-;; Version: 0.1
-
-;; This file is not part of GNU Emacs.
-
-;; This program is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Test swift-mode indentation behaviour
-
-;;; Code:
-
-(require 'ert)
-(require 'swift-mode)
-(require 's)
-
-;;; Test utilities
-
-(defmacro check-indentation (description before after &optional var-bindings)
-  "Declare an ert test for indentation behaviour.
-The test will check that the swift indentation command changes the buffer
-from one state to another.  It will also test that point is moved to an
-expected position.
-
-DESCRIPTION is a symbol describing the test.
-
-BEFORE is the buffer string before indenting, where a pipe (|) represents
-point.
-
-AFTER is the expected buffer string after indenting, where a pipe (|)
-represents the expected position of point.
-
-VAR-BINDINGS is an optional let-bindings list.  It can be used to set the
-values of customisable variables."
-  (declare (indent 1))
-  (let ((fname (intern (format "indentation/%s" description))))
-    `(ert-deftest ,fname ()
-       (let* ((after ,after)
-              (expected-cursor-pos (1+ (s-index-of "|" after)))
-              (expected-state (delete ?| after))
-
-              ;; Bind customisable vars to default values for tests.
-              (swift-indent-offset 4)
-              (swift-indent-switch-case-offset 0)
-              (swift-indent-multiline-statement-offset 2)
-              (swift-indent-hanging-comma-offset nil)
-              ,@var-bindings)
-         (with-temp-buffer
-           (insert ,before)
-           (goto-char (point-min))
-           (search-forward "|")
-           (delete-char -1)
-           (swift-mode)
-           (setq smie-forward-token-function 'swift-smie--forward-token-debug)
-           (setq smie-backward-token-function 
'swift-smie--backward-token-debug)
-           (indent-according-to-mode)
-
-           (should (equal expected-state (buffer-string)))
-           (should (equal expected-cursor-pos (point)))
-
-           (goto-char (point-min))
-           (forward-sexp 10)
-           (should (equal (point-max) (point)))
-           (forward-sexp -10)
-           (should (equal (point-min) (point)))
-
-           (goto-char (point-min))
-           (forward-list 10)
-           (should (equal (point-max) (point)))
-           (forward-list -10)
-           (should (equal (point-min) (point)))
-           )))))
-
-;; Provide font locking for easier test editing.
-
-(font-lock-add-keywords
- 'emacs-lisp-mode
- `((,(rx "(" (group "check-indentation") eow)
-    (1 font-lock-keyword-face))
-   (,(rx "("
-         (group "check-indentation") (+ space)
-         (group bow (+ (not space)) eow)
-         )
-    (1 font-lock-keyword-face)
-    (2 font-lock-function-name-face))))
-
-
-;;; Tests
-
-
-(check-indentation no-indentation-at-top-level
-  "|x"
-  "|x")
-
-(check-indentation toplevel-exprs-indented-to-same-level/1
-  "
-x
-|y
-" "
-x
-|y
-")
-
-(check-indentation toplevel-exprs-indented-to-same-level/2
-  "
-x
-     |y
-" "
-x
-|y
-")
-
-(check-indentation nested-exprs-indented-to-same-level/1
-  "
-{
-    x
-    |y
-}
-" "
-{
-    x
-    |y
-}
-")
-
-(check-indentation nested-exprs-indented-to-same-level/2
-  "
-{
-    x
-        |y
-}
-" "
-{
-    x
-    |y
-}
-")
-
-(check-indentation nested-exprs-indented-to-same-level/3
-  "
-{
-    x
-|y
-}
-" "
-{
-    x
-    |y
-}
-")
-
-(check-indentation indent-if-body
-  "
-if true {
-|x
-}
-" "
-if true {
-    |x
-}
-")
-
-(check-indentation indent-if-else
-  "
-if true {
-} else {
-|foo
-}
-" "
-if true {
-} else {
-    |foo
-}
-")
-
-(check-indentation indent-if-else-if
-  "
-if true {
-} else if false {
-|foo
-}
-" "
-if true {
-} else if false {
-    |foo
-}
-")
-
-(check-indentation indent-if-body--no-effect-if-already-indented
-  "
-if true {
-    |x
-}
-""
-if true {
-    |x
-}
-")
-
-(check-indentation indent-if-body-nested
-  "
-if foo {
-    if true {
-|foo
-    }
-}
-" "
-if foo {
-    if true {
-        |foo
-    }
-}
-")
-
-(check-indentation indents-case-statements-to-same-level-as-enclosing-switch/1
-  "
-switch true {
-    |case foo:
-}
-" "
-switch true {
-|case foo:
-}
-")
-
-(check-indentation indents-case-statements-to-same-level-as-enclosing-switch/2
-  "
-switch true {
-          |case foo:
-}
-" "
-switch true {
-|case foo:
-}
-")
-
-(check-indentation indents-case-statements-to-same-level-as-enclosing-switch/3
-  "
-{
-    switch true {
-|case foo:
-    }
-}
-" "
-{
-    switch true {
-    |case foo:
-    }
-}
-")
-
-(check-indentation indents-case-statements-to-same-level-as-enclosing-switch/4
-  "
-{
-    switch true {
-              |case foo:
-    }
-}
-" "
-{
-    switch true {
-    |case foo:
-    }
-}
-")
-
-(check-indentation indents-case-statements-to-same-level-as-enclosing-switch/5
-                   "
-switch {
-    |case foo,
-     bar, buz:
-    foo
-}
-" "
-switch {
-|case foo,
-     bar, buz:
-    foo
-}
-")
-
-(check-indentation indents-case-statements-to-same-level-as-enclosing-switch/6
-                   "
-switch {
-    |case
-    foo, bar, buz:
-    foo
-}
-" "
-switch {
-|case
-    foo, bar, buz:
-    foo
-}
-")
-
-(check-indentation indents-case-statements-to-same-level-as-enclosing-switch/7
-                   "
-switch {
-case foo:
-    foo
-    bar
-  |case baz:
-}
-" "
-switch {
-case foo:
-    foo
-    bar
-|case baz:
-}
-")
-
-(check-indentation indents-case-statement-bodies/1
-"
-switch x {
-case y:
-|return z
-}
-" "
-switch x {
-case y:
-    |return z
-}
-")
-
-(check-indentation indents-case-statement-bodies/2
-"
-switch x {
-case y:
-       |return z
-}
-" "
-switch x {
-case y:
-    |return z
-}
-")
-
-(check-indentation indents-case-statement-bodies/3
-"
-switch x {
-case y:
-    |return z
-}
-" "
-switch x {
-case y:
-    |return z
-}
-")
-
-(check-indentation indents-case-statement-bodies/4
-"
-switch x {
-case y:
-    x
-    |return z
-}
-" "
-switch x {
-case y:
-    x
-    |return z
-}
-")
-
-(check-indentation indents-case-statement-bodies/5
-"
-switch x {
-case y:
-    x
-|return z
-}
-" "
-switch x {
-case y:
-    x
-    |return z
-}
-")
-
-(check-indentation indents-case-statement-bodies/6
-"
-switch x {
-case y:
-    x
-        |return z
-}
-" "
-switch x {
-case y:
-    x
-    |return z
-}
-")
-
-
-(check-indentation 
indents-default-statements-to-same-level-as-enclosing-switch/1
-  "
-{
-    switch true {
-    case y:
-        x
-|default:
-    }
-}
-" "
-{
-    switch true {
-    case y:
-        x
-    |default:
-    }
-}
-")
-
-(check-indentation 
indents-default-statements-to-same-level-as-enclosing-switch/2
-  "
-{
-    switch true {
-    case y:
-        x
-              |default:
-    }
-}
-" "
-{
-    switch true {
-    case y:
-        x
-    |default:
-    }
-}
-")
-
-(check-indentation 
indents-default-statements-to-same-level-as-enclosing-switch/3
-                   "
-{
-    switch true {
-    case y:
-        x
-    default:
-        foo
-        |}
-}
-" "
-{
-    switch true {
-    case y:
-        x
-    default:
-        foo
-    |}
-}
-")
-
-(check-indentation indents-statements-under-default-case/1
-  "
-{
-    switch true {
-    case y:
-        x
-    default:
-    |z
-    }
-}
-" "
-{
-    switch true {
-    case y:
-        x
-    default:
-        |z
-    }
-}
-")
-
-(check-indentation indents-case-statements-with-destucturing/1
-  "
-switch true {
-case let(x, y) where x < y:
-|foo
-}
-" "
-switch true {
-case let(x, y) where x < y:
-    |foo
-}
-")
-
-(check-indentation indents-case-statements-with-destucturing/2
-  "
-switch true {
-case let .Foo(x) where x > 0:
-|foo
-}
-" "
-switch true {
-case let .Foo(x) where x > 0:
-    |foo
-}
-")
-
-(check-indentation indents-case-statements-with-guard
-  "
-switch true {
-case foo where bar:
-|foo
-}
-" "
-switch true {
-case foo where bar:
-    |foo
-}
-")
-
-(check-indentation indents-case-statements-with-multiline-guard/1
-  "
-switch true {
-case foo where bar,
-|bar where baz:
-}
-" "
-switch true {
-case foo where bar,
-     |bar where baz:
-}
-")
-
-(check-indentation indents-case-statements-with-multiline-guard-custom-offset/1
-                   "
-switch true {
-case foo where bar,
-|bar where baz:
-}
-" "
-switch true {
-case foo where bar,
-   |bar where baz:
-}
-"
-((swift-indent-hanging-comma-offset 3)))
-
-(check-indentation indents-case-statements-with-multiline-guard/2
-  "
-switch true {
-case foo where bar,
-     bar where baz:
-|foo
-}
-" "
-switch true {
-case foo where bar,
-     bar where baz:
-    |foo
-}
-")
-
-
-(check-indentation indents-case-statements-to-user-defined-offset/1
-  "
-switch true {
-    |case foo:
-}
-" "
-switch true {
-  |case foo:
-}
-"
-((swift-indent-switch-case-offset 2)))
-
-(check-indentation indents-case-statements-to-user-defined-offset/2
-  "
-switch true {
-          |default:
-}
-" "
-switch true {
-  |default:
-}
-"
-((swift-indent-switch-case-offset 2)))
-
-
-(check-indentation indents-case-statements-in-enum/1
-  "
-enum T {
-|case
-}
-" "
-enum T {
-    |case
-}
-")
-
-(check-indentation indents-case-statements-in-enum/2
-  "
-enum T {
-         |case
-}
-" "
-enum T {
-    |case
-}
-")
-
-(check-indentation indents-case-statements-in-enum/3
-  "
-enum Foo: Bar {
-         |case
-}
-" "
-enum Foo: Bar {
-    |case
-}
-")
-
-(check-indentation indents-declaration-statements-in-enum/1
-                   "
-enum Foo: Bar {
-    case foo
-    case bar
-         |var foo
-}
-" "
-enum Foo: Bar {
-    case foo
-    case bar
-    |var foo
-}
-")
-
-(check-indentation indents-for-statements/1
-  "
-for index in 1..5 {
-|foo
-}
-" "
-for index in 1..5 {
-    |foo
-}
-")
-
-(check-indentation indents-for-statements/2
-  "
-for (key, value) in dict {
-|foo
-}
-" "
-for (key, value) in dict {
-    |foo
-}
-")
-
-(check-indentation indents-for-statements/3
-  "
-for var index = 0; index < 3; ++index  {
-|foo
-}
-" "
-for var index = 0; index < 3; ++index  {
-    |foo
-}
-")
-
-(check-indentation indents-while-statements
-  "
-while foo < bar{
-|foo
-}
-" "
-while foo < bar{
-    |foo
-}
-")
-
-(check-indentation indents-import-statements/1
-  "
-import Foo
-        |import Bar
-" "
-import Foo
-|import Bar
-")
-
-(check-indentation indents-import-statements/2
-  "
-import Darwin
-    |class Test {
-}
-" "
-import Darwin
-|class Test {
-}
-")
-
-(check-indentation indents-class-declaration/1
-  "
-class Foo {
-          |foo
-}
-" "
-class Foo {
-    |foo
-}
-")
-
-(check-indentation indents-class-declaration/2
-  "
-class Foo: Bar {
-          |foo
-}
-" "
-class Foo: Bar {
-    |foo
-}
-")
-
-(check-indentation indents-class-declaration/3
-  "
-class Foo: Foo, Bar, Baz {
-          |foo
-}
-" "
-class Foo: Foo, Bar, Baz {
-    |foo
-}
-")
-
-(check-indentation indents-class-declaration/4
-  "
-class Foo: Bar {
-|class Baz: Bar {
-    }
-}
-" "
-class Foo: Bar {
-    |class Baz: Bar {
-    }
-}
-")
-
-(check-indentation indents-class-declaration/5
-                   "
-class Foo: Foo, Bar,
-|Baz {
-}
-" "
-class Foo: Foo, Bar,
-      |Baz {
-}
-")
-
-(check-indentation indents-class-declaration-custom-offset/1
-                   "
-class Foo: Foo, Bar,
-|Baz {
-}
-" "
-class Foo: Foo, Bar,
-   |Baz {
-}
-"
-((swift-indent-hanging-comma-offset 3)))
-
-(check-indentation indents-class-declaration/6
-                   "
-class Foo:
-|Foo, Bar, Baz {
-}
-" "
-class Foo:
-    |Foo, Bar, Baz {
-}
-")
-
-(check-indentation indents-class-declaration/7
-                   "
-class Foo: Bar<A, B,
-|C>
-" "
-class Foo: Bar<A, B,
-               |C>
-")
-
-(check-indentation indents-class-declaration/8
-                   "
-class Foo<A: B<C>>:
-                   |Bar
-" "
-class Foo<A: B<C>>:
-    |Bar
-")
-
-(check-indentation indents-class-declaration/9
-                   "
-class Foo: Foo,
-      Bar,
-      Bar2,
-         |Baz {
-}
-" "
-class Foo: Foo,
-      Bar,
-      Bar2,
-      |Baz {
-}
-")
-
-(check-indentation indents-class-declaration/10
-                   "
-class Foo: Foo,
-      Bar,
-      Bar2,
-      Baz {
-  |}
-" "
-class Foo: Foo,
-      Bar,
-      Bar2,
-      Baz {
-|}
-")
-
-(check-indentation indents-public-class-declaration/1
-                   "
-public class Foo: Foo, Bar,
-|Baz {
-}
-" "
-public class Foo: Foo, Bar,
-             |Baz {
-}
-")
-
-(check-indentation indents-public-class-declaration-custom-offset/1
-                   "
-public class Foo: Foo, Bar,
-|Baz {
-}
-" "
-public class Foo: Foo, Bar,
-   |Baz {
-}
-"
-((swift-indent-hanging-comma-offset 3)))
-
-(check-indentation indents-public-class-declaration/2
-  "
-public class Foo {
-          |foo
-}
-" "
-public class Foo {
-    |foo
-}
-")
-
-(check-indentation indents-public-class-declaration/3
-                   "
-public class Foo: Foo, Bar,
-             Baz {
-  |}
-" "
-public class Foo: Foo, Bar,
-             Baz {
-|}
-")
-
-(check-indentation indents-public-class-declaration/4
-                   "
-public class Foo: Foo, Bar,
-             Baz {
-|foo
-}
-" "
-public class Foo: Foo, Bar,
-             Baz {
-    |foo
-}
-")
-
-(check-indentation indents-func-declaration/1
-  "
-func Foo(a: String) {
-|foo
-}
-" "
-func Foo(a: String) {
-    |foo
-}
-")
-
-(check-indentation indents-func-declaration/2
-  "
-override func Foo() {
-|foo
-}
-" "
-override func Foo() {
-    |foo
-}
-")
-
-(check-indentation indents-func-declaration/3
-  "
-func Foo(b: Double...) -> Bool {
-|foo
-}
-" "
-func Foo(b: Double...) -> Bool {
-    |foo
-}
-")
-
-(check-indentation indents-func-declaration/4
-  "
-class Foo {
-    override func Foo(b: Double...) -> Bool {
-|foo
-    }
-}
-" "
-class Foo {
-    override func Foo(b: Double...) -> Bool {
-        |foo
-    }
-}
-")
-
-(check-indentation indents-func-declaration/5
-                   "
-class func Foo() {
-|foo
-}
-" "
-class func Foo() {
-    |foo
-}
-")
-
-(check-indentation indents-func-declaration/6
-                   "
-func Foo(aaaaaaaaa:
-         |AAAAAAAAA) {
-}
-" "
-func Foo(aaaaaaaaa:
-         |AAAAAAAAA) {
-}
-")
-
-(check-indentation indents-func-declaration/7
-  "
-func foo() ->
-|Foo
-" "
-func foo() ->
-    |Foo
-")
-
-(check-indentation indents-func-declaration/8
-  "
-func foo() ->
-|(A, B) {}
-" "
-func foo() ->
-    |(A, B) {}
-")
-
-(check-indentation indents-func-declaration/9
-  "
-func foo() ->
-|[A] {}
-" "
-func foo() ->
-    |[A] {}
-")
-
-(check-indentation indents-func-declaration/10
-                   "
-func a(a: NSString = 1,
-                     |b: NSString = 2) {}
-" "
-func a(a: NSString = 1,
-       |b: NSString = 2) {}
-")
-
-(check-indentation indents-func-declaration/11
-                   "
-class Foo: Bar {
-    func Foo() {
-|foo
-    }
-}
-" "
-class Foo: Bar {
-    func Foo() {
-        |foo
-    }
-}
-")
-
-(check-indentation indents-func-declaration/12
-                   "
-class Foo: Bar {
-    override func Foo() {
-|foo
-    }
-}
-" "
-class Foo: Bar {
-    override func Foo() {
-        |foo
-    }
-}
-")
-
-(check-indentation indents-protocol-declaration/1
-                   "
-protocol Foo {
-    func foo()
-|func bar()
-}
-" "
-protocol Foo {
-    func foo()
-    |func bar()
-}
-")
-
-(check-indentation indents-protocol-declaration/2
-                   "
-protocol Foo {
-    func foo() -> Foo
-|func bar() -> Bar
-}
-" "
-protocol Foo {
-    func foo() -> Foo
-    |func bar() -> Bar
-}
-")
-
-(check-indentation indents-protocol-declaration/3
-                   "
-protocol Foo {
-    func foo() -> Foo<A>
-|func bar() -> Bar<A>
-}
-" "
-protocol Foo {
-    func foo() -> Foo<A>
-    |func bar() -> Bar<A>
-}
-")
-
-(check-indentation indents-protocol-declaration/4
-                   "
-protocol Foo {
-    func foo() -> [A]
-|func bar() -> [A]
-}
-" "
-protocol Foo {
-    func foo() -> [A]
-    |func bar() -> [A]
-}
-")
-
-(check-indentation indents-declaration/1
-  "
-var foo = bar + baz
-          |
-" "
-var foo = bar + baz
-|
-")
-
-(check-indentation indents-declaration/2
-  "
-let foo = bar +
-|baz
-" "
-let foo = bar +
-          |baz
-")
-
-(check-indentation indents-declaration/3
-  "
-let foo = [foo: bar, bar: baz]
-          |
-" "
-let foo = [foo: bar, bar: baz]
-|
-")
-
-(check-indentation indents-declaration/4
-  "
-let foo = [
-|bar: baz
-]
-" "
-let foo = [
-    |bar: baz
-]
-")
-
-(check-indentation indents-declaration/5
-  "
-let foo = [foo, bar]
-          |
-" "
-let foo = [foo, bar]
-|
-")
-
-(check-indentation indents-declaration/6
-  "
-let foo = [
-|bar
-]
-" "
-let foo = [
-    |bar
-]
-")
-
-(check-indentation indents-declaration/7
-                   "
-var result = Dictionary<String, V>()
-    |foo
-" "
-var result = Dictionary<String, V>()
-|foo
-")
-(check-indentation indents-declaration/8
-  "
-let foo =
-|bar
-" "
-let foo =
-    |bar
-")
-
-(check-indentation indents-declaration/9
-  "
-let foo: Foo? =
-|bar
-" "
-let foo: Foo? =
-    |bar
-")
-
-(check-indentation indents-declaration/10
-  "
-let foo: Foo<A> =
-|bar
-" "
-let foo: Foo<A> =
-    |bar
-")
-
-(check-indentation indents-declaration/11
-  "
-let foo = [
-    foo:
-|bar
-]
-" "
-let foo = [
-    foo:
-    |bar
-]
-")
-
-(check-indentation indents-declaration/12
-  "
-let foo = [
-|[]]
-" "
-let foo = [
-    |[]]
-")
-
-(check-indentation indents-declaration/13
-                   "
-let foo = [
-|[
-        bar: baz
-    ]
-]
-" "
-let foo = [
-    |[
-        bar: baz
-    ]
-]
-")
-
-(check-indentation indents-declaration/14
-                   "
-let foo = [
-    [
-    |bar: baz
-    ]
-]
-" "
-let foo = [
-    [
-        |bar: baz
-    ]
-]
-")
-
-(check-indentation indents-declaration/15
-                   "
-let foo = [
-    [
-        bar: baz
-|]
-]
-" "
-let foo = [
-    [
-        bar: baz
-    |]
-]
-")
-
-(check-indentation indents-expressions/1
-                   "
-class Foo {
-    func a() {
-    |[a]
-    }
-}
-" "
-class Foo {
-    func a() {
-        |[a]
-    }
-}
-")
-
-(check-indentation indents-expressions/2
-                   "
-class Foo {
-    func a() {
-        a
-    |[a]
-    }
-}
-" "
-class Foo {
-    func a() {
-        a
-        |[a]
-    }
-}
-")
-
-(check-indentation indents-multiline-expressions/1
-"
-Foo.bar([foo: bar,
-|bar: baz
-])
-" "
-Foo.bar([foo: bar,
-         |bar: baz
-])
-")
-
-(check-indentation indents-multiline-expressions/2
-                   "
-Foo.bar(bar!,
-|baz)
-" "
-Foo.bar(bar!,
-        |baz)
-")
-
-(check-indentation indents-multiline-expressions/3
-                   "
-Foo.bar(bar?,
-|baz)
-" "
-Foo.bar(bar?,
-        |baz)
-")
-
-(check-indentation indents-multiline-expressions/4
-                   "
-let json_ary = NSJSONSerialization.
-|JSONObjectWithData(data, options: nil, error: &json_err) as NSArray
-" "
-let json_ary = NSJSONSerialization.
-               |JSONObjectWithData(data, options: nil, error: &json_err) as 
NSArray
-")
-
-(check-indentation indents-multiline-expressions/5
-                   "
-let json_ary = NSJSONSerialization
-|.JSONObjectWithData(data, options: nil, error: &json_err) as NSArray
-" "
-let json_ary = NSJSONSerialization
-               |.JSONObjectWithData(data, options: nil, error: &json_err) as 
NSArray
-")
-
-(check-indentation indents-multiline-expressions/6
-                   "
-let json_ary = NSJSONSerialization.
-               |JSONObjectWithData(data, options: nil, error: &json_err) as 
NSArray
-" "
-let json_ary = NSJSONSerialization.
-               |JSONObjectWithData(data, options: nil, error: &json_err) as 
NSArray
-")
-
-(check-indentation indents-multiline-expressions/7
-                   "
-let json_ary = NSJSONSerialization
-               |.JSONObjectWithData(data, options: nil, error: &json_err) as 
NSArray
-" "
-let json_ary = NSJSONSerialization
-               |.JSONObjectWithData(data, options: nil, error: &json_err) as 
NSArray
-")
-
-(check-indentation indents-multiline-expressions/8
-                   "
-let options = NSRegularExpressionOptions.CaseInsensitive &
-|NSRegularExpressionOptions.DotMatchesLineSeparators
-" "
-let options = NSRegularExpressionOptions.CaseInsensitive &
-              |NSRegularExpressionOptions.DotMatchesLineSeparators
-")
-
-(check-indentation indents-multiline-expressions/9
-                   "
-foo?[bar] +
-     |a
-" "
-foo?[bar] +
-  |a
-")
-
-(check-indentation indents-multiline-expressions/10
-                   "
-foo?(bar) +
-     |a
-" "
-foo?(bar) +
-  |a
-")
-
-(check-indentation indents-multiline-expressions/11
-                   "
-func a () {
-    a +
-|a
-}
-" "
-func a () {
-    a +
-      |a
-}
-")
-
-(check-indentation indents-multiline-expressions/12
-                   "
-func a () {
-    a
-|.a()
-}
-" "
-func a () {
-    a
-      |.a()
-}
-")
-
-(check-indentation indents-multiline-expressions/13
-                   "
-if (a
-|.b){}
-" "
-if (a
-     |.b){}
-")
-
-(check-indentation indents-multiline-expressions/14
-                   "
-a ??
-|b
-" "
-a ??
-  |b
-")
-
-(check-indentation indents-multiline-expressions/15
-                   "
-a as
-|b
-" "
-a as
-  |b
-")
-
-(check-indentation indents-multiline-expressions/16
-                   "
-a as?
-|b
-" "
-a as?
-  |b
-")
-
-(check-indentation indents-multiline-expressions/17
-                   "
-a is
-|b
-" "
-a is
-  |b
-")
-
-(check-indentation indents-multiline-expressions/18
-                   "
-CGPoint(x: aaaaaaaaaaaaaaa.x +
-|bbbbbbbbbbbbbbbb,
-        y: aaaaaaaaaaaaaaa.y +
-           bbbbbbbbbbbbbbbb)
-" "
-CGPoint(x: aaaaaaaaaaaaaaa.x +
-           |bbbbbbbbbbbbbbbb,
-        y: aaaaaaaaaaaaaaa.y +
-           bbbbbbbbbbbbbbbb)
-")
-
-(check-indentation indents-multiline-expressions/19
-                   "
-let x = 1
-|+ 1
-" "
-let x = 1
-        |+ 1
-")
-
-(check-indentation indents-multiline-expressions/20
-                   "
-let x = foo ??
-            |bar
-" "
-let x = foo ??
-        |bar
-")
-
-(check-indentation indents-multiline-expressions/21
-                   "
-let foo = a +
-          b +
-            |c +
-          d
-" "
-let foo = a +
-          b +
-          |c +
-          d
-")
-
-(check-indentation indents-multiline-expressions/22
-                   "
-let foo = a +
-          b +
-          c +
-              |d
-" "
-let foo = a +
-          b +
-          c +
-          |d
-")
-
-(check-indentation indents-multiline-expressions/23
-                   "
-let x = bar
-        .buz() ??
-|defaultValue
-" "
-let x = bar
-        .buz() ??
-        |defaultValue
-")
-
-(check-indentation indents-multiline-expressions/24
-  "
-let foo =
-    bar +
-  |baz +
-    a
-" "
-let foo =
-    bar +
-    |baz +
-    a
-")
-
-(check-indentation indents-long-parameters/1
-                   "
-func foo() {
-    timer = NSTimer.scheduledTimerWithTimeInterval(
-            |1.0,
-                target: self,
-                selector: Selector(\"onTimer\"),
-                userInfo: nil,
-                repeats: true)
-}
-" "
-func foo() {
-    timer = NSTimer.scheduledTimerWithTimeInterval(
-                |1.0,
-                target: self,
-                selector: Selector(\"onTimer\"),
-                userInfo: nil,
-                repeats: true)
-}
-")
-
-(check-indentation indents-long-parameters/2
-                   "
-aaaaaa.aaaaaaaaaaaaaaaaaaaaa(
-  |aaaaaaaaaaaaaaaaaaaaa
-)
-" "
-aaaaaa.aaaaaaaaaaaaaaaaaaaaa(
-    |aaaaaaaaaaaaaaaaaaaaa
-)
-")
-
-(check-indentation indents-long-parameters/3
-                   "
-public func tableView(
-|tableView: UITableView,
-    commitEditingStyle editingStyle: UITableViewCellEditingStyle,
-    forRowAtIndexPath indexPath: NSIndexPath) {
-}
-" "
-public func tableView(
-    |tableView: UITableView,
-    commitEditingStyle editingStyle: UITableViewCellEditingStyle,
-    forRowAtIndexPath indexPath: NSIndexPath) {
-}
-")
-
-(check-indentation indents-long-parameters/4
-                   "
-func a(
-        |a: a,
-    a: a,
-    a: a) {
-}
-" "
-func a(
-    |a: a,
-    a: a,
-    a: a) {
-}
-")
-
-(check-indentation indents-long-parameters/5
-                   "
-func foo() {
-    timer = NSTimer.scheduledTimerWithTimeInterval(
-                1.0,
-                target: self,
-                selector: Selector(\"onTimer\"),
-                userInfo: nil,
-                repeats: true
-|)
-}
-" "
-func foo() {
-    timer = NSTimer.scheduledTimerWithTimeInterval(
-                1.0,
-                target: self,
-                selector: Selector(\"onTimer\"),
-                userInfo: nil,
-                repeats: true
-            |)
-}
-")
-
-(check-indentation indents-multiline-expressions-to-user-defined-offset/1
-                   "
-NSNotificationCenter.defaultCenter()
-|.postNotificationName(foo, object: nil)
-" "
-NSNotificationCenter.defaultCenter()
-    |.postNotificationName(foo, object: nil)
-"
-((swift-indent-multiline-statement-offset 4)))
-
-(check-indentation indents-multiline-expressions-to-user-defined-offset/2
-                   "
-let json_ary = NSJSONSerialization
-               |.JSONObjectWithData(data, options: nil, error: &json_err) as 
NSArray
-" "
-let json_ary = NSJSONSerialization
-                 |.JSONObjectWithData(data, options: nil, error: &json_err) as 
NSArray
-"
-((swift-indent-multiline-statement-offset 4)))
-
-(check-indentation indents-multiline-expressions-to-user-defined-offset/3
-                   "
-let options = NSRegularExpressionOptions.CaseInsensitive &
-|NSRegularExpressionOptions.DotMatchesLineSeparators
-" "
-let options = NSRegularExpressionOptions.CaseInsensitive &
-              |NSRegularExpressionOptions.DotMatchesLineSeparators
-"
-((swift-indent-multiline-statement-offset 4)))
-
-(check-indentation indents-type-annotations/1
-                   "
-typealias Foo = Bar<Foo.Baz, Foo>
-    |foo
-" "
-typealias Foo = Bar<Foo.Baz, Foo>
-|foo
-")
-
-(check-indentation indents-type-annotations/2
-                   "
-typealias Foo = Bar<Foo.Baz,
-|Foo>
-" "
-typealias Foo = Bar<Foo.Baz,
-                    |Foo>
-")
-
-(check-indentation indents-type-works-with-less-operator/1
-                   "
-typealias Foo = Bar<Foo.Baz, Foo>
-let foo = bar <
-|baz
-" "
-typealias Foo = Bar<Foo.Baz, Foo>
-let foo = bar <
-          |baz
-")
-
-(check-indentation indents-type-works-with-less-operator/2
-                   "
-typealias Foo = Bar<Foo.Baz, Foo>
-let foo = bar >
-|baz
-" "
-typealias Foo = Bar<Foo.Baz, Foo>
-let foo = bar >
-          |baz
-")
-
-(check-indentation indents-multiline-operators-only-once/1
-                   "
-1 +
-  2 + 5 *
-|3
-" "
-1 +
-  2 + 5 *
-      |3
-"
-)
-
-(check-indentation indents-multiline-operators-only-once/2
-                   "
-1 +
-  2 * 5 +
-|3
-" "
-1 +
-  2 * 5 +
-  |3
-"
-)
-
-(check-indentation conditional-operator/1
-                   "
-let a = a
-        |? a +
-          1
-        : a +
-          1
-" "
-let a = a
-        |? a +
-          1
-        : a +
-          1
-")
-
-(check-indentation conditional-operator/2
-                   "
-let a = a
-        ? a +
-          |1
-        : a +
-          1
-" "
-let a = a
-        ? a +
-          |1
-        : a +
-          1
-")
-
-(check-indentation conditional-operator/3
-                   "
-let a = a
-        ? a +
-          1
-        |: a +
-          1
-" "
-let a = a
-        ? a +
-          1
-        |: a +
-          1
-")
-
-(check-indentation conditional-operator/4
-                   "
-let a = a
-        ? a +
-          1
-        : a +
-          |1
-" "
-let a = a
-        ? a +
-          1
-        : a +
-          |1
-")
-
-(check-indentation conditional-operator/5
-                   "
-let a = a ?
-|a : a
-" "
-let a = a ?
-        |a : a
-")
-
-(check-indentation conditional-operator/6
-                   "
-let a = a ?
-      |b :
-        c
-" "
-let a = a ?
-        |b :
-        c
-")
-
-(check-indentation conditional-operator/7
-                   "
-let a = a ?
-        b :
-      |c
-" "
-let a = a ?
-        b :
-        |c
-")
-
-(check-indentation conditional-operator/8
-                   "
-let a = a //foo
-        |? a +
-          1
-        : a +
-          1
-" "
-let a = a //foo
-        |? a +
-          1
-        : a +
-          1
-")
-
-(check-indentation conditional-operator/9
-                   "
-func foo() {
-    return order!.deliver ?
-         |OrderViewTableDeliveryCells.lastCellIndex.rawValue :
-           OrderViewTableTakeAwayCells.lastCellIndex.rawValue
-}
-" "
-func foo() {
-    return order!.deliver ?
-           |OrderViewTableDeliveryCells.lastCellIndex.rawValue :
-           OrderViewTableTakeAwayCells.lastCellIndex.rawValue
-}
-")
-
-(check-indentation conditional-operator/10
-                   "
-func foo() {
-    return order!.deliver ?
-           OrderViewTableDeliveryCells.lastCellIndex.rawValue :
-         |OrderViewTableTakeAwayCells.lastCellIndex.rawValue
-}
-" "
-func foo() {
-    return order!.deliver ?
-           OrderViewTableDeliveryCells.lastCellIndex.rawValue :
-           |OrderViewTableTakeAwayCells.lastCellIndex.rawValue
-}
-")
-
-(check-indentation conditional-operator/11
-                   "
-let a = a ? a +
-              1
-        |: a +
-              1
-" "
-let a = a ? a +
-              1
-          |: a +
-              1
-")
-
-(check-indentation blank-line/1
-                   "
-func foo() {
-    let a = 1
-
-|let b = 1
-}
-" "
-func foo() {
-    let a = 1
-
-    |let b = 1
-}
-")
-
-(check-indentation block-inside-parenthesis/3
-  "
-\({
-|a
-})
-" "
-\({
-     |a
-})
-")
-
-(check-indentation indent-long-if-else-if/1
-  "
-if a {
-    a
-} else if a {
-    a
-} else if a {
-    |a
-} else {
-    a
-}
-" "
-if a {
-    a
-} else if a {
-    a
-} else if a {
-    |a
-} else {
-    a
-}
-")
-
-(check-indentation indent-long-if-else-if/2
-  "
-if a {
-    a
-} else if a {
-    a
-} else if a {
-    a
-|} else {
-    a
-}
-" "
-if a {
-    a
-} else if a {
-    a
-} else if a {
-    a
-|} else {
-    a
-}
-")
-
-(check-indentation indent-long-if-else-if/3
-  "
-class Foo {
-    func a() {
-        if a {
-            a
-        } else if b {
-        |a
-        } else if a {
-            a
-        } else {
-            a
-        }
-    }
-}
-" "
-class Foo {
-    func a() {
-        if a {
-            a
-        } else if b {
-            |a
-        } else if a {
-            a
-        } else {
-            a
-        }
-    }
-}
-")
-
-(check-indentation indent-long-if-else-if/4
-  "
-class Foo {
-    func a() {
-        if a {
-            a
-        } else if b {
-            a
-    |} else if a {
-            a
-        } else {
-            a
-        }
-    }
-}
-" "
-class Foo {
-    func a() {
-        if a {
-            a
-        } else if b {
-            a
-        |} else if a {
-            a
-        } else {
-            a
-        }
-    }
-}
-")
-
-(check-indentation anonymous-function-as-a-argument/1
-                   "
-UIView.animateWithDuration(1.0,
-                           animations: {
-|})
-" "
-UIView.animateWithDuration(1.0,
-                           animations: {
-                           |})
-")
-
-(check-indentation anonymous-function-as-a-argument/2
-                   "
-UIView.animateWithDuration(
-    1.0,
-    animations: {
-|})
-" "
-UIView.animateWithDuration(
-    1.0,
-    animations: {
-    |})
-")
-
-(check-indentation anonymous-function-as-a-argument/3
-                   "
-func foo() {
-    UIView.animateWithDuration(1.0,
-                               animations: {
-                                   |}
-    ) {
-        completed in
-    }
-}
-" "
-func foo() {
-    UIView.animateWithDuration(1.0,
-                               animations: {
-                               |}
-    ) {
-        completed in
-    }
-}
-")
-
-(check-indentation anonymous-function-as-a-argument/4
-                   "
-func foo() {
-    UIView.animateWithDuration(1.0,
-                               animations: {
-                               }
-|) {
-        completed in
-    }
-}
-" "
-func foo() {
-    UIView.animateWithDuration(1.0,
-                               animations: {
-                               }
-    |) {
-        completed in
-    }
-}
-")
-
-(check-indentation anonymous-function-as-a-argument/5
-                   "
-foo.bar(10,
-        completionHandler: { complete in
-        |foo
-        }
-)
-" "
-foo.bar(10,
-        completionHandler: { complete in
-            |foo
-        }
-)
-")
-
-(check-indentation anonymous-function-as-a-argument/6
-                   "
-foo.bar(10,
-        completionHandler: {
-            complete in
-        |foo
-        }
-)
-" "
-foo.bar(10,
-        completionHandler: {
-            complete in
-            |foo
-        }
-)
-")
-
-(check-indentation anonymous-function-as-a-argument/7
-                   "
-foo.bar(10,
-        completionHandler: { (
-        |bar, baz) in
-            foo
-        }
-)
-" "
-foo.bar(10,
-        completionHandler: { (
-            |bar, baz) in
-            foo
-        }
-)
-")
-
-(check-indentation anonymous-function-as-a-argument/8
-                   "
-foo.bar(10,
-        completionHandler: { (bar, baz) -> Void in
-        |foo
-        })
-" "
-foo.bar(10,
-        completionHandler: { (bar, baz) -> Void in
-            |foo
-        })
-")
-
-(check-indentation anonymous-function-as-a-argument/9
-                   "
-foo.bar(10,
-        completionHandler: { complete in
-
-            if foo {
-                bar
-            } else {
-            |bar
-            }
-        }
-)
-" "
-foo.bar(10,
-        completionHandler: { complete in
-
-            if foo {
-                bar
-            } else {
-                |bar
-            }
-        }
-)
-")
-
-(check-indentation anonymous-function-as-a-argument/10
-                   "
-foo.bar(10,
-        completionHandler: { complete in
-
-            if foo {
-                bar
-            } else {
-                bar
-        |}
-        }
-)
-" "
-foo.bar(10,
-        completionHandler: { complete in
-
-            if foo {
-                bar
-            } else {
-                bar
-            |}
-        }
-)
-")
-
-(check-indentation trailing-closure/1
-                   "
-a(){
-    (b: String, c:String) -> String in
-        |println(c)
-}
-" "
-a(){
-    (b: String, c:String) -> String in
-    |println(c)
-}
-")
-
-(check-indentation trailing-closure/2
-                   "
-a(){
-    b,c in
-        |println(c)
-}
-" "
-a(){
-    b,c in
-    |println(c)
-}
-")
-
-(check-indentation indents-expression-with-optional-type/1
-                   "
-var object: JsonObject?
-    |var object: JsonObject
-" "
-var object: JsonObject?
-|var object: JsonObject
-")
-
-(check-indentation indents-expression-with-optional-type/2
-                   "
-var object: JsonObject<Foo>?
-    |var object: JsonObject
-" "
-var object: JsonObject<Foo>?
-|var object: JsonObject
-")
-
-(check-indentation indents-expression-with-implicit-unwrapped-type/1
-                   "
-var object: JsonObject!
-    |var object: JsonObject
-" "
-var object: JsonObject!
-|var object: JsonObject
-")
-
-(check-indentation indents-expression-with-implicit-unwrapped-type/2
-                   "
-var object: JsonObject<Foo>!
-    |var object: JsonObject
-" "
-var object: JsonObject<Foo>!
-|var object: JsonObject
-")
-
-(check-indentation indents-expression-with-comment/1
-                   "
-func foo() {
-    foo() // foo
-       |foo()
-}
-" "
-func foo() {
-    foo() // foo
-    |foo()
-}
-")
-
-(check-indentation indents-expression-with-comment/2
-                   "
-func foo() {
-    let x = 1 // foo
-    |/ 1
-}
-" "
-func foo() {
-    let x = 1 // foo
-            |/ 1
-}
-")
-
-(check-indentation indents-expression-with-comment/3
-                   "
-func foo() {
-    foo()
-    //
-        |foo()
-}
-" "
-func foo() {
-    foo()
-    //
-    |foo()
-}
-")
-
-(check-indentation indents-guard-statement/1
-                   "
-guard let x = y else {
-        |return
-}
-" "
-guard let x = y else {
-    |return
-}
-")
-
-(provide 'indentation-tests)
-
-;;; indentation-tests.el ends here
diff --git a/test/swift-files/comment.swift b/test/swift-files/comment.swift
new file mode 100644
index 0000000..8c44d03
--- /dev/null
+++ b/test/swift-files/comment.swift
@@ -0,0 +1,35 @@
+// swift-mode:test:eval (setq-local swift-mode:basic-offset 4)
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
2)
+// swift-mode:test:eval (setq-local swift-mode:multiline-statement-offset 2)
+// swift-mode:test:eval (setq-local swift-mode:switch-case-offset 0)
+
+// aaa
+// bbb
+// ccc
+/*
+ * aa
+ * aa
+ * aa
+ */
+
+/* */ class Foo {
+    // aaa
+    // bbb
+      // ccc // swift-mode:test:keep-indent
+      // ddd // swift-mode:test:known-bug
+      /* // swift-mode:test:known-bug
+       * aa
+         * aa // swift-mode:test:keep-indent
+         * aa
+         */
+}
+
+@Annotation(aaa)
+private
+  /* */ final /*
+               */ class /*
+                         */ Foo /*
+                                 */ {
+    aaa()
+    bbb()
+}
diff --git a/test/swift-files/declarations.swift 
b/test/swift-files/declarations.swift
new file mode 100644
index 0000000..3f9549b
--- /dev/null
+++ b/test/swift-files/declarations.swift
@@ -0,0 +1,376 @@
+// swift-mode:test:eval (setq-local swift-mode:basic-offset 4)
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
2)
+// swift-mode:test:eval (setq-local swift-mode:multiline-statement-offset 2)
+// swift-mode:test:eval (setq-local swift-mode:switch-case-offset 0)
+
+// Constant declarations
+
+let
+  foo
+  .bar
+  =
+  bar
+  .baz
+
+class Foo {
+    @ABC
+    open
+      weak
+      let
+      (
+        x,
+        y
+      )
+      :
+      (
+        Int,
+        Int
+      )
+      =
+      xx
+
+    @ABC
+    final
+      unowned(safe)
+      fileprivate
+      let
+      Foo
+      .Bar(x)
+      :
+      Foo
+      .Bar
+      =
+      xx
+
+    let f
+      = g
+      :
+      (
+        Int,
+        Int
+      )
+      ->
+      throws
+      [
+        X
+      ]
+
+
+    let x = 1,
+        y = 1,
+        z = 1
+
+    let
+      x = 1,
+      y = 1,
+      z = 1
+
+    let x = 1
+      , y = 1
+      , z = 1
+
+    // Declaring multiple variables with single `let` statement doesn't seem to
+    // be popular. Rather, we choose saving columns for the first variable.
+    private final let x = foo
+      .foo // This is intended.
+      .foo,
+                      y = foo
+                        .then { x // This is intended.
+                                in
+                            foo
+
+                            return foo
+                        }
+                        .then { x
+                                in
+                            foo
+
+                            return foo
+                        },
+                      z = foo
+                        .foo
+                        .foo
+}
+
+// Variable declarations
+
+class Foo {
+    internal var x = foo
+      .foo
+      .foo,
+                 y = foo
+                   .foo
+                   .foo,
+                 z = foo
+                   .foo
+                   .foo
+
+    internal var x
+      : (Int, Int) {
+        foo()
+
+        return foo()
+    }
+
+    internal var x
+      : (Int, Int) {
+        @A
+        mutating
+          get {
+            foo()
+
+            return foo()
+        }
+
+        @A
+        mutating
+          set
+          (it) {
+            foo()
+            foo(it)
+        }
+    }
+
+    internal var x
+      : (Int, Int) {
+        @A
+        mutating
+          get
+
+        @A
+        mutating
+          set
+    }
+
+    internal var x
+      :
+      (Int, Int)
+      =
+      foo
+      .bar {
+          return thisIsFunctionBlock
+      } {
+          // This is bad, but cannot decide indentation without looking forward
+          // tokens.
+          @A
+          willSet(a) {
+              foo()
+              foo()
+          }
+
+          @A
+          didSet(a) {
+              foo()
+              foo()
+          }
+      } // This is bad
+
+    internal var x
+      :
+      (Int, Int) {
+        @A
+        willSet(a) {
+            foo()
+            foo()
+        }
+
+        @A
+        didSet(a) {
+            foo()
+            foo()
+        }
+    }
+}
+
+// Type alias declaration
+
+class Foo {
+    typealias A<B> = C
+      .D
+
+    @A
+    private typealias A<B>
+      =
+      C
+      .D
+}
+
+// Function declarations
+
+@A
+private
+  final
+  func
+  foo<A, B>(
+    x:
+      Int
+    y:
+      Int
+      =
+      1
+    z
+    w:
+      Int
+      ...
+  )
+  throws
+  ->
+  [A]
+  where
+    A:
+      C,
+    B =
+      C<D> {
+    foo()
+    foo()
+}
+
+func
+  foo()
+  ->
+  @A
+  B {
+    foo()
+    foo()
+}
+
+// Enumeration declarations
+
+fileprivate
+  indirect
+  enum
+  Foo<A, B>
+  : X,
+    Y,
+    Z
+  where
+    A:
+      C,
+    B =
+      D<E> {
+    @A
+    case A
+    case B
+    case C,
+         D,
+         E
+    indirect
+      case
+      F(
+        x:
+          X,
+        y:
+          Y
+      ),
+      G,
+      H
+
+    func foo() {
+    }
+
+    case I
+    case J
+}
+
+fileprivate
+  enum
+  Foo<A, B>
+  :
+  Int
+  where
+    A:
+      C,
+    B =
+      D<E> {
+    case A =
+           1, // swift-mode:test:known-bug
+         B =
+           2,
+         C =
+           3
+    case D
+           = 1, // swift-mode:test:known-bug
+         E
+           = 2,
+         F
+           = 3
+
+    func foo() {
+    }
+}
+
+
+enum Foo
+  : X,
+    Y,
+    Z {
+}
+
+enum Foo
+  : X
+  , Y
+  , Z
+{
+}
+
+// Struct declarations
+
+@A
+fileprivate
+  struct
+  Foo<A, B>
+  : Bar<A, B>,
+    Baz<A, B>,
+    AAA<A, B>
+  where
+    A:
+      C,
+    B =
+      D<E> {
+    func foo()
+    func foo()
+}
+
+// Protocol declarations
+
+protocol Foo {
+    func foo(x, y) -> throws (A, B)
+    init<A, B>(x: Int) throws
+      where
+        A: C
+    subscript(x: Int) -> Int {
+        get
+        set
+    }
+    associatedtype AAA = BBB
+    convenience
+      init(x: Int, y, Int)
+}
+
+// Operator declarations
+
+infix
+  operator
+  +++
+  :
+  precedenceGroupName
+
+prefix
+  operator
+  +++
+
+postfix
+  operator
+  +++
+
+precedencegroup
+  precedenceGroupName {
+    higherThan:
+      lowerGroupName
+    lowerThan:
+      higherGroupName
+    assignment:
+      false
+    associativity:
+      left
+}
diff --git a/test/swift-files/expressions.swift 
b/test/swift-files/expressions.swift
new file mode 100644
index 0000000..c34bc21
--- /dev/null
+++ b/test/swift-files/expressions.swift
@@ -0,0 +1,571 @@
+// swift-mode:test:eval (setq-local swift-mode:basic-offset 4)
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
2)
+// swift-mode:test:eval (setq-local swift-mode:multiline-statement-offset 2)
+// swift-mode:test:eval (setq-local swift-mode:switch-case-offset 0)
+
+// Prefix expressions
+// See also operators.swift
+
+foo(
+  +a,
+  +b,
+  &x
+)
+
+// Try operators
+
+let foo = try
+  a() + try
+  b()
+
+let foo = try!
+  a() + try!
+  b()
+
+let foo = try?
+  a() + try?
+  b()
+
+let foo = a+try
+  a() +b+try
+  b()
+
+let foo = a+try!
+  a() + b+try!
+  b()
+
+let foo = a+try?
+  a() + b+try?
+  b()
+
+// Binary expressions
+// See also operators.swift
+
+let foo = 1 +
+  /* */ 2 +
+  3 + 4 +
+  /* */ 5
+
+let foo = 1 +
+  2 +
+    3 + 4 + // swift-mode:test:keep-indent
+    5
+
+// swift-mode:test:eval (setq-local swift-mode:multiline-statement-offset 4)
+
+let foo = 1 +
+    2 +
+    3 + 4 +
+    5
+
+// swift-mode:test:eval (setq-local swift-mode:multiline-statement-offset 2)
+
+// Ternary conditional operator
+
+let foo = a()
+  ? b()
+  : c()
+
+let foo = a() ?
+  b() :
+  c()
+
+// Type-casting operators
+
+let foo = a is
+  A || b is
+  B
+
+let foo = a
+  is A || b
+  is B
+
+let foo = a as
+  A +++ b as
+  B
+
+let foo = a
+  as A +++ b
+  as B
+
+let foo = a as?
+  A +++ b as?
+  B
+
+let foo = a
+  as? A +++ b
+  as? B
+
+let foo = a as!
+  A +++ b as!
+  B
+
+let foo = a
+  as! A +++ b
+  as! B
+
+// Literal expression
+
+// Special literal
+
+let foo =
+  #file
+
+let foo = #file
+  +++ #function
+
+if
+  #file == a {
+}
+
+// Array literal
+
+let x = [
+  1,
+  2,
+  3, 4,
+  5
+]
+
+let x = [
+  1,
+  2,
+  3, 4,
+  5,
+]
+
+let x =
+  [
+    1,
+    2,
+    3, 4,
+    5
+  ]
+
+let x = [ 1,
+          2,
+          3, 4,
+          5 ]
+
+let x =
+  [ 1
+  , 2
+  , 3, 4
+  , 5
+  ]
+
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
3)
+
+let x = [
+   1,
+   2,
+   3, 4,
+   5
+]
+
+let x = [
+   1,
+   2,
+   3, 4,
+   5,
+]
+
+let x =
+  [
+     1,
+     2,
+     3, 4,
+     5
+  ]
+
+let x = [ 1,
+          2,
+          3, 4,
+          5 ]
+
+let x =
+  [ 1
+  , 2
+  , 3, 4
+  , 5 ]
+
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
2)
+
+// Dictionary literal
+
+let x = [
+  aaa:
+    aaa
+    + aaa,
+  aaa:
+    aaa
+    + aaa,
+  aaa: aaa, aaa:
+              aaa
+              + aaa,
+  aaa
+    : aaa
+    + aaa,
+  aaa: aaa, aaa
+              : aaa
+              + aaa,
+  aaa
+    : aaa
+    + aaa
+]
+
+let x =
+  [
+    aaa:
+      aaa
+      + aaa,
+    aaa:
+      aaa
+      + aaa,
+    aaa: aaa, aaa:
+                aaa
+                + aaa,
+    aaa
+      : aaa
+      + aaa,
+    aaa: aaa, aaa
+                : aaa
+                + aaa,
+    aaa
+      : aaa
+      + aaa
+  ]
+
+let x = [ aaa:
+            aaa
+            + aaa,
+          aaa:
+            aaa
+            + aaa,
+          aaa: aaa, aaa:
+                      aaa
+                      + aaa,
+          aaa:
+            aaa
+            + aaa
+          aaa
+            : aaa
+            + aaa,
+          aaa: aaa, aaa
+                      : aaa
+                      + aaa,
+          aaa
+            : aaa
+            + aaa ]
+
+let x = [
+  :
+]
+
+let x =
+  [
+    :
+  ]
+
+let x = [ :
+]
+
+// Closure expressions
+
+let x = {
+    println("Hello, World!")
+    println("Hello, World!")
+}
+
+let x = { x in
+    println("Hello, World! " + x)
+    println("Hello, World! " + x)
+}
+
+let x = { x
+          in
+    println("Hello, World! " + x)
+    println("Hello, World! " + x)
+}
+
+let x = {
+    x in
+    println("Hello, World! " + x)
+    println("Hello, World! " + x)
+}
+
+let x = {
+    x
+    in
+    println("Hello, World! " + x)
+    println("Hello, World! " + x)
+}
+
+let x = { (
+            x: Int,
+            y: Int
+          )
+            ->
+            throws
+            Foo
+          in
+    println("Hello, World! " + x + y)
+    println("Hello, World! " + x + y)
+
+    return foo
+}
+
+let x = { [
+            weak
+              self,
+            unowned(unsafe)
+              foo
+          ]
+          (
+            x: Int,
+            y: Int
+          )
+            throws
+            ->
+            Foo
+          in
+    println("Hello, World! " + x + y)
+    println("Hello, World! " + x + y)
+
+    return foo
+}
+
+let x = {
+    [
+      weak self,
+      weak foo
+    ]
+    (
+      x: Int,
+      y: Int
+    )
+      throws
+      ->
+      Foo
+    in
+    println("Hello, World! " + x + y)
+    println("Hello, World! " + x + y)
+
+    return foo
+}
+
+
+let x = { a,
+          b,
+          c, d,
+          e
+          in
+    println("Hello, World! " + x + y)
+}
+
+let x = {
+    a,
+    b,
+    c, d,
+    e
+    in
+    println("Hello, World! " + x + y)
+}
+
+let x = { a
+        , b
+        , c, d
+        , e
+          in
+    println("Hello, World! " + x + y)
+}
+
+// Implicit member expressions
+
+x =
+  .aaa
+
+// Parenthesized expressions
+
+let x = (
+  a,
+  b, c,
+  d,
+  e,
+  ++,
+  **, --,
+  aaa
+)
+
+let x = (
+  aaa:
+    a,
+  aaa: b, aaa:
+            c,
+  aaa:
+    d,
+  aaa
+    :e,
+  aaa:
+    ++,
+  aaa: **, aaa:
+             --,
+  aaa:
+    aaa
+)
+
+let x =
+  (
+    1,
+    2,
+    3, 4,
+    5
+  )
+
+let x = ( 1,
+          2,
+          3, 4,
+          5 )
+
+let x =
+  ( 1
+  , 2
+  , 3, 4
+  , 5
+  )
+
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
3)
+
+
+let x = (
+   a,
+   b, c,
+   d,
+   e,
+   ++,
+   **, --,
+   aaa
+)
+
+let x = (
+   aaa:
+     a,
+   aaa: b, aaa:
+             c,
+   aaa:
+     d,
+   aaa
+     :e,
+   aaa:
+     ++,
+   aaa: **, aaa:
+              --,
+   aaa:
+     aaa
+)
+
+let x =
+  (
+     1,
+     2,
+     3, 4,
+     5
+  )
+
+let x = ( 1,
+          2,
+          3, 4,
+          5 )
+
+let x =
+  ( 1
+  , 2
+  , 3, 4
+  , 5
+  )
+
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
2)
+
+// Selector expressions
+
+let x =
+  #selector(
+    Foo.bar(
+      _:,
+      aaa:,
+      bbb:
+    )
+  )
+
+let x =
+  #selector(
+    getter:
+      Foo.ppp
+  )
+
+// Funcation call expressions and explicit member expressions
+
+let x =
+  foo(a,
+      b,
+      c)
+
+let x =
+  foo(
+    a,
+    b,
+    c
+  )
+
+let x = foo
+  .bar(a:
+         aaa,
+       b:
+         bbb(c:
+               c,
+             c:
+               c) { x in
+             foo
+             bar
+         },
+       c:
+         aaaa[
+           aaa
+         ]
+  ) { aaa in
+      aaa
+      aaa
+      aaa
+  }
+
+let x = foo
+  .bar() { a in
+      aaa
+  }
+
+let x = foo
+  .bar() {
+      a in
+      aaa
+  }
+
+let x = foo
+  .bar() {
+      a
+      in
+      aaa
+  }
+
+foo
+(bar) // this is not a function call
+
+// Subscript expression
+
+foo[
+  1,
+  2, 3,
+  4
+]
+
+foo
+[1] // this is not a subscript expression
diff --git a/test/swift-files/identifiers.swift 
b/test/swift-files/identifiers.swift
new file mode 100644
index 0000000..7bff27f
--- /dev/null
+++ b/test/swift-files/identifiers.swift
@@ -0,0 +1,40 @@
+// swift-mode:test:eval (setq-local swift-mode:basic-offset 4)
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
2)
+// swift-mode:test:eval (setq-local swift-mode:multiline-statement-offset 2)
+// swift-mode:test:eval (setq-local swift-mode:switch-case-offset 0)
+
+
+// Backquoted identifier must behave like normal identifier
+
+enum `switch` {
+    case 1
+}
+
+do {
+} catch `case`
+          where a
+
+
+let foo = `var`
+  .then {
+  }
+
+let x = `where` +
+  a
+
+
+// Keywords after dot must behave like normal identifier
+// 
https://github.com/apple/swift-evolution/blob/master/proposals/0071-member-keywords.md
+
+let foo = foo.var
+  .then {
+  }
+
+let x = foo.where +
+  a
+
+// Unicode identifiers
+
+let こんにちは = 你好 +
+  안녕하세요 +
+  😊
diff --git a/test/swift-files/operators.swift b/test/swift-files/operators.swift
new file mode 100644
index 0000000..7f95ef6
--- /dev/null
+++ b/test/swift-files/operators.swift
@@ -0,0 +1,70 @@
+// swift-mode:test:eval (setq-local swift-mode:basic-offset 4)
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
2)
+// swift-mode:test:eval (setq-local swift-mode:multiline-statement-offset 2)
+// swift-mode:test:eval (setq-local swift-mode:switch-case-offset 0)
+
+
+// Simple case
+
+let x = 1 +
+  2 +
+  3 + 4 +
+  5
+
+let x = 1
+  + 2
+  + 3 + 4
+  + 5
+
+// User defined operator
+
+let x = 1 +++
+  2 /=-+!*%<>&|^?~
+  3 +++ 4 +++
+  5
+
+// Prefix operators and postfix operators
+
+let x = 1
++++foo()
+
+let x = 1+++
+foo()
+
+// Comments precede over operators
+
+let x = 1 +// abc
+  2 +/* abc*/
+  3
+
+// Comments behave like whitespaces
+// 
https://github.com/apple/swift-evolution/blob/master/proposals/0037-clarify-comments-and-operators.md
+let x = 1
+/*a*/+++foo()
+
+let x = 1
+  /*a*/+++ foo()
+
+let x = 1+++//
+foo()
+
+let x = 1+++/*a*/
+foo()
+
+let x = 1 +++/*a*/
+  foo()
+
+// Operators with dot
+
+// This must be equal to let x = (a.++.) a
+let x = a.++.
+b
+
+// This must be equal to let x = (a++) . a
+let x = a++.
+  a
+
+// Unicode operators
+
+let x = a ×
+  a  // swift-mode:test:known-bug
diff --git a/test/swift-files/statements.swift 
b/test/swift-files/statements.swift
new file mode 100644
index 0000000..67c6a28
--- /dev/null
+++ b/test/swift-files/statements.swift
@@ -0,0 +1,805 @@
+// swift-mode:test:eval (setq-local swift-mode:basic-offset 4)
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
2)
+// swift-mode:test:eval (setq-local swift-mode:multiline-statement-offset 2)
+// swift-mode:test:eval (setq-local swift-mode:switch-case-offset 0)
+
+// For-in statements
+
+for x in xs {
+    foo()
+    foo()
+}
+
+for x
+    in xs {
+    foo()
+    foo()
+}
+
+for x in
+    xs {
+    foo()
+    foo()
+}
+
+for x
+    in
+    xs {
+    foo()
+    foo()
+}
+
+for
+  x
+  in
+  xs {
+    foo()
+    foo()
+}
+
+for
+  x
+  in xs
+    .foo() { // swift-mode:test:known-bug
+    foo()
+    foo()
+}
+
+for
+  (
+    x,
+    y
+  )
+  in
+  xs
+    .foo() +++ { z in // swift-mode:test:known-bug
+        bar()
+    } {
+    foo()
+    foo()
+}
+
+for
+  case
+    ( // swift-mode:test:known-bug
+      x,
+      y
+    )
+  in
+  xs
+    .foo() +++ { z in // swift-mode:test:known-bug
+        bar()
+        bar()
+    } {
+    foo()
+    foo()
+}
+
+for case
+      ( // swift-mode:test:known-bug
+        x,
+        y
+      )
+    in
+    xs
+      .foo() +++ { z in // swift-mode:test:known-bug
+          bar()
+          bar()
+      } {
+    foo()
+    foo()
+}
+
+
+for Foo
+      .Bar(x) // swift-mode:test:known-bug
+    in
+    xs {
+    foo()
+    foo()
+}
+
+for
+  Foo
+    .Bar(x) // swift-mode:test:known-bug
+  in
+  xs {
+    foo()
+    foo()
+}
+
+
+
+for x as
+      Foo // swift-mode:test:known-bug
+    in
+    xs {
+    foo()
+    foo()
+}
+
+
+for x
+    in
+    xs
+      .foo // swift-mode:test:known-bug
+    where // swift-mode:test:known-bug
+      aaa
+        .bbb(x) {
+    foo()
+    foo()
+}
+
+for x
+    in
+    xs where
+      aaa
+        .bbb(x) {
+    foo()
+    foo()
+}
+
+for x
+    in
+    xs
+      where aaa
+        .bbb(x) { // swift-mode:test:known-bug
+    foo()
+    foo()
+}
+
+for x
+    in
+    xs where aaa
+      .bbb(x) { // swift-mode:test:known-bug
+    foo()
+    foo()
+}
+
+for
+  x in xs
+    where
+      aaa.bbb(x) {
+    foo()
+    foo()
+}
+
+// While statements
+
+while foo
+        .bar() +++ { x in
+            foo()
+            foo()
+        } {
+    foo()
+    foo()
+}
+
+while
+  foo
+    .bar() +++ { x in
+        foo()
+        foo()
+    } {
+    foo()
+    foo()
+}
+
+while
+  let
+    x
+    =
+    xx,
+  var
+    y
+    =
+    yy,
+  x
+    ==
+    y,
+  case
+    (
+      a,
+      b
+    )
+    =
+    ab {
+    foo()
+    foo()
+}
+
+while let
+        x
+        =
+        xx,
+      var
+        y
+        =
+        yy,
+      x
+        ==
+        y,
+      case
+        (
+          a,
+          b
+        )
+        =
+        ab {
+    foo()
+    foo()
+}
+
+
+while let
+        x
+        =
+        xx
+    , var
+        y
+        =
+        yy
+    , x
+        ==
+        y
+    , case
+        (
+          a,
+          b
+        )
+        =
+        ab
+{
+    foo()
+    foo()
+}
+
+// Repeat-while statements
+
+repeat {
+    foo()
+    foo()
+} while foo
+  .bar() // swift-mode:test:known-bug
+  .baz()
+
+repeat {
+    foo()
+    foo()
+} while
+  foo
+  .bar() // swift-mode:test:known-bug
+  .baz()
+
+repeat {
+    foo()
+    foo()
+}
+  while
+  foo
+  .bar() // swift-mode:test:known-bug
+  .baz()
+
+repeat {
+    foo()
+    foo()
+}
+  while foo
+  .bar() // swift-mode:test:known-bug
+  .baz()
+
+// If statement
+
+if x
+     .foo()
+     .bar() {
+    foo()
+    foo()
+}
+
+if
+  x
+    .foo()
+    .bar() {
+    foo()
+    foo()
+}
+
+if
+  let
+    x
+    =
+    xx,
+  var
+    y
+    =
+    yy,
+  x
+    ==
+    y,
+  case
+    (
+      a,
+      b
+    )
+    =
+    ab {
+    foo()
+    foo()
+}
+
+if foo() {
+    foo()
+    foo()
+    foo()
+} else if foo() {
+    foo()
+    foo()
+    foo()
+} else if foo
+            .bar()
+            .baz() +++ { x in
+                return x
+            },
+          foo
+            .bar()
+            .baz() +++ { x in
+                return x
+            } {
+    foo()
+    foo()
+    foo()
+} else if
+  foo
+    .bar()
+    .baz() +++ { x in
+        return x
+    },
+  foo
+    .bar()
+    .baz() +++ { x in
+        return x
+    } {
+    foo()
+    foo()
+    foo()
+}
+
+// Guard statement
+
+guard
+  foo
+    .foo() else {
+    bar()
+    bar()
+}
+
+guard
+  foo
+    .foo()
+else {
+    bar()
+    bar()
+}
+
+guard foo
+        .foo()
+        .foo() +++ { x in
+            foo()
+        } else {
+    bar()
+    bar()
+}
+
+guard
+  foo
+    .foo()
+    .foo() +++ { x in
+        foo()
+    } else {
+    bar()
+    bar()
+}
+
+guard
+  let
+    x
+    =
+    xx,
+  var
+    y
+    =
+    yy,
+  x
+    ==
+    y,
+  case
+    (
+      a,
+      b
+    )
+    =
+    ab
+else {
+    foo()
+    foo()
+}
+
+guard
+  let
+    x
+    =
+    xx,
+  var
+    y
+    =
+    yy,
+  x
+    ==
+    y,
+  case
+    (
+      a,
+      b
+    )
+    =
+    ab else {
+    foo() // swift-mode:test:known-bug
+    foo()
+} // swift-mode:test:known-bug
+
+// Switch statement
+
+switch foo
+  .bar {
+case foo:
+    foo()
+    foo()
+default:
+    foo()
+    foo()
+} // swift-mode:test:known-bug
+
+switch
+  foo
+  .bar {
+case foo:
+    foo()
+    foo()
+default:
+    foo()
+    foo()
+} // swift-mode:test:known-bug
+
+
+switch foo {
+case foo:
+    foo()
+      .bar()
+    foo()
+default:
+    foo()
+    foo()
+}
+
+switch foo {
+case .P(let x)
+       where
+         foo
+           .bar(),
+     .Q(let x)
+       where
+         foo
+           .bar(),
+     .R(let x)
+       where
+         foo
+           .bar():
+    foo()
+    foo()
+default:
+    foo()
+    foo()
+}
+
+switch foo {
+case let .P(x)
+       where
+         foo
+           .bar(),
+     let .Q(x)
+       where
+         foo
+           .bar(),
+     let .R(x)
+       where
+         foo
+           .bar():
+    foo()
+    foo()
+default:
+    foo()
+    foo()
+}
+
+switch foo {
+case
+  let .P(x)
+    where
+      foo
+        .bar(),
+  let .Q(x)
+    where
+      foo
+        .bar(),
+  let .R(x)
+    where
+      foo
+        .bar():
+    foo()
+    foo()
+default:
+    foo()
+    foo()
+}
+
+switch foo {
+case
+  let .P(x)
+    where
+      foo
+        .bar(),
+  let .Q(x)
+    where
+      foo
+        .bar(),
+  let .R(x)
+    where
+      foo
+        .bar():
+    foo()
+    foo()
+default:
+    foo()
+    foo()
+}
+
+switch foo {
+case let
+       .P(x) // swift-mode:test:known-bug
+         where // swift-mode:test:known-bug
+           foo
+             .bar(),
+     let
+       .Q(x)
+         where // swift-mode:test:known-bug
+           foo
+             .bar(),
+     let
+       .R(x)
+         where // swift-mode:test:known-bug
+           foo
+             .bar():
+    foo()
+    foo()
+default:
+    foo()
+    foo()
+}
+
+switch foo {
+case
+  let
+    .P(x) // swift-mode:test:known-bug
+      where // swift-mode:test:known-bug
+        foo
+          .bar(),
+  let
+    .Q(x)
+      where // swift-mode:test:known-bug
+        foo
+          .bar(),
+  let
+    .R(x)
+      where // swift-mode:test:known-bug
+        foo
+          .bar():
+    foo()
+    foo()
+default:
+    foo()
+    foo()
+}
+
+switch foo {
+case
+  let Foo
+    .P(x) // swift-mode:test:known-bug
+      where // swift-mode:test:known-bug
+        foo
+          .bar(),
+  let Foo
+    .Q(x)
+      where // swift-mode:test:known-bug
+        foo
+          .bar(),
+  let Foo
+    .R(x)
+      where // swift-mode:test:known-bug
+        foo
+          .bar():
+    foo()
+    foo()
+case
+  Foo
+    .P, // swift-mode:test:known-bug
+  Foo
+    .Q,
+  Foo
+    .R:
+default:
+    foo()
+    foo()
+}
+
+switch foo {
+case
+  let
+    Foo // swift-mode:test:known-bug
+    .P(x)
+      where // swift-mode:test:known-bug
+        foo
+          .bar(),
+  let
+    Foo
+    .Q(x)
+      where // swift-mode:test:known-bug
+        foo
+          .bar(),
+  let
+    Foo
+    .R(x)
+      where // swift-mode:test:known-bug
+        foo
+          .bar():
+    foo()
+    foo()
+default:
+    foo()
+    foo()
+}
+
+switch foo {
+case
+  is
+    Foo // swift-mode:test:known-bug
+      where // swift-mode:test:known-bug
+        foo
+          .bar(),
+  is
+    Foo
+      where // swift-mode:test:known-bug
+        foo
+          .bar(),
+  let Foo
+    .Bar
+    .Baz
+      where // swift-mode:test:known-bug
+        foo
+          .bar():
+    foo()
+    foo()
+default:
+    foo()
+    foo()
+}
+
+// swift-mode:test:eval (setq-local swift-mode:switch-case-offset 2)
+
+switch foo {
+  case foo:
+    foo() // swift-mode:test:known-bug
+    foo()
+  default:
+    foo() // swift-mode:test:known-bug
+    foo()
+}
+
+// swift-mode:test:eval (setq-local swift-mode:switch-case-offset 0)
+
+
+
+// Labeled statements
+
+
+foo:
+  if foo
+       .bar == baz {
+}
+
+foo:
+  if
+  foo
+    .bar == baz {
+}
+
+
+foo:
+  for
+  x
+  in
+  xs {
+    foo()
+    foo()
+}
+
+// Control transfer statements
+
+while foo() {
+    break
+    continue
+    return
+      foo()
+    throw
+      foo()
+
+    switch foo() {
+    case A:
+        foo()
+        fallthrough
+    case B:
+        foo()
+        fallthrough
+    default:
+        foo()
+    }
+}
+
+// Defer statements
+
+defer {
+    foo()
+    bar()
+    baz()
+}
+
+// Do statements
+
+do {
+} catch Foo
+  .Bar(x)
+    where // swift-mode:test:known-bug
+      foo()
+        .bar() {
+    foo()
+    foo()
+} catch
+  Foo // swift-mode:test:known-bug
+  .Bar(x)
+    where
+      foo()
+        .bar() {
+    foo()
+    foo()
+} catch
+    where // swift-mode:test:known-bug
+      foo()
+        .bar() {
+    foo()
+    foo()
+}
+
+// Conditional control statements
+
+func foo() {
+    #if foo
+    foo()
+    foo()
+    #elsif foo
+    foo()
+    foo()
+    #else
+    foo()
+    foo()
+    #end
+}
diff --git a/test/swift-files/types.swift b/test/swift-files/types.swift
new file mode 100644
index 0000000..e058e44
--- /dev/null
+++ b/test/swift-files/types.swift
@@ -0,0 +1,274 @@
+// swift-mode:test:eval (setq-local swift-mode:basic-offset 4)
+// swift-mode:test:eval (setq-local swift-mode:parenthesized-expression-offset 
2)
+// swift-mode:test:eval (setq-local swift-mode:multiline-statement-offset 2)
+// swift-mode:test:eval (setq-local swift-mode:switch-case-offset 0)
+
+// Simple types
+
+let foo: A
+  = abc
+
+let foo:
+  A = abc
+
+let foo
+  :A = abc
+
+class Foo:
+  A,
+  B, C,
+  D {
+}
+
+class Foo
+  : A,
+    B, C,
+    D {
+}
+
+
+class Foo: A
+         , B , C
+         , D
+{
+}
+
+class Foo
+  : A
+  , B , C
+  , D
+{
+}
+
+
+// Types with attribute
+
+let foo: @A A
+  = abc
+
+let foo: @A
+  A = abc
+
+let foo:
+  @A
+  A = abc
+
+let foo
+  :@A
+  A = abc
+
+class Foo:
+  @A
+  A,
+  B {
+}
+
+class Foo
+  : @A
+    A, // swift-mode:test:known-bug
+    B {
+}
+
+class Foo: @A
+           A // swift-mode:test:known-bug
+         , B
+{
+}
+
+class Foo
+  : @A
+    A // swift-mode:test:known-bug
+  , B
+{
+}
+
+// Member types
+
+let foo:
+  /* */ A.
+  /* */ B = abc
+
+let foo:
+  /* */ A
+  /* */ .B = abc
+
+class Foo:
+  A.
+    B, // swift-mode:test:known-bug
+  A.
+    B,
+  A
+    .B {
+}
+
+class Foo
+  : A.
+      B, // swift-mode:test:known-bug
+    A.
+      B,
+    A
+      .B {
+}
+
+class Foo: A.
+             B, // swift-mode:test:known-bug
+         , A.
+             B
+         , A
+             .B
+{
+}
+
+class Foo
+  : A.
+      B // swift-mode:test:known-bug
+  , A.
+      B,
+  , A
+      .B {
+}
+
+// Array types
+
+let foo: [
+  A
+]
+  = abc
+
+let foo:
+  [
+    A
+  ] = abc
+
+let foo
+  :[
+    A
+  ] = abc
+
+// Tuple types
+
+let foo: (
+  /* */ A,
+  B
+)
+  = abc
+
+let foo:
+  (
+    /* */ A,
+    B
+  ) = abc
+
+let foo
+  :(
+    /* */ A,
+    B
+  ) = abc
+
+// Dictionary types
+
+let foo: [
+  /* */ A:
+    B
+]
+  = abc
+
+let foo:
+  [
+    /* */ A:
+      B
+  ] = abc
+
+let foo
+  :[
+    /* */ A:
+      B
+  ] = abc
+
+// Function types
+
+let foo: (
+  A,
+  B
+)
+  ->
+  throws (
+    A,
+    B
+  )
+  ->
+  throws
+  [
+    A
+  ]
+  = abc
+
+
+let foo:
+  (
+    A,
+    B
+  )
+  ->
+  throws
+  (
+    A,
+    B
+  )
+  ->
+  throws
+  [
+    B
+  ]
+  = abc
+
+let foo
+  :(
+    A,
+    B
+  )
+  ->
+  throws
+  B
+  = abc
+
+let foo:
+  (A, B)
+  ->
+  rethrows
+  B
+  = abc
+
+let foo
+  :(A, B)
+  ->
+  rethrows
+  B
+  = abc
+
+
+// Optional types
+
+let foo: A?
+  = abc
+
+let foo:
+  A? = abc
+
+let foo: A!
+  = abc
+
+let foo:
+  A! = abc
+
+// Protocol composition types
+
+let foo: protocol<A<[B]>,
+                  C<(D, E)>>
+  = a
+
+let foo: protocol<
+  A, // swift-mode:test:known-bug
+  B
+> // swift-mode:test:known-bug
+  = a
diff --git a/test/swift-mode-test-indent.el b/test/swift-mode-test-indent.el
new file mode 100644
index 0000000..caad818
--- /dev/null
+++ b/test/swift-mode-test-indent.el
@@ -0,0 +1,164 @@
+;;; swift-mode-test-indent.el --- Test for swift-mode: indentation  -*- 
lexical-binding: t -*-
+
+;; Copyright (C) 2016 taku0
+
+;; Authors: taku0 (http://github.com/taku0)
+;;
+;; Version: 2.1
+;; Package-Requires: ((emacs "24.4"))
+;; Keywords: languages swift
+;; URL: https://github.com/swift-emacs/swift-mode
+
+;; This file is not part of GNU Emacs.
+
+;; This program is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Test for swift-mode: indentation.
+;; Execute swift-mode:run-test:indent interactively or in batch mode.
+
+;;; Code:
+
+(require 'swift-mode)
+(require 'swift-mode-indent)
+
+(defvar swift-mode:test:basedir
+  (file-name-directory (or load-file-name buffer-file-name)))
+
+(defun swift-mode:setup-error-buffer ()
+  "Initialize and switch to the error buffer.
+
+Return the error-buffer"
+  (switch-to-buffer (get-buffer-create "*swift-mode-test-indent*"))
+  (fundamental-mode)
+  (setq view-read-only nil)
+  (erase-buffer)
+  (current-buffer))
+
+(defun swift-mode:run-test:indent ()
+  "Run indentation test for swift-mode."
+  (interactive)
+  (let ((error-buffer
+         (if noninteractive nil (swift-mode:setup-error-buffer)))
+        (current-line 0)
+        (error-count 0))
+    (setq default-directory
+          (concat (file-name-as-directory swift-mode:test:basedir)
+                  "swift-files"))
+
+    (dolist (swift-file (file-expand-wildcards "*.swift"))
+      (with-temp-buffer
+        (switch-to-buffer (current-buffer))
+        (insert-file-contents-literally swift-file)
+        (swift-mode)
+        (setq current-line 0)
+        (while (not (eobp))
+          (setq current-line (1+ current-line))
+          (cond
+           ((looking-at ".*//.*swift-mode:test:keep-indent")
+            nil)
+
+           ((= (line-beginning-position) (line-end-position))
+            ;; Empty line
+            nil)
+
+           (t
+            (when (looking-at ".*//.*swift-mode:test:eval\\(.*\\)")
+              (eval-region (match-beginning 1) (match-end 1)))
+            (unless
+                (swift-mode:test-current-line-indent
+                 swift-file current-line error-buffer)
+              (setq error-count (1+ error-count)))))
+          (forward-line))))
+    (when (= error-count 0)
+      (swift-mode:print-message error-buffer "no regressions\n"))
+    (when (not noninteractive)
+      (compilation-mode))))
+
+(defun swift-mode:test-current-line-indent
+    (swift-file current-line error-buffer)
+  "Run indentation test for swift-mode on current line.
+
+SWIFT-FILE is the filename of the current test case.
+CURRENT-LINE is the current line number.
+ERROR-BUFFER is the buffer to output errors."
+  (back-to-indentation)
+  (let ((original-indent (current-column))
+        computed-indent
+        (known-bug (looking-at ".*//.*swift-mode:test:known-bug")))
+    (delete-horizontal-space)
+    (when (= original-indent 0)
+      (indent-line-to 1))
+
+    (swift-mode:indent-line)
+    (back-to-indentation)
+    (setq computed-indent (current-column))
+    (indent-line-to original-indent)
+
+    (when (/= original-indent computed-indent)
+      (swift-mode:show-error
+       error-buffer swift-file current-line
+       (if known-bug "warning" "error")
+       (concat
+        (if known-bug "(knwon bug) " "")
+        "expected "
+        (prin1-to-string original-indent)
+        " but "
+        (prin1-to-string computed-indent))))
+
+    (when (and (= original-indent computed-indent) known-bug)
+      (swift-mode:show-error
+       error-buffer swift-file current-line
+       "info"
+       "known-bug is fixed somehow"))
+
+    (= original-indent computed-indent)))
+
+(defun swift-mode:show-error (error-buffer file line level message)
+  "Show an error message to the ERROR-BUFFER or stdout.
+
+If the Emacs is in the batch mode, the message is printed to the stdout.
+Otherwise, the message is appended to the ERROR-BUFFER.
+
+FILE is the filename of the test case.
+LINE is the line number of the error.
+LEVEL is the error level (e.g. error, warning).
+MESSAGE is the error message."
+  (let ((formatted
+         (concat
+          "swift-mode-test:"
+          file
+          ":"
+          (prin1-to-string line)
+          ": "
+          level
+          ": "
+          message
+          "\n")))
+    (swift-mode:print-message error-buffer formatted)))
+
+(defun swift-mode:print-message (error-buffer message)
+  "Print a message to the ERROR-BUFFER or stdout.
+
+If the Emacs is in the batch mode, MESSAGE is printed to the stdout.
+Otherwise, MESSAGE is appended to the ERROR-BUFFER."
+  (if noninteractive
+      (princ message)
+    (with-current-buffer error-buffer
+      (insert-and-inherit message))))
+
+(provide 'swift-mode-test-indent)
+
+;;; swift-mode-test-indent.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]