Neovim plugin to help writing and testing CodeQL queries.
use {
"pwntester/codeql.nvim",
requires = {
"MunifTanjim/nui.nvim",
"nvim-lua/telescope.nvim",
"kyazdani42/nvim-web-devicons",
{
's1n7ax/nvim-window-picker',
tag = 'v1.*',
config = function()
require'window-picker'.setup({
autoselect_one = true,
include_current = false,
filter_rules = {
bo = {
filetype = {
"codeql_panel",
"codeql_explorer",
"qf",
"TelescopePrompt",
"TelescopeResults",
"notify",
"NvimTree",
"neo-tree",
},
buftype = { 'terminal' },
},
},
current_win_hl_color = '#e35e4f',
other_win_hl_color = '#44cc41',
})
end,
}
},
config = function()
require("codeql").setup {}
end
}
Create qlpack.yaml
(see QL packs). E.g:
name: test
version: 0.0.1
libraryPathDependencies: [codeql-java]
Create .ql
file with query
Use SetDatabase <path to db>
to let the plugin know what DB to work with.
Use UnsetDatabase
to unregister the current registered database.
Use RunQuery
or QuickEval
commands or qr
, qe
shortcuts respectively to run the query or evaluate the predicate under the cursor.
eg:
require("codeql").setup {
results = {
max_paths = 10,
max_path_depth = nil,
},
panel = {
group_by = "sink", -- "source"
show_filename = true,
long_filename = false,
context_lines = 3,
},
max_ram = 32000,
format_on_save = true,
search_path = {
"/Users/pwntester/codeql-home/codeql",
"/Users/pwntester/codeql-home/codeql-go",
"/Users/pwntester/codeql-home/codeql-ruby",
"./codeql",
},
}
SetDatabase <path to db>
: Required before running any query.RunQuery
: Runs the query on the current buffer. Requires a DB to be set first.QuickEval
: Quick evals the predicate or selection under cursor. Requires a DB to be set first.History
: Shows a menu to render results of previous queries (on the same nvim session).StopServer
: Stops the query server associated with the query buffer. A new one will be started upon query evaluation.PrintAST
: On a codeql:/
buffer, prints the AST of the current file.LoadSarif
: Loads the issues of a SARIF file. To browse the results, use SetDatabase
before.ArchiveTree
: Shows source archive tree explorergd
: On a codeql:/
file, jumps to the symbol definition.gr
: On a codeql:/
file, show symbol references in the QuickFix window.qr
: Runs the current query.qe
: QuickEvals the selected predicate.<Plug>(CodeQLGrepSource)
: shows a telescope menu to grep the source archiveAfter running a query or quick evaluating a predicate, results will be rendered in a special panel.
o
: collapses/Expands resultEnter
(on a visitable result node): opens node file in nvim and moves cursor to window with source code file p
: similar to Enter
but keeps cursor on the results panelN
: change to next pathP
: change to previous pathf
: filter issues by issue labelF
: filter issuesc
: clear filtert
: open all foldsT
: closes all foldsq
: closes result panels
: show context snippetThis plugin does not provide any support for the Language Server Protocol (LSP). But in order to have the best CodeQL writing experience it is recommended to configure a LSP client to connect to the CodeQL Language Server.
There are many LSP clients in the NeoVim ecosystem. The following clients have been tested with CodeQL Language Server:
It is possible to configure the built-in LSP client without any additional plugins, but a default configuration for the CodeQL Language Server has been added to Nvim-LSP. If you are using packer
, it is a matter of adding following line to you vim config:
use 'neovim/nvim-lsp'
Using this client, it is only required to configure the client with:
local nvim_lsp = require 'nvim_lsp'
nvim_lsp.codeqlls.setup{
on_attach = on_attach_callback;
settings = {
search_path = {'~/codeql-home/codeql-repo'};
};
}
NOTE: change search_path
to the path where the CodeQL repo has been installed to.
It is also recommended to add an on_attach
callback to define LSP mappings. E.g:
local function on_attach_callback(client, bufnr)
api.nvim_buf_set_keymap(bufnr, "n", "gD", "<Cmd>lua show_diagnostics_details()<CR>", { silent = true; })
api.nvim_buf_set_keymap(bufnr, "n", "gd", "<Cmd>lua vim.lsp.buf.definition()<CR>", { silent = true; })
api.nvim_buf_set_keymap(bufnr, "n", "gi", "<Cmd>lua vim.lsp.buf.implementation()<CR>", { silent = true; })
api.nvim_buf_set_keymap(bufnr, "n", "gK", "<Cmd>lua vim.lsp.buf.hover()<CR>", { silent = true; })
api.nvim_buf_set_keymap(bufnr, "n", "gh", "<Cmd>lua vim.lsp.buf.signature_help()<CR>", { silent = true; })
api.nvim_buf_set_keymap(bufnr, "n", "gr", "<Cmd>lua vim.lsp.buf.references()<CR>", { silent = true; })
api.nvim_buf_set_keymap(bufnr, "n", "gF", "<Cmd>lua vim.lsp.buf.formatting()<CR>", { silent = true; })
api.nvim_command [[autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()]]
api.nvim_command [[autocmd CursorHoldI <buffer> lua vim.lsp.buf.document_highlight()]]
api.nvim_command [[autocmd CursorMoved <buffer> lua vim.lsp.util.buf_clear_references()]]
end
local nvim_lsp = require 'nvim_lsp'
nvim_lsp.codeqlls.setup{
on_attach = on_attach_callback;
settings = {
search_path = {'~/codeql-home/codeql-repo'};
};
}
Check my dotfiles for examples on how to configure the NVIM LSP client.
It is possible to add codeql language server to coc.nvim
using coc-settings.json
as an
executable language server
{
"languageserver": {
"codeql" : {
"command": "<path to codeql binary>",
"args": [
"execute",
"language-server",
"--check-errors=ON_CHANGE",
"--search-path=./:<path to semmle/ql repo maybe>:<any more paths>",
"-q"
],
"filetypes": ["ql"],
"rootPatterns": ["qlpack.yml"],
"requireRootPattern": true
}
}
}