drop-platform-support
Skill181 starsChanged 17 days agoApache-2.0View on GitHub
Drops support for an old IntelliJ platform version in the JetBrains Academy plugin — removes `branches/<old>` code, moves shared platform-specific code to the main source set, and fixes `BACKCOMPAT` comments and `isAtLeast<version>` checks. Use when asked to "drop platform 261", "drop 2026.1 support", or "remove support for an old IntelliJ platform version".
In this repository13 other files it gives its agents.
- AGENTS.mdAGENTS.md
- openspec-apply-changeSkill
- openspec-archive-changeSkill
- openspec-exploreSkill
- openspec-proposeSkill
- openspec-sync-specsSkill
- openspec-update-changeSkill
- openspec-apply-changeSkill
- openspec-archive-changeSkill
- openspec-exploreSkill
- openspec-proposeSkill
- openspec-sync-specsSkill
- openspec-update-changeSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
20 rules. About 0 are common, 7 are distinctive, and 13 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
13
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 18
Remove platform-specific code for the old platform (steps 1–3)
- Very specific: line 47
No nested worktrees or checkouts inside the repository (e.g.
- Distinctive: line 49
No staged or unstaged changes to tracked files (untracked files are fine).
- Distinctive: line 57
Check the current branch: git rev-parse --abbrev-ref HEAD
- Very specific: line 58
If it is already drop-{platform_version}, continue on it.
- Very specific: line 61
Check for a remote branch with git ls-remote --heads origin drop-{platform_version}.
- Distinctive: line 63
Make sure there are no changes to tracked files before continuing.
- Very specific: line 100
keep the branches/$environmentName/...
- Distinctive: line 102
Commit any fixes from this step separately, or fold them into the phase 3 commit.
- Very specific: line 106
Read the supported values line in gradle.properties after step 3.
- Very specific: line 112
Prefer JetBrains MCP tools (search_regex, search_text, search_symbol).
- Very specific: line 118
Don't restrict file types — BACKCOMPAT notes appear in .kt, .java, .kts, .xml, .properties, .py, .md, etc.
- Distinctive: line 149
If the body is only a delegation to a newer API, call that API directly.
- Very specific: line 167
If Gradle build logic (buildSrc, build.gradle.kts) changed, this also checks it.
- Very specific: line 174
Use the project format <ticket>: <subject> with the real ticket ID, e.g.
- Very specific: line 185
update EducationalSupportedReleases in the intellij-teamcity-config repository
- Distinctive: line 208
Fix: Remove the condition and keep the body unconditionally:
- Very specific: line 253
Fix: Keep only newImplementation().
- Very specific: line 283
Search for both the dotted (2026.1) and numeric (261) forms, and don't require a colon after BACKCOMPAT.
- Very specific: line 284
Use get_symbol_info to understand a symbol before removing it.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Drop Platform Support Skill
This skill runs the whole process of removing support for an old IntelliJ platform version in the JetBrains Academy plugin.
This skill implements the "Dropping the old platform version" section of
documentation/different-platform-versions.md
and adds more detail. If the two directly contradict each other, report the contradiction to the user.
Overview
Dropping platform support has three phases:
- Remove platform-specific code for the old platform (steps 1–3)
- Move remaining platform-specific code (that's identical across all supported platforms) to the main source set (steps 1–3)
- Fix
BACKCOMPATcomments and version checks that reference the old platform version (steps 4–6)
helpers/drop_platform_support_local.py automates most of phases 1 and 2. It does not move a file if a file
with the same path already exists in the main source set. Those files stay in branches/<remaining>/ and have to be
merged by hand. Phase 3 is done by the agent.
Arguments
The platform version to drop is the one the user asked for, referred to below as {platform_version}
(e.g. 261). Its dotted form is {dotted_version} (e.g. 2026.1, see below). If the user did not give a version, ask. Do not guess.
Version naming
Platform versions appear in two forms. BACKCOMPAT comments in this repository use the dotted form.
To convert: NNN → 20 + first two digits + . + last digit.
Numeric (environmentName, branches/<v>, isAtLeast<v>) | Dotted (BACKCOMPAT comments) |
253 | 2025.3 |
261 | 2026.1 |
262 | 2026.2 |
The same conversion is Project.platformVersion in buildSrc/src/main/kotlin/intellijUtils.kt.
Prerequisites
- Python 3 (
python3), run from the repository root - No nested worktrees or checkouts inside the repository (e.g.
.claude/worktrees/*). The script walks the whole tree withos.walk(".")and would change theirbranches/directories too. - No staged or unstaged changes to tracked files (untracked files are fine). The script's changes are committed
with
git add -u, so any unrelated change to a tracked file would end up in the commit. - A YouTrack ticket ID for the commits (ask the user if it isn't known — do not commit
EDU-XXXX)
Instructions
1. Prepare the branch
- Check the current branch:
git rev-parse --abbrev-ref HEAD - If it is already
drop-{platform_version}, continue on it. If that branch exists locally, switch to it withgit checkout drop-{platform_version}. Otherwise create it:git checkout -b drop-{platform_version}. drop-{platform_version}is the same branch name the CI script (helpers/drop_platform_support.py) pushes. Check for a remote branch withgit ls-remote --heads origin drop-{platform_version}. If one already exists, tell the user and ask whether to continue on it rather than creating a separate local one.- Make sure there are no changes to tracked files before continuing.
2. Run the script
- From the repository root:
python3 helpers/drop_platform_support_local.py --platform_version={platform_version} - It deletes
branches/{platform_version}/, moves files that are identical in every remainingbranches/<v>/directory into the main source set, deletesgradle-{platform_version}.properties, and updates thesupported valuesline ingradle.properties. - If the script fails partway, the tree is left half-applied. Stop, show the user
git status, and ask how to proceed. Don't try to "finish" the changes by hand. - Review the result with
git status, then commit it with the ticket ID:git add -u && git commit -m "<ticket>: Drop {platform_version} support".
3. Check what the script did not do
gradle.properties: The script only rewrites thesupported valuesline when{platform_version}is the first entry, and it never touchesenvironmentName. Check that:{platform_version}no longer appears in# supported values: ...environmentNameis not{platform_version}(if it is, set it to a remaining version)
- Leftover platform-specific files: List everything still under
*/branches/*/(e.g.find . -path '*/branches/*' -type f -not -path '*/build/*' -not -path './.git/*' -not -path './.claude/*'). For each file that exists in every remaining version but was not moved (because the main source set already has a file at that path), merge it by hand. The script removes only the immediate parent directory of deleted files, so review and then delete empty directories left behind:find . -path '*/branches/*' -type d -empty -not -path './.git/*' -not -path './.claude/*' -delete. - Always platform-specific modules: the script deliberately leaves the remaining
branches/<v>/of the modules inALWAYS_PLATFORM_SPECIFIC_MODULES(helpers/platform_support_common.py, e.g.intellij-plugin/integration-tests) untouched. Don't move, merge, inline, or simplify those files, even if only one platform is left. - Only one platform left: This is the usual case, since the plugin normally supports two versions. With one
version left, the script moves every file from its
branches/<v>/whose path doesn't already exist in main. Then also (except for the always platform-specific modules above):- inline
*platform*.xmlfiles pulled in withxi:includeinto the main XML, if any remain (e.g.educational-core-platform.xmlincluded fromeducational-core.xml). Put the content exactly in place of thexi:includeline and don't reorder the other entries - simplify compat shims that now have a single implementation (
compatibilityUtils.ktfunctions,*Baseclasses,typealiases) — see "Tips and tricks" in the platform document - keep the
branches/$environmentName/...source dirs inbuildSrc/src/main/kotlin/intellij-plugin-common-conventions.gradle.kts: they are needed again when the next platform is added
- inline
- Commit any fixes from this step separately, or fold them into the phase 3 commit.
4. Determine the next oldest version
- Read the
supported valuesline ingradle.propertiesafter step 3. - The next oldest version is the smallest remaining one.
Example: when dropping
261andsupported values: 262, 263remain, the next oldest is262.
5. Find BACKCOMPAT comments and version checks
Prefer JetBrains MCP tools (search_regex, search_text, search_symbol). Fall back to grep.
- Primary: BACKCOMPAT comments with the dotted version. The colon is optional in this repo
(both
BACKCOMPAT: 2026.1andBACKCOMPAT 2026.1exist):grep -rnE "BACKCOMPAT:? *{dotted_version}" --exclude-dir=build --exclude-dir=.git --exclude-dir=localization --exclude-dir=.claude .(escape the dot, e.g.2026\.1). Don't restrict file types — BACKCOMPAT notes appear in.kt,.java,.kts,.xml,.properties,.py,.md, etc..claude/is excluded on purpose. The examples in this skill use real versions, so don't edit them as part of the drop. - Secondary: the numeric form (
BACKCOMPAT.*{platform_version}) and bareBACKCOMPATcomments with no version that mention the dropped platform. - Older versions: BACKCOMPAT comments for versions older than
{platform_version}can be left over from past drops. Fix them if they are simple. Otherwise list them in the summary for the user. Don't skip them silently. - Version checks for the next oldest version only (these are now always
true):- build scripts:
isAtLeast{NextOldestVersion}(defined inbuildSrc/src/main/kotlin/intellijUtils.kt, used inintellij-plugin/**/build.gradle.ktsandbuildSrc). Usesearch_symbolto find all usages.
- build scripts:
- Runtime and test checks for any version ≤ the next oldest version (always
trueor alwaysfalse):- runtime: search
BuildNumber\.fromString\("[0-9]{3}— this covers named constants (BUILD_242) and inline checks (build < BuildNumber.fromString("252")!!) compared withApplicationInfo.getInstance().build. Checks for versions older than{NextOldestVersion}are leftovers from past drops. Treat them the same way as older BACKCOMPAT comments: fix them if simple, otherwise report them. - tests:
@MinPlatformVersion("...")whose version is ≤ the next oldest version (intellij-plugin/educational-core/testSrc/com/jetbrains/edu/rules/ConditionalExecutionRule.kt)
- runtime: search
- Leave checks for newer versions alone. Example: when dropping 261 with 262 and 263 remaining,
remove
isAtLeast262, but leaveisAtLeast263alone — it still distinguishes 262 from 263. - Final sweep: plain-grep for
\b{platform_version}\band{dotted_version}(excludingbranches/,build,.git,.claude,localization, and test data), and review the hits by hand. This catches hard-coded values likeenvironment("IDEA_BUILD_NUMBER", "261"). Don't auto-fix anything here. Many hits are legitimate, e.g. dependency versions such aspsiViewerPlugin=PsiViewer:2026.1ingradle-262.propertiesor release history indocumentation/PluginVersionsInfo.md.
6. Fix each occurrence
For each BACKCOMPAT comment or version check:
- Read the surrounding code and, if the intent isn't clear, look at
git log -S/git blamefor why it was added. - Apply the fix that the comment asks for:
Inline it→ inline the declaration into all call sites (prefer an IDE inline refactoring if one is available), then remove it. If the body is only a delegation to a newer API, call that API directly.Merge it with X→ merge the class/file intoX, update imports and references, delete the original.Drop it→ delete the code and anything that becomes unused.Update value to X/Check ...→ update the value, then either remove the comment or point it at the next oldest platform if the check has to be repeated at the next drop.- Any other instruction → follow it. General comment with no instruction → work out what the workaround was for and replace it with the straightforward code for the remaining platforms.
- Version check → keep only the "new" code path (the
if (isAtLeastN)branch, or theelseofif (!isAtLeastN)/if (build < BUILD_N)), then remove the check definition once it has no usages. If a value was nullable only because of the check, make it non-null and simplify its callers.
- Remove the BACKCOMPAT comment once the fix is applied (unless it was updated to point at the next platform).
See Common patterns below for concrete examples from this repository.
7. Verify
- Compile production and test code against every remaining platform version:
./gradlew testClasses -PenvironmentName=<v>for each<v>insupported values. - If Gradle build logic (
buildSrc,build.gradle.kts) changed, this also checks it. - Optionally run tests for modules you changed in a non-trivial way:
./gradlew <gradle-module-path>:test --continue -PexcludeTests=**/slow/** - Fix failures before committing. Report any you can't fix.
8. Commit
- Use the project format
<ticket>: <subject>with the real ticket ID, e.g.EDU-1234: Fix BACKCOMPAT comments for 2026.1. - The script's changes are already committed separately in step 2. Commit the phase 3 fixes on top of that commit.
9. Summary
Report:
- the number of BACKCOMPAT comments and version checks fixed, grouped by fix type
- files that the script left under
branches/and how they were merged - stale older-version BACKCOMPAT comments left for the user
- which platform versions were compiled, and the results
- manual follow-ups outside this repository/change:
- update
EducationalSupportedReleasesin theintellij-teamcity-configrepository
- update
Common patterns
The examples assume dropping 261 (2026.1), with 262 as the next oldest version.
Pattern 1: Version check property in buildSrc
// buildSrc/src/main/kotlin/intellijUtils.kt
// BACKCOMPAT: 2026.1. Drop it
val Project.isAtLeast262: Boolean get() = environmentName.toInt() >= 262Fix: Simplify every usage (patterns 2–4), then delete the property.
Pattern 2: Conditional dependencies in Gradle
// intellij-plugin/Edu-Python/build.gradle.kts
intellijPlugins(pythonPlugin)
testIntellijPlugins(tomlPlugin)
if (isAtLeast262) {
intellijPlugins(testRunnerPlugin)
}Fix: Remove the condition and keep the body unconditionally:
intellijPlugins(pythonPlugin)
testIntellijPlugins(tomlPlugin)
intellijPlugins(testRunnerPlugin)Pattern 3: Conditional list entries
val Project.commonTestPlugins: List<String> get() = listOfNotNull(
imagesPlugin,
if (isAtLeast262) "intellij.structureView.plugin" else null,
if (isAtLeast262) testRunnerPlugin else null,
jcefPlugin,
)Fix: Replace each ternary with its value. If nothing nullable is left, listOfNotNull can become listOf:
val Project.commonTestPlugins: List<String> get() = listOf(
imagesPlugin,
"intellij.structureView.plugin",
testRunnerPlugin,
jcefPlugin,
)Pattern 4: Nullable only because of the version check
// BACKCOMPAT: 2026.1. Always use `jcefPlugin` property and make it non-null
val Project.jcefPlugin: String? get() = if (isAtLeast262) resolvePluginPlaceholders(prop("jcefPlugin")) else nullFix: Make it non-null and update callers that handled null:
val Project.jcefPlugin: String get() = resolvePluginPlaceholders(prop("jcefPlugin"))Pattern 5: Runtime build check
val BUILD_262 = BuildNumber.fromString("262")!!
if (ApplicationInfo.getInstance().build < BUILD_262) {
oldImplementation()
} else {
newImplementation()
}Fix: Keep only newImplementation(). Delete BUILD_262 if it's no longer used.
These checks live in normal source files, not in branches/, so they are easy to miss — search for them explicitly.
Pattern 6: Update the comment to the next version
// buildSrc/src/main/kotlin/common-conventions.gradle.kts
// BACKCOMPAT: 2026.1. Check the minimal required API version.
// Update this message and api version value if needed
apiVersion = KotlinVersion.KOTLIN_2_3Fix: Set apiVersion to the Kotlin version bundled with the oldest remaining platform
(see https://plugins.jetbrains.com/docs/intellij/using-kotlin.html#bundled-stdlib-versions). It must never be higher
than that version, because raising it is the risky direction. Keep it if unsure and report it.
Then update the comment to the next oldest platform:
// BACKCOMPAT: 2026.2. Check the minimal required API version.
// Update this message and api version value if needed
apiVersion = KotlinVersion.KOTLIN_2_3Pattern 7: Inline / merge / drop
// BACKCOMPAT: 2026.1. Inline it
fun oldHelper() = newApi()Fix: Replace oldHelper() calls with newApi() and remove oldHelper.
Merge it with X and Drop it work the same way: move or delete the code, then fix references and imports.
Tips
- Search for both the dotted (
2026.1) and numeric (261) forms, and don't require a colon afterBACKCOMPAT. - Use
get_symbol_infoto understand a symbol before removing it. - Gradle changes break the whole build — compile after changing
buildSrc.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

