IntelliJ IDEA Community Edition 源码实战指南:三步构建完整 IDE,并追到补全与断点的实现
当你和同事争论"为什么输入一个词 IDE 就能建议出那个方法名"、"条件断点到底是怎么挂上去的"时,答案就写在 IDE 自己的代码里。IntelliJ IDEA 社区版(intellij-community)是 JetBrains 开源的这个仓库:你日常用的 Java 补全、重构、断点调试,连同承载它们的 IntelliJ Platform 底层,全部在这里,免费可读、可构建、可二开。本文带你走一遍"构建 → 读目录 → 追实现 → 动手写插件"的完整路径。
🛠 先跑起来:从 clone 到一个能打断点的 IDE
第一次面对一个百万行级的源码仓库,最忌讳"还没跑起来就开始读"。按下面的顺序操作,一两个小时之内你就能用自己构建的 IDE 打开自己的项目。
-
准备 Git。Windows 用户先执行
git config --global core.longpaths true和git config --global core.autocrlf input,否则 clone 时会报路径过长。 -
克隆仓库:
git clone https://gitcode.com/GitHub_Trending/in/intellij-community cd intellij-community -
在项目根目录执行
./getPlugins.sh(Windows 用getPlugins.bat)。它会把 IDEA 依赖的 Android 相关模块从独立仓库拉到本地android/目录,缺了它项目里会少一批模块。注意脚本要求两个仓库的分支保持一致。 -
安装 IntelliJ IDEA 2026.1 或更新版本,并通过 Settings | Plugins 装好 Bazel 插件——仓库正在向 Bazel 构建系统迁移,纯 IDE 内置构建已不再支持。
-
用 IDE 打开根目录下的
.bazelproject文件(不是打开整个目录),等待索引。 -
菜单 Build | Build Project 完成构建;之后在 Run 配置里直接运行预置好的
Run //build:idea_community,就会弹出你自己编译出来的 IDE。命令行方式等价:./bazel.cmd run //build:idea_community。 -
想产出安装包,执行
./installers.cmd -Dintellij.build.target.os=current,只构建当前操作系统的版本。
跑通之后,你会得到一个可以完整使用的社区版 IDE,界面大致长这样(仓库内置的新 UI 预览图):
一个实用场景:以后你怀疑某个功能在某次改版中行为变了,可以把对应版本的分支 checkout 下来按同样流程构建,新旧并排对比,比翻 release notes 直接得多。
🗺 读懂目录地图:你每天用的功能分别睡在哪个模块
构建成功后不要急着通读,先建立地图。顶层目录就是按"能力"切的:
- java/:Java 语言支持的全部实现。其中
compiler/是编译器集成,debugger/是调试器的前端与后端,execution/管运行配置和终端,java-impl/放代码洞察核心——补全、intentions(快捷键修复)、重构都在这一个模块里,java-impl-inspections/放内置检查规则,java-impl-refactorings/放重命名、提取方法这类重构的实现,java-psi-api/与java-psi-impl/则是语法树(PSI)的契约与实现。 - platform/:与语言无关的平台底座。
core-api/、core-impl/是基础 API,completion/是补全框架,diff-api/、diff-impl/是文本对比,code-style-*/是格式化,external-system-api/负责 Maven、Gradle 等外部构建工具集成。 jps/:构建系统后端,项目模型(model-api/model-impl)和各种 builder 都在这。- 零散但值得知道:
RegExpSupport/是正则表达式的 PSI 支持,commandInterface/是命令行接口,libraries/用 Bazel 规则集中声明了全部第三方依赖。 - docs/:设计文档与 PlantUML 架构图源码,装个 PlantUML 插件就能直接渲染。
想确认某个模块依赖谁,不要靠猜:每个模块目录下都有 BUILD.bazel,打开看 deps 列表,比在 IDE 里逐个查 import 系统得多。例如想看 java-impl 依赖了哪些平台模块,直接打开 java/java-impl/BUILD.bazel。
🔎 挑两个功能追下去:补全与条件断点
地图有了,挑两条你最关心的线深挖。
第一条:输入 sout 为什么会补出 System.out.println。 触发场景就是你写代码时敲下缩写的那一刻。阅读路径:从 java/ 下的 java-impl/ 找 Java 补全贡献者(completion contributor),顺着调用链会看到模板文本(live template)的展开逻辑——sout 这类缩写本质是 Live Template 的触发词,补全列表负责把它展示出来,模板负责展开。想验证自己没读错,java/java-completion-tests/ 下有专门的补全测试,改一行代码跑对应测试即可看到补全结果的变化。
第二条:条件断点为什么只在该停的时候停。 场景是循环体里几十次迭代你只想停一次。从断点标记的 UI 入手:java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/ 下就是断点管理的实现层,再往下会看到调试器通过 JDI(Java Debug Interface)协议与目标 JVM 通信,条件表达式被发送到调试端在每次命中时求值。追完这条线,你对"IDE 只是一个把 UI 事件翻译成调试协议指令的客户端"这件事会有直观认识。
还有一份现成的地图值得先读:java/AGENTS.md。它明文规定了代码放置规则——契约放 API 模块、行为放 impl 模块(如 java-psi-api 配 java-psi-impl),java-impl 持有补全、intentions 与重构,java-tests 持有全部测试数据。以后你往这个目录加代码,照它执行就不会放错地方。
🧩 插件开发第一步:给 IDE 加一个设置面板
如果你最终的目标是做插件,仓库自带了一个最小学习材料:docs/ 下的 configurable.md。它讲的是如何往 Settings 对话框里挂一个自己的设置页:
- 实现
com.intellij.openapi.options.Configurable接口(源码在platform/ide-core/src/com/intellij/openapi/options/Configurable.java),核心是四个方法:createComponent()建界面、reset()恢复默认值、isModified()判断是否被改动、apply()落盘配置。 - 在
plugin.xml里用applicationConfigurable(全局设置)或projectConfigurable(项目级设置)扩展点注册你的类,通过key/bundle提供显示名——文档特别建议直接写死显示名,否则每次打开设置对话框都要先加载你的类,会明显变慢。 - 想控制设置在树里的层级,用
parentId挂到 Editor、Tools 等已知分组下。
做完这一步你的插件就有了"存在感",之后再加动作、检查、工具窗口都是同一套扩展点机制。完整的插件开发文档入口在仓库 README 里有指向,配合本仓库源码对照着看,比只看抽象文档顺。
🧯 四个真实会踩的坑
- Windows 上 clone 报路径错误。 原因是 Git 默认限制路径长度。解决:clone 前先执行
git config --global core.longpaths true,已 clone 失败则删目录重来(本仓库目录较深,这个坑出现频率很高)。 - 项目打开后缺模块、索引不全。 十有八九是漏跑了
getPlugins.sh,Android 相关模块还没拉下来。补跑一次即可;同时确认intellij-community与android两个仓库在同一分支/标签上,版本错位会导致模块解析异常。 - 模块解析失败、Bazel 目标不识别。 你用的 IDE 版本低于 2026.1,或没装 Bazel 插件。仓库 README 明确要求这个组合,且纯 IDE 内置构建已废弃,不要用旧 IDE 硬试。
- 本地构建慢到怀疑人生。 仓库自带 Docker 构建环境(根目录
Dockerfile),容器内预装了依赖与工具链,按 README 的两条docker build/docker run命令执行即可,不用在宿主机上折腾环境。
📣 这个仓库最值钱的三件事,分别给谁
给想搞懂 IDE 的人:补全为什么准、重命名为什么敢全项目替换、断点为什么能停在精确行——所有答案都能在 java/ 和 platform/ 里追到具体实现,这是市面上极少数能完整读到答案的地方。
给写 IntelliJ Platform 插件的人:源码就是最权威的 API 文档。仓库里每个插件化的功能都是一个可仿照的样例,docs/configurable.md 可以直接作为你的第一个练手任务。
给做二次开发的人:Bazel 化的模块边界(每个目录一个 BUILD.bazel)让"只构建你改动的部分"成为可能,fork 一个分支、改一处行为、installers.cmd 打包,整条链路在本地就能闭环。
明天可以做的事只有一件:把仓库 clone 下来,按第一节跑通第一个自己构建的窗口,然后在 java-impl 里随便找一个补全类打断点,用另一个实例观察它如何被调用——亲手跑一遍,胜过读十篇架构分析。觉得有用就去仓库 Star 一下。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/gitblog_00314/article/details/158277196





