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

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

[nongnu] elpa/typescript-mode 1cea84486f 064/222: Merge pull request #35


From: ELPA Syncer
Subject: [nongnu] elpa/typescript-mode 1cea84486f 064/222: Merge pull request #35 from lddubeau/feature/indent-return-annotations
Date: Sun, 6 Feb 2022 16:59:16 -0500 (EST)

branch: elpa/typescript-mode
commit 1cea84486f937946a90caacf2a7c86ca855d1c9d
Merge: 9ad892fb22 d155a4b623
Author: Louis-Dominique Dubeau <ldd@lddubeau.com>
Commit: GitHub <noreply@github.com>

    Merge pull request #35 from lddubeau/feature/indent-return-annotations
    
    This fixes the indentation of functions that have return value annotations. 
The number of cases in the test suite makes the change look broader than it 
really was. Fixing how return value annotations were handled had the potential 
to impact many other cases. This is why the  suite is so large.
---
 test-files/indentation-reference-document.ts | 215 +++++++++++++++++++++++++++
 typescript-mode.el                           | 113 +++++++++++++-
 2 files changed, 327 insertions(+), 1 deletion(-)

diff --git a/test-files/indentation-reference-document.ts 
b/test-files/indentation-reference-document.ts
index da1dd7d80c..d6e3124f0f 100644
--- a/test-files/indentation-reference-document.ts
+++ b/test-files/indentation-reference-document.ts
@@ -50,6 +50,8 @@ namespace ts.server {
         pid: number;
     }
 
+    export type SomeType = string | number;
+
     class Logger implements ts.server.Logger {
         private firstInGroup = true;
 
@@ -237,3 +239,216 @@ namespace ts.server {
             /def/);
     }
 }
