How Autocomplete and Go-to-Definition Actually Work in VS Code

June 23, 2026 · The Engine Behind Every AI Code Editor (part 3)

▶ Watch on YouTube & subscribe to The Stack Underflow

You type a dot. A list of method suggestions appears. You press F12 and jump instantly to where a function is defined — across files, across packages. It feels like your editor truly understands your code. It doesn’t. Something else does, and the distinction matters far more than you might think.

This post unpacks the architecture behind those two magic features: what the editor actually does when you trigger autocomplete, how language-specific intelligence is kept separate from the editor itself, and why every modern AI code editor — Cursor, Windsurf, GitHub Copilot — is built on top of a layer that was already there long before any LLM showed up.

The one-sentence version: Your editor is just a client that asks a dedicated language server for answers — they talk over the Language Server Protocol (LSP), one shared protocol that lets any editor work with any language without the editor needing to understand the language itself.

The Editor Is Only a Client

When you trigger autocomplete or jump to a definition, your editor doesn’t compute anything. It fires off a request to a separate process — a language server — and then renders whatever comes back. The editor is thin by design: it handles UI, key bindings, and display. It deliberately knows nothing about Python, TypeScript, or Rust.

The language server is where the smarts live. It parses your source files, builds an in-memory model of your project’s symbols and types, and answers queries like:

  • “What methods are available on this object at cursor position X?”
  • “Where is this function defined?”
  • “Is this variable used anywhere else?”

These are running as separate OS processes. You can actually see them if you open a task manager while editing — pylsp, tsserver, rust-analyzer, and so on, all humming away in the background.

The Language Server Protocol (LSP)

The reason one editor can talk to a Python server, a TypeScript server, and a Rust server without special-casing any of them is the Language Server Protocol — LSP. It’s a JSON-RPC specification originally designed by Microsoft for VS Code, then open-sourced so the entire ecosystem could benefit.

The protocol defines a common vocabulary for editor-to-server communication. Both sides agree on message shapes like textDocument/completion and textDocument/definition, so the editor never needs to know what language it’s dealing with — it just sends standard requests and receives standard responses.

Editor (client)                   Language Server (server)
─────────────────                 ──────────────────────────
User types "foo."    ──request──▶  Parses AST, resolves type
                     ◀─response─  Returns completion list
Renders dropdown

Adding support for a new language means shipping a new language server — not modifying the editor. The editor never changes. That’s the entire point.

Here’s a simplified picture of how the moving parts relate:

┌───────────────────┐     LSP (JSON-RPC)     ┌─────────────────────┐
│   VS Code / Editor │ ◀────────────────────▶ │  Language Server     │
│   (thin client)    │                        │  (e.g. tsserver,     │
│                    │                        │   pylsp, rust-analyzer)│
└───────────────────┘                        └─────────────────────┘

                                             Parses source files,
                                             builds symbol index,
                                             answers queries
Request typeLSP methodWhat the server does
AutocompletetextDocument/completionReturns a list of valid completions at cursor
Go to definitiontextDocument/definitionReturns file path + line number of definition
Find all referencestextDocument/referencesReturns every usage of a symbol
Hover documentationtextDocument/hoverReturns inline docs/type info
Rename symboltextDocument/renameReturns all edits needed across the workspace

Why AI Editors Didn’t Rebuild This

Here’s the part that surprises most people: Cursor, Windsurf, and GitHub Copilot did not build their own autocomplete or go-to-definition. They didn’t need to — they inherited the entire LSP layer from VS Code. Those editors are VS Code forks or VS Code extensions. The code intelligence that makes your editor feel smart was already there.

The AI sits on top of this layer. When an AI model suggests a multi-line completion, it’s a different code path from the LSP-powered single-token autocomplete, but the underlying symbol resolution, type checking, and definition jumping still go through the same language servers. The AI enhances the experience; LSP is the foundation.

This is also why AI editors can support any language that already has a language server — they get that for free. The AI doesn’t need to understand Python to give you go-to-definition in a Python file. The language server does that work.

Common Misconceptions

  • “The editor is smart about my language.” The editor is deliberately dumb about languages. All language intelligence lives in the language server process, not in VS Code itself.
  • “Autocomplete is AI.” The dropdown that appears when you type a dot is classic LSP autocomplete — deterministic, type-aware, no LLM involved. AI completions (multi-line ghost text) are a separate feature riding alongside LSP, not replacing it.
  • “AI editors rebuilt everything from scratch.” They didn’t. Cursor, Windsurf, and similar tools are built on top of VS Code and its LSP infrastructure. The AI layer is additive.
  • “One language, one editor plugin.” With LSP, it’s one language server per language — not one per editor. A single rust-analyzer binary serves VS Code, Neovim, Emacs, and any other LSP-compatible editor simultaneously.

Frequently Asked Questions

What actually happens at the OS level when I press F12? Your editor sends a textDocument/definition JSON-RPC request over a local socket (or stdin/stdout pipe) to the language server. The server looks up its in-memory symbol index, finds the file and line number where the symbol is defined, and sends back a response. Your editor then opens that file and moves the cursor to the reported position. The whole round-trip typically takes a few milliseconds.

Can a language server serve multiple editors at the same time? Generally, no — each editor instance spawns its own language server process and communicates with it exclusively. However, some servers (like clangd with its shared index) can share cached build artifacts across instances to speed up startup.

Why does the language server sometimes feel slow when I first open a project? The server needs to index your entire project before it can answer queries accurately. For large TypeScript projects, tsserver may spend 10–30 seconds building its symbol graph. After that initial warmup, responses are typically sub-millisecond from cache.

Does LSP work in Neovim or other non-VS Code editors? Yes. LSP is an open standard and has been adopted by virtually every serious editor — Neovim (via nvim-lspconfig), Emacs (via eglot or lsp-mode), Sublime Text, and more. One language server works everywhere.

Where This Fits in the Series

This episode is part of “The Engine Behind Every AI Code Editor” — a course in the How Claude Actually Works series on The Stack Underflow. The previous episodes covered how VS Code’s extension host works and how the editor and renderer communicate. The next episode dives into the integrated terminal: what actually happens at the OS level when an AI agent runs a shell command inside your editor.

Browse all tutorials in the series to follow the full arc from editor architecture to AI agent behavior.

Found this useful? The deep version lives on YouTube — new breakdowns of how AI dev tools actually work, weekly.

Subscribe on YouTube →