diff options
author | Wilfred Hughes <me@wilfred.me.uk> | 2023-08-08 23:26:49 -0700 |
---|---|---|
committer | Wilfred Hughes <me@wilfred.me.uk> | 2023-08-08 23:26:49 -0700 |
commit | 20760558ff8a8895b49ce49304f9ade50561bceb (patch) | |
tree | 2caf8060cf55fc76baf4ee0f75bd457cd088f7e1 | |
parent | 3612c472f5f62f6f95219f84c6c0c47bf4f81a4c (diff) | |
parent | 338db38330f0d25cba8e2c6428240ebc5e020264 (diff) |
Merge commit '338db38330f0d25cba8e2c6428240ebc5e020264'
3 files changed, 246 insertions, 0 deletions
diff --git a/vendored_parsers/tree-sitter-commonlisp/package.json b/vendored_parsers/tree-sitter-commonlisp/package.json index d2f574875..7ceefd422 100644 --- a/vendored_parsers/tree-sitter-commonlisp/package.json +++ b/vendored_parsers/tree-sitter-commonlisp/package.json @@ -2,6 +2,14 @@ "name": "tree-sitter-commonlisp", "version": "0.3.0", "description": "Tree-sitter grammar for Common Lisp", + "tree-sitter": [ + { + "scope": "source.lisp", + "file-types": [ + "lisp" + ] + } + ], "main": "bindings/node", "scripts": { "test": "tree-sitter generate && tree-sitter test" diff --git a/vendored_parsers/tree-sitter-commonlisp/queries/tags.scm b/vendored_parsers/tree-sitter-commonlisp/queries/tags.scm new file mode 100644 index 000000000..2341c9628 --- /dev/null +++ b/vendored_parsers/tree-sitter-commonlisp/queries/tags.scm @@ -0,0 +1,122 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Function Definitions ;;;;;;;;;;;;;;;;;;;;;;; + +(defun_header + function_name: (sym_lit) @name) @definition.function + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Function Calls ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; Basically, we consider every list literal with symbol as the +;;; first element to be a call to a function named by that element. +;;; But we must exclude some cases. Note, tree-sitter @ignore +;;; cases only work if they are declared before the cases +;;; we want to include. + +;; Exclude lambda lists for function definitions +;; For example: +;; +;; (defun my-func (arg1 arg2) ...) +;; +;; do not treat (arg1 arg2) as a call of function arg1 +;; +(defun_header + lambda_list: (list_lit . [(sym_lit) (package_lit)] @ignore)) + +;; Similar to the above, but for +;; +;; (defmethod m ((type1 param1) (type2 param2)) ...) +;; +;; where list literals having symbol as their first element +;; are nested inside the lambda list. +(defun_header + lambda_list: (list_lit (list_lit . [(sym_lit) (package_lit)] @ignore))) + +;; +;; (let ((var ...) (var2 ...)) ...) +;; +;; - exclude var, var2 +;; - the same for let*, flet, labels, macrolet, symbol-macrolet +(list_lit . [(sym_lit) (package_lit)] @name + . (list_lit (list_lit . [(sym_lit) (package_lit)] @ignore)) + (#match? @name + "(?i)^(cl:)?(let|let\\*|flet|labels|macrolet|symbol-macrolet)$") + ) + +;; TODO: +;; - exclude also: +;; - (defclass name (parent parent2) +;; ((slot1 ...) +;; (slot2 ...)) +;; exclude the parent, slot1, slot2 +;; - (flet ((func-1 (param1 param2))) ...) +;; - we already exclude func-1, but param1 is still recognized +;; as a function call - exclude it too +;; - the same for labels +;; - the same macrolet +;; - what else? +;; (that's a non-goal to completely support all macros +;; and special operators, but every one we support +;; makes the solution a little bit better) +;; - (flet ((func-1 (param1 param2))) ...) +;; - instead of simply excluding it, as we do today, +;; tag func-1 as @local.definition.function (I suppose) +;; - the same for labels, macrolet +;; - @local.scope for let, let*, flet, labels, macrolet +;; - I guess the whole span of the scope text, +;; till the closing paren, should be tagged as @local.scope; +;; Hopefully, combined with @local.definition.function +;; withing the scope, the usual @reference.call within +;; that scope will refer to the local definition, +;; and there will be no need to use @local.reference.call +;; (which is more difficult to implement). +;; - When implementing, remeber the scope rules differences +;; of let vs let*, flet vs labels. + + +;; Inlclude all other cases - list literal with symbol as the +;; first element +(list_lit . [(sym_lit) (package_lit)] @name) @reference.call + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; classes + +(list_lit . [(sym_lit) (package_lit)] @ignore + . [(sym_lit) (package_lit)] @name + (#match? @ignore "(?i)^(cl:)?defclass$") + ) @definition.class + +(list_lit . [(sym_lit) (package_lit)] @ignore + . (quoting_lit [(sym_lit) (package_lit)] @name) + (#match? @ignore "(?i)^(cl:)?make-instance$") + ) @reference.class + +;;; TODO: +;; - @reference.class for base classes + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; TODO: +;; - Symbols referenced in defpackage +;; +;; (defpackage ... +;; (:export (symbol-a :symbol-b #:symbol-c "SYMBOL-D"))) +;; +;; The goal is to allow quick navigation from the API +;; overview in the form of defpackage, to the definition +;; where user can read parameters, docstring, ect. +;; - The @name must not include the colon, or sharpsign colon, quotes, +;; just symbol-a, symbol-b, symbol-c, sybmol-d +;; - Downcase the names specified as stirng literals? +;; ("SYMBOL-D" -> symbol-d) +;; - We don't know if the exported symbol is a function, variable, +;; class or something else. The oficial doc +;; (https://tree-sitter.github.io/tree-sitter/code-navigation-systems) +;; does not even suggest a tag for variable reference. +;; (Although in practice, the `tree-sitter tags` command +;; allows any @reference.* and @definition.* tags) +;; Probably it's better to just use @reference.call for all +;; the symbols in the :export clause. +;; +;; - The same for the export function call: +;; +;; (export '(symbol-a :symbol-b #:symbol-c "SYMBOL-D")) diff --git a/vendored_parsers/tree-sitter-commonlisp/test/tags/tags-test.lisp b/vendored_parsers/tree-sitter-commonlisp/test/tags/tags-test.lisp new file mode 100644 index 000000000..d1fb7a97f --- /dev/null +++ b/vendored_parsers/tree-sitter-commonlisp/test/tags/tags-test.lisp @@ -0,0 +1,116 @@ +;;;; -*- buffer-auto-save-file-name: nil; Mode: LISP; Syntax: COMMON-LISP; indent-tabs-mode: nil; coding: utf-8; show-trailing-whitespace: t -*- +;;;; Disabled Emacs auto save, by setting buffer-auto-save-file-name: nil +;;;; because `tree-sitter tests` complains about +;;;; the auto save file with tilda at the end of the name. + +;;;; Negative assertions are not supported, +;;;; https://github.com/tree-sitter/tree-sitter/issues/2304 +;;;; But I use exclamation sign to mark the places that +;;;; must not be tagged: +;;;; +;;;; ! tag.name +;;;; +;;;; They are not checked automatically, but we can check +;;;; those places manually, by reviewing the output +;;;; of `tree-sitter tags tags/tags-test.lisp` + + +(defun test-fn (a b) + ;; ^ definition.function + (let ((x (+ a b)) + ;; ^ reference.call + (y (- a b))) + ;; ^ reference.call + (* x y))) + ;; ^ reference.call + + +(let ((a 1) (b 2)) + ;; ! reference.call + ;; ! reference.call + ) + +(cl:let ((a 1) (b 2)) + ;; ! reference.call + ;; ! reference.call + ) + +(let* ((a 1) (b 2)) + ;; ! reference.call + ;; ! reference.call + ) + +(cl:let* ((a 1) (b 2)) + ;; ! reference.call + ;; ! reference.call + ) + + +(LET ((a 1) (bb 2)) + ;; ! reference.call + ;; ! reference.call + ) + +(lets ((a 1) (bb 2)) + ;; ! reference.call + ;; ! reference.call + ) + +(zlet ((a 1) (bb 2)) + ;; ! reference.call + ;; ! reference.call + ) + +(defun tst () + ;; ^ definition.function + (CL:LET ((a 1) + ;; ! reference.call + (x 2) + ;; ! reference.call + (y (add 3 7))) + ;; ^ reference.call + ;; ! reference.call + )) + +(flet ((my-add (a b) (+ a b)) + (my-mul (a b) (* a b))) + (my-add 1 (my-mul 7 3))) +;; ^ reference.call +;; ^ reference.call + +(defclass test-class (base-class) + ;; ^ reference.call + ;; ^ definition.class + ((slot-a) + (slot-b))) + +(dEFclass test-class (base-class) + ;; ^ definition.class + ((slot-a) + (slot-b))) + +(maKE-instance 'test-class) +;; ^ reference.call +;; ^ reference.class + +(make-instance 'test-class) +;; ^ reference.call +;; ^ reference.class + +(defclasses test-class2 (base-class) + ;; ! reference.class + ((slot-a) + (slot-b))) + +(make-instances 'test-class2) +;; ! reference.class + +(ddddefclass test-class3 (base-class) + ;; ! definition.class + ((slot-a) + (slot-b))) + +(mmmmake-instance 'test-class3) +;; ! reference.class + + |