From 22a7522ef3f0f3c13618214e61f60cb01d80eef4 Mon Sep 17 00:00:00 2001 From: Justin Davis Date: Tue, 26 Oct 2021 13:28:16 -0400 Subject: [PATCH] Fix emacs erlang-mode: xref switched to CL-Lib Fix for GitHub issue #5314. Xref is a package which is also bundled with emacs: http://elpa.gnu.org/packages/xref.html Xref switched its own internally defined classes from EIEIO to CL-lib (emacs-mirror/emacs@86da812afb2572c7fead2bb07570b976bffd7c55). erlang-mode subclasses xref-file-location in order to add a function arity slot to xrefs. If xref-file-location is a class, use defclass to subclass it. Otherwise use cl-defstruct. Avoids referencing make-instance, slot-value functions from EIEIO. Only references constructor, accessor, and predicate functions. Updates comments that make references to classes. Testing: - cd into lib/tools/emacs. - Run the tests included with erlang-mode from the shell: emacs -Q -batch -L . -l erlang.el -l erlang-test.el \ -f ert-run-tests-batch-and-exit - Copy xref.el from the xref package (>=1.3.1) into the lib/tools/emacs directory. - Run the tests again. This will load xref.el automatically and use the new interface. --- lib/tools/emacs/erlang.el | 48 +++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el index 69a5fdaeb55..40fe32689e7 100644 --- a/lib/tools/emacs/erlang.el +++ b/lib/tools/emacs/erlang.el @@ -5120,8 +5120,8 @@ about Erlang modules." ;; ;; As mentioned this xref implementation is based on the etags xref ;; implementation. But in the cases where arity is considered the -;; etags information structures (class xref-etags-location) will be -;; translated to our own structures which include arity (class +;; etags information structures (struct xref-etags-location) will be +;; translated to our own structures which include arity (struct ;; erlang-xref-location). This translation is started in the function ;; `erlang-refine-xrefs'. @@ -5129,6 +5129,11 @@ about Erlang modules." ;; with xref items with xref-etags-location and some deal with xref ;; items with erlang-xref-location. +;; NOTE: Around Sept 2021, the xrefs package changed all of its defined types +;; (i.e. xref-location, xref-file-location) from EIEIO classes to CL-Lib +;; structures. These are both supported. Older Emacsen with earlier versions of +;; xref will continue to use defclass. Newer Emacsen will use cl-defstruct. + (defun erlang-etags--xref-backend () 'erlang-etags) (defun erlang-soft-require (feature) @@ -5137,6 +5142,7 @@ about Erlang modules." (when (and (erlang-soft-require 'xref) (erlang-soft-require 'cl-generic) + (erlang-soft-require 'cl-lib) (erlang-soft-require 'eieio) (erlang-soft-require 'etags)) ;; The purpose of using eval here is to avoid compilation @@ -5165,10 +5171,20 @@ about Erlang modules." (let ((erlang-replace-etags-tags-completion-table t)) (tags-completion-table))) - (defclass erlang-xref-location (xref-file-location) - ((arity :type fixnum :initarg :arity - :reader erlang-xref-location-arity)) - :documentation "An erlang location is a file location plus arity.") + ;; Xref 1.3.1 bundled with Emacs 28+ switched from using EIEIO classes to + ;; using CL-Lib structs. + (if (find-class 'xref-file-location) + (progn + (defclass erlang-xref-location (xref-file-location) + ((arity :type fixnum :initarg :arity + :reader erlang-xref-location-arity)) + :documentation "An erlang location is a file location plus arity.") + ;; Make a constructor with the same name that a CL structure would have. + (defalias 'make-erlang-xref-location 'erlang-xref-location)) + (cl-defstruct (erlang-xref-location + (:include xref-file-location)) + "An erlang location is a file location plus arity." + (arity 0 :type fixnum))) ;; This method definition only calls the superclass which is ;; the default behaviour if it was not defined. It is only @@ -5331,8 +5347,7 @@ is non-nil then TAG is a regexp." xrefs (when (and xrefs (fboundp 'xref-item-location) - (fboundp 'xref-location-group) - (fboundp 'slot-value)) + (fboundp 'xref-location-group)) (let (files) (cl-loop for xref in xrefs for loc = (xref-item-location xref) @@ -5357,7 +5372,8 @@ is non-nil then TAG is a regexp." t)))) (defun erlang-xrefs-in-file (file kind tag is-regexp) - (when (fboundp 'make-instance) + (when (and (fboundp 'make-erlang-xref-location) + (fboundp 'xref-make)) (with-current-buffer (find-file-noselect file) (save-excursion (goto-char (point-min)) @@ -5369,17 +5385,15 @@ is non-nil then TAG is a regexp." for name = (match-string-no-properties 1) for arity = (save-excursion (erlang-get-arity)) - for loc = (make-instance 'erlang-xref-location - :file file - :line (line-number-at-pos) - :column 0 - :arity arity) + for loc = (make-erlang-xref-location + :file file + :line (line-number-at-pos) + :column 0 + :arity arity) for sum = (erlang-xref-summary kind name arity) when (and arity (not (eq arity last-arity))) - collect (make-instance 'xref-item - :summary sum - :location loc) + collect (xref-make sum loc) do (setq last-arity arity))))))) (defun erlang-xref-summary (kind tag arity)