Subject: 25.0.92; Can xref-find-references work without a "project"?
From: Eli Zaretskii <[email-masked]>
To: [email-masked]
Date: Tue, 05 Apr 2016 18:23:08 +0300
List-Id: <debbugs-submit.debbugs.gnu.org>

In an Emacs tree that is not under any VCS, type:

  emacs -Q
  M-x xref-find-references RET current_buffer RET

When prompted to choose a project directory, accept the default by
typing RET.  The result:

  No project found in ‘THE-DEFAULT-DIRECTORY/’

This is disappointing, since the default implementation of
xref-find-references is fully capable of producing the requested
results even if no project (in the project.el sense) was created in
the directory.

I think we shouldn't fail the operation in this case, but instead use
the directory specified by the user as the single project root.  The
proposed patch below implements this.  (I'm not married to the patch
as shown, so if someone comes up with a more elegant solution, I'd be
as happy.  The important part is that we should allow this command to
be usable even if no project infrastructure was created.)

--- lisp/progmodes/project.el~0	2016-01-31 06:43:03.000000000 +0200
+++ lisp/progmodes/project.el	2016-04-05 18:06:43.146022700 +0300
@@ -98,10 +98,12 @@
 that it is not applicable, or a project instance.")
 
 ;;;###autoload
-(defun project-current (&optional maybe-prompt dir)
+(defun project-current (&optional maybe-prompt dir noerror)
   "Return the project instance in DIR or `default-directory'.
 When no project found in DIR, and MAYBE-PROMPT is non-nil, ask
-the user for a different directory to look in."
+the user for a different directory to look in.
+Optional third argument NOERROR, if non-nil, means don't signal
+an error if no project is found in the specified directory."
   (unless dir (setq dir default-directory))
   (let ((pr (project--find-in-directory dir)))
     (cond
@@ -109,6 +111,8 @@
      (maybe-prompt
       (setq dir (read-directory-name "Choose the project directory: " dir nil t)
             pr (project--find-in-directory dir))
+      (if (and (not pr) noerror)
+          (setq pr dir))
       (unless pr
         (user-error "No project found in `%s'" dir))))
     pr))
--- lisp/progmodes/xref.el~0	2016-03-20 06:53:36.000000000 +0200
+++ lisp/progmodes/xref.el	2016-04-05 18:18:47.257475600 +0300
@@ -245,14 +245,19 @@
 
 The default implementation uses `semantic-symref-tool-alist' to
 find a search tool; by default, this uses \"find | grep\" in the
-`project-current' roots."
+`project-current' roots, falling back to the directory tree
+rooted at the directory specified by user."
   (cl-mapcan
    (lambda (dir)
      (xref-collect-references identifier dir))
-   (let ((pr (project-current t)))
-     (append
-      (project-roots pr)
-      (project-external-roots pr)))))
+   (let* ((pr (project-current t nil 'noerror))
+          (roots (ignore-errors (project-roots pr)))
+          (eroots (ignore-errors (project-external-roots pr))))
+     ;; If we didn't find any project files in PR, default to PR
+     ;; itself as the project's single root.
+     (if (and (null roots) (null eroots))
+         (setq roots (list (expand-file-name pr))))
+     (append roots eroots))))
 
 (cl-defgeneric xref-backend-apropos (backend pattern)
   "Find all symbols that match PATTERN.

In GNU Emacs 25.0.92.75 (i686-pc-mingw32)
 of 2016-04-04 built on HOME-C4E4A596F7
Repository revision: f501116ea896b20f195f5c841e8770d7fe0418b9
Windowing system distributor 'Microsoft Corp.', version 5.1.2600
Configured using:
 'configure --prefix=/d/usr --enable-checking=yes,glyphs --with-wide-int
 --with-modules 'CFLAGS=-O0 -gdwarf-4 -g3''

Configured features:
XPM JPEG TIFF GIF PNG RSVG SOUND NOTIFY ACL GNUTLS LIBXML2 ZLIB
TOOLKIT_SCROLL_BARS MODULES

Important settings:
  value of $LANG: ENU
  locale-coding-system: cp1255

Major mode: Message

Minor modes in effect:
  mml-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  auto-fill-function: message-do-auto-fill
  transient-mark-mode: t
  abbrev-mode: t

Recent messages:
Checking 167 files in d:/gnu/git/emacs/branch/lisp/emacs-lisp...
Checking 24 files in d:/gnu/git/emacs/branch/lisp/cedet...
Checking 57 files in d:/gnu/git/emacs/branch/lisp/calendar...
Checking 87 files in d:/gnu/git/emacs/branch/lisp/calc...
Checking 122 files in d:/gnu/git/emacs/branch/lisp/obsolete...
Checking for load-path shadows...done
Mark set [2 times]
Saved text from "From: [email-masked]"
Auto-saving...
Modification-flag cleared

Load-path shadows:
None found.

Features:
(pp shadow sort mail-extr emacsbug message dired format-spec rfc822 mml
mml-sec password-cache epg epg-config gnus-util mm-decode mm-bodies
mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail
rfc2047 rfc2045 ietf-drums mm-util help-fns help-mode easymenu
cl-loaddefs pcase cl-lib mail-prsvr mail-utils time-date mule-util
tooltip eldoc electric uniquify ediff-hook vc-hooks lisp-float-type
mwheel dos-w32 ls-lisp disp-table w32-win w32-vars term/common-win
tool-bar dnd fontset image regexp-opt fringe tabulated-list newcomment
elisp-mode lisp-mode prog-mode register page menu-bar rfn-eshadow timer
select scroll-bar mouse jit-lock font-lock syntax facemenu font-core
frame cl-generic cham georgian utf-8-lang misc-lang vietnamese tibetan
thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian
slovak czech european ethiopic indian cyrillic chinese charscript
case-table epa-hook jka-cmpr-hook help simple abbrev minibuffer
cl-preloaded nadvice loaddefs button faces cus-face macroexp files
text-properties overlay sha1 md5 base64 format env code-pages mule
custom widget hashtable-print-readable backquote w32notify w32 multi-tty
make-network-process emacs)

Memory information:
((conses 16 95005 11151)
 (symbols 56 20730 0)
 (miscs 48 46 126)
 (strings 16 17838 6291)
 (string-bytes 1 448071)
 (vectors 16 12532)
 (vector-slots 8 432331 7162)
 (floats 8 167 313)
 (intervals 40 563 63)
 (buffers 856 13))