Skip to content
This repository has been archived by the owner on Jul 30, 2020. It is now read-only.
Fangrui Song edited this page Feb 25, 2018 · 67 revisions
  1. See Getting started to build the bin/cquery executable
  2. Install lsp-mode
  3. Install cquery.el and configure it
  4. Open a source file where either .cquery or compile_commands.json is in the project root (it may work without them, though not recommended)
  5. M-x lsp-cquery-enable. Don't invoke M-x lsp-mode. lsp-cquery-enable will turn on lsp-mode for you

Install cquery.el

Configure

(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"))
;; ;; Initialization options
;; (setq cquery-extra-init-params '())

Checklist

  • 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

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.

Initialization options are written 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"))

Find definitions/references

xref-find-definitions (default: M-.) should work without other tuning. If not, check if M-: xref-backend-functions is (lsp--xref-backend), which should be set by lsp-mode when you execute (lsp-cquery-enable).

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. If you feel the same pain, please report what you feel on this bug.)

There are Helm/Ivy alternatives:

Alternatively, use lsp-ui-peek-find-{definitions,references} provided by lsp-ui-peek.el. An additional benefit is you get a window local jump list dedicated to cross references:

(lsp-ui-peek-jump-backward)
(lsp-ui-peek-jump-forward)

xref-find-references

Document/workspace symbol search

Use lsp-imenu.el for textDocument/documentSymbol (symbol search in the current document). Alternativel,y use lsp-ui-imenu.el.

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, just with different priorities.

cquery cross-reference extension

Aside from definitions/references/workspace symbol, cquery provides some LSP extensions that find base/derived 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/derived")
(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")

Check https://github.com/emacs-lsp/lsp-ui for a supplement of lsp-mode. It provides some higher level UI features.

    (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

Check out MaskRay's config for some (ab)use, e.g. a hydra for next/prev arbitrary/read/write reference. The "role" is highly experimental, and you need a trunk libclang (>= 7.0.0) for the role feature.

    (defhydra hydra/ref (spacemacs-lsp-mode-map "l")
      "reference"
      ("d" lsp-ui-peek-find-definitions "next" :bind nil)
      ("n" lsp-ui-find-next-reference "next")
      ("p" lsp-ui-find-prev-reference "prev")
      ("R" (lsp-ui-find-prev-reference
            (lambda (x)
              (/= (logand (ht-get x "role") 8) 0))) "prev read" :bind nil)
      ("r" (lsp-ui-find-next-reference
            (lambda (x)
              (/= (logand (ht-get x "role") 8) 0))) "next read" :bind nil)
      ("W" (lsp-ui-find-prev-reference
            (lambda (x)
              (/= (logand (ht-get x "role") 16) 0))) "prev write")
      ("w" (lsp-ui-find-next-reference
            (lambda (x)
              (/= (logand (ht-get x "role") 16) 0))) "next write")
      )

Completion

Install company-lsp and add company-lsp to company-backends.

(setq company-transformers nil company-lsp-async t company-lsp-cache-candidates nil)

Comments

Refer to Initialization options to index comments. Use lsp-ui-doc.el from the lsp-ui package to render comments in a child frame when you hover on a symbol.

Semantic highlighting

To enable semantic highlighting:

(setq cquery-sem-highlight-method 'overlay)
(setq cquery-sem-highlight-method 'font-lock)

Different variables/functions/types will be assigned different faces, while uses of the same variable/function/type share the same face. You need to customize the 5 face sets:

cquery-sem-free-func-faces
cquery-sem-member-func-faces
cquery-sem-free-var-faces
cquery-sem-member-var-faces
cquery-sem-type-faces

because by default there is only one face for each face set.

Using the noverlay branch of Emacs may improve the performance of overlays.

If you do not want to customize faces, you may use the default rainbow semantic highlighting (experimental).

(cquery-use-default-rainbow-sem-highlight)

Misc

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.