Dev ToolingDev Tooling
A Practical Guide to Best Code Editor
Dev Tooling

A Practical Guide to Best Code Editor

Anthony HarveyArticle by Anthony Harvey

Two programs share one window and take credit for the same work. The editor owns the buffer, the keymap, the render loop and the decision to send a request. The language server owns the parse tree, the type resolution, the diagnostics and the text it sends back. Completion, rename, go-to-definition and every red squiggle arrive from the second program. The feel of typing comes from the first.

Keep the two apart and the title's question splits in two. Which editor routes bytes between a buffer and a server with the least friction, and which server can answer for the language in front of you.

Three editors, each a particular kind of program

Visual Studio Code is an Electron application. Microsoft provides a main process, a renderer process for each window, and an extension host process. A window costs a main process, a renderer process and an extension host before any language server starts.

Neovim is a terminal modal editor. It runs as a single process and has shipped a built-in LSP client for years. Configuration is Lua.

IntelliJ IDEA is a JVM application. It indexes a project into its own syntax and semantic model and answers from that index. For the languages JetBrains maintains, no server process exists.

Visual Studio Code, Neovim and IntelliJ IDEA are the comparison. Every attribute below gets a value for each of them.

Process model fixes the latency floor

Visual Studio Code runs a main process, a renderer process per window, and an extension host process, plus a child process per language server. A stall in the extension host halts extensions and leaves the renderer painting. That separation is the entire reason the host process exists. The cost is a memory floor and inter-process messaging.

Neovim runs as a single process and starts a child process for each language server. A keystroke goes directly to the terminal emulator. The ceiling is the emulator. The editor has no render loop of its own in the graphical sense.

IntelliJ IDEA runs a single JVM with a shared heap and keeps the project index in files on disk. A diagnostic costs a heap allocation. The JVM startup cost is paid once per session.

The analysis engine determines which diagnostics exist.

Visual Studio Code delegates analysis to language servers. The TypeScript server, Pylance, rust-analyzer and their peers supply completion, diagnostics and refactoring. The editor supplies the transport and the UI. A missing server means missing diagnostics, regardless of editor version.

Neovim uses the same servers through its built-in client. Configuration in Lua wires each server to a filetype. The editor does not include a server of its own; it includes the client.

IntelliJ IDEA builds its own index. The engine parses source into a syntax tree, resolves symbols, and stores the result in a persistent index. Diagnostics come from inspections that run over that index. For Java, Kotlin, Groovy and Scala, no separate server process exists.

The difference matters because poor diagnostic latency has a price. Codacy reports that the cost of poor software quality in the United States was at least 2.41 trillion dollars in 2022, citing CISQ's 2022 report. The same Codacy article reports that 58 per cent of developers say not having enough time is the single most common challenge faced during code reviews, according to its 2024 State of Software Quality report. An editor that surfaces a type error while you type removes a review comment before it is written.

Configuration surface determines how much you can enforce

Coding standards only matter if the editor applies them without a manual step. BrowserStack's guide to coding standards recommends linters and formatters to check stylistic issues and adjust formatting automatically. Anthony Steele suggests that a style guide should link to industry standards and that automation is fast and consistent. Both points favour editors that read configuration files from the project root.

Visual Studio Code uses settings.json, .editorconfig and extension-specific configuration. A project can pin the TypeScript version, the formatter and the linter in the repository. Extensions run in the extension host, so a crash does not take down the window.

Neovim uses Lua configuration. The built-in LSP client starts servers per filetype. A formatter plugin such as conform.nvim or a null-ls bridge applies the same tools. Configuration lives in a versioned repository and can be shared across a team.

IntelliJ IDEA stores code style and inspection profiles in the .idea directory. A team can commit that directory and share the profile. The IDE applies the profile to every file it opens. For languages without a server, the profile is the only enforcement mechanism.

A project-root configuration file is the shared contract. This snippet works in all three editors:

# .editorconfig
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

W3Schools' HTML style guide gives concrete rules that an editor can enforce: lowercase element names, quoted attribute values, two spaces of indentation, and no tab characters. GeeksforGeeks coding standards and guidelines add naming conventions, standard headers for modules, and limits on function length. The awesome-guidelines repository collects style guides for many languages, from Ada to XML, so the configuration burden is not writing rules but wiring existing ones into the editor.

Resource cost per window

Visual Studio Code pays for a main process, a renderer process, an extension host and each language server. The floor is higher than a terminal editor. The benefit is isolation.

Neovim pays for a single process plus each language server. Startup is measured in milliseconds. The trade is that the terminal emulator owns font rendering and mouse handling.

IntelliJ IDEA pays for a single JVM with a persistent index. The floor is the highest of the group. The trade is that analysis is local and does not require a separate server process.

Shared attributes, a value per editor

Attribute Visual Studio Code Neovim IntelliJ IDEA
Process model Electron: main, renderer, extension host, plus child per server Single process, plus child per server Single JVM with shared heap and disk index
LSP client Built-in client in the editor Built-in client in the editor Not used for maintained languages
Configuration settings.json, .editorconfig, extensions Lua configuration and plugins .idea profiles and inspection settings
Diagnostic engine Language servers Language servers Own index and inspections
Standards enforcement Extensions and formatters LSP, formatters, linters Inspection profiles and code style
Resource floor Main, renderer, extension host plus servers Single process plus servers Single JVM plus index

Each row gives a value for each editor. No cell is empty.

What the comparison leaves out

The best editor for a team is the one whose configuration can be committed and reviewed. Anthony Steele recommends aligning with industry standards by default and using prior art instead of writing rules from scratch. That recommendation applies to editors. A repository that contains an .editorconfig, a settings.json and a .idea directory lets any of the three editors enforce the same rules.

The choice between them is a choice about where the analysis runs. Visual Studio Code and Neovim put it in a separate process. IntelliJ IDEA runs it in the same process. That single decision explains most of the differences in latency, memory and configuration.

Sources

The figures behind this

US software quality cost
$2.41 trillion
Developer review hurdle
58% (Codacy)
VS Code process model
Electron
IntelliJ IDEA runtime
JVM
Neovim configuration
Lua

Related guides

How to Evaluate Code Review Platforms
How to Evaluate Code Review Platforms
Static Code Analysis Tools: Where to Start
Static Code Analysis Tools: Where to Start
What Code Quality Tools Actually Do
What Code Quality Tools Actually Do

← All Guides