-
Notifications
You must be signed in to change notification settings - Fork 162
Emacs
- Install lsp-mode
- Install emacs-cquery and configure it
- Open a source file where either .cquery or compile_commands.json is in the project root (it may work without them, though not recommended)
-
M-x lsp
.
Install emacs-cquery
The only required configuration is cquery-executable
. Others have good
defaults.
xref-find-definitions
(default: M-.
) / highlighting of the symbol at point /
type signature in echo area should work out-of-box. Read on for customization
and more features.
(setq cquery-executable "/path/to/cquery/build/release/bin/cquery")
;; ;; Arch Linux aur/cquery-git aur/cquery
;; (setq cquery-executable "/usr/bin/cquery")
;; ;; Log file
;; (setq cquery-extra-args '("--log-file=/tmp/cq.log"))
;; ;; Cache directory, both relative and absolute paths are supported
;; (setq cquery-cache-dir ".cquery_cached_index")
;; ;; Initialization options
;; (setq cquery-extra-init-params '(:cacheFormat "msgpack"))
For each source file that has turned on lsp
, variable
cquery-project-roots
, projectile, compile_commands.json
are consulted to
locate the project root and the associated lsp-mode workspace. If your project
has subprojects, (projectile-project-root)
may think files in the subproject
belong to the child workspace, which is not desired.
(setq cquery-project-roots '("~/my-root-project" ))
to override projectile
roots.
If you do not mind files in subprojects are treated as part of the whole project in projectile:
(with-eval-after-load 'projectile
(setq projectile-project-root-files-top-down-recurring
(append '("compile_commands.json"
".cquery")
projectile-project-root-files-top-down-recurring)))
To turn on cquery for all C/C++ modes:
(defun cquery//enable ()
(condition-case nil
(lsp)
(user-error nil)))
(use-package cquery
:commands lsp
:init (add-hook 'c-mode-hook #'cquery//enable)
(add-hook 'c++-mode-hook #'cquery//enable))
;; Also see lsp-project-whitelist lsp-project-blacklist cquery-root-matchers
-
M-x lsp-capabilities
LSP workspace is initialized correctly -
M-: xref-backend-functions
is(lsp--xref-backend)
for cross references -
M-: completion-at-point-functions
is(lsp-completion-at-point)
for completion
The buffer *lsp-cquery stderr*
and --log-file=/tmp/cq.log
contain logs.
Initialization options are defined in
config.h,
but you need to customize them in S-exp. Use t
for true, :json-false
for
false, :json-null
for null.
(setq cquery-extra-init-params '(:index (:comments 2) :cacheFormat "msgpack" :completion (:detailedLabel t)))
xref-find-definitions
(default: M-.
) should work out-of-box. If not, check
if M-: xref-backend-functions
is (lsp--xref-backend)
, which should be set by
lsp-mode when you execute (lsp)
.
There is heuristic to make textDocument/definition
work in comments and macro
replacement-list, which does something similar to rtags-find-symbol-at-point
xref-find-references
(default: M-?
) will give a prompt. To inhibit the
prompt, add xref-find-references
to xref-prompt-for-identifier
. (See
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=29619 for changing the default
behavior.)
There are Helm/Ivy alternatives for xref-find-{definitions,references,apropos}
Check https://github.com/emacs-lsp/lsp-ui for a supplement of lsp-mode. It provides some higher level UI features.
lsp-ui-peek-find-{definitions,references}
from
lsp-ui-peek.el
provide peek views. An additional benefit is you get a window local jump list
dedicated to cross references which I bind to C-p and C-t
(define-key evil-normal-state-map (kbd "C-p") 'lsp-ui-peek-jump-forward)
(define-key evil-normal-state-map (kbd "C-t") 'lsp-ui-peek-jump-backward)
The identifier (or user-defined operator) at point is highlighted with its other references. If you build trunk libclang, the references will be differentiated for different usage: read/write.
Use
lsp-imenu.el
for textDocument/documentSymbol
(outline).
lsp-ui-imenu.el
provides a sidebar.
xref-find-apropos
(default: C-M-.
) invokes workspace/symbol
to fuzzy-find
symbols in the project. However, the function tries to be smart and splits the
pattern and regexp-quote
them for you, which actually gets in the way.
Consider using lsp-ui{,-peek}-workspace-symbol
in the lsp-ui package.
For a symbol named Name::FooBar
, all of FooBar
, foo bar
, nafoba
find
them, but with different priorities.
Aside from definitions/references/workspace symbol, cquery provides some LSP extensions that find base classes/methods, vars of a type, callers of a function. You may call:
(cquery-xref-find-custom "$cquery/base")
(cquery-xref-find-custom "$cquery/callers")
(cquery-xref-find-custom "$cquery/vars")
;; Alternatively, use lsp-ui-peek interface
(lsp-ui-peek-find-custom 'base "$cquery/base")
(lsp-ui-peek-find-custom 'callers "$cquery/callers")
(lsp-ui-peek-find-custom 'random "$cquery/random") ;; jump to a random declaration
"$cquery/derived"
has been removed. To find derived classes/methods, use lsp-goto-implementation
or lsp-ui-peek-find-implementation
.
lsp-ui-doc.el renders comments in a child frame (Emacs >= 26) or inline (< 26).
(setq lsp-ui-doc-include-signature nil) ; don't include type signature in the child frame
(setq lsp-ui-sideline-show-symbol nil) ; don't show symbol on the right of info
Install company-lsp and add
company-lsp
to company-backends
. Consider disabling client-side cache and
sorting because the server does a better job.
(setq company-transformers nil company-lsp-async t company-lsp-cache-candidates nil)
Type #i"
(or #include "
) for quote-style includes and #i<
(or
#include <
) for system headers.
See https://github.com/cquery-project/cquery/pull/391#issuecomment-362872732 for an alternative view (contextual parent as detail, signature as label)
(setq cquery-extra-init-params '(:completion (:detailedLabel t)))
To enable semantic highlighting:
(setq cquery-sem-highlight-method 'font-lock)
;; alternatively, (setq cquery-sem-highlight-method 'overlay)
;; For rainbow semantic highlighting
(cquery-use-default-rainbow-sem-highlight)
Different variables/functions/types will be assigned different faces, while uses of the same variable/function/type share the same face. The colors can be customized:
cquery-sem-function-colors
cquery-sem-macro-colors
;; ...
cquery-sem-member-face ;; defaults to t :slant italic
by default only one face is used for each symbol kind (type/function/variable/member function)
While (setq cquery-sem-highlight-method 'overlay)
is more accurate than
'font-lock
, it may cause severe performance issues. The short story is that
the large number of overlays generated by cquery creates a similarly large
number of markers. If the buffer currently edited is a multibyte buffer and
contains at least one non-ASCII character, these markers may slow down
line-number-at-pos
(a function heavily relied upon by lsp-mode
) by orders of
magnitude; the effect gets worse with increasing distance from (point-min)
.
For the long story, refer to the corresponding
emacs-devel thread;
if you wish to use cquery-sem-highlight
without the associated slowdown, the
following options exist (should you find more, please add them to this wiki
page):
-
while this patch by Stefan Monnier does not completely solve the underlying performance issue, it significantly alleviates it for usual buffer sizes
-
the noverlay branch of Emacs reimplements overlays in a way that avoids markers. Although large numbers of markers would still lead to performance issues with the noverlay branch, cquery performance should be excellent
-
both 1. and 2. require recompiling Emacs from sources; if that is unacceptable, performance can be restored using
(set-buffer-multibyte nil)
. Note, however, that this will lead to non-ASCII characters being displayed as escape sequences. Also, this workaround has been verified to remove the performance penalty affectingline-number-at-pos
, but it has not been tested whether disabling multibyte handling causes other issues withlsp-mode
or cquery.
M-x cquery-member-hierarchy
(cquery-call-hierarchy nil) ; caller hierarchy
(cquery-call-hierarchy t) ; callee hierarchy
(cquery-inheritance-hierarchy nil) ; base hierarchy
(cquery-inheritance-hierarchy t) ; derived hierarchy
For out-of-band changes to the files in the workspace that are not made in the
LSP client (e.g. git pull), call (cquery-freshen-index)
to rebuild indexes for
every file or (cquery-freshen-index (list "^/tmp/c/"))
to rebuild indexes for
files matched by a regex whitelist.
- PR to add +tools/cquery to spacemacs
- A proposal to integrate cquery and lsp-mode into spacemacs: https://github.com/syl20bnr/spacemacs/issues/10134
- Discussion of symbol hierarchies (member hierarchy, inheritance hierarchy, call hierarchy) https://github.com/emacs-lsp/lsp-ui/issues/73
- Performance of lsp-ui-flycheck https://github.com/emacs-lsp/lsp-ui/issues/45