@@ -1015,7 +1015,7 @@ lines."
10151015 (progn
10161016 (forward-comment most-positive-fixnum)
10171017 (memq (char-after ) '(?\, ?\; ?\] ?\) ?\} ))))
1018- do (forward-sexp )))
1018+ do (forward-sexp )))
10191019 while (and (eq (char-after ) ?\n )
10201020 (save-excursion
10211021 (forward-char )
@@ -1686,6 +1686,82 @@ point of view of font-lock. It applies highlighting directly with
16861686 ; ; Matcher always "fails"
16871687 nil )
16881688
1689+ (defun typescript--function-argument-matcher (limit )
1690+ " Font-lock matcher for variables in argument lists.
1691+
1692+ Because the syntax of the argument list is shared between
1693+ functions, arrow functions and methods, this same matcher is used
1694+ for all of them. The context for the search is set up as
1695+ anchored matcher.
1696+
1697+ This is a cc-mode-style matcher that *always* fails, from the
1698+ point of view of font-lock. It applies highlighting directly
1699+ with `font-lock-apply-highlight' ."
1700+ (condition-case nil
1701+ (save-restriction
1702+ (widen )
1703+ (narrow-to-region (point-min ) limit)
1704+ (while (re-search-forward
1705+ (rx (group
1706+ (regexp " [a-zA-Z_$]\\ (?:\\ s_\\ |\\ sw\\ )*" )
1707+ ; ; name can be optionally followed by ? to mark
1708+ ; ; the argument optional
1709+ (? " ?" ))
1710+ (* whitespace)
1711+ (group (or " ," " :" " )"
1712+ ; ; last variable in the list with a
1713+ ; ; paren on next line and no hanging
1714+ ; ; comma. extra logic is added to deal
1715+ ; ; with possible comments after the
1716+ ; ; variable.
1717+ eol
1718+ (and (* whitespace) (or " //" " /*" ) (* any) eol))))
1719+ nil t )
1720+ (font-lock-apply-highlight '(1 font-lock-variable-name-face t ))
1721+
1722+ ; ; If ender is a ":" it means that the currently matched
1723+ ; ; variable also has a type signature.
1724+ (let ((ender (match-string 2 )))
1725+ ; ; We need to skip the type specification. The regexp
1726+ ; ; basically either searches for the next thing which we
1727+ ; ; believe is a parameter or the end of the argument list.
1728+ (when (equal ender " :" )
1729+ (let ((perform-match t ))
1730+ (while (and perform-match
1731+ (re-search-forward
1732+ (rx (or
1733+ ; ; variable without type at the end
1734+ ; ; of line
1735+ (and " ," eol)
1736+ ; ; next thing is a functional
1737+ ; ; argument, such as f:(x) => void
1738+ (and " (" )
1739+ ; ; closing of a function type argument.
1740+ ; ; here, the type of `f' .
1741+ ; ; (f: (x: number) => foo): void => { }
1742+ (and " )" (? (* whitespace) " =>" (* whitespace)))
1743+ (and " ,"
1744+ (* whitespace)
1745+ (regexp " [a-zA-Z_$]\\ (?:\\ s_\\ |\\ sw\\ )*" )
1746+ ; ; optional ? to mark the
1747+ ; ; argument optional
1748+ (? " ?" )
1749+ (group (or " :" " )" )))))
1750+ nil t ))
1751+ ; ; In case the skipped type was the end of a
1752+ ; ; function type argument, the next token is the
1753+ ; ; return type of the inner function, so we need to
1754+ ; ; match but not fontify the next "name" (which
1755+ ; ; really is the type).
1756+ (if (string-match-p " =>" (match-string 0 ))
1757+ (setq perform-match t )
1758+ (goto-char (match-beginning 0 ))
1759+ (setq perform-match nil ))))))))
1760+ ; ; conditions to handle
1761+ (scan-error nil )
1762+ (end-of-buffer nil ))
1763+ nil )
1764+
16891765(defun typescript--in-documentation-comment-p ()
16901766 " Reports whether point is inside a documentation comment."
16911767 (let ((parse (syntax-ppss )))
@@ -1855,16 +1931,48 @@ and searches for the next token to be highlighted."
18551931 (concat " \\ _<instanceof\\ _>\\ s-+\\ (" typescript--dotted-name-re " \\ )" )
18561932 (list 1 'font-lock-type-face ))
18571933
1858- ; ; formal parameters
1934+ ; ; formal parameters in "function" function call
1935+ ; ; function helloWorld(a: number, b: Promise<number>): void { }
18591936 ,(list
18601937 (concat
18611938 " \\ _<function\\ _>\\ (\\ s-+" typescript--name-re " \\ )?\\ s-*\\ (<.*>\\ )?\\ s-*(\\ s-*"
18621939 " \\ (?:$\\ |" typescript--name-start-re " \\ )" )
1863- `(,( concat " \\ ( " typescript--name-re " \\ ) \\ (?: \\ s-*? \\ ([,:)] \\ |$ \\ ) \\ ) " )
1864- (prog1 (save-excursion (re-search-forward " ) " nil t ))
1940+ `(typescript--function-argument-matcher
1941+ (prog1 (save-excursion (ignore-errors ( up-list )) ( point ))
18651942 (backward-char ))
18661943 nil
1867- (1 font-lock-variable-name-face ))))
1944+ nil ))
1945+
1946+ ; ; formal parameters in arrow function
1947+ ; ; const helloWorld = (a: number, b: Promise<number>): void => { }
1948+ ,(list
1949+ (rx (group " =>" ) (* whitespace) (? eol) (* whitespace) " {" )
1950+ '(1 font-lock-keyword-face )
1951+ `(typescript--function-argument-matcher
1952+ (prog1 (progn
1953+ (backward-char )
1954+ (typescript--backward-to-parameter-list)
1955+ (point ))
1956+ (backward-sexp ))
1957+ (re-search-forward " {" nil t )
1958+ nil ))
1959+
1960+ ; ; formal parameters in method definitions
1961+ ; ; class Foo { helloWorld(a: number, b: Promise<number>): void { } }
1962+ ,(list
1963+ typescript--function-call-re
1964+ `(typescript--function-argument-matcher
1965+ (let ((point-orig (point ))
1966+ (is-method-def
1967+ (ignore-errors
1968+ (up-list )
1969+ (looking-at-p
1970+ (rx (* (or whitespace ?\n )) (or " :" " {" ))))))
1971+ (if is-method-def
1972+ (prog1 (point ) (goto-char point-orig))
1973+ (point )))
1974+ nil
1975+ nil )))
18681976 " Level three font lock for `typescript-mode' ." )
18691977
18701978(defun typescript--flyspell-mode-predicate ()
0 commit comments