This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is the Bazel for CLion plugin (and historically IntelliJ) repository. The plugin is maintained by JetBrains as of July 2025. It provides Bazel build system integration for JetBrains IDEs.
Important: The CLion plugin is built from the master branch. The IntelliJ plugin is built from the ijwb branch (maintenance-only). The Android Studio plugin is maintained in AOSP.
Build the plugin for CLion:
bazel build //clwb:clwb_bazel_zip --define=ij_product=clion-oss-latest-stableThe plugin zip will be created at bazel-bin/clwb/clwb_bazel.zip.
The ij_product flag controls which IDE version to build for:
clion-oss-oldest-stable- Oldest supported IDE versionclion-oss-latest-stable- Latest supported IDE versionclion-oss-under-dev- Upcoming IDE version being worked on- Direct versions:
clion-2025.2,clion-2025.3, etc.
Version mappings are defined in intellij_platform_sdk/build_defs.bzl.
Important: Always run tests against ALL supported IDE versions to ensure compatibility:
clion-oss-oldest-stableclion-oss-latest-stableclion-oss-under-dev
Run unit tests for a specific module:
bazel test //base:unit_tests --define=ij_product=clion-oss-latest-stable
bazel test //base:unit_tests --define=ij_product=clion-oss-oldest-stable
bazel test //base:unit_tests --define=ij_product=clion-oss-under-devRun integration tests:
bazel test //base:integration_tests --define=ij_product=clion-oss-latest-stable
bazel test //base:integration_tests --define=ij_product=clion-oss-oldest-stable
bazel test //base:integration_tests --define=ij_product=clion-oss-under-devRun all tests for a language plugin:
bazel test //cpp/... --define=ij_product=clion-oss-latest-stable
bazel test //cpp/... --define=ij_product=clion-oss-oldest-stable
bazel test //cpp/... --define=ij_product=clion-oss-under-devRun aspect tests:
bazel test //aspect/... --define=ij_product=clion-oss-latest-stable
bazel test //aspect/... --define=ij_product=clion-oss-oldest-stable
bazel test //aspect/... --define=ij_product=clion-oss-under-devTests are organized into three categories:
unittests/- Fast, isolated unit testsintegrationtests/- Still relatively fast, used for interacting with IntelliJ platformheadlesstests/- Slow, require headless CLion, used for testing the entire sync process
.bazelproject files control what gets imported. Key sections:
directories:- Which directories to include/exclude (prefix with-to exclude)targets:- Which Bazel targets to buildbuild_flags:- Bazel flags to use (including--define=ij_product=...)workspace_type: intellij_plugin- Marks this as a plugin project
The plugin is organized as:
/base- Core plugin machinery (sync, project import, run configurations, etc.)- Language plugins -
/cpp,/python,/javascript,/skylark - Product bundles -
/clwb(CLion),/ijwb(IntelliJ, deprecated) - Supporting dirs -
/aspect,/sdkcompat,/testing
Each language plugin historically followed this structure:
language/
├── BUILD # Single BUILD file per plugin (600+ lines)
├── src/
│ ├── META-INF/ # Plugin XML config files
│ └── com/google/... # Source code
└── tests/
├── unittests/ # Fast unit tests
└── integrationtests/ # Tests requiring IDE instance
Examples: /base/BUILD (628 lines), /cpp/BUILD, /python/BUILD
This monolithic approach has all targets for a plugin in one BUILD file, making it harder to maintain as the plugin grows.
New code follows a more Bazel-like, fine-grained project structure:
module/
├── BUILD # Aggregator with exports
├── src/com/google/idea/blaze/
│ ├── submodule1/
│ │ ├── BUILD # Individual library
│ │ └── *.java
│ └── submodule2/
│ ├── BUILD # Individual library
│ └── *.java
└── tests/unittests/com/google/idea/blaze/
├── BUILD # Every test file is a Bazel target
└── *Test.java
This approach provides:
- Better dependency visibility and control
- Easier to understand module boundaries
- More parallelizable builds
- Cleaner refactoring paths
"Syncing" translates the Bazel build into IntelliJ's project model:
-
Build Phase: Run
bazel buildwith the aspect in/aspect- The aspect traverses targets and outputs
*.intellij-info.txtproto files - These protos contain information needed by the IDE (generated files, dependencies, etc.)
- The aspect traverses targets and outputs
-
Update Phase: Read the protos and:
- Generate a
TargetMap(in-memory representation of the Bazel build) - Translate into IntelliJ modules and libraries
- Update project structure
- Generate a
-
Index Phase: IntelliJ re-indexes changed symbols
Key classes:
BlazeSyncManager- Entry point for sync operationsSyncPhaseCoordinator- Orchestrates the sync phasesSyncListener- Extension point for reacting to sync events (hooks:onSyncStart,onSyncComplete,afterSync)BlazeSyncPlugin- Main interface for language plugins to interact with sync
TargetMap- In-memory representation of Bazel build, accessible viaBlazeProjectDataManagerTargetKey- Keys intoTargetMap(represents a Bazel target)TargetIdeInfo- Values inTargetMap(info gathered from a target: sources, deps, etc.)SourceToTargetMap- Maps source files to Bazel targetsKind- How the plugin represents Bazel rules (e.g.,py_binary,go_library)- Sub-plugins register
Kinds viaKind.Provider - Unregistered rules are ignored by the plugin
- Sub-plugins register
ProjectView- In-memory representation of a.bazelprojectfileProjectViewSet- Hierarchy of composedProjectViews (viaimportstatements)UserSettings- Global settings for the plugin (accessible viaCmd+, -> Bazel)
Flow: Context → Producer → RunConfiguration → Handler → Runner → Execution
RunConfigurationProducer- Creates run configurations from contexts (gutter icons in BUILD files, test classes, main functions)RunConfiguration- Stateful representation of what to runBlazeCommandRunConfigurationHandler- Holds state and creates runnersBlazeCommandRunConfigurationRunner- Crafts the command line to execute
See run/ subdirectories in language plugins (e.g., /golang/src/com/g.../golang/run).
The plugin supports multiple IntelliJ versions simultaneously. SDK compatibility code lives in:
/sdkcompat- Production compatibility code/testing/testcompat- Test-only compatibility code
Each directory contains version-specific subdirectories (e.g., v252/, v253/).
Three patterns for handling incompatibilities:
- Compat - Static utility methods wrapping changed APIs
- Adapter - New class extending changed superclass, plugin extends the adapter
- Wrapper - Wraps interfaces to provide old/new interface based on SDK version
Important rules:
- All compat changes must be commented with
#api{VERSION}(e.g.,#api252) - This marks the last API version requiring the code
- Compat classes must never import plugin code
- Keep compat code minimal
The base plugin defines extension points that language plugins can implement:
SyncPlugin- Hook into sync processSyncListener- React to sync eventsRunConfigurationProducer- Define how to run/test targetsKind.Provider- Register new Bazel rule types
Check base/src/META-INF/blaze-base.xml and language plugin XML files for extension points.
Familiarize yourself with these IntelliJ Platform concepts:
The project is migrating from monolithic BUILD files (one large file per plugin) to fine-grained BUILD files (distributed across the codebase following package structure). This follows Bazel best practices and improves maintainability.
Use fine-grained layout for:
- New modules or subsystems
- Shared libraries (like
/shared,/common) - Code that will be reused across plugins
- Modules with clear boundaries
For each logical module, create a BUILD file in its package directory.
Example: Creating a fine-grained library
Before (monolithic /base/BUILD):
kt_jvm_library(
name = "base",
srcs = glob([
"src/**/*.java",
"src/**/*.kt",
]),
deps = [
# 50+ dependencies...
],
)After (fine-grained /base/src/com/google/idea/blaze/base/command/buildresult/bepparser/BUILD):
load("//build_defs:build_defs.bzl", "intellij_plugin_library")
intellij_plugin_library(
name = "bepparser",
srcs = glob([
"*.java",
"*.kt",
]),
deps = [
"//common/experiments",
"//intellij_platform_sdk:plugin_api",
"//proto:proto_deps",
"//shared:artifact",
"//shared:exception",
"@com_google_guava_guava//jar",
],
)Note: Always prefer intellij_plugin_library over manually creating kt_jvm_library or java_library targets. The rule handles compilation internally and provides proper plugin integration.
Always prefer intellij_plugin_library over manually creating kt_jvm_library or java_library targets. The rule handles compilation internally and provides proper plugin integration.
Preferred approach:
load("//build_defs:build_defs.bzl", "intellij_plugin_library")
intellij_plugin_library(
name = "mymodule",
srcs = glob(["*.kt"]), # Rule handles Kotlin compilation internally
plugin_xmls = ["META-INF/mymodule.xml"],
deps = [
"//intellij_platform_sdk:plugin_api",
"//shared",
],
)When you don't have sources (pure aggregator):
intellij_plugin_library(
name = "mymodule",
plugin_xmls = ["META-INF/mymodule.xml"],
deps = [
"//base",
"//shared",
],
)The intellij_plugin_library rule:
- Automatically compiles sources if
srcsis provided (creates internalkt_jvm_library) - Merges
plugin_xmlsfrom all dependencies - Handles optional plugin XMLs
- Manages resources and data files
- Provides
IntellijPluginLibraryInfoprovider for plugin assembly - Supports inter-plugin dependencies
- Exposes
JavaInfoprovider for downstream consumers
- Prefer
intellij_plugin_library: For plugin code, always useintellij_plugin_libraryinstead of manually creatingkt_jvm_library/java_librarytargets. It handles compilation and plugin integration automatically.- Exception: Pure shared utilities with no IntelliJ Platform dependencies (like
/shared) can usejava_library - Rule of thumb: If it depends on
//intellij_platform_sdk:plugin_apior might have plugin XMLs, useintellij_plugin_library
- Exception: Pure shared utilities with no IntelliJ Platform dependencies (like
- Start Small: Migrate one logical module at a time
- Use Precise Dependencies: Depend on specific sub-modules, not entire plugins
- Follow Package Structure: BUILD files should align with Java package structure
- One Library Per BUILD: Each BUILD file should define one primary library (plus tests/utilities)
- Use Visibility Controls: Set appropriate visibility for each target
visibility = ["//visibility:private"]- Only usable in same BUILD filevisibility = ["//base:__subpackages__"]- Usable within base plugin
intellij_plugin_library(
name = "mylib",
srcs = glob(["*.java"]), # Can also use *.kt for Kotlin
visibility = ["//base:__subpackages__"],
deps = [
"//shared",
"@com_google_guava_guava//jar",
],
)intellij_plugin_library(
name = "mylib",
srcs = glob(["*.kt"]),
plugin_xmls = ["META-INF/mylib-plugin.xml"],
deps = [
"//intellij_platform_sdk:plugin_api",
"//shared",
],
)intellij_plugin_library(
name = "mylib",
srcs = glob(["*.kt"]),
resources = {
"icons/myicon.svg": "//resources/icons:myicon",
},
deps = ["//shared"],
)intellij_plugin_library(
name = "mylib",
srcs = glob(["*.kt"]),
data = {
"templates/default.xml": "//resources/templates:default",
},
deps = ["//shared"],
)intellij_plugin_library(
name = "mylib",
plugin_xmls = ["META-INF/mylib-plugin.xml"],
deps = [
"//base/src/com/google/idea/blaze/base/submodule1",
"//base/src/com/google/idea/blaze/base/submodule2",
],
)/aspect- Starlark aspect code that traverses Bazel build during sync/base- Core plugin machinery (sync, project import, run configurations)/build_defs- Bazel build definitions andij_productversion mappings/clwb- CLion plugin bundle/common- Shared utilities and settings (fine-grained layout)/cpp,/python,/javascript,/skylark- Language-specific plugin implementations/examples- Self-contained example projects for manual testing/intellij_platform_sdk- BUILD files for IntelliJ Platform SDK dependencies/sdkcompat- Multi-version IntelliJ SDK compatibility layer/shared- Shared libraries and utilities (fine-grained layout)/testing- Test utilities and test runner infrastructure/tools- Build and maintenance tools
The workspace may include reference directories from the IntelliJ IDEA monorepo. These are for context only - use them to understand IntelliJ Platform APIs, research implementation patterns, or learn how core IDE features work. Never modify files in these directories.
ultimate/- IntelliJ IDEA Ultimate monorepo (full source, including proprietary modules)community/- For external contributors, this directory contains the open-source IntelliJ Community Edition
When to use the IntelliJ monorepo:
- Understanding how to use IntelliJ Platform APIs correctly
- Finding examples of extension point implementations
- Researching how core IDE features work (VFS, indexing, PSI, etc.)
- Debugging unexpected IDE behavior
- Understanding sdkcompat requirements for new IDE versions
How to search the monorepo:
# From the plugin directory, search IntelliJ source
cd /path/to/ultimate
# or for external contributors:
cd /path/to/community
# Find usage examples of an API
git grep "SomeIntelliJClass"
# Find extension point definitions
find . -name "*.xml" -exec grep -l "extensionPoint.*myExtensionPoint" {} \;Important: Always implement solutions in the plugin repository, not in the IntelliJ monorepo. The monorepo is read-only reference material.
When implementing features or fixing bugs, leverage the IntelliJ IDEA source code (located at /ultimate or community/ for external contributors) as reference:
- Before implementing a feature: Search the IntelliJ source for similar implementations
- When using unfamiliar APIs: Find real usage examples in the IDE source
- For extension points: Look up extension point definitions and implementations
- When debugging: Compare plugin behavior with how the core IDE handles similar cases
Example workflow:
# Find how IntelliJ implements run configurations
cd /path/to/ultimate
git grep "class.*RunConfiguration" -- "*.java" "*.kt"
# ... make your changes ...Remember: The IntelliJ monorepo is read-only reference material. All implementations go in the plugin repository.
When supporting new IDE versions:
- Keep PRs small and focused on specific incompatible changes
- First try to make code work across versions directly (use newer APIs available in all versions)
- For non-trivial changes, add compat code in
/sdkcompat - Comment compat changes with
#api{VERSION} - Ensure changes work across all supported versions (presubmit tests will verify)
- Use the IntelliJ monorepo to understand API changes between versions
- ijwb - IntelliJ With Bazel
- clwb - CLion With Bazel
- aswb - Android Studio With Bazel (now in AOSP)