# LSP and Code Intelligence
LSP (Language Server Protocol) gives LazyVim IDE-like features: autocomplete, go to definition, refactoring, inline errors, and more. Understanding how to use LSP effectively makes you 10× faster.
## What is LSP?
**LSP** is a protocol that allows editors to communicate with language-specific servers that understand your code.
```
LazyVim (client) ←→ typescript-language-server (server)
←→ pyright (Python)
←→ lua-language-server (Lua)
```
**What LSP provides:**
- ✅ Autocomplete with type information
- ✅ Go to definition/references
- ✅ Inline error diagnostics
- ✅ Hover documentation
- ✅ Code actions (refactoring)
- ✅ Rename symbols across files
- ✅ Signature help (function parameters)
**What LSP does NOT do:**
- Run your code (that's a REPL/debugger)
- Format your code (that's a formatter like Prettier)
- Lint your code (that's a linter like ESLint - though some LSPs include it)
## Essential LSP Keybindings
### Go to Definition
```
gd
```
**What it does:** Jumps to where a function/variable is defined.
**Example:**
```typescript
// In file A:
import { calculateTotal } from './utils';
const result = calculateTotal(100, 0.2);
↑ cursor here
// Press gd → Jumps to file B:
export function calculateTotal(price: number, tax: number) {
return price + (price * tax);
}
```
**Return to previous location:**
```
Ctrl+o # Jump back
```
### Go to Type Definition
```
gy
```
**What it does:** Jumps to the type definition.
**Example:**
```typescript
const user: User = getUser();
↑ cursor here
// Press gy → Jumps to:
interface User {
name: string;
email: string;
}
```
### Find References
```
gr
```
**What it does:** Shows everywhere a symbol is used.
**Example:**
```typescript
function calculateTotal(a, b) { return a + b; }
↑ cursor here
// Press gr → Shows list:
1. src/utils.ts:12 - function calculateTotal
2. src/App.tsx:45 - const total = calculateTotal(x, y)
3. src/Cart.tsx:23 - return calculateTotal(price, tax)
```
### Hover Documentation
```
K (Shift+k)
```
**What it does:** Shows documentation for symbol under cursor.
**Example:**
```typescript
const result = Math.max(10, 20);
↑ cursor here
// Press K → Shows popup:
┌─────────────────────────────────────┐
│ Math.max(...values: number[]): number │
│ │
│ Returns the larger of a set of │
│ supplied numeric expressions. │
└─────────────────────────────────────┘
```
**Close popup:** Press `K` again or `Esc`
### Code Actions
```
Space + c + a
```
**What it does:** Shows available refactorings and quick fixes.
**Examples:**
**Import missing symbol:**
```typescript
const result = calculateTotal(10, 20);
↑ (red underline: not imported)
Space + c + a → Shows:
1. Import calculateTotal from './utils'
2. Create function calculateTotal
```
**Extract to constant:**
```typescript
return price * 0.2;
↑ select "price * 0.2"
Space + c + a → Shows:
1. Extract to constant
2. Extract to function
```
**Fix all in file:**
```
Space + c + A # Capital A
```
### Rename Symbol
```
Space + c + r
```
**What it does:** Renames a symbol everywhere in the project.
**Example:**
```typescript
function calculateTotal(price, tax) {
return price + tax;
}
const result = calculateTotal(100, 20);
↑ cursor on "calculateTotal"
Space + c + r
Type: "computeSum"
→ Renames in ALL files where it's used
```
**This is extremely powerful:**
- Refactor safely across entire codebase
- Renames in imports/exports too
- Updates all references
### Signature Help
```
# Automatically shows when typing function call
# Or manually trigger:
Ctrl+k
```
**Example:**
```typescript
Math.max(
↑ cursor here
// Automatically shows:
┌──────────────────────────────────┐
│ max(value1: number, value2: number, ...values: number[]): number │
│ ^^^^^^ │
└──────────────────────────────────┘
```
Shows which parameter you're on and its type.
## Diagnostics (Errors/Warnings)
LSP shows errors and warnings inline.
### See Diagnostics
**Visual indicators:**
- Red underline = Error
- Yellow underline = Warning
- Blue underline = Info
- Gray text = Hint
**See full diagnostic message:**
```
# Hover over error
K
```
### Navigate Diagnostics
```
]d # Next diagnostic
[d # Previous diagnostic
```
### Show All Diagnostics
```
Space + x + x # Diagnostics in current file
Space + x + X # Diagnostics in all files
```
**Opens list:**
```
1. error: Cannot find name 'calculateTotal'
2. warning: Unused variable 'result'
3. info: Consider using const instead of let
```
### Fix Diagnostic
```
# Cursor on error
Space + c + a # Shows available fixes
```
## Autocomplete
LazyVim has intelligent autocomplete via nvim-cmp.
### Trigger Autocomplete
**Autocomplete triggers automatically as you type.**
**Manual trigger:**
```
Ctrl+Space
```
### Navigate Completions
```
Ctrl+n # Next item
Ctrl+p # Previous item
Ctrl+y # Accept (yes)
Ctrl+e # Cancel (exit)
Enter # Accept selected
```
### Autocomplete Sources
LazyVim pulls suggestions from:
- LSP (functions, variables, types)
- Buffer (words in current file)
- Path (file paths)
- Snippets (code templates)
**Example:**
```typescript
const user = {
name: "John",
email: "
[email protected]"
};
user.
↑ Press Ctrl+Space
→ Shows:
name: string
email: string
```
## Code Actions Examples
### Import Missing Modules
```typescript
const result = calculateTotal(10, 20);
↑ Red underline
Space + c + a
→ Import calculateTotal from './utils'
```
### Add Missing Types
```typescript
function greet(name) {
↑
Space + c + a
→ Infer type from usage
→ Add explicit type annotation
```
### Extract to Function
```typescript
const total = price * (1 + taxRate);
↑ Select expression
Space + c + a
→ Extract to function
→ Extract to constant
```
### Organize Imports
```
Space + c + o
```
**What it does:**
- Removes unused imports
- Sorts imports
- Groups imports by type
### Format Document
```
Space + c + f
```
**Uses configured formatter:**
- Prettier for JS/TS
- Black for Python
- stylua for Lua
## LSP Server Management
### Check LSP Status
```
:LspInfo
```
**Shows:**
- Active LSP servers
- Server capabilities
- Configuration details
### Install Language Server
```
:Mason
```
**Interface:**
- `i` - Install server
- `u` - Update server
- `X` - Uninstall server
**Recommended servers:**
```
typescript-language-server (JS/TS)
pyright (Python)
lua-language-server (Lua)
rust-analyzer (Rust)
gopls (Go)
```
### Restart LSP
```
:LspRestart
```
**Use when:**
- Changed configuration
- Server is behaving strangely
- After installing new dependencies
## Snippets
Snippets are code templates that expand.
### Trigger Snippet
```
# Type trigger word
# Press Tab to expand
```
**Examples:**
**TypeScript:**
```
fun<Tab>
→ Expands to:
function name(params) {
}
```
**React:**
```
rfc<Tab>
→ Expands to:
import React from 'react';
export const ComponentName = () => {
return <div></div>;
};
```
### Navigate Snippet Placeholders
```
Tab # Next placeholder
Shift+Tab # Previous placeholder
```
**Example:**
```typescript
fun<Tab>
→ function |name|(params) { }
↑ cursor here
Tab
→ function name(|params|) { }
↑ cursor here
```
## Advanced Features
### Workspace Symbols
```
Space + s + S # Capital S
```
**Search for symbols across entire project:**
```
Type: "User"
→ Shows:
interface User (types.ts)
class UserService (services.ts)
const userSchema (schemas.ts)
```
### Peek Definition
```
gD # Capital D
```
**Shows definition in popup without jumping:**
```typescript
const result = calculateTotal(10, 20);
↑
gD
→ Shows popup with function definition
→ Close with Esc, don't lose your place
```
### Show Call Hierarchy
```
Space + c + h
```
**Shows:**
- Where function is called (incoming calls)
- What function calls (outgoing calls)
### Code Lens
Some LSP servers show inline information:
```typescript
function test() { // ← 3 references
// ...
}
```
Click or `Space + c + l` to trigger code lens action.
## Language-Specific Features
### TypeScript
```typescript
// Organize imports
Space + c + o
// Auto-import on complete
Ctrl+Space → Select → Auto-imports
// Type checking
:TSServer typeCoverage
```
### Python
```python
# Auto-import
Space + c + a → Import missing module
# Rename
Space + c + r → Renames across all files
# Sort imports
Space + c + o
```
### Lua (Neovim config)
```lua
-- Hover for Neovim API docs
K → Shows documentation for vim.opt, etc.
-- Go to source
gd → Jump to where function is defined
```
## Common Workflows
### Workflow 1: Explore Unfamiliar Code
```
1. Open file
2. Cursor on function name
3. K → Read documentation
4. gd → See implementation
5. gr → Find where it's used
6. Ctrl+o → Jump back
```
### Workflow 2: Refactor Function Name
```
1. Cursor on function name
2. Space + c + r → Rename symbol
3. Type new name
4. Enter → Renames everywhere
```
### Workflow 3: Fix Import Errors
```
1. See red underline
2. Space + c + a → Code actions
3. Select "Import from..."
4. Done
```
### Workflow 4: Extract Repeated Code
```
1. Visual select code
2. Space + c + a
3. "Extract to function"
4. Name the function
5. LSP updates all call sites
```
### Workflow 5: Add Types to Untyped Code
```typescript
function greet(name) {
return "Hello, " + name;
}
1. Cursor on "name"
2. Space + c + a
3. "Add type annotation"
4. Select inferred type
```
## Keybinding Reference
| Action | Keybinding | Description |
|--------|------------|-------------|
| **Go to definition** | `gd` | Jump to where symbol is defined |
| **Go to type def** | `gy` | Jump to type definition |
| **Find references** | `gr` | Show all uses of symbol |
| **Hover docs** | `K` | Show documentation |
| **Code actions** | `Space c a` | Show refactorings/fixes |
| **Rename** | `Space c r` | Rename symbol everywhere |
| **Next diagnostic** | `]d` | Jump to next error/warning |
| **Prev diagnostic** | `[d` | Jump to previous error/warning |
| **Signature help** | `Ctrl+k` | Show function parameters |
| **Format** | `Space c f` | Format document |
| **Organize imports** | `Space c o` | Clean up imports |
## Tips and Tricks
**1. Learn `gd` and `gr` first**
- These are the most-used LSP features
- Navigate code like a pro
**2. Use `K` liberally**
- Hover documentation saves trips to MDN/docs
- Learn APIs without leaving editor
**3. `Space c a` fixes most issues**
- Auto-import missing modules
- Convert to const/let
- Extract code
- Add types
**4. Rename is safer than find-replace**
- `Space c r` understands scope
- Won't rename unrelated symbols
**5. Organize imports frequently**
- `Space c o` after adding imports
- Keeps code clean
**6. Use diagnostics to learn**
- Red underlines teach best practices
- Read the full error message with `K`
## Common Mistakes
**❌ Not installing language servers**
→ Run `:Mason` and install servers for your languages
**❌ Ignoring code actions**
→ `Space c a` solves most issues automatically
**❌ Using find-replace instead of rename**
→ `Space c r` is scope-aware and safer
**❌ Not reading hover docs**
→ `K` shows types and documentation inline
**❌ Manually fixing imports**
→ `Space c o` organizes imports automatically
## Troubleshooting
**LSP not working:**
```vim
:LspInfo # Check server status
:Mason # Install missing server
:LspRestart # Restart server
```
**Autocomplete not showing:**
```vim
:checkhealth nvim-cmp # Check completion health
Ctrl+Space # Manually trigger
```
**Diagnostics not appearing:**
```vim
:LspInfo # Verify server is attached
:checkhealth lsp # Check LSP health
```
**Wrong language server:**
```lua
-- In ~/.config/nvim/lua/config/lsp.lua
-- Configure which server for which filetype
```
**Related:**
- [[File Navigation in LazyVim]] - Finding code
- [[Code Editing Workflows]] - Making changes
- [[Git Integration in LazyVim]] - Committing changes
- [[LazyVim Setup]] - Installing language servers