[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/typescript-mode acd8d79952 10/10: Merge pull request #170
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/typescript-mode acd8d79952 10/10: Merge pull request #170 from Fuco1/feature/fontify-arrow-fn-args |
Date: |
Sat, 30 Jul 2022 06:59:04 -0400 (EDT) |
branch: elpa/typescript-mode
commit acd8d7995204c1faf14383b8236e57f4da380ecf
Merge: e5704af123 84bab53b7a
Author: Jostein Kjønigsen <jostein@kjonigsen.net>
Commit: GitHub <noreply@github.com>
Merge pull request #170 from Fuco1/feature/fontify-arrow-fn-args
feat(fontlock): fontify arrow fn arguments
---
typescript-mode-general-tests.el | 191 ++++++++++++++++++++++++++++++++++----
typescript-mode-test-utilities.el | 22 ++---
typescript-mode.el | 118 ++++++++++++++++++++++-
3 files changed, 298 insertions(+), 33 deletions(-)
diff --git a/typescript-mode-general-tests.el b/typescript-mode-general-tests.el
index 34add73657..686db6bfdf 100644
--- a/typescript-mode-general-tests.el
+++ b/typescript-mode-general-tests.el
@@ -371,7 +371,7 @@ declare function declareFunctionDefn(x3: xty3, y3: yty3):
ret3;"
("exportedDefaultDefn" . font-lock-function-name-face)
("declareFunctionDefn" . font-lock-function-name-face)
(("x0" "x1" "x2" "x3") . font-lock-variable-name-face)
- (("y0" "y1" "y2" "y3") . font-lock-variable-name-face)
+ (("\\by0" "\\by1" "\\by2" "\\by3") . font-lock-variable-name-face)
(("ret0" "ret1" "ret2" "ret3") . nil))))
(ert-deftest font-lock/level-four ()
@@ -393,7 +393,7 @@ snake_cased_function(1, 2, 3)"
("methodCall" . font-lock-function-name-face)
("snake_cased_function" . font-lock-function-name-face)
(("string" "boolean" "number" "any") . typescript-primitive-face)
- (("endpoint" "data") . nil)
+ (("endpoint" "data") . font-lock-variable-name-face)
(("<" ">" ",") . nil))))
(ert-deftest font-lock/method-call-with-keyword-name ()
@@ -621,19 +621,24 @@ should be fontified as variable, keyword and type."
(should (eq (get-face-at "Namespaced") 'font-lock-type-face))
(should (eq (get-face-at "ClassName") 'font-lock-type-face))))
-(ert-deftest font-lock/variables-in-declaration-multiline-with-types ()
+(ert-deftest font-lock/funargs--function--multiline-with-types ()
"Variables should be highlighted in multiline declarations with types."
(test-with-fontified-buffer
"function test(
-var1: Type1,
-var2: Type2,
+var1: Promise<U1, V1>,
+var2: (xxx: Foo) => Bar,
+var3: Type3,
): RetType {\n}"
(should (eq (get-face-at "var1") 'font-lock-variable-name-face))
(should (eq (get-face-at "var2") 'font-lock-variable-name-face))
- (should (eq (get-face-at "Type1") 'font-lock-type-face))
- (should (eq (get-face-at "Type2") 'font-lock-type-face))))
+ (should (eq (get-face-at "var3") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "xxx") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "Promise") 'font-lock-type-face))
+ (should (eq (get-face-at "U1") 'font-lock-type-face))
+ (should (eq (get-face-at "Foo") 'font-lock-type-face))
+ (should (eq (get-face-at "Type3") 'font-lock-type-face))))
-(ert-deftest font-lock/variables-in-declaration-multiline-without-types ()
+(ert-deftest font-lock/funargs--function--multiline-without-types ()
"Variables should be highlighted in multiline declarations without types."
(test-with-fontified-buffer
"function test(
@@ -643,8 +648,8 @@ var2,
(should (eq (get-face-at "var1") 'font-lock-variable-name-face))
(should (eq (get-face-at "var2") 'font-lock-variable-name-face))))
-(ert-deftest font-lock/variables-in-declaration-multiline-no-hanging-paren ()
- "Variables should be highlighted in multiline declarations with no hanging
paren."
+(ert-deftest font-lock/funargs--function--multiline-hanging-paren ()
+ "Variables should be highlighted in multiline declarations with hanging
paren."
(test-with-fontified-buffer
"function test(
var1,
@@ -652,8 +657,8 @@ var2): RetType {\n}"
(should (eq (get-face-at "var1") 'font-lock-variable-name-face))
(should (eq (get-face-at "var2") 'font-lock-variable-name-face))))
-(ert-deftest
font-lock/variables-in-declaration-multiline-ending-comma-no-hanging-paren ()
- "Variables should be highlighted in multiline declarations with no hanging
paren and trailing comma."
+(ert-deftest font-lock/funargs--function--multiline-ending-comma-hanging-paren
()
+ "Variables should be highlighted in multiline declarations with hanging
paren and trailing comma."
(test-with-fontified-buffer
"function test(
var1,
@@ -661,15 +666,15 @@ var2,): RetType {\n}"
(should (eq (get-face-at "var1") 'font-lock-variable-name-face))
(should (eq (get-face-at "var2") 'font-lock-variable-name-face))))
-(ert-deftest
font-lock/variables-in-declaration-singleline-ending-comma-hanging-paren ()
- "Variables should be highlighted in singleline declarations with hanging
paren and trailing comma."
+(ert-deftest
font-lock/funargs--function--singleline-ending-comma-no-hanging-paren ()
+ "Variables should be highlighted in singleline declarations with no hanging
paren and trailing comma."
(test-with-fontified-buffer
"function test(var1,var2,
): RetType {\n}"
(should (eq (get-face-at "var1") 'font-lock-variable-name-face))
(should (eq (get-face-at "var2") 'font-lock-variable-name-face))))
-(ert-deftest font-lock/variables-in-declaration-singleline-with-types ()
+(ert-deftest font-lock/funargs--function--singleline-with-types ()
"Variables should be highlighted in singleline declarations with types."
(test-with-fontified-buffer
"function test(var1: Foo, var2: Bar,): RetType {\n}"
@@ -678,13 +683,165 @@ var2,): RetType {\n}"
(should (eq (get-face-at "Foo") 'font-lock-type-face))
(should (eq (get-face-at "Bar") 'font-lock-type-face))))
-(ert-deftest
font-lock/variables-in-declaration-singleline-ending-comma-no-hanging-paren ()
- "Variables should be highlighted in singleline declarations with no hanging
paren and trailing comma."
+(ert-deftest
font-lock/funargs--function--singleline-ending-comma-hanging-paren ()
+ "Variables should be highlighted in singleline declarations with hanging
paren and trailing comma."
(test-with-fontified-buffer
"function test(var1,var2,): RetType {\n}"
(should (eq (get-face-at "var1") 'font-lock-variable-name-face))
(should (eq (get-face-at "var2") 'font-lock-variable-name-face))))
+(ert-deftest font-lock/funargs--function--keywords-as-variables ()
+ "Keywords when used as variables should have variable face"
+ (test-with-fontified-buffer
+ "function test(type, unknown): void {}"
+ (should (eq (get-face-at "type") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "unknown") 'font-lock-variable-name-face))))
+
+(ert-deftest font-lock/funargs--arrow--keywords-as-variables ()
+ "Keywords when used as variables should have variable face"
+ (test-with-fontified-buffer
+ "const test = (type, unknown): void => {}"
+ (should (eq (get-face-at "type") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "unknown") 'font-lock-variable-name-face))))
+
+(ert-deftest font-lock/funargs--arrow--single-line--no-type ()
+ (test-with-fontified-buffer
+ "const test = (aaa, bbb, ccc): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ccc") 'font-lock-variable-name-face))))
+
+(ert-deftest font-lock/funargs--arrow--single-line--no-type--no-return-type ()
+ (test-with-fontified-buffer
+ "const test = (aaa, bbb, ccc) => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ccc") 'font-lock-variable-name-face))))
+
+(ert-deftest font-lock/funargs--arrow--single-line--no-type--trailing-comma ()
+ (test-with-fontified-buffer
+ "const test = (aaa, bbb, ccc,): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ccc") 'font-lock-variable-name-face))))
+
+(ert-deftest font-lock/funargs--arrow--single-line--no-type--optional ()
+ (test-with-fontified-buffer
+ "const test = (aaa, bbb?): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb?") 'font-lock-variable-name-face))))
+
+(ert-deftest font-lock/funargs--arrow--multiline--no-type ()
+ (test-with-fontified-buffer
+ "const test = (aaa, bbb,
+ccc, ddd): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ccc") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ddd") 'font-lock-variable-name-face))))
+
+(ert-deftest font-lock/funargs--arrow--multiline--no-type--newline-after-last
()
+ (test-with-fontified-buffer
+ "const test = (aaa, bbb,
+ccc, ddd
+): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ccc") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ddd") 'font-lock-variable-name-face))))
+
+(ert-deftest
font-lock/funargs--arrow--multiline--no-type--newline-before-first ()
+ (test-with-fontified-buffer
+ "const test = (
+aaa, bbb,
+ccc, ddd
+): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ccc") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ddd") 'font-lock-variable-name-face))))
+
+(ert-deftest font-lock/funargs--arrow--multiline--no-type--with-comment ()
+ (test-with-fontified-buffer
+ "const test = (
+aaa, bbb, // comment
+ccc, ddd // comment
+): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ccc") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ddd") 'font-lock-variable-name-face))))
+
+(ert-deftest
font-lock/funargs--arrow--single--mixed-type--newline-before-first ()
+ (test-with-fontified-buffer
+ "const test = (aaa, bbb: Promise, ccc: number, ddd): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ccc") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "ddd") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "Promise") 'font-lock-type-face))
+ (should (eq (get-face-at "number") 'typescript-primitive-face))))
+
+(ert-deftest font-lock/funargs--arrow--single--with-type--complex-type ()
+ (test-with-fontified-buffer
+ "const test = (aaa: Promise<U, V, (xxx: A) => Foo>, bbb): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "xxx") 'font-lock-variable-name-face))))
+
+(ert-deftest
font-lock/funargs--arrow--multiline--with-type--newline-before-first-after-last
()
+ (test-with-fontified-buffer
+ "const test = (
+aaa: Foo,
+bbb: Bar
+): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "Foo") 'font-lock-type-face))
+ (should (eq (get-face-at "Bar") 'font-lock-type-face))))
+
+(ert-deftest
font-lock/funargs--arrow--multiline--with-type--newline-before-first-after-last--hanging-comma
()
+ (test-with-fontified-buffer
+ "const test = (
+aaa: Foo,
+bbb: Bar,
+): void => {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "Foo") 'font-lock-type-face))
+ (should (eq (get-face-at "Bar") 'font-lock-type-face))))
+
+(ert-deftest font-lock/funargs--method--multiline--with-type ()
+ (test-with-fontified-buffer
+ "class Foo { foo(
+aaa: Foo,
+bbb: Bar,
+): void {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "Foo") 'font-lock-type-face))
+ (should (eq (get-face-at "Bar") 'font-lock-type-face))))
+
+(ert-deftest font-lock/funargs--method--single-line--with-type ()
+ (test-with-fontified-buffer
+ "class Foo { foo(aaa: Foo,bbb: Bar,): void {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "Foo") 'font-lock-type-face))
+ (should (eq (get-face-at "Bar") 'font-lock-type-face))))
+
+(ert-deftest font-lock/funargs--method--single-line--no-type ()
+ (test-with-fontified-buffer
+ "class Foo { foo(aaa, bbb): void {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))))
+
+(ert-deftest font-lock/funargs--method--single-line--no-return-type ()
+ (test-with-fontified-buffer
+ "class Foo { foo(aaa, bbb) {}"
+ (should (eq (get-face-at "aaa") 'font-lock-variable-name-face))
+ (should (eq (get-face-at "bbb") 'font-lock-variable-name-face))))
+
(defun flyspell-predicate-test (search-for)
"This function runs a test on
`typescript--flyspell-mode-predicate'. `SEARCH-FOR' is a string
diff --git a/typescript-mode-test-utilities.el
b/typescript-mode-test-utilities.el
index faa6c1166a..8a1d21e1ae 100644
--- a/typescript-mode-test-utilities.el
+++ b/typescript-mode-test-utilities.el
@@ -26,8 +26,8 @@
(declare (debug t)
(indent 1))
`(test-with-temp-buffer
- ,content
- (font-lock-fontify-buffer)
+ ,content
+ (font-lock-ensure (point-min) (point-max))
,@body))
(defun get-face-at (loc)
@@ -48,15 +48,15 @@ It should be a list of (LOCATION . FACE) pairs, where
LOCATION can be either a single location, or list of locations,
that are all expected to have the same face."
(test-with-fontified-buffer
- contents
- ;; Make sure our propertize function has been applied to the whole
- ;; buffer.
- (syntax-propertize (point-max))
- (dolist (spec expected)
- (if (listp (car spec))
- (dolist (source (car spec))
- (should (eq (get-face-at source) (cdr spec))))
- (should (eq (get-face-at (car spec)) (cdr spec)))))))
+ contents
+ ;; Make sure our propertize function has been applied to the whole
+ ;; buffer.
+ (syntax-propertize (point-max))
+ (dolist (spec expected)
+ (if (listp (car spec))
+ (dolist (source (car spec))
+ (should (eq (get-face-at source) (cdr spec))))
+ (should (eq (get-face-at (car spec)) (cdr spec)))))))
(provide 'typescript-mode-test-utilities)
diff --git a/typescript-mode.el b/typescript-mode.el
index e3ad84c499..032abbc7a5 100644
--- a/typescript-mode.el
+++ b/typescript-mode.el
@@ -1015,7 +1015,7 @@ lines."
(progn
(forward-comment most-positive-fixnum)
(memq (char-after) '(?\, ?\; ?\] ?\) ?\}))))
- do (forward-sexp)))
+ do (forward-sexp)))
while (and (eq (char-after) ?\n)
(save-excursion
(forward-char)
@@ -1686,6 +1686,82 @@ point of view of font-lock. It applies highlighting
directly with
;; Matcher always "fails"
nil)
+(defun typescript--function-argument-matcher (limit)
+ "Font-lock matcher for variables in argument lists.
+
+Because the syntax of the argument list is shared between
+functions, arrow functions and methods, this same matcher is used
+for all of them. The context for the search is set up as
+anchored matcher.
+
+This is a cc-mode-style matcher that *always* fails, from the
+point of view of font-lock. It applies highlighting directly
+with `font-lock-apply-highlight'."
+ (condition-case nil
+ (save-restriction
+ (widen)
+ (narrow-to-region (point-min) limit)
+ (while (re-search-forward
+ (rx (group
+ (regexp "[a-zA-Z_$]\\(?:\\s_\\|\\sw\\)*")
+ ;; name can be optionally followed by ? to mark
+ ;; the argument optional
+ (? "?"))
+ (* whitespace)
+ (group (or "," ":" ")"
+ ;; last variable in the list with a
+ ;; paren on next line and no hanging
+ ;; comma. extra logic is added to deal
+ ;; with possible comments after the
+ ;; variable.
+ eol
+ (and (* whitespace) (or "//" "/*") (* any)
eol))))
+ nil t)
+ (font-lock-apply-highlight '(1 font-lock-variable-name-face t))
+
+ ;; If ender is a ":" it means that the currently matched
+ ;; variable also has a type signature.
+ (let ((ender (match-string 2)))
+ ;; We need to skip the type specification. The regexp
+ ;; basically either searches for the next thing which we
+ ;; believe is a parameter or the end of the argument list.
+ (when (equal ender ":")
+ (let ((perform-match t))
+ (while (and perform-match
+ (re-search-forward
+ (rx (or
+ ;; variable without type at the end
+ ;; of line
+ (and "," eol)
+ ;; next thing is a functional
+ ;; argument, such as f:(x) => void
+ (and "(")
+ ;; closing of a function type argument.
+ ;; here, the type of `f'.
+ ;; (f: (x: number) => foo): void => { }
+ (and ")" (? (* whitespace) "=>" (*
whitespace)))
+ (and ","
+ (* whitespace)
+ (regexp
"[a-zA-Z_$]\\(?:\\s_\\|\\sw\\)*")
+ ;; optional ? to mark the
+ ;; argument optional
+ (? "?")
+ (group (or ":" ")")))))
+ nil t))
+ ;; In case the skipped type was the end of a
+ ;; function type argument, the next token is the
+ ;; return type of the inner function, so we need to
+ ;; match but not fontify the next "name" (which
+ ;; really is the type).
+ (if (string-match-p "=>" (match-string 0))
+ (setq perform-match t)
+ (goto-char (match-beginning 0))
+ (setq perform-match nil))))))))
+ ;; conditions to handle
+ (scan-error nil)
+ (end-of-buffer nil))
+ nil)
+
(defun typescript--in-documentation-comment-p ()
"Reports whether point is inside a documentation comment."
(let ((parse (syntax-ppss)))
@@ -1863,16 +1939,48 @@ and searches for the next token to be highlighted."
(concat "\\_<instanceof\\_>\\s-+\\(" typescript--dotted-name-re "\\)")
(list 1 'font-lock-type-face))
- ;; formal parameters
+ ;; formal parameters in "function" function call
+ ;; function helloWorld(a: number, b: Promise<number>): void { }
,(list
(concat
"\\_<function\\_>\\(\\s-+" typescript--name-re
"\\)?\\s-*\\(<.*>\\)?\\s-*(\\s-*"
"\\(?:$\\|" typescript--name-start-re "\\)")
- `(,(concat "\\(" typescript--name-re "\\)\\(?:\\s-*?\\([,:)]\\|$\\)\\)")
- (prog1 (save-excursion (re-search-forward ")" nil t))
+ `(typescript--function-argument-matcher
+ (prog1 (save-excursion (ignore-errors (up-list)) (point))
(backward-char))
nil
- (1 font-lock-variable-name-face))))
+ nil))
+
+ ;; formal parameters in arrow function
+ ;; const helloWorld = (a: number, b: Promise<number>): void => { }
+ ,(list
+ (rx (group "=>") (* whitespace) (? eol) (* whitespace) "{")
+ '(1 font-lock-keyword-face)
+ `(typescript--function-argument-matcher
+ (prog1 (progn
+ (backward-char)
+ (typescript--backward-to-parameter-list)
+ (point))
+ (backward-sexp))
+ (re-search-forward "{" nil t)
+ nil))
+
+ ;; formal parameters in method definitions
+ ;; class Foo { helloWorld(a: number, b: Promise<number>): void { } }
+ ,(list
+ typescript--function-call-re
+ `(typescript--function-argument-matcher
+ (let ((point-orig (point))
+ (is-method-def
+ (ignore-errors
+ (up-list)
+ (looking-at-p
+ (rx (* (or whitespace ?\n)) (or ":" "{"))))))
+ (if is-method-def
+ (prog1 (point) (goto-char point-orig))
+ (point)))
+ nil
+ nil)))
"Level three font lock for `typescript-mode'.")
(defun typescript--flyspell-mode-predicate ()
- [nongnu] elpa/typescript-mode updated (83bf47e406 -> acd8d79952), ELPA Syncer, 2022/07/30
- [nongnu] elpa/typescript-mode d21c9837cb 04/10: feat(fontlock): fontify arrow fn arguments, ELPA Syncer, 2022/07/30
- [nongnu] elpa/typescript-mode 84bab53b7a 05/10: test(fontlock): update tests related to arglist fontification, ELPA Syncer, 2022/07/30
- [nongnu] elpa/typescript-mode acd8d79952 10/10: Merge pull request #170 from Fuco1/feature/fontify-arrow-fn-args,
ELPA Syncer <=
- [nongnu] elpa/typescript-mode 93e1040ea9 01/10: feat(tests): use font-lock-ensure instead of font-lock-fontify-buffer, ELPA Syncer, 2022/07/30
- [nongnu] elpa/typescript-mode e5704af123 09/10: Merge pull request #171 from Fuco1/bugfix/fontify-return-type-function-type, ELPA Syncer, 2022/07/30
- [nongnu] elpa/typescript-mode ec2c4c11fc 08/10: Merge pull request #172 from Fuco1/fix/keywords-method-calls, ELPA Syncer, 2022/07/30
- [nongnu] elpa/typescript-mode 367cfb70f5 02/10: fix(fontlock): do not fontify function calls as keywords, ELPA Syncer, 2022/07/30
- [nongnu] elpa/typescript-mode 9bd226b386 06/10: fix(fontlock): do not fontify builtins in object/interface key context, ELPA Syncer, 2022/07/30
- [nongnu] elpa/typescript-mode ba047458dd 03/10: fix(fontlock): fontify return type in a function type definition, ELPA Syncer, 2022/07/30
- [nongnu] elpa/typescript-mode 35f01b3aeb 07/10: Merge pull request #173 from Fuco1/fix/keywords-in-interfaces, ELPA Syncer, 2022/07/30