+
+// Tests for return value annotations.
+
+// Unannotated.
+function moo(x: any,
+             f: string) {
+    return null;
+}
+
+// Parens around return type.
+function foo(x: any,
+             f: string): ((a: number) => void) {
+    return null;
+}
+
+class Moo {}
+
+// Type guard.
+function foo2(x: any,
+              f: string): x is Moo {
+    return x.something === 1;
+}
+
+// Usage of generic in return type.
+function foo3(a: number,
+              b: number): Array<Array<(a: number) => void>> {
+    return [];
+}
+
+// Curly brackets in return type.
+function bar(a: number,
+             b: number): { z(): string } {
+    return {
+        z() { return "a"; }
+    };
+}
+
+// The sequence ): in the return type.
+function bif(a: number,
+             b: number): "abc):d" {
+    return "abc):d";
+}
+
+// Comment where the return type would appear.
+function gogo(a: number,
+              b: number) /* foo */ {
+}
+
+// Function call in the list of arguments.
+function foo5(x: any,
+              f: string = bif(1, 2)): ((a: number) => void) {
+    return null;
+}
+
+// Dotted name in return type.
+function foo6(x: any,
+              f: number): ts.server.SomeType {
+    return "string";
+}
+
+// First parameter has function signature.
+function foo7(x: (a: string, b: string) => Array<number>,
+              b: number): void {
+}
+
+// Second parameter has function signature.
+function foo7b(a: string,
+               x: (a: number, b: number) => Array<number>): void {
+}
+
+function foo8(): void {
+    // Arrow function in first parameter.
+    foo7((a: string): Array<number> => {
+        return [1];
+    },
+         1);
+
+    // Arrow function in first parameter, line break in parameters.
+    foo7((a: string,
+          b: string): Array<number> => {
+        return [1];
+    },
+         1);
+
+    // Arrow function in second parameter.
+    foo7b("1",
+          (a: number, b: number): Array<number> => {
+              return [1];
+          });
+
+    // Arrow function in second parameter, line break in parameters.
+    foo7b("1",
+          (a: number,
+           b: number): Array<number> => {
+              return [1];
+          });
+}
+
+// Arrow function assignment, line break in parameters.
+const foo9 = (a: string,
+              b: string): Array<number> => {
+    return [1];
+}
+
+// Arrow function assignment.
+const foo10 = (a: string, b: string): Array<number> => {
+    return [1];
+}
+
+// Arrow function assignment, parenthesized.
+const foo11 = ((a: string, b: string): Array<number> => {
+    return [1];
+});
+
+function foo12(): void {
+    // Function in first parameter.
+    foo7(function (a: string): Array<number> {
+        return [1];
+    },
+         1);
+
+    // Function in first parameter, line break in parameters.
+    foo7(function (a: string,
+                   b: string): Array<number> {
+        return [1];
+    },
+         1);
+
+    // Arrow function in second parameter.
+    foo7b("1",
+          function (a: number, b: number): Array<number> {
+              return [1];
+          });
+
+    // Arrow function in second parameter, line break in parameters.
+    foo7b("1",
+          function (a: number,
+                    b: number): Array<number> {
+              return [1];
+          });
+
+    // Same cases as above but named.
+
+    // Function in first parameter.
+    foo7(function _mip(a: string): Array<number> {
+        return [1];
+    },
+         1);
+
+    // Function in first parameter, line break in parameters.
+    foo7(function _mip(a: string,
+                       b: string): Array<number> {
+        return [1];
+    },
+         1);
+
+    // Arrow function in second parameter.
+    foo7b("1",
+          function _mip(a: number, b: number): Array<number> {
+              return [1];
+          });
+
+    // Arrow function in second parameter, line break in parameters.
+    foo7b("1",
+          function _mip(a: number,
+                        b: number): Array<number> {
+              return [1];
+          });
+
+    // Same cases as above but generators.
+
+    // Function in first parameter.
+    foo7(function *(a: string): Array<number> {
+        return [1];
+    },
+         1);
+
+    // Function in first parameter, line break in parameters.
+    foo7(function *(a: string,
+                    b: string): Array<number> {
+        return [1];
+    },
+         1);
+
+    // Arrow function in second parameter.
+    foo7b("1",
+          function *(a: number, b: number): Array<number> {
+              return [1];
+          });
+
+    // Arrow function in second parameter, line break in parameters.
+    foo7b("1",
+          function *(a: number,
+                     b: number): Array<number> {
+              return [1];
+          });
+
+    // Check that JavaScript objects are still handled right. Whether
+    // in the 1st or subsequent position of a call.
+    function smurf(a: {}, b: {}) {}
+    smurf({
+        a: {},
+    },
+          {
+        a: {},
+    });
+
+    smurf({
+        a: {},
+    }, {
+        a: {},
+    });
+}
diff --git a/typescript-mode.el b/typescript-mode.el
index 8baad489d3..4b091fa64d 100644
--- a/typescript-mode.el
+++ b/typescript-mode.el
@@ -1759,6 +1759,110 @@ nil."
          (list (cons 'c typescript-comment-lineup-func))))
     (c-get-syntactic-indentation (list (cons symbol anchor)))))
 
+(defun typescript--backward-over-generic-parameter-list ()
+  "Search backward for the start of a generic's parameter list and move to it.
+
+This is a utility function for
+`typescript--backward-to-parameter-list'.
+
+This function must be called with the point placed on the final >
+of the generic's parameter list.  It will scan backwards to find
+the start.  If successful, it will move the point to the start of
+the list.  If not, it does not move the point.
+
+Returns nil on failure, or the position to which the point was
+moved on success."
+  (when (eq (char-after) ?>)
+    (let ((depth 1))
+      (loop named search-loop
+            while (> depth 0)
+            do (progn
+                 (unless (re-search-backward "[<>]" nil t)
+                   (cl-return-from search-loop nil))
+                 (cond
+                  ((looking-at ">")
+                   (unless (eq (char-before) ?=)
+                     (setq depth (1+ depth))))
+                  ((looking-at "<") (setq depth (1- depth)))))
+            finally return (point)))))
+
+(defun typescript--backward-to-parameter-list ()
+  "Search backward for the end of a parameter list and move to it.
+
+This is a utility function for `typescript--proper-indentation'.
+
+This function must be called with the point placed before an
+opening curly brace.  It will try to skip over the type
+annotation that would mark the return value of a function and
+move to the end of the parameter list.  If it is unsuccessful, it
+does not move the point. \"Unsuccessful\" here also means that
+the position at which we started did not in fact mark the
+beginning of a function. The curly brace belonged to some other
+syntactic construct than a function.
+
+Returns nil on failure, or the position to which the point was
+moved on success."
+  (let ((location
+         (or
+          ;; This handles the case of a function with return type annotation.
+          (save-excursion
+            (loop named search-loop
+                  do (progn
+                       (if (eq (char-before) ?>)
+                           (if (looking-back "=>" (- (point) 2))
+                               ;; Move back over the arrow of an arrow 
function.
+                               (backward-char 2)
+                             ;; Otherwise, we are looking at the end of the 
parameters
+                             ;; list of a generic. We need to move back over 
the list.
+                             (backward-char)
+                             
(typescript--backward-over-generic-parameter-list))
+                         ;; General case: we just move back over the current 
sexp.
+                         (condition-case nil
+                             (backward-sexp)
+                           (scan-error nil)))
+                       (typescript--backward-syntactic-ws)
+                       (let ((before (char-before)))
+                         ;; Check whether we are at "):".
+                         (when (and (eq before ?\:)
+                                    (progn
+                                      (backward-char)
+                                      (skip-syntax-backward " ")
+                                      (eq (char-before) ?\))))
+                           ;; Success! This the end of the parameter list.
+                           (cl-return-from search-loop (point)))
+                         ;; All the following cases are constructs that are 
allowed to
+                         ;; appear between the opening brace of a function and 
the
+                         ;; end of a parameter list.
+                         (unless
+                             (or
+                              ;; End of a generic.
+                              (eq before ?>)
+                              ;; Union of types
+                              (eq before ?|)
+                              ;; Dotted names
+                              (eq before ?.)
+                              ;; Typeguard (eg. foo is SomeClass)
+                              (looking-back "is" (- (point) 2))
+                              ;; This is also dealing with dotted names. This 
may come
+                              ;; into play if a jump back moves over an entire 
dotted
+                              ;; name at once.
+                              ;;
+                              ;; The earlier test for dotted names comes into 
play if the
+                              ;; logic moves over one part of a dotted name at 
a time (which
+                              ;; is what `backward-sexp` normally does).
+                              (looking-back typescript--dotted-name-re nil)
+                             )
+                           ;; We did not encounter a valid construct, so
+                           ;; the search is unsuccessful.
+                           (cl-return-from search-loop nil))))))
+          ;; This handles the case of a function without return type 
annotation.
+          (progn
+            (typescript--backward-syntactic-ws)
+            (when (eq (char-before) ?\))
+              (point))))))
+    (when location
+      (goto-char location))))
+
 (defun typescript--proper-indentation (parse-status)
   "Return the proper indentation for the current line."
   (save-excursion
@@ -1777,7 +1881,14 @@ nil."
              (if (looking-at "[({[]\\s-*\\(/[/*]\\|$\\)")
                  (progn
                    (skip-syntax-backward " ")
-                  (when (eq (char-before) ?\)) (backward-list))
+                   (when (or (typescript--backward-to-parameter-list)
+                             (eq (char-before) ?\)))
+                     (backward-list))
+                   ;; If the parameter list is preceded by (, take the
+                   ;; start of the parameter list as our reference.
+                   ;; This allows handling functions in parameter
+                   ;; lists. Otherwise, we want to go back to the
+                   ;; start of function declaration.
                    (back-to-indentation)
                    (cond (same-indent-p
                           (current-column))



reply via email to

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