# 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