Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TSX (web-mode) tree-sitter-hl not working #23

Open
loafofpiecrust opened this issue Oct 30, 2020 · 11 comments
Open

TSX (web-mode) tree-sitter-hl not working #23

loafofpiecrust opened this issue Oct 30, 2020 · 11 comments
Labels
bug Something isn't working more information needed

Comments

@loafofpiecrust
Copy link

I've been using tree-sitter-hl-mode for rustic-mode and js2-mode and it seems to be working great. When I try to enable it in a .tsx file (typescript-tsx-mode), however, I get an error and the mode fails to start.

font-lock-eval-keywords: Wrong number of arguments: #<subr quote>, 0

Here's the backtrace:

Debugger entered--Lisp error: (wrong-number-of-arguments #<subr quote> 0)
  quote()
  font-lock-eval-keywords(quote)
  tree-sitter-hl--minimize-font-lock-keywords()
  #<subr tree-sitter-hl--setup>()
  apply(#<subr tree-sitter-hl--setup> nil)
  tree-sitter-hl--setup()
  tree-sitter-hl-mode(toggle)
  funcall-interactively(tree-sitter-hl-mode toggle)
  command-execute(tree-sitter-hl-mode record)
  counsel-M-x-action("tree-sitter-hl-mode")
  #f(compiled-function (x) #<bytecode -0x20a815e057386a3>)("tree-sitter-hl-mode")
...
@ubolonton
Copy link
Collaborator

Can you provide more details to reproduce the issue? For example:

  • Your OS and Emacs build, e.g. the result of (emacs-version).
  • The installation mechanism, e.g. package.el vs. straight.el.
  • What is typescript-tsx-mode? Where does it come from? It doesn't seem to be on MELPA.
  • A minimal init.el with the issue. This can be a good start: https://gist.github.com/ubolonton/a4cfe85782f40e280570b3ef393ded5f
  • The values of font-lock-keywords and font-lock-defaults before enabling tree-sitter-hl.

@loafofpiecrust
Copy link
Author

loafofpiecrust commented Jan 19, 2021

Sorry that I'm just now responding to this. It still doesn't seem to work on the latest commit.

  • Result of M-x emacs-version: GNU Emacs 28.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.21, cairo version 1.16.0), this is native-comp running on NixOS 20.09 with doom.
  • Installation: straight.el, which comes with doom
  • typescript-tsx-mode comes from DOOM, just derived from `web-mode, described like so:
Major mode derived from web-mode by define-derived-mode.

It inherits all of the parent's attributes, but has its own keymap,
abbrev table and syntax table:

  typescript-tsx-mode-map, typescript-tsx-mode-abbrev-table and typescript-tsx-mode-syntax-table

Here's the relevant part of my config:

(use-package tree-sitter
  :hook ((rustic-mode python-mode json-mode js-mode js2-mode typescript-mode go-mode sh-mode) . tree-sitter-mode)
  :config
  (require 'tree-sitter-langs)
  (push '(typescript-tsx-mode . typescript) tree-sitter-major-mode-language-alist)
  (add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode))

Here's font-lock-keywords:

(t
 (web-mode-fontify
  (whitespace-point--flush-used)
  ("\\(	+\\)" 1 whitespace-tab t))
 (web-mode-fontify
  (0 font-lock-keyword-face))
 (whitespace-point--flush-used
  (0 nil))
 ("\\(	+\\)"
  (1 whitespace-tab t)))

Here's font-lock-defaults:

('(web-mode-fontify)
 t)

EDIT 2: I just tried it with plain web-mode and got the same error that I put in my first comment.

@loafofpiecrust loafofpiecrust changed the title TSX (Typescript JSX) tree-sitter-hl not working TSX (web-mode) tree-sitter-hl not working Feb 10, 2021
@srcreigh
Copy link

srcreigh commented Feb 13, 2021

typescript and typescript-tsx have different syntax see tree-sitter-typescript

It's a conflict between <div></div> JSX syntax and the <number>foo Typescript casting syntax. In typescript-tsx you cast using foo as number. see here https://www.typescriptlang.org/docs/handbook/jsx.html#the-as-operator

I think the fix is to have separate mode, grammar, and HL queries for typescript-tsx

I also get parsing errors from a normal TSX file using typescript-mode, even though it compiles correctly.

@srcreigh
Copy link

Turns out tree-sitter-langs already comes with the TSX grammar, you can set it up with a typescript-tsx mode.

Still missing TSX highlighting queries I think. but this is a pretty good start.

Here's my config that lets me parse TSX

;; Typescript
(setq typescript-indent-level 2)
;; you can also use the DOOM one if you wish
(define-derived-mode typescript-tsx-mode typescript-mode "TSX"
  "Major mode for editing TSX files.

Refer to Typescript documentation for syntactic differences between normal and TSX
variants of Typescript.")
(add-to-list 'auto-mode-alist '("\\.tsx?\\'" . typescript-tsx-mode))

(use-package tree-sitter
  :ensure t)

(use-package tree-sitter-langs
  :ensure t
  :after tree-sitter
  :config
  (tree-sitter-require 'tsx)
  (add-to-list 'tree-sitter-major-mode-language-alist '(typescript-tsx-mode . tsx)))

With this config, if I open a typescript file and check M-x tree-sitter-debug-mode, I get some nice jsx nodes in the parse tree:

program:
  import_statement:
    import_clause:
      namespace_import:
        identifier:
    string:
  import_statement:
    string:
  import_statement:
    import_clause:
      identifier:
    string:
  lexical_declaration:
    variable_declarator:
      identifier:
      arrow_function:
        formal_parameters:
        statement_block:
          return_statement:
            parenthesized_expression:
              jsx_element:
                jsx_opening_element:
                  identifier:
                jsx_text:
                jsx_element:
                  jsx_opening_element:
                    identifier:
                  jsx_text:
                  jsx_closing_element:
                    identifier:
                jsx_text:
                jsx_element:
                  jsx_opening_element:
                    identifier:
                    jsx_attribute:
                      property_identifier:
                      string:
                  jsx_text:
                  jsx_element:
                    jsx_opening_element:
                      identifier:
                      jsx_attribute:
                        property_identifier:
                        string:
                    jsx_text:
                    jsx_closing_element:
                      identifier:
                  jsx_text:
                  jsx_element:
                    jsx_opening_element:
                      identifier:
                      jsx_attribute:
                        property_identifier:
                        string:
                    jsx_text:
                    jsx_closing_element:
                      identifier:
                  jsx_text:
                  jsx_element:
                    jsx_opening_element:
                      identifier:
                      jsx_attribute:
                        property_identifier:
                        string:
                    jsx_text:
                    jsx_closing_element:
                      identifier:
                  jsx_text:
                  jsx_closing_element:
                    identifier:
                jsx_text:
                jsx_closing_element:
                  identifier:
  export_statement:
    identifier:

@dpassen
Copy link

dpassen commented Feb 26, 2021

@srcreigh I wonder if a very small MELPA package that sets up the derived mode as a target for hooks wouldn't be such a bad idea.

@vconcat
Copy link
Contributor

vconcat commented Feb 27, 2021

https://github.com/tree-sitter/tree-sitter-javascript/blob/master/queries/highlights-jsx.scm

simple jsx highlights.scm, can be used with existed typescript and javascript query.

Update: the query for typescript may need some changes since the grammer for typescript and tsx are different.

@sangaline
Copy link

This is a crude workaround, but if you set

(setq tree-sitter-hl-use-font-lock-keywords nil)

then you'll bypass the logic in tree-sitter-hl--minimize-font-lock-keywords that causes the error. Highlighting works correctly after that.

My value of font-lock-keywords when I get the error is:

 (("\\_<[[:digit:]]+\\(?:\\.[0-9]*\\)?\\_>" quote highlight-numbers-number)
  web-mode-fontify
  ((lambda
     (bound)
     (hl-todo--search nil bound))
   (1
    (hl-todo--get-face)
    t t))
  (whitespace-point--flush-used)
  ("\\(  +\\)" 1 whitespace-tab t))

Unlike what @loafofpiecrust posted, this does include quote as seen in the error, so maybe that's helpful for somebody who understands the tree-sitter-hl--minimize-font-lock-keywords code better than I do.

@Abdillah
Copy link

Abdillah commented May 23, 2021

Thanks @sangaline for the workaround.

Oh It seems my concern below actually has been handled well. The problem came on the (dolist (keyword keywords-list) ...) construct, which still iterate on quote of '(web-mode-fontify).


Previously:

I'm exploring a bit and found this bug is mainly due to this construct, right?

;; In web-mode
(setq font-lock-defaults '('(web-mode-fontify) t))
;; In emacs-tree-sitter
(setq keywords-spec (car font-lock-defaults))
(car (cdr keywords-spec)))
;; Which led to an equivalent
(car (car '('(web-mode-fontify)))) ;; => quote

If font-lock-defaults value allow to have quote, I think any mode will be broken on this part. Maybe someone has the idea on what value font-lock-defaults allows?

@ubolonton ubolonton transferred this issue from emacs-tree-sitter/elisp-tree-sitter Jul 24, 2021
@shackra shackra added bug Something isn't working more information needed labels Jul 24, 2021
@OrionRandD
Copy link

Perhaps, related to this issue?
https://hungyi.net/posts/use-emacs-tree-sitter-doom-emacs/

@Abdillah
Copy link

Yes, albeit not a solution. I remember started using this after reading the post.
I'm assuming that web-mode quite dependent on font-lock or syntax table, thus sometime using tree-sitter make some commands go awry.

@mkcode
Copy link

mkcode commented Jan 18, 2023

In case anyone else comes across this -

The following pattern works well enough for me as a workaround for tree-sitter in a derived web-mode.

(defun typescript-tsx-mode-fix-tree-sitter()
   (set (make-local-variable 'tree-sitter-hl-use-font-lock-keywords) nil))
(add-hook 'typescript-tsx-mode-hook #'typescript-tsx-mode-fix-tree-sitter)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working more information needed
Projects
None yet
Development

No branches or pull requests

10 participants