Home

Awesome

CodeQL.nvim

Neovim plugin to help writing and testing CodeQL queries.

Features

Requirements

Install

<details> <summary>Using lazy.nvim</summary>
{
  "pwntester/codeql.nvim",
  dependencies = {
    "MunifTanjim/nui.nvim",
    "nvim-lua/telescope.nvim",
    "kyazdani42/nvim-web-devicons",
    {
      's1n7ax/nvim-window-picker',
      version = 'v1.*',
      opts = {
        autoselect_one = true,
        include_current = false,
        filter_rules = {
          bo = {
            filetype = {
              "codeql_panel",
              "codeql_explorer",
              "qf",
              "TelescopePrompt",
              "TelescopeResults",
              "notify",
              "noice",
              "NvimTree",
              "neo-tree",
            },
            buftype = { 'terminal' },
          },
        },
        current_win_hl_color = '#e35e4f',
        other_win_hl_color = '#44cc41',
      },
    }
  },
  opts = {}
}
</details> <details> <summary>Using packer.nvim</summary>
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",
                "noice",
                "NvimTree",
                "neo-tree",
              },
              buftype = { 'terminal' },
            },
          },
          current_win_hl_color = '#e35e4f',
          other_win_hl_color = '#44cc41',
        })
      end,
    }
  },
  config = function()
    require("codeql").setup {}
  end
}
</details>

Usage

Query

Database

Use QL database set <path to db> to let the plugin know what DB to work with. Use QL database unset to unregister the current registered database.

Run query or eval predicates

Use QL query run or QL query quick-eval commands or qr, qp shortcuts respectively to run the query or evaluate the predicate under the cursor.

Configuration options

eg:

require("codeql").setup {
  results = {
    max_paths = 10,
    max_path_depth = nil,
  },
  panel = {
    width = 50,
    pos = "botright",
    group_by = "sink", -- "source"
    show_filename = true,
    long_filename = false,
    context_lines = 3,
  },
  max_ram = 32000,
  job_timeout = 15000,
  format_on_save = true,
  additional_packs = {
    "/Users/pwntester/codeql-home/codeql",
    "/Users/pwntester/codeql-home/codeql-go",
    "/Users/pwntester/codeql-home/codeql-ruby",
    "./codeql",
  },
  mappings = {
    run_query = { modes = { "n" }, lhs = "<space>qr", desc = "run query" },
    quick_eval = { modes = { "x", "n" }, lhs = "<space>qe", desc = "quick evaluate" },
    quick_eval_predicate = { modes = { "n" }, lhs = "<space>qp", desc = "quick evaluate enclosing predicate" },
  },
}

Commands

Mappings

Result Browser

After running a query or quick evaluating a predicate, results will be rendered in a special panel.

Language Server Protocol

This 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:

Neovim Built-In LSP

It is possible to configure the built-in LSP client without any additional plugins, but a configuration for the CodeQL Language Server is included in nvim-lspconfig. If you are using packer, it is a matter of adding following line to your neovim config:

use 'neovim/nvim-lspconfig'

Using this client, it is only required to configure the client with:

local lspconfig = require'lspconfig'

lspconfig.codeqlls.setup{
    on_attach = on_attach_callback;
    settings = {
        additional_packs = {'~/codeql-home/codeql-repo'};
    };
}

NOTE: change additional_packs 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 lspconfig = require'lspconfig'

lspconfig.codeqlls.setup{
    on_attach = on_attach_callback;
    settings = {
        additional_packs = {'~/codeql-home/codeql-repo'};
    };
}

Check my dotfiles for examples on how to configure the NVIM LSP client.

Coc.nvim

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
    }
  }
}

🙏 Say Thanks

If you like this plugin and would like to buy me a coffee, you can!

<img src="https://cdn.buymeacoffee.com/buttons/v2/default-violet.png" alt="BuyMeACoffee" width="140">

GitHub Sponsors