From 0b8a4ae66d1ddcc286cf1b7a54fb82894dcb0b9d Mon Sep 17 00:00:00 2001 From: Noah Peart Date: Wed, 13 Dec 2023 00:10:19 -0800 Subject: [PATCH] Add font-locking for assignments in typescript-ts-mode * lisp/progmodes/typescript-ts-mode.el (typescript-ts-mode--font-lock-settings): Add font-locking for left-hand side of assignments. (typescript-ts-mode--fontify-assignment-lhs): New function to fontify typescript-ts-mode assignments. (typescript-ts-mode--assignment-lhs-query): Add tree-sitter query to capture assignment nodes for font-locking. * test/lisp/progmodes/typescript-ts-mode-tests.el (typescript-ts-mode-test-font-lock): New test for font-locking in typescript-ts-mode. * test/lisp/progmodes/typescript-ts-mode-resources/font-lock.ts: New file with font-lock tests for typescript-ts-mode. --- lisp/progmodes/typescript-ts-mode.el | 51 ++++++++++++++++++- .../typescript-ts-mode-resources/font-lock.ts | 50 ++++++++++++++++++ .../progmodes/typescript-ts-mode-tests.el | 6 +++ 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 test/lisp/progmodes/typescript-ts-mode-resources/font-lock.ts diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index 7f0b7236301..8c3370ddc93 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -199,6 +199,38 @@ tsx-ts-mode--font-lock-compatibility-bb1f97b [(nested_identifier (identifier)) (identifier)] @typescript-ts-jsx-tag-face))))) +(defvar typescript-ts-mode--assignment-lhs-query + (when (treesit-available-p) + (treesit-query-compile + 'typescript + '((subscript_expression object: (identifier) @id) + (subscript_expression index: (identifier) @index) + (member_expression object: (identifier) @id) + (member_expression property: (property_identifier) @property)))) + "Query that captures object, index, and property identifiers.") + +(defun typescript-ts-mode--fontify-assignment-lhs (node override start end &rest _) + "Fontify the lhs NODE of an assignment_expression. +For OVERRIDE, START, END, see `treesit-font-lock-rules'." + ;; when INDEX > 1, apply `-*use-face' to identifiers/properties + (let ((index 0)) + (pcase-dolist (`(,name . ,node) + (treesit-query-capture + node typescript-ts-mode--assignment-lhs-query)) + (treesit-fontify-with-override + (treesit-node-start node) (treesit-node-end node) + (pcase name + ('id (prog1 (if (zerop index) + 'font-lock-variable-name-face + 'font-lock-variable-use-face) + (cl-incf index))) + ('property (if (= 1 index) + 'font-lock-property-name-face + 'font-lock-property-use-face)) + ('index 'font-lock-variable-use-face) + (_ nil)) + override start end)))) + (defun typescript-ts-mode--font-lock-settings (language) "Tree-sitter font-lock settings. Argument LANGUAGE is either `typescript' or `tsx'." @@ -314,6 +346,8 @@ typescript-ts-mode--font-lock-settings :feature 'property `((property_signature name: (property_identifier) @font-lock-property-name-face) + (index_signature + name: (identifier) @font-lock-property-name-face) (public_field_definition name: (property_identifier) @font-lock-property-name-face) @@ -353,6 +387,21 @@ typescript-ts-mode--font-lock-settings (append (tsx-ts-mode--font-lock-compatibility-bb1f97b language) `((jsx_attribute (property_identifier) @typescript-ts-jsx-attribute-face))) + :language language + :feature 'assignment + '((assignment_expression + left: (identifier) @font-lock-variable-name-face) + (assignment_expression + left: (_) @typescript-ts-mode--fontify-assignment-lhs) + (augmented_assignment_expression + left: (identifier) @font-lock-variable-name-face) + (augmented_assignment_expression + left: (_) @typescript-ts-mode--fontify-assignment-lhs) + (update_expression + argument: (identifier) @font-lock-variable-name-face) + (update_expression + argument: (_) @typescript-ts-mode--fontify-assignment-lhs)) + :language language :feature 'number `((number) @font-lock-number-face @@ -486,7 +535,7 @@ typescript-ts-mode '((comment declaration) (keyword string escape-sequence) (constant expression identifier number pattern property) - (operator function bracket delimiter))) + (assignment operator function bracket delimiter))) (setq-local syntax-propertize-function #'typescript-ts--syntax-propertize) (treesit-major-mode-setup))) diff --git a/test/lisp/progmodes/typescript-ts-mode-resources/font-lock.ts b/test/lisp/progmodes/typescript-ts-mode-resources/font-lock.ts new file mode 100644 index 00000000000..f9680886c57 --- /dev/null +++ b/test/lisp/progmodes/typescript-ts-mode-resources/font-lock.ts @@ -0,0 +1,50 @@ +// Test assignment left-hand side fontification +const assignment = (): number => { + // ^ font-lock-function-name-face + // ^ font-lock-type-face + let foo = 0; + // ^ font-lock-variable-name-face + foo += 1; + //^ font-lock-variable-name-face + let obj: {[key: string]: any} = {}; + // ^ font-lock-variable-name-face + // ^ font-lock-property-name-face + // ^ font-lock-type-face + // ^ font-lock-type-face + obj.x.y = 0; + //^ font-lock-variable-name-face + // ^ font-lock-property-name-face + // ^ font-lock-property-name-face + ++obj.x++; + // ^ font-lock-variable-name-face + // ^ font-lock-property-name-face + arr[obj.x * obj.x] = 1; + //^ font-lock-variable-name-face + // ^ font-lock-variable-use-face + // ^ font-lock-property-use-face + let x = 0, y = 0, arr = [0,0], mat = [[0],[0]]; + [ x, y] = [y, x]; + //^ font-lock-variable-name-face + // ^ font-lock-variable-name-face + if ((x = 1)) x++; + // ^ font-lock-variable-name-face + // ^ font-lock-variable-name-face + arr[arr[0]] = 2; + //^ font-lock-variable-name-face + // ^ font-lock-variable-use-face + // ^ font-lock-number-face + ++mat[x][arr[0]]; + // ^ font-lock-variable-name-face + // ^ font-lock-variable-use-face + mat[mat[arr[arr[obj.x]]][x]][arr[0]] = 2; + //^ font-lock-variable-name-face + // ^ font-lock-variable-use-face + // ^ font-lock-variable-use-face + // ^ font-lock-variable-use-face + // ^ font-lock-variable-use-face + // ^ font-lock-property-use-face + // ^ font-lock-variable-use-face + // ^ font-lock-variable-use-face + // ^ font-lock-number-face + return 0; +}; diff --git a/test/lisp/progmodes/typescript-ts-mode-tests.el b/test/lisp/progmodes/typescript-ts-mode-tests.el index 126f5e3298f..d426c4e50eb 100644 --- a/test/lisp/progmodes/typescript-ts-mode-tests.el +++ b/test/lisp/progmodes/typescript-ts-mode-tests.el @@ -27,5 +27,11 @@ typescript-ts-mode-test-indentation (skip-unless (treesit-ready-p 'typescript)) (ert-test-erts-file (ert-resource-file "indent.erts"))) +(ert-deftest typescript-ts-mode-test-font-lock () + (skip-unless (treesit-ready-p 'typescript)) + (let ((treesit-font-lock-level 4)) + (ert-font-lock-test-file + (ert-resource-file "font-lock.ts") 'typescript-ts-mode))) + (provide 'typescript-ts-mode-tests) ;;; typescript-ts-mode-tests.el ends here -- 2.34.1