Skip to content

Commit

Permalink
Auto-configure compile-commands-dir for clangd
Browse files Browse the repository at this point in the history
Fix emacs-lsp#2278

Depends on fixing lsp-workspace-root to be available
when opening a new workspace

Tested locally on projects with and without a compile_commands.json
file.
  • Loading branch information
petr-tik committed Oct 23, 2020
1 parent b76b85e commit 3b1e267
Showing 1 changed file with 43 additions and 1 deletion.
44 changes: 43 additions & 1 deletion clients/lsp-clangd.el
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,48 @@ This must be set only once after loading the clang client.")
:risky t
:type '(repeat string))

(defun lsp-clangd-find-compile-commands-dir ()
"Return the full directory path (or nil) that contain a compile_commands.json.
If multiple compile_commands.json files are
found in the project directory tree - ask the user to choose."
;; TODO lsp-workspace-root won't find anything at the start of the workspace
(let ((candidate-dirs (directory-files-recursively (lsp-workspace-root) "compile_commands.json")))
(pcase (length candidate-dirs)
;; TODO can I lsp--warn-user-in-message-and-log at the same time
(`0 (lsp--warn "Cannot find compile_commands.json - intellisense might not work")
nil)
;; if you find 1 only - assume it's correct and strip the dirname from the full path
;; happy path
(`1 (file-name-directory (car candidate-dirs)))
;; if you have several - ask the user to choose with lsp--completing-read
;; TODO if Ctrl-G from inside this completing read still falls to default lsp-clients-clangd-args
(_ (file-name-directory (lsp--completing-read
"Found compile_commands.json in several directories, which one do you want to use?"
candidate-dirs
(lambda (candidate) candidate)))))))


(defun lsp-clangd-update-args-with-compile-commands ()
"Return the default or updated clangd-args for the start command.
If --compile-commands-dir is already set - return it.
Else run a potentially interactive search for the directory
that contains compile_commands.json.
Then return either the default args or the modified args"
(if (-first
;; lsp-client-clangd-args might already lists a "--compile-commands-dir=build/" and will fail if we pass another one
;; trust the user - if it's already set, don't mess around
(lambda (arg) (string-prefix-p "--compile-commands-dir" arg))
lsp-clients-clangd-args)
((lsp--info "compilation_commands_dir set in clangd-args")
lsp-clients-clangd-args)
(if-let (found-dir (lsp-clangd-find-compile-commands-dir))
;; TODO expensive to create a list from 1 element - how to append atom to list
(append lsp-clients-clangd-args (list (concat "--compile-commands-dir=" found-dir)))
lsp-clients-clangd-args)))


(defun lsp-clients--clangd-command ()
"Generate the language server startup command."
(unless lsp-clients--clangd-default-executable
Expand All @@ -190,7 +232,7 @@ This must be set only once after loading the clang client.")
(lsp-clients-executable-find "xcrun" "--find" "clangd"))))

`(,(or lsp-clients-clangd-executable lsp-clients--clangd-default-executable "clangd")
,@lsp-clients-clangd-args))
,@(lsp-clangd-update-args-with-compile-commands)))

(lsp-register-client
(make-lsp-client :new-connection (lsp-stdio-connection
Expand Down

0 comments on commit 3b1e267

Please sign in to comment.