branch: elpa/kotlin-mode
commit 76921927defb863c543faf0862a8444ac9ffe94c
Author: Martin Blake <[email protected]>
Commit: Martin Blake <[email protected]>
Add a test for correct indentation of sample.kt, and get it to pass (with a
few tweaks)
---
kotlin-mode.el | 65 +++++++++++++++++++++++++++------------------
test/kotlin-mode-test.el | 68 ++++++++++++++++++++++++++++++++++--------------
test/sample.kt | 30 +++++++++++----------
3 files changed, 104 insertions(+), 59 deletions(-)
diff --git a/kotlin-mode.el b/kotlin-mode.el
index a5df662fbc..cfa8bfc5d1 100644
--- a/kotlin-mode.el
+++ b/kotlin-mode.el
@@ -331,34 +331,43 @@
"Return whether the current line ends with the given pattern"
(looking-at (format ".*%s[ \t]*$" pattern)))
-(defun kotlin-mode--count-brackets ()
- "Count the brackets on the current line, counting
- +1 for open-brackets, -1 for close-brackets"
- (let ((net-count 0))
- (save-excursion
- (while (not (eolp))
- (cond ((looking-at "\\s\(")
- (incf net-count))
- ((looking-at "\\s\)")
- (decf net-count)))
- (forward-char 1)))
- net-count))
+(defun kotlin-mode--update-bracket-count (net-count)
+ "Count the brackets on the current line, incrementing the count
+ +1 for open-brackets, -1 for close-brackets.
+ Return as soon as the overall count exceeds zero."
+ (save-excursion
+ (end-of-line)
+ (while (and (<= net-count 0) (not (bolp)))
+ (backward-char)
+ (cond ((looking-at "\\s\(")
+ (incf net-count))
+ ((looking-at "\\s\)")
+ (decf net-count)))))
+ net-count)
+
+(defun kotlin-mode--base-indentation ()
+ "Return the indentation level of the current line based on brackets only,
+ i.e. ignoring 'continuation' indentation."
+ (if (kotlin-mode--line-begins "\\.")
+ (- (current-indentation) kotlin-tab-width)
+ (current-indentation)))
(defun kotlin-mode--post-bracket-indent ()
"Return the indentation at the first non-whitespace character
following the last un-closed open-bracket on the line.
- If no non-whitespace character follows, return nil."
+ If no non-whitespace character follows, return the default
+ indentation level."
(let ((net-count 0) position)
(save-excursion
(end-of-line)
(while (and (<= net-count 0) (not (bolp)))
+ (backward-char)
(cond ((looking-at "\\s\(")
(incf net-count))
((looking-at "\\s\)")
- (decf net-count)))
- (backward-char))
+ (decf net-count))))
(if (kotlin-mode--line-ends "\\s\(")
- nil
+ (+ (kotlin-mode--base-indentation) kotlin-tab-width)
(forward-char)
(skip-syntax-forward "(")
(skip-syntax-forward "-")
@@ -378,31 +387,35 @@
(kotlin-mode--beginning-of-buffer-indent))
(let ((not-indented t) cur-indent (net-bracket-count 0))
;; Count any close-bracket at the start of the current line
- (if (kotlin-mode--line-begins "\\s\)")
- (decf net-bracket-count))
+ (save-excursion
+ (skip-syntax-forward "-")
+ (decf net-bracket-count (skip-syntax-forward ")")))
(save-excursion
(while not-indented
;; Count-up the brackets in the previous line
(kotlin-mode--prev-line)
- (incf net-bracket-count (kotlin-mode--count-brackets))
+ (setq net-bracket-count
+ (kotlin-mode--update-bracket-count net-bracket-count))
(cond
;; If the net-bracket-count is zero, use this indentation
((= net-bracket-count 0)
- (setq cur-indent (current-indentation))
+ (setq cur-indent (kotlin-mode--base-indentation))
(setq not-indented nil))
;; If we've now counted more open-brackets than close-brackets,
- ;; use the indentation of the content immediately following the
final open-bracket.
- ;; But if the line *ends* with an open-bracket, apply the default
indentation.
+ ;; use the indentation of the content immediately following the
+ ;; final open-bracket.
+ ;; But if the line *ends* with an open-bracket, apply the default
+ ;; indentation.
((> net-bracket-count 0)
- (let ((post-bracket-indent (kotlin-mode--post-bracket-indent)))
- (if post-bracket-indent
- (setq cur-indent post-bracket-indent)
- (setq cur-indent (+ (current-indentation) kotlin-tab-width))))
+ (setq cur-indent (kotlin-mode--post-bracket-indent))
(setq not-indented nil))
((bobp)
(setq not-indented nil)))))
+ ;; Add extra indentation if the line starts with a period
+ (if (kotlin-mode--line-begins "\\.")
+ (incf cur-indent kotlin-tab-width))
(if cur-indent
(indent-line-to cur-indent)
diff --git a/test/kotlin-mode-test.el b/test/kotlin-mode-test.el
index 3504bc19e5..8cbabe3316 100644
--- a/test/kotlin-mode-test.el
+++ b/test/kotlin-mode-test.el
@@ -47,28 +47,58 @@ return a + b
return a + b
}")))))
-;; (ert-deftest kotlin-mode--chained-methods ()
-;; (with-temp-buffer
-;; (let ((text "names.filter { it.empty }
-;; .sortedBy { it }
-;; .map { it.toUpperCase() }
-;; .forEach { print(it) }"))
+(ert-deftest kotlin-mode--chained-methods ()
+ (with-temp-buffer
+ (let ((text "names.filter { it.empty }
+.sortedBy { it }
+.map { it.toUpperCase() }
+.forEach { print(it) }"))
+
+ (insert text)
+ (beginning-of-buffer)
+
+ (kotlin-mode--indent-line)
+
+ (next-line)
+ (kotlin-mode--indent-line)
-;; (insert text)
-;; (beginning-of-buffer)
+ (next-line)
+ (kotlin-mode--indent-line)
+
+ (next-line)
+ (kotlin-mode--indent-line)
-;; (kotlin-mode--indent-line)
+ (should (equal (buffer-string) "names.filter { it.empty }
+ .sortedBy { it }
+ .map { it.toUpperCase() }
+ .forEach { print(it) }")))))
+
+(defun next-non-empty-line ()
+ "Moves to the next non-empty line"
+ (forward-line)
+ (while (and (looking-at "^[ \t]*$") (not (eobp)))
+ (forward-line)))
+
+(ert-deftest kotlin-mode--sample-test ()
+ (with-temp-buffer
+ (insert-file-contents "sample.kt")
+ (beginning-of-buffer)
+ (while (not (eobp))
+ (let ((expected-line (thing-at-point 'line)))
-;; (next-line)
-;; (kotlin-mode--indent-line)
+ ;; Remove existing indentation
+ (beginning-of-line)
+ (delete-region (point) (progn (skip-chars-forward " \t") (point)))
-;; (next-line)
-;; (kotlin-mode--indent-line)
+ ;; Indent the line
+ (kotlin-mode--indent-line)
-;; (next-line)
-;; (kotlin-mode--indent-line)
+ ;; Check that the correct indentation is re-applied
+ (should (equal expected-line (thing-at-point 'line)))
-;; (should (equal (buffer-string) "names.filter { it.empty }
-;; .sortedBy { it }
-;; .map { it.toUpperCase() }
-;; .forEach { print(it) }")))))
+ ;; Go to the next non-empty line
+ (next-non-empty-line)
+ )
+ )
+ )
+ )
diff --git a/test/sample.kt b/test/sample.kt
index 069c879711..0e59c5691d 100644
--- a/test/sample.kt
+++ b/test/sample.kt
@@ -105,14 +105,14 @@ if (text in names) // names.contains(text) is called
print("Yes")
names.filter { it.startsWith("A") }
- .sortedBy { it }
- .map { it.toUpperCase() }
- .forEach { print(it) }
+ .sortedBy { it }
+ .map { it.toUpperCase() }
+ .forEach { print(it) }
fun f() {
things.f()
- .g()
- .h()
+ .g()
+ .h()
}
data class Customer(val name: String, val email: String)
@@ -191,18 +191,19 @@ class Turtle {
}
val myTurtle = Turtle()
-with(myTurtle) { //draw a 100 pix square
-penDown()
-for(i in 1..4) {
- forward(100.0)
- turn(90.0)
-}
-penUp()
+with(myTurtle) {
+ //draw a 100 pix square
+ penDown()
+ for(i in 1..4) {
+ forward(100.0)
+ turn(90.0)
+ }
+ penUp()
}
val stream = Files.newInputStream(Paths.get("/some/file.txt"))
-stream.buffered().reader().use { reader ->
- println(reader.readText())
+stream.buffered().reader().use {
+ reader -> println(reader.readText())
}
inline fun <reified T: Any> Gson.fromJson(json): T = this.fromJson(json,
T::class.java)
@@ -718,3 +719,4 @@ fun itpl() {
print("${foo}bar");
print("${`weird$! identifier`}bar");
}
+