본문으로 건너뛰기
cccskills
무료GitHub에 공개한국어 소개

extract-module

IntelliJ 플러그인의 선택적 의존성을 별도 콘텐츠 모듈로 옮겨, 해당 모듈이 없어도 호스트가 동작하도록 안내합니다. 독립 파일 이동과 확장 지점 도입 중 방식을 고르고 모듈 설정, 하위 의존성, 패키징 검사를 갱신합니다.

원문원문 설명 보기

Extract optional plugin dependencies into IntelliJ content modules.

JetBrains/intellij-community스타 20,684(GitHub 20,684 + cccskills 0)

실행 점수 미검증

설치 방법 보기

이럴 때 유용합니다

  • 플러그인 의존성을 선택 사항으로 만들기
  • 기능을 별도 모듈로 옮기기
  • 확장 지점으로 의존성 분리하기
  • 모듈 분리 후 검사 계획하기

한국어 소개

할 수 있는 일

이 스킬은 플러그인 의존성을 별도의 IntelliJ 콘텐츠 모듈로 옮기는 절차를 안내합니다. 새 모듈이 없어도 호스트 모듈이 계속 동작하고, 모듈이 있으면 이전과 같은 동작을 유지하는 것이 목표입니다. 의존성을 사용하는 코드가 몇 개의 독립 파일에 모여 있으면 파일을 옮깁니다. 호스트 전반에 참조가 흩어져 있으면 호스트에 확장 지점(EP) 인터페이스를 두고 새 모듈에서 구현합니다. .iml, 플러그인 XML, 소스 위치, 가시성, 하위 모듈의 의존성 선언도 다룹니다.

이럴 때 유용합니다

큰 플러그인에서 기능을 분리하거나 특정 언어나 프레임워크에 필요한 의존성을 선택 사항으로 만들 때 유용합니다. Kotlin 모듈의 의존성, 패키지 이름, Free 모드에서의 제공 여부, 다른 플러그인에서의 사용처럼 빌드와 이용 가능성에 영향을 주는 사항도 확인할 수 있습니다.

사용 예시

  • “이 의존성을 별도 콘텐츠 모듈로 옮기는 설계를 세워 주세요.”
  • “흩어진 의존성 호출을 확장 지점으로 옮기는 절차를 알려 주세요.”
  • “모듈 분리 뒤 필요한 의존성 선언과 검사를 정리해 주세요.”

주의 사항

IntelliJ 플랫폼 저장소의 구조와 명령을 전제로 합니다. .iml, 플러그인 XML 또는 모듈 구조를 바꾼 뒤 생성 도구와 지정된 테스트를 실행해야 합니다.

이 소개문은 공개된 SKILL.md를 바탕으로 AI(OpenAI Codex)가 작성했습니다. 정확한 사양은 아래 원문을 확인하세요.

문서 점검

AI가 SKILL.md의 내용에서 주의가 필요한 작업과 도입 전제를 확인했습니다. 점수는 실제로 실행한 결과(실행 검증)만으로 매깁니다.

안전성전송·삭제·명령 실행 등을 명시하고 있는가
B일부 부족소스와 패키징 설정을 바꾸고 테스트하지만 변경 전 확인 절차는 제한적입니다.
도입의 용이성필요한 도구나 API 키가 적고 적혀 있는가
B일부 부족IntelliJ 저장소와 빌드 도구, 테스트가 필요하며 설치 안내는 일부에 그칩니다.

점수에는 넣지 않았습니다. 2026년 10월 28일 기준으로 AI(OpenAI Codex)가 판정했습니다. 참고용이므로 설치 전에 원문도 확인해 주세요.

평가가 다르다고 생각되면 재검토를 요청하기

어느 항목이 왜 다르다고 생각하는지 적어 주세요. 로그인은 필요 없습니다. SKILL.md와 대조해 평가를 다시 만들고 이곳에 반영합니다.

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

포함된 파일(1)

  • SKILL.md20.6 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

<!-- Generated by community/.ai/render-guides.mjs; edit community/.agents/skills/extract-module/SKILL.md -->

Extracting an Optional Dependency into a New Content Module

Use this guide when making a dependency of a plugin module optional by moving it into a separate content module.

Goal: the host module continues to work when the new module is absent, and behaves identically when it is present.


When to Use Each Pattern

Pattern A — Simple move

All code that touches dependency X is isolated in a few files with no callers inside the host module. Move those files wholesale into the new module.

Pattern B — Extension Point (EP)

The host module's core files contain scattered references to X. Introduce an EP interface in the host module (no X imports), implement it in the new module, and replace direct X calls with null-safe static helpers.


Steps

1. Create the module directory

plugins/<plugin-name>/<module-dir>/
  resources/
    intellij.<module-name>.xml    ← module descriptor
  src/
    com/intellij/<...>/           ← sources (directory must match package)
  intellij.<module-name>.iml      ← module definition

2. Write the .iml

<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
  <component name="NewModuleRootManager" inherit-compiler-output="true">
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
    <orderEntry type="library" name="jetbrains-annotations" level="project" />
    <orderEntry type="module" module-name="intellij.<host-module>" />
    <!-- add other required modules -->
  </component>
</module>

Rules:

  • Never use packagePrefix on <sourceFolder>. Use a matching directory structure instead.
  • .iml files are serialized in canonical form — no trailing newline, no reformatting, no reordering.

Kotlin stdlib — mandatory for any Kotlin module

Every new Kotlin module needs the kotlin-stdlib library on its Bazel compilation classpath. Add it as a direct IML library dependency:

<orderEntry type="library" name="kotlin-stdlib" level="project" />
Cannot access built-in declaration 'kotlin.Any'. Ensure that you have a dependency on the Kotlin standard library.

This error is deceptive: it looks like a single missing type, but it means the entire stdlib is absent, so virtually every Kotlin annotation (@JvmStatic, @Throws, checkNotNull, ::class.java, …) and all built-in types fail simultaneously.

Common class-to-module mapping

Bazel strict-deps requires every class to be in a direct IML dependency. The following classes live in modules that differ from what their package names suggest:

Class(es)PackageIML moduleBazel target
ExecutionException, GeneralCommandLine, KillableColoredProcessHandler, OSProcessHandler, ScriptRunnerUtil, Url, NetUtilscom.intellij.execution.*, com.intellij.util.*intellij.platform.ide.util.io@community//platform/platform-util-io:ide-util-io
AsyncPromise, Promiseorg.jetbrains.concurrencyintellij.platform.concurrency@community//platform/util/concurrency
AppExecutorUtil, ProcessAdapter, ProcessEvent, ProcessOutputTypes, ParametersListUtil, FileUtil, StringUtilcom.intellij.util.*, com.intellij.openapi.util.*intellij.platform.util@community//platform/util
Editorcom.intellij.openapi.editorintellij.platform.editor.ui@community//platform/editor-ui-api
MultipleLangCommentProvidercom.intellij.psi.templateLanguagesintellij.platform.lang.impl@community//platform/lang-impl

Note: the IML module name for AsyncPromise/Promise is intellij.platform.concurrency (not intellij.platform.util.concurrency), even though the source lives under platform/util/concurrency/.

If the new module calls a method whose return type comes from a third module (e.g. a method returning ImmutableList<String>), that third module (intellij.libraries.guava) must also be a direct IML dep — Kotlin's type checker needs to verify the return type at compile time.

3. Write the module descriptor XML

If a class in the new module is used directly by another plugin (not just another module within the same plugin), set the module's visibility on the <idea-plugin> root. Choose the level by who the consumer is:

  • visibility="internal" — the consumer is another plugin inside this monorepo (a separate <plugin id="...">, e.g. a class subclassed or called from it). This is the common case.
  • visibility="public" — the class is part of API meant for external third-party plugins.
<idea-plugin visibility="internal">
  ...
</idea-plugin>

Without this, the other plugin cannot load the class even if it declares the module as a dependency.

The generator manages a <dependencies> region. For dependencies the generator doesn't produce automatically (e.g. a plugin dependency that was removed from the host), declare them before the <!-- region --> marker, inside the same <dependencies> tag:

<idea-plugin>
  <dependencies>
    <plugin id="com.example.some-plugin"/>   <!-- manual: not emitted by generator -->
    <!-- region Generated dependencies - run `Generate Product Layouts` to regenerate -->
    <module name="intellij.<host-module>"/>
    <!-- ... -->
    <!-- endregion -->
  </dependencies>

  <extensions defaultExtensionNs="com.intellij">
    <!-- register extensions here -->
  </extensions>
</idea-plugin>

Do not create a second standalone <dependencies> block before the region — this makes the file "out of sync" and breaks AllProductsPackagingTest#suiteValidations.

4. Package and source file conventions

  • Always create Kotlin files for new code. But when you just move the file, please keep it the same type it was (Kotlin or Java).
  • Source files must live in a directory matching their package: src/com/intellij/foo/bar/MyClass.kt for package com.intellij.foo.bar.
  • Package names must follow the com.<module-name> convention:
    • Module intellij.foo.bar → package com.intellij.foo.bar
  • IntelliJProjectPackageNamesTest enforces this. Do not add exceptions to non-standard-root-packages.txt for new modules.
  • Preserve freemium availability: both the host module and the new content module must have the same availability in IDEA Free mode as the original module had. If the original module was available in free mode, both new modules must remain available there. If the original was not available in free mode, neither should the new modules be. PluginsAvailableInIdeaFreeModeTest enforces this.

5. Declare the EP in the host module (Pattern B only)

In the host module's XML, declare the EP with qualifiedName:

<extensionPoints>
  <extensionPoint qualifiedName="com.intellij.<language>.<epName>"
                  interface="com.intellij.<language>.<feature>.MyFeatureHelper"
                  dynamic="true"/>
</extensionPoints>

qualifiedName format: com.intellij.<language/framework, lowercase>.<epNameLikeThisOne>

Write the EP interface in the host module (no X imports). Provide @JvmStatic companion helpers that gracefully return no-op defaults when the EP is absent:

interface MyFeatureHelper {
  fun doSomething(element: PsiElement): Boolean

  companion object {
    @JvmField
    val EP = ExtensionPointName.create<MyFeatureHelper>("com.intellij.<language>.<epName>")

    // An EP can have several registered extensions — process all of them, not just the first.
    @JvmStatic fun checkSomething(element: PsiElement?): Boolean =
      element != null && EP.extensionList.any { it.doSomething(element) }
  }
}

Register the implementation in the new module's XML:

<extensions defaultExtensionNs="com.intellij">
  <<language>.<epName> implementation="com.intellij.<language>.<feature>.MyFeatureHelperImpl"/>
</extensions>

Multi-method EP bundling and opaque state pattern

When separating a library whose operations form a lifecycle (capture some state, then use it later), bundle all related operations into one EP rather than creating one EP per method. This avoids proliferating EP registrations and keeps the implementation cohesive.

When lifecycle EP methods need to pass typed state between calls (e.g., capture a List<CssSelectorSuffix> in step 1, consume it in step 2), but the host module cannot import that type, use Any? as the state type. The EP interface uses Any?; the implementation casts internally with @Suppress("UNCHECKED_CAST"):

// In host module (no X imports)
interface MyLifecycleHelper {
  fun captureState(file: PsiFile): Any?       // returns X-typed data, opaque to host
  fun applyState(file: PsiFile, state: Any?)  // receives it back; casts inside impl

  companion object {
    val EP = ExtensionPointName.create<MyLifecycleHelper>("com.intellij.<language>.myLifecycleHelper")
    fun captureState(file: PsiFile): Any? = EP.extensionList.firstOrNull()?.captureState(file)
    fun applyState(file: PsiFile, state: Any?) = EP.extensionList.firstOrNull()?.applyState(file, state)
  }
}

// In new CSS/X module
internal class MyLifecycleHelperImpl : MyLifecycleHelper {
  override fun captureState(file: PsiFile): Any? = getThings(file)  // returns List<XThing>

  override fun applyState(file: PsiFile, state: Any?) {
    @Suppress("UNCHECKED_CAST")
    val things = state as? List<XThing> ?: emptyList()
    // use things...
  }
}

6. Register the new module in the plugin

plugin/resources/META-INF/plugin.xml — add a <module> content entry. That entry is the whole packaging statement: the dev distribution derives the member's jar from its loading rule and its own descriptor, so no packaging file needs a new line. Run ./build/jpsModelToBazel.cmd and never hand-edit a dev-dist.yaml.

Project module files — register the new module with the helper; it updates .idea/modules.xml, updates community/.idea/modules.xml for community modules, preserves canonical entry order, and removes the .iml trailing newline:

bun build/jps-module.mjs register plugins/<plugin-name>/<module-dir>/intellij.<module-name>.iml --fix-iml-eof

7. Fix downstream consumers of the removed transitive dependency

Removing a dependency from the host module may break modules that relied on it transitively. AllProductsPackagingTest#targetValidations will report which ones.

Fix: add explicit deps to their plugin XML in the manual section before the <!-- region --> marker:

<dependencies>
  <module name="intellij.some.formerly.transitive.module"/>
  <!-- region Generated dependencies ... -->
  ...
  <!-- endregion -->
</dependencies>

Also check other plugins. If the moved code was a superclass or utility called from a different plugin, that plugin will fail to compile. For each such plugin:

  1. Add <module name="intellij.new.module"/> to its plugin XML.
  2. Add <orderEntry type="module" module-name="intellij.new.module" /> to its .iml.
  3. Ensure visibility="public" is set on the new module's XML (see step 3).

Kotlin open — required when a class is subclassed from outside the module

Kotlin classes are final by default. If the moved class is:

  • subclassed by another module or plugin, or
  • has an inner class that is anonymously subclassed elsewhere,

both the outer class and the relevant inner class must be marked open:

open class MyStrategy : BaseStrategy() {
  // ...
  open class MyTokenizer : BaseTokenizer() {
    protected open fun shouldSkip(element: MyElement): Boolean { ... }
  }
}

Forgetting open produces cannot inherit from final class compile errors in the downstream plugin.

8. git add all new files

New files are untracked. Add them explicitly before running tests:

git add plugins/<plugin-name>/<new-module>/

Required Commands After Changes

After any .iml change

./build/jpsModelToBazel.cmd

After any .iml, plugin XML, or module structure change

./bazel.cmd run //platform/buildScripts:plugin-model-tool

Expected: ✓ All files unchanged. If files change, inspect them — the generator may be removing deps you set incorrectly, or adding ones you missed.

Required tests

# Validates packaging: runtime deps available, generated XMLs in sync
./bazel.cmd test //build:all-products-packaging_test

# Validates package naming: com.<module-name> convention
./tests.cmd --module intellij.projectStructureTests \
  --test "com.intellij.ideaProjectStructure.fast.IntelliJProjectPackageNamesTest"

# Validates plugin availability in IDEA Free mode
./tests.cmd --module intellij.projectStructureTests \
  --test "com.intellij.ideaProjectStructure.fast.PluginsAvailableInIdeaFreeModeTest"

All three must pass before the work is done.

Run them one at a time. tests.cmd kills leftover processes by name on startup (Killing process containing subpath 'ide-tests'), so a concurrent run shoots down the one already in flight — which surfaces as an unrelated-looking failure such as AllProductsPackagingTest#build.


Common Pitfalls

PitfallSymptomFix
packagePrefix in .imlIntelliJProjectPackageNamesTest finds wrong root packageRemove packagePrefix; use matching directory structure
Package doesn't match module nameIntelliJProjectPackageNamesTest failsRename to com.<module-name> and move files
EP registered with name instead of qualifiedNameEP not foundUse qualifiedName="com.intellij.<language>.epName"
Manual <dependencies> block as a separate tag (not inside the region's block)AllProductsPackagingTest#suiteValidations: "Generated file is out of sync"Merge into one <dependencies> block; manual entries go before <!-- region -->
Module registered by appending to modules.xmlnoisy project-file diff or project-structure driftUse bun build/jps-module.mjs register <path-to-iml> --fix-iml-eof; order is by .iml basename
New files not git addedBuild/tests miss new sourcesgit add new module directory
Skipped plugin-model-toolGenerated XML has stale/missing depsRun ./bazel.cmd run //platform/buildScripts:plugin-model-tool
New source file created as JavaStyle violationAlways use .kt for new code
Removed transitive dep breaks callersAllProductsPackagingTest#targetValidations failsAdd explicit <module name="..."/> to affected modules' plugin XMLs
Cross-plugin subclass of moved classcannot inherit from final class in another pluginMark the class (and subclassable inner classes) open; add visibility="public" to the new module XML; add module dep to the other plugin's IML and plugin.xml
File moved but package declaration not updatedIntelliJProjectPackageNamesTest: "packages [com.old.pkg] are found in the module"Change the package declaration and physically move the file to the matching directory
File moved but physical directory not movedIDE confused, search finds file in two placesAlways move both the file AND update its package declaration
Nullable override mismatch after Java→Kotlin conversion'override' overrides nothingMatch the Kotlin override param types exactly — if the base class uses platform types (unannotated Java), both nullable and non-null work; but if a subclass uses ? the base must too
return@label in val lambdaUnresolved label 'myLabel'Labels only work at the call site. Use .let { ... } chaining instead
Kotlin interface constant access from Javacannot find symbol CONSTANT_NAMEUse explicit class qualification: MyInterface.CONSTANT_NAME
Kotlin-defined fun getXxx() not auto-exposed as propertyUnresolved reference 'xxx'Call with explicit (): element.getXxx()
object : JavaInterface() with parenthesesThis type does not have a constructorInterfaces have no constructor; use object : JavaInterface without ()
Top-level Kotlin function imported from Javacannot find symbol myFunctionFrom Java the class is MyFileKt; use import static com.pkg.MyFileKt.myFunction
Supertype cascade after removing a depCannot access 'com.X.BaseClass' which is a supertype of 'SubClass' — even though BaseClass is never directly importedKotlin needs the full supertype chain of every used type. If you use SubClass (from dep Y) whose supertype BaseClass lives in dep X, removing X breaks compilation even without direct X imports. Fix: move the SubClass usage entirely into the EP implementation in the new module, and expose only a non-X return type (e.g. Language instead of PostCssLanguage) through the EP interface
Class hierarchy access fails after removing a depcannot access BaseClass: class file not foundSubclasses of platform types may transitively require the platform dep; keep it even without direct imports
Broad downstream breakage after large file moveMany unrelated modules fail to compileAfter moving 10+ files, build //plugins/... //contrib/... immediately to find all broken consumers
Two tests.cmd runs at onceA test that passes on its own fails, typically AllProductsPackagingTest#build; log shows Killing process containing subpath 'ide-tests'Run the required tests one at a time — each tests.cmd kills leftover ide-tests processes on startup, including a run still in flight

Examples in the JavaScript Plugin

  • intellij.javascript.regexp (Pattern A) — moved JSRegexpInjector, JSRegexpHost, JSRegExpModifierProvider out of javascript-backend to make the regexp dependency optional.

  • intellij.javascript.backend.css (Pattern B) — introduced JsCssIntegrationHelper EP in javascript-backend, implemented in the new module. Also moved JavaScriptCssUsagesProvider, JQueryCssElementDescriptorProvider, JQueryCssInspectionSuppressor. Downstream fixes required in javascript-ultimate, jsf-core, webpack.

  • intellij.javascript.backend.spellchecker (Pattern A) — moved all spellchecker-related files out of javascript-backend. Required visibility="public" because CoffeeScript plugin (a separate plugin) subclasses JSSpellcheckingStrategy — both the class and its inner tokenizer had to be marked open after Java→Kotlin conversion. javascript-grazie required a manual dep added outside the generated region.

  • intellij.javascript.backend.xml (Pattern A + B) — largest extraction to date (~40 files). Pattern A: moved all JSX/HTML/injection files wholesale. Pattern B: introduced JsXmlContextHelper EP (interface + static dispatch companion) for scattered instanceof XmlTag/XmlElement checks across ~60 core files. Required visibility="public". Downstream fixes required in javascript-ultimate, jsf-core, webpack, flex, vuejs, svelte, react and others. Note: not all XML IML deps could be removed from javascript-backend — some remained due to indirect class hierarchy usage.

Examples in the Vue Plugin

  • intellij.vuejs.backend.css (Pattern B, 3 EPs) — removed all CSS plugin dependencies from intellij.vuejs.backend. Three EPs introduced:
    1. VueCssLanguageProvider — exposes getCssLanguage(), getDefaultStyleLanguage(), getStyleCommenter(). Implemented by VueCssLanguageProviderImpl using CSSLanguage.INSTANCE, PostCssLanguage.INSTANCE, and PostCssCommentProvider. The getDefaultStyleLanguage()/getStyleCommenter() methods were needed because PostCssLanguage extends CssLanguageProperties (supertype cascade): even removing a direct PostCssLanguage reference left the compiler needing intellij.css.common. The fix was to move all PostCssLanguage usage into the EP implementation and return Language (not PostCssLanguage) across the boundary.
    2. VueCssExtractHelper — multi-method lifecycle EP using opaque Any? state. captureUnusedStyles(file): Any? returns a List<CssSelectorSuffix> opaquely; optimizeStyles(file, state: Any?) casts it back with @Suppress("UNCHECKED_CAST") inside the impl. This kept CssSelectorSuffix (from intellij.css.analysis) entirely within the CSS module.
    3. VueCssBindingHelper — single-method EP wrapping CssClassInJSLiteralOrIdentifierReferenceProvider.getClassesFromEmbeddedContent() to remove the intellij.javascript.web.css dep from the host.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

actions

무료요약 있음

IntelliJ `AnAction` 클래스를 구현하거나 수정하고 `plugin.xml`에 등록하도록 안내합니다. 표시 이름과 설명은 메시지 번들에 두고, 필요하면 아이콘을 설정하며, 이벤트 코루틴 범위에서 중단 함수를 실행해 동기식 처리로 IDE가 멈추는 일을 방지합니다.

  • IDE 메뉴에 새 동작 추가
  • 동작 등록이나 아이콘 변경
  • 동작 이름과 설명 정리
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

bazel-test-migration

무료요약 있음

IntelliJ JPS 테스트 모듈을 Bazel로 옮기고 Bazel에서만 발생하는 실패를 조사하는 안내서입니다. 의존성, 플러그인, 테스트 데이터와 runfiles 문제를 확인하고 생성된 대상과 이전된 테스트를 검증합니다.

  • 기존 JPS 테스트 모듈을 Bazel로 이전할 때
  • Bazel에서만 실패하는 테스트를 조사할 때
  • 테스트 의존성과 데이터 설정을 확인할 때
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

code-style

무료요약 있음

IntelliJ 프로젝트 규칙에 맞춰 Kotlin과 Java 코드를 작성하거나 검토합니다. 언어 선택, 서식, 봉인 타입, 스레드 주석, 제어 흐름 예외 처리를 확인합니다.

  • IntelliJ 규칙에 맞는 Kotlin 작성
  • Java 코드 검토
  • 예외 처리와 봉인 타입 분기 확인
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

commits

무료요약 있음

이 가이드는 IntelliJ 프로젝트의 변경 사항을 목적별로 나누고 프로젝트 형식에 맞는 커밋 메시지를 작성하도록 돕습니다. 티켓이 있으면 번호와 변경 설명을, 없으면 레이블과 하위 시스템명을 사용하며 필요에 따라 이유와 판단을 본문에 담습니다.

  • 티켓이 있는 변경의 프로젝트 형식 메시지 작성
  • 테스트나 문서 커밋에 적절한 레이블 적용
  • 기존 커밋 메시지를 규칙에 맞게 수정
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

compare-python-typecheckers

무료요약 있음

여러 Python 타입 검사기로 코드 조각이나 파일의 타입 추론과 오류 판정을 비교합니다. 도구별 결과, 실행 시간, 진단 내용을 Markdown 보고서로 모아 저장할 수 있습니다.

  • 검사기별 타입 추론 비교
  • 코드가 타입 오류로 판정되는지 확인
  • 여러 도구의 진단 결과 비교
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

compose-ui-architecture

무료요약 있음

Compose Desktop 화면을 구성할 때 컴포저블은 렌더링을 맡고 프레젠터나 코디네이터는 앱 결정을 맡도록 구조를 정리합니다. 상태 소유권, Effect, 재사용 컴포넌트 API, 지연 목록 키, 애니메이션과 성능을 개별 UI 변경에 맞춰 살펴봅니다.

  • 화면 렌더링과 프레젠터 판단 분리
  • UI 상태를 둘 위치 정리
  • Effect 키와 코루틴 사용 검토
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

JetBrains의 스킬 모두 보기

이 스킬의 문제 신고