tessl install tessl/npm-coc-nvim@0.0.0LSP based intellisense engine for neovim & vim8.
Complexity: Basic | Category: Navigation | Keywords: definition, references, jump, goto
Common Tasks: Jump to definition | Find references | View implementations
Navigate to definitions, declarations, implementations, type definitions, and references using LSP.
gd
" Or programmatically:
call CocAction('jumpDefinition')Most common navigation task - goes to where symbol is defined.
gr
" Or with options:
let refs = CocAction('references', {'includeDeclaration': v:false})Find everywhere a symbol is used.
gi
" Particularly useful for interfaces/abstract methodsgy
" See the type definition of a variablecall CocAction('jumpDefinition', 'split')
" Opens definition in split windowDecision Tree:
Want to jump? → Use <Plug>(coc-definition)
↓ Need split? → Use CocAction('jumpDefinition', 'split')
↓ Need tab? → Use CocAction('jumpDefinition', 'tabe')
↓ Custom logic? → Use CocAction('definitions') then coc#util#jump()Decision Tree:
Just navigate? → Use <Plug>(coc-references)
↓ Exclude declarations? → Use <Plug>(coc-references-used)
↓ Need the list? → Use CocAction('references')
↓ Need count? → len(CocAction('references'))When there are multiple definitions/references:
g:coc_enable_locationlist = 1: Opens location list automaticallyg:coc_enable_locationlist = 0: Opens quickfix listg:coc_jump_locations variable<Plug>(coc-definition)Jump to definition(s) of symbol under cursor. Opens in current window or location list if multiple.
Example:
nmap <silent> gd <Plug>(coc-definition)Behavior:
<Plug>(coc-declaration)Jump to declaration(s) of symbol under cursor. Declaration is where the symbol is declared (e.g., function prototype), while definition is where it's implemented.
Example:
nmap <silent> gD <Plug>(coc-declaration)Use Case: In C/C++, jump to header declaration from implementation.
<Plug>(coc-implementation)Jump to implementation(s) of interface or abstract method. Particularly useful in object-oriented languages.
Example:
nmap <silent> gi <Plug>(coc-implementation)Use Case:
<Plug>(coc-type-definition)Jump to type definition of symbol under cursor. Shows where the type itself is defined.
Example:
nmap <silent> gy <Plug>(coc-type-definition)Use Case:
let user: User = getUser(); // Cursor on 'user' → jumps to User interface<Plug>(coc-references)Jump to references of symbol under cursor. Includes declarations.
Example:
nmap <silent> gr <Plug>(coc-references)Includes:
<Plug>(coc-references-used)Jump to references excluding declarations. Only shows actual usage.
Example:
nmap <silent> gu <Plug>(coc-references-used)Use Case: Find where function is actually called, excluding its definition.
CocAction('jumpDefinition', [openCommand])Jump to definition with optional open command.
Parameters:
openCommand: Optional command to open location
'edit': Current window (default)'split': Horizontal split'vsplit': Vertical split'tabe': New tab'drop': Reuse existing window if openExample:
" Jump in current window
call CocAction('jumpDefinition')
" Jump in split
call CocAction('jumpDefinition', 'split')
" Jump in new tab
call CocAction('jumpDefinition', 'tabe')
" Reuse window if already open
call CocAction('jumpDefinition', 'drop')Returns: Nothing (performs jump as side effect)
CocAction('definitions')
" Returns: listGet definition locations without jumping. Useful for custom navigation logic.
Returns: List of location objects with:
uri: File URI ('file:///path/to/file.js')range: Position range (LSP format, 0-indexed)targetUri: Target file URI (if different)targetRange: Target rangeExample:
let defs = CocAction('definitions')
echo 'Found ' . len(defs) . ' definitions'
for def in defs
let file = substitute(def.uri, 'file://', '', '')
let line = def.range.start.line + 1
echo file . ':' . line
endforUse Cases:
CocAction('jumpDeclaration', [openCommand])Jump to declaration with optional open command.
Parameters:
openCommand: Same options as jumpDefinitionExample:
call CocAction('jumpDeclaration', 'vsplit')CocAction('jumpImplementation', [openCommand])Jump to implementation with optional open command.
Example:
call CocAction('jumpImplementation')
" Or in split
call CocAction('jumpImplementation', 'split')Use Case: Navigate from interface to concrete classes.
CocAction('jumpTypeDefinition', [openCommand])Jump to type definition with optional open command.
Example:
call CocAction('jumpTypeDefinition')Use Case: See type definition while debugging type issues.
CocAction('jumpReferences', [openCommand])Jump to references with optional open command.
Example:
call CocAction('jumpReferences')
" Open in new tab
call CocAction('jumpReferences', 'tabe')CocAction('jumpUsed', [openCommand])Jump to references excluding declarations.
Example:
call CocAction('jumpUsed')Use Case: Find actual usage, not definitions.
CocAction('declarations')
" Returns: listGet declaration locations without jumping.
Returns: List of location objects (same format as definitions)
CocAction('implementations')
" Returns: listGet implementation locations without jumping.
Example:
let impls = CocAction('implementations')
if len(impls) == 0
echo "No implementations found"
else
echo len(impls) . " implementation(s) found"
endifCocAction('typeDefinitions')
" Returns: listGet type definition locations without jumping.
CocAction('references', [options])
" Returns: listGet reference locations without jumping.
Parameters:
options: Optional dictionary with:
includeDeclaration: Include declaration in results (default: true)Returns: List of location objects.
Example:
" With declarations
let refs = CocAction('references')
" Without declarations (usage only)
let refs = CocAction('references', {'includeDeclaration': v:false})
echo 'Found ' . len(refs) . ' references'CocLocations(id, method, [...])
" Returns: anyQuery LSP locations synchronously. Advanced API for direct LSP communication.
Parameters:
id: Language server ID (e.g., 'tsserver', 'pylance')method: LSP method name (e.g., 'textDocument/definition')...: Additional arguments for the LSP methodReturns: Result from LSP method.
Example:
let result = CocLocations('tsserver', 'textDocument/definition')Use Case: Direct LSP communication for custom integrations.
CocLocationsAsync(id, method, [...])Query LSP locations asynchronously. Non-blocking version.
Example:
call CocLocationsAsync('tsserver', 'textDocument/references')coc#util#jump(cmd, filepath, [line, col])Jump to a specific location in a file. Low-level utility for custom navigation.
Parameters:
cmd: Open command ('edit', 'split', 'vsplit', 'tabe')filepath: File path (absolute or relative)line: Optional line number (1-based, Vim format)col: Optional column number (1-based, Vim format)Example:
" Jump to file
call coc#util#jump('edit', '/path/to/file.js')
" Jump to line and column
call coc#util#jump('edit', '/path/to/file.js', 42, 10)
" Open in split
call coc#util#jump('split', '/path/to/file.js', 42)
" Open in new tab
call coc#util#jump('tabe', 'src/main.js', 100, 5)Use Case: Custom navigation logic after getting locations from API.
coc#util#jumpTo(line, character)Jump to position in current buffer. Uses LSP format (0-indexed).
Parameters:
line: Line number (0-indexed, LSP format)character: Character position (0-indexed, LSP format)Example:
" Jump to line 10, column 5 (LSP format)
call coc#util#jumpTo(9, 4)
" Note: LSP uses 0-indexing, Vim uses 1-indexing
" Line 10 in Vim = line 9 in LSPlet g:coc_enable_locationlist = 1Use location list for multiple jump targets. When disabled, uses quickfix list instead.
Type: Number
Default: 1
Values:
1: Use location list (buffer-local)0: Use quickfix list (global)Example:
" Use quickfix instead of location list
let g:coc_enable_locationlist = 0Behavior:
g:coc_jump_locationsRuntime variable containing last jump locations.
Type: List (read-only) Structure: List of location objects
Example:
if exists('g:coc_jump_locations')
echo 'Last jump had ' . len(g:coc_jump_locations) . ' locations'
" Access first location
if len(g:coc_jump_locations) > 0
let loc = g:coc_jump_locations[0]
echo 'First location: ' . loc.filename . ':' . loc.lnum
endif
endifautocmd User CocLocationsChange {command}Triggered when location list is updated after a jump operation.
When Fired:
g:coc_jump_locations is populatedExample:
autocmd User CocLocationsChange call HandleLocations()
function! HandleLocations() abort
let count = len(get(g:, 'coc_jump_locations', []))
echo 'Found ' . count . ' locations'
" Auto-open location list for multiple results
if count > 1
lopen
endif
endfunctionCocTagFunc(pattern, flags, info)
" Returns: list or nullTag function for Vim's tagfunc option. Integrates LSP definitions with Vim's tag system.
Parameters:
pattern: Tag pattern to searchflags: Tag search flagsinfo: Tag search infoReturns: List of tag matches or null.
Setup:
" Use coc.nvim for tag lookups
set tagfunc=CocTagFuncBenefits:
Ctrl-] uses LSP definitionsCtrl-t returns from LSP jumpsExample:
set tagfunc=CocTagFunc
" Now Ctrl-] jumps to LSP definition
" Ctrl-t returns from jump
" :tag <name> searches LSP symbolsNavigation settings in coc-settings.json:
{
"coc.preferences.jumpCommand": "edit",
"coc.preferences.currentFunctionSymbolAutoUpdate": true,
"suggest.detailField": "preview"
}Available Settings:
jumpCommand: Default command for jumps ("edit", "split", "vsplit", "tabe")currentFunctionSymbolAutoUpdate: Auto-update current function in statusline" Standard navigation mappings
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
" Custom jump commands
nnoremap <silent> <leader>gd :call CocAction('jumpDefinition', 'vsplit')<CR>
nnoremap <silent> <leader>gt :call CocAction('jumpDefinition', 'tabe')<CR>
" Navigate declarations
nmap <silent> gD <Plug>(coc-declaration)" Jump to definition in split based on window size
function! SmartDefinition() abort
let width = winwidth(0)
if width > 160
call CocAction('jumpDefinition', 'vsplit')
elseif width > 80
call CocAction('jumpDefinition', 'split')
else
call CocAction('jumpDefinition')
endif
endfunction
nnoremap <silent> gd :call SmartDefinition()<CR>function! CountReferences() abort
let refs = CocAction('references')
let total = len(refs)
let refs_only = CocAction('references', {'includeDeclaration': v:false})
let usage_count = len(refs_only)
echo 'Total references: ' . total . ' (used: ' . usage_count . ')'
endfunction
nnoremap <silent> <leader>rc :call CountReferences()<CR>" Track navigation history
let g:nav_stack = []
function! PushLocation() abort
let pos = [bufnr('%'), line('.'), col('.')]
call add(g:nav_stack, pos)
endfunction
function! PopLocation() abort
if len(g:nav_stack) == 0
echo "Navigation stack empty"
return
endif
let pos = remove(g:nav_stack, -1)
execute 'buffer ' . pos[0]
call cursor(pos[1], pos[2])
endfunction
" Push before jumping
nnoremap <silent> gd :call PushLocation()<CR><Plug>(coc-definition)
nnoremap <silent> <C-o> :call PopLocation()<CR>" Build custom location list from references
function! CustomReferenceList() abort
let refs = CocAction('references')
let qflist = []
for ref in refs
let uri = ref.uri
let filepath = substitute(uri, 'file://', '', '')
let range = ref.range
call add(qflist, {
\ 'filename': filepath,
\ 'lnum': range.start.line + 1,
\ 'col': range.start.character + 1,
\ 'text': 'Reference'
\ })
endfor
call setqflist(qflist)
copen
endfunction
nnoremap <silent> <leader>rl :call CustomReferenceList()<CR>" Check if definition exists before jumping
function! SafeDefinitionJump() abort
let defs = CocAction('definitions')
if len(defs) == 0
echohl WarningMsg
echo "No definition found"
echohl None
return
endif
call CocAction('jumpDefinition')
endfunction
nnoremap <silent> gd :call SafeDefinitionJump()<CR>" Handle multiple definitions explicitly
function! HandleMultipleDefinitions() abort
let defs = CocAction('definitions')
if len(defs) == 0
echo "No definition found"
elseif len(defs) == 1
call CocAction('jumpDefinition')
else
echo len(defs) . " definitions found - opening location list"
call CocAction('jumpDefinition')
" Location list opens automatically
endif
endfunction" Wait for LSP before jumping
function! WaitForLSP() abort
if !get(g:, 'coc_service_initialized', 0)
echo "Waiting for coc.nvim to initialize..."
return v:false
endif
return v:true
endfunction
function! SafeJump() abort
if !WaitForLSP()
return
endif
call CocAction('jumpDefinition')
endfunctionProblem: gd or other jump commands do nothing.
Solutions:
:CocInfo:nmap gd:CocCommand workspace.showOutputCocAction('ensureDocument')Problem: "No definition/reference found" messages.
Solutions:
:CocList services:CocRestartProblem: Multiple results don't show location list.
Solutions:
let g:coc_enable_locationlist = 1let g:coc_enable_locationlist = 0Problem: Jump goes to wrong location.
Solutions:
g:coc_uri_prefix_replace_patterns if using remote devProblem: Ctrl-t doesn't work after LSP jump.
Solutions:
tagfunc is set: set tagfunc=CocTagFunc:tag command instead of <Plug> mappingstagfunc (Vim 8.1.1228+)" Limit reference search scope for performance
let refs = CocAction('references', {
\ 'includeDeclaration': v:false,
\ 'maxResults': 100
\ })" Use async for non-blocking navigation
call CocActionAsync('jumpDefinition')
" Or for getting results:
call CocLocationsAsync('tsserver', 'textDocument/references'):CocRestart