]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve parameter checking in tree-sitter functions
authorYuan Fu <casouri@gmail.com>
Wed, 7 Dec 2022 03:56:25 +0000 (19:56 -0800)
committerYuan Fu <casouri@gmail.com>
Wed, 7 Dec 2022 20:01:37 +0000 (12:01 -0800)
* src/treesit.c (treesit_check_position): Extract out new function.
(Ftreesit_node_first_child_for_pos)
(Ftreesit_node_descendant_for_range): Replace code with the new
function.
(Ftreesit_query_capture): Add missing check for node and parser.  Add
check for range for BEG and END.  Move treesit_initialize to the
beginning of the function.

* test/src/treesit-tests.el (treesit-node-api)
(treesit-query-api): Add tests for out-of-range error.

src/treesit.c
test/src/treesit-tests.el

index 9926806612a679c7a68ca996f13e204fdfcde8fa..8b485ca4ecedb6a428f1c41593bfbc61ba21a7ef 100644 (file)
@@ -1642,6 +1642,17 @@ treesit_check_node (Lisp_Object obj)
     xsignal1 (Qtreesit_node_outdated, obj);
 }
 
+/* Checks that OBJ is a positive integer and it is within the visible
+   portion of BUF. */
+static void
+treesit_check_position (Lisp_Object obj, struct buffer *buf)
+{
+  treesit_check_positive_integer (obj);
+  ptrdiff_t pos = XFIXNUM (obj);
+  if (pos < BUF_BEGV (buf) || pos > BUF_ZV (buf))
+    xsignal1 (Qargs_out_of_range, obj);
+}
+
 bool
 treesit_node_uptodate_p (Lisp_Object obj)
 {
@@ -1990,14 +2001,12 @@ Note that this function returns an immediate child, not the smallest
   if (NILP (node))
     return Qnil;
   treesit_check_node (node);
-  treesit_check_positive_integer (pos);
 
   struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer);
   ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg;
   ptrdiff_t byte_pos = buf_charpos_to_bytepos (buf, XFIXNUM (pos));
 
-  if (byte_pos < BUF_BEGV_BYTE (buf) || byte_pos > BUF_ZV_BYTE (buf))
-    xsignal1 (Qargs_out_of_range, pos);
+  treesit_check_position (pos, buf);
 
   treesit_initialize ();
 
@@ -2028,19 +2037,14 @@ If NODE is nil, return nil.  */)
 {
   if (NILP (node)) return Qnil;
   treesit_check_node (node);
-  CHECK_INTEGER (beg);
-  CHECK_INTEGER (end);
 
   struct buffer *buf = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer);
   ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg;
   ptrdiff_t byte_beg = buf_charpos_to_bytepos (buf, XFIXNUM (beg));
   ptrdiff_t byte_end = buf_charpos_to_bytepos (buf, XFIXNUM (end));
 
-  /* Checks for BUFFER_BEG <= BEG <= END <= BUFFER_END.  */
-  if (!(BUF_BEGV_BYTE (buf) <= byte_beg
-       && byte_beg <= byte_end
-       && byte_end <= BUF_ZV_BYTE (buf)))
-    xsignal2 (Qargs_out_of_range, beg, end);
+  treesit_check_position (beg, buf);
+  treesit_check_position (end, buf);
 
   treesit_initialize ();
 
@@ -2426,21 +2430,24 @@ the query.  */)
   (Lisp_Object node, Lisp_Object query,
    Lisp_Object beg, Lisp_Object end, Lisp_Object node_only)
 {
-  if (!NILP (beg))
-    CHECK_INTEGER (beg);
-  if (!NILP (end))
-    CHECK_INTEGER (end);
-
   if (!(TS_COMPILED_QUERY_P (query)
        || CONSP (query) || STRINGP (query)))
     wrong_type_argument (Qtreesit_query_p, query);
 
+  treesit_initialize ();
+
   /* Resolve NODE into an actual node.  */
   Lisp_Object lisp_node;
   if (TS_NODEP (node))
-    lisp_node = node;
+    {
+      treesit_check_node (node); /* Check if up-to-date.  */
+      lisp_node = node;
+    }
   else if (TS_PARSERP (node))
-    lisp_node = Ftreesit_parser_root_node (node);
+    {
+      treesit_check_parser (node); /* Check if deleted.  */
+      lisp_node = Ftreesit_parser_root_node (node);
+    }
   else if (SYMBOLP (node))
     {
       Lisp_Object parser
@@ -2452,8 +2459,6 @@ the query.  */)
              list4 (Qor, Qtreesit_node_p, Qtreesit_parser_p, Qsymbolp),
              node);
 
-  treesit_initialize ();
-
   /* Extract C values from Lisp objects.  */
   TSNode treesit_node
     = XTS_NODE (lisp_node)->node;
@@ -2464,6 +2469,13 @@ the query.  */)
   const TSLanguage *lang
     = ts_parser_language (XTS_PARSER (lisp_parser)->parser);
 
+  /* Check BEG and END.  */
+  struct buffer *buf = XBUFFER (XTS_PARSER (lisp_parser)->buffer);
+  if (!NILP (beg))
+    treesit_check_position (beg, buf);
+  if (!NILP (end))
+    treesit_check_position (end, buf);
+
   /* Initialize query objects.  At the end of this block, we should
      have a working TSQuery and a TSQueryCursor.  */
   TSQuery *treesit_query;
index 80fde408cd389ff174bf2b4ff5c6cda6c3e90659..aba12759c34869d1660c944088a5684409ad9630 100644 (file)
                      (treesit-node-string
                       (treesit-node-first-child-for-pos
                        doc-node 3))))
+      (should-error (treesit-node-first-child-for-pos doc-node 100)
+                    :type 'args-out-of-range)
       ;; `treesit-node-descendant-for-range'.
       (should (equal "(\"{\")"
                      (treesit-node-string
                      (treesit-node-string
                       (treesit-node-descendant-for-range
                        root-node 6 7 t))))
+      (should-error (treesit-node-descendant-for-range
+                     root-node 100 101)
+                    :type 'args-out-of-range)
       ;; `treesit-node-eq'.
       (should (treesit-node-eq root-node root-node))
       (should (not (treesit-node-eq root-node doc-node))))))
         (setq root-node (treesit-parser-root-node
                          parser)))
 
+      (should-error (treesit-query-capture root-node "" 100 101)
+                    :type 'args-out-of-range)
+
       ;; Test `treesit-query-capture' on string, sexp and compiled
       ;; queries.
       (dolist (query1