diff --git a/configure.ac b/configure.ac index 0d7c58d8020..420ab6dabe6 100644 --- a/configure.ac +++ b/configure.ac @@ -4069,39 +4069,15 @@ TREE_SITTER_OBJ= NEED_DYNLIB=no if test "${with_tree_sitter}" != "no"; then - dnl Tree-sitter 0.20.2 added support to change the malloc it uses - dnl at runtime, we need that feature. However, tree-sitter's - dnl Makefile has problems, until that's fixed, all tree-sitter - dnl libraries distributed are versioned 0.6.3. We try to - dnl accept a tree-sitter library that has incorrect version as long - dnl as it supports changing malloc. - EMACS_CHECK_MODULES([TREE_SITTER], [tree-sitter >= 0.20.2], + dnl Tree-sitter 0.20.10 added ts_tree_cursor_goto_previous_sibling, we + dnl need it for a more efficient implementation for traversing the + dnl parse tree backwards (bug#80108). + EMACS_CHECK_MODULES([TREE_SITTER], [tree-sitter >= 0.20.10], [HAVE_TREE_SITTER=yes], [HAVE_TREE_SITTER=no]) if test "${HAVE_TREE_SITTER}" = yes; then AC_DEFINE(HAVE_TREE_SITTER, 1, [Define if using tree-sitter.]) NEED_DYNLIB=yes - else - EMACS_CHECK_MODULES([TREE_SITTER], [tree-sitter >= 0.6.3], - [HAVE_TREE_SITTER=yes], [HAVE_TREE_SITTER=no]) - if test "${HAVE_TREE_SITTER}" = yes; then - OLD_CFLAGS=$CFLAGS - OLD_LIBS=$LIBS - CFLAGS="$CFLAGS $TREE_SITTER_CFLAGS" - LIBS="$TREE_SITTER_LIBS $LIBS" - AC_CHECK_FUNCS([ts_set_allocator]) - CFLAGS=$OLD_CFLAGS - LIBS=$OLD_LIBS - if test "$ac_cv_func_ts_set_allocator" = yes; then - AC_DEFINE(HAVE_TREE_SITTER, 1, [Define if using tree-sitter.]) - NEED_DYNLIB=yes - else - AC_MSG_ERROR([Tree-sitter library exists but its version is too old]); - TREE_SITTER_CFLAGS= - TREE_SITTER_LIBS= - fi - fi fi - # Windows loads tree-sitter dynamically if test "${opsys}" = "mingw32"; then TREE_SITTER_LIBS= diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 35840024326..997c876b1fa 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -841,6 +841,7 @@ See `project-vc-extra-root-markers' for the marker value format.") (project--value-in-dir 'project-vc-ignores dir))) (defun project--vc-ignores (dir backend extra-ignores) + (require 'vc) (append (when backend (delq diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 22797335b10..df9e00a0d36 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -269,9 +269,7 @@ To create an xref object, call `xref-make'.") The result must be a list of xref objects. If no references can be found, return nil. -The default implementation uses `semantic-symref-tool-alist' to -find a search tool; by default, this uses \"find | grep\" in the -current project's main and external roots." +The default implementation uses `xref-references-in-directory'." (mapcan (lambda (dir) (message "Searching %s..." dir) @@ -1793,15 +1791,43 @@ and just use etags." (declare-function grep-expand-template "grep") (defvar ede-minor-mode) ;; ede.el +(defcustom xref-references-in-directory-function + #'xref-references-in-directory-semantic + "Function to find all references to a symbol in a directory. +It should take two string arguments: SYMBOL and DIR. +And return a list of xref values representing all code references to +SYMBOL in files under DIR." + :type '(choice + (const :tag "Using Grep via Find" xref-references-in-directory-grep) + (const :tag "Using Semantic Symbol Reference API" + xref-references-in-directory-semantic) + function) + :version "31.1") + ;;;###autoload (defun xref-references-in-directory (symbol dir) "Find all references to SYMBOL in directory DIR. +See `xref-references-in-directory-function' for the implementation. +Return a list of xref values." + (cl-assert (directory-name-p dir)) + (funcall xref-references-in-directory-function symbol dir)) + +(defun xref-references-in-directory-grep (symbol dir) + "Find all references to SYMBOL in directory DIR using find and grep. +Return a list of xref values. The files in DIR are filtered according +to its project's list of ignore patterns (as returned by +`project-ignores'), or the default ignores if there is no project." + (let ((ignores (project-ignores (project-current nil dir) dir))) + (xref-matches-in-directory (regexp-quote symbol) "*" dir ignores + 'symbol))) + +(defun xref-references-in-directory-semantic (symbol dir) + "Find all references to SYMBOL in directory DIR. Return a list of xref values. This function uses the Semantic Symbol Reference API, see `semantic-symref-tool-alist' for details on which tools are used, and when." - (cl-assert (directory-name-p dir)) (require 'semantic/symref) (defvar semantic-symref-tool) @@ -1831,12 +1857,13 @@ and when." "27.1") ;;;###autoload -(defun xref-matches-in-directory (regexp files dir ignores) +(defun xref-matches-in-directory (regexp files dir ignores &optional delimited) "Find all matches for REGEXP in directory DIR. Return a list of xref values. Only files matching some of FILES and none of IGNORES are searched. FILES is a string with glob patterns separated by spaces. -IGNORES is a list of glob patterns for files to ignore." +IGNORES is a list of glob patterns for files to ignore. +If DELIMITED is `symbol', only select matches that span full symbols." ;; DIR can also be a regular file for now; let's not advertise that. (grep-compute-defaults) (defvar grep-find-template) @@ -1855,6 +1882,9 @@ IGNORES is a list of glob patterns for files to ignore." (local-dir (directory-file-name (file-name-unquote (file-local-name (expand-file-name dir))))) + (hits-regexp (if (eq delimited 'symbol) + (format "\\_<%s\\_>" regexp) + regexp)) (buf (get-buffer-create " *xref-grep*")) (`(,grep-re ,file-group ,line-group . ,_) (car grep-regexp-alist)) (status nil) @@ -1877,7 +1907,7 @@ IGNORES is a list of glob patterns for files to ignore." (concat local-dir (substring (match-string file-group) 1)) (buffer-substring-no-properties (point) (line-end-position))) hits))) - (xref--convert-hits (nreverse hits) regexp))) + (xref--convert-hits (nreverse hits) hits-regexp))) (define-obsolete-function-alias 'xref-collect-matches diff --git a/src/image.c b/src/image.c index 5a4bc3024c3..ccbf5db028f 100644 --- a/src/image.c +++ b/src/image.c @@ -2131,6 +2131,7 @@ image_clear_image_1 (struct frame *f, struct image *img, int flags) static void image_clear_image (struct frame *f, struct image *img) { + img->lisp_data = Qnil; block_input (); image_clear_image_1 (f, img, (CLEAR_IMAGE_PIXMAP @@ -9653,24 +9654,6 @@ static const struct image_keyword gif_format[GIF_LAST] = {":background", IMAGE_STRING_OR_NIL_VALUE, 0} }; -#endif - -#if defined HAVE_GIF || defined HAVE_WEBP - -/* Free X resources of GIF image IMG which is used on frame F. - Also used by other image types. */ - -static void -gif_clear_image (struct frame *f, struct image *img) -{ - img->lisp_data = Qnil; - image_clear_image (f, img); -} - -#endif /* defined HAVE_GIF || defined HAVE_WEBP */ - -#if defined (HAVE_GIF) - /* Return true if OBJECT is a valid GIF image specification. */ static bool @@ -10900,15 +10883,6 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] = {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0} }; -/* Free X resources of imagemagick image IMG which is used on frame F. */ - -static void -imagemagick_clear_image (struct frame *f, - struct image *img) -{ - image_clear_image (f, img); -} - /* Return true if OBJECT is a valid IMAGEMAGICK image specification. Do this by calling parse_image_spec and supplying the keywords that identify the IMAGEMAGICK format. */ @@ -12954,7 +12928,7 @@ static struct image_type const image_types[] = #endif #ifdef HAVE_IMAGEMAGICK { SYMBOL_INDEX (Qimagemagick), imagemagick_image_p, imagemagick_load, - imagemagick_clear_image }, + image_clear_image }, #endif #ifdef HAVE_RSVG { SYMBOL_INDEX (Qsvg), svg_image_p, svg_load, image_clear_image, @@ -12965,7 +12939,7 @@ static struct image_type const image_types[] = IMAGE_TYPE_INIT (init_png_functions) }, #endif #if defined HAVE_GIF - { SYMBOL_INDEX (Qgif), gif_image_p, gif_load, gif_clear_image, + { SYMBOL_INDEX (Qgif), gif_image_p, gif_load, image_clear_image, IMAGE_TYPE_INIT (init_gif_functions) }, #endif #if defined HAVE_TIFF @@ -12982,7 +12956,7 @@ static struct image_type const image_types[] = IMAGE_TYPE_INIT (init_xpm_functions) }, #endif #if defined HAVE_WEBP - { SYMBOL_INDEX (Qwebp), webp_image_p, webp_load, gif_clear_image, + { SYMBOL_INDEX (Qwebp), webp_image_p, webp_load, image_clear_image, IMAGE_TYPE_INIT (init_webp_functions) }, #endif { SYMBOL_INDEX (Qxbm), xbm_image_p, xbm_load, image_clear_image }, diff --git a/src/treesit.c b/src/treesit.c index ae73885e71d..e9ae1ad3605 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -4278,50 +4278,14 @@ treesit_traverse_sibling_helper (TSTreeCursor *cursor, } else /* Backward. */ { - /* Go to first child and go through each sibling, until we find - the one just before the starting node. */ - TSNode start = ts_tree_cursor_current_node (cursor); - if (!ts_tree_cursor_goto_parent (cursor)) - return false; - treesit_assume_true (ts_tree_cursor_goto_first_child (cursor)); - - /* Now CURSOR is at the first child. If we started at the first - child, then there is no further siblings. */ - TSNode first_child = ts_tree_cursor_current_node (cursor); - if (ts_node_eq (first_child, start)) - return false; - - /* PROBE is always DELTA siblings ahead of CURSOR. */ - TSTreeCursor probe = ts_tree_cursor_copy (cursor); - /* This is position of PROBE minus position of CURSOR. */ - ptrdiff_t delta = 0; - TSNode probe_node; - TSNode cursor_node; - while (ts_tree_cursor_goto_next_sibling (&probe)) + if (!named) + return ts_tree_cursor_goto_previous_sibling (cursor); + /* Else named... */ + while (ts_tree_cursor_goto_previous_sibling (cursor)) { - /* Move PROBE forward, if it equals to the starting node, - CURSOR points to the node we want (prev valid sibling of - the starting node). */ - delta++; - probe_node = ts_tree_cursor_current_node (&probe); - - /* PROBE matched, depending on NAMED, return true/false. */ - if (ts_node_eq (probe_node, start)) - { - ts_tree_cursor_delete (&probe); - cursor_node = ts_tree_cursor_current_node (cursor); - ts_tree_cursor_delete (&probe); - return (!named || (named && ts_node_is_named (cursor_node))); - } - - /* PROBE didn't match, move CURSOR forward to PROBE's - position, but if we are looking for named nodes, only - move CURSOR to PROBE if PROBE is at a named node. */ - if (!named || (named && ts_node_is_named (probe_node))) - for (; delta > 0; delta--) - treesit_assume_true (ts_tree_cursor_goto_next_sibling (cursor)); + if (ts_node_is_named (ts_tree_cursor_current_node (cursor))) + return true; } - ts_tree_cursor_delete (&probe); return false; } } diff --git a/test/src/process-tests.el b/test/src/process-tests.el index 29e9d3323ce..2cc5b37b187 100644 --- a/test/src/process-tests.el +++ b/test/src/process-tests.el @@ -108,7 +108,7 @@ process to complete." (goto-char (point-min)) ;; Instrument for bug#80166. (when (getenv "EMACS_EMBA_CI") - (message "stderr\n%s" (buffer-string)) + (message "stderr\n%s" (buffer-string))) (looking-at "hello stderr!")))))) (ert-deftest process-test-stderr-filter ()