;; -*- lexical-binding: t; -*- ;; Tree sitter is a fast parser that supports a number of programming languages (use-package tree-sitter :hook (after-init . global-tree-sitter-mode) :config (add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode) (defun tree-sitter-first-matching-child (node pred) "Returns the first child of `node' for which `pred' returns true." (cl-loop for i from 0 below (tsc-count-children node) for child = (tsc-get-nth-child node i) if (funcall pred child) return child)) (defun tree-sitter-get-package-name () "Gets the identifier name of the current buffer's package (for languages that have them)." ;; TODO is there a better way to do this? (condition-case nil (let* ((root (tsc-root-node tree-sitter-tree)) (child (tsc-get-nth-named-child root 0))) (when (eq (tsc-node-type child) 'package_declaration) (tsc-node-text (tsc-get-nth-child child 1)))) (error nil))) (defun tree-sitter-get-enclosing-function-name (pos) "Gets the identifier name of the method or function enclosing the position `pos', if it exists." (condition-case nil (let ((func (tree-sitter-node-at-pos 'method_declaration pos))) (tsc-node-text (tsc-get-child-by-field func :name))) (error nil))) (defun tree-sitter-get-enclosing-class-name (pos) "Gets the identifier name of the class enclosing the position `pos', if it exists." (condition-case nil (let ((class (tree-sitter-node-at-pos 'class_declaration pos))) (tsc-node-text (tsc-get-child-by-field class :name))) (error nil))) (defun tree-sitter-fully-qualified-class-name (pos) "Gets the fully-qualified class name enclosing `pos', if it exists." (when-let* ((package (tree-sitter-get-package-name)) (class (tree-sitter-get-enclosing-class-name pos))) (format "%s.%s" package class))) (defun tree-sitter-get-enclosing-annotations (pos) "Returns a list of annotation name strings for the current method or class." (when-let* ((node (or (tree-sitter-node-at-pos 'method_declaration pos) (tree-sitter-node-at-pos 'class_declaration pos))) (mods (tree-sitter-first-matching-child node (lambda (n) (eq (tsc-node-type n) 'modifiers))))) (cl-loop for i from 0 below (tsc-count-children mods) for child = (tsc-get-nth-child mods i) if (not (null (tsc-get-child-by-field child :name))) collect (tsc-node-text (tsc-get-child-by-field child :name)))))) (use-package tree-sitter-langs) (provide 'init-tree-sitter)