IJPL-244586 Exclude .worktrees in content roots of non-java modules

(cherry picked from commit 8ab64f379224e0487d7c6bae5b02cdcb60378d3e)

IJ-CR-218120

GitOrigin-RevId: eb3d171a32a70c06cdb4480a971c266caf07b36f
This commit is contained in:
Liudmila Kornilova
2026-08-17 11:31:11 +00:00
committed by intellij-monorepo-bot
parent cad67986c3
commit a7b268f9dc
3 changed files with 51 additions and 0 deletions
@@ -3,10 +3,14 @@ package com.intellij.workspaceModel.core.fileIndex
import com.intellij.openapi.application.readAction
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.platform.backend.workspace.workspaceModel
import com.intellij.platform.workspace.jps.entities.ModuleEntity
import com.intellij.platform.workspace.jps.entities.modifyModuleEntity
import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.junit5.RegistryKey
import com.intellij.testFramework.junit5.TestApplication
import com.intellij.testFramework.rules.ProjectModelExtension
import com.intellij.workspaceModel.ide.legacyBridge.impl.java.JAVA_MODULE_ENTITY_TYPE_ID
import com.intellij.workspaceModel.ide.registerProjectRoot
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions.assertFalse
@@ -34,6 +38,11 @@ class AutoExcludeWorkspaceFileIndexContributorTest {
@Test
fun `default excluded directories are not in content after project root entity is added`() = runBlocking {
projectModel.project.workspaceModel.update("convert module to java") {
it.modifyModuleEntity(it.entities(ModuleEntity::class.java).first()) {
type = JAVA_MODULE_ENTITY_TYPE_ID
}
}
val worktreesDir = projectModel.baseProjectDir.newVirtualDirectory("projectRoot/.worktrees")
val claudeWorktreesDir = projectModel.baseProjectDir.newVirtualDirectory("projectRoot/.claude/worktrees")
val srcDir = projectModel.baseProjectDir.newVirtualDirectory("projectRoot/src")
@@ -48,6 +57,24 @@ class AutoExcludeWorkspaceFileIndexContributorTest {
assertTrue(readAction { fileIndex.isInContent(srcDir) })
}
@Test
fun `default excluded directories are not in content after non-java module is added`() = runBlocking {
val moduleRoot = projectModel.baseProjectDir.newVirtualDirectory("moduleRoot")
val worktreesDir = projectModel.baseProjectDir.newVirtualDirectory("moduleRoot/.worktrees")
val claudeWorktreesDir = projectModel.baseProjectDir.newVirtualDirectory("moduleRoot/.claude/worktrees")
val srcDir = projectModel.baseProjectDir.newVirtualDirectory("moduleRoot/src")
assertFalse(readAction { fileIndex.isInContent(worktreesDir) })
assertFalse(readAction { fileIndex.isInContent(srcDir) })
val module = projectModel.createModule("nonJavaModule")
PsiTestUtil.addSourceContentToRoots(module, moduleRoot)
assertFalse(readAction { fileIndex.isInContent(worktreesDir) })
assertFalse(readAction { fileIndex.isInContent(claudeWorktreesDir) })
assertTrue(readAction { fileIndex.isInContent(srcDir) })
}
@Test
@RegistryKey(key = "ide.workspace.model.relative.paths.to.exclude.automatically", value = "custom-dir")
fun `custom registry value specifies which directories to exclude`() = runBlocking {
@@ -15,6 +15,7 @@
<backgroundPostStartupActivity implementation="com.intellij.workspaceModel.ide.impl.VirtualFileUrlsLazyInitializer"/>
<workspaceModel.fileIndexContributor implementation="com.intellij.workspaceModel.ide.ProjectRootEntityWorkspaceFileIndexContributor"/>
<workspaceModel.fileIndexContributor implementation="com.intellij.workspaceModel.ide.AutoExcludeWorkspaceFileIndexContributor"/>
<workspaceModel.fileIndexContributor implementation="com.intellij.workspaceModel.ide.AutoExcludeInContentRootsWorkspaceFileIndexContributor"/>
</extensions>
<applicationListeners>
<listener class="com.intellij.workspaceModel.ide.impl.GlobalWorkspaceModelSeparationListener"
@@ -2,7 +2,10 @@
package com.intellij.workspaceModel.ide
import com.intellij.openapi.util.registry.Registry
import com.intellij.platform.workspace.jps.entities.ContentRootEntity
import com.intellij.platform.workspace.jps.entities.ModuleEntity
import com.intellij.platform.workspace.storage.EntityStorage
import com.intellij.workspaceModel.core.fileIndex.DependencyDescription
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileIndexContributor
import com.intellij.workspaceModel.core.fileIndex.WorkspaceFileSetRegistrar
@@ -22,3 +25,23 @@ internal class AutoExcludeWorkspaceFileIndexContributor : WorkspaceFileIndexCont
}
}
}
internal class AutoExcludeInContentRootsWorkspaceFileIndexContributor : WorkspaceFileIndexContributor<ContentRootEntity> {
override val entityClass: Class<ContentRootEntity>
get() = ContentRootEntity::class.java
override val dependenciesOnOtherEntities: List<DependencyDescription<ContentRootEntity>>
get() = listOf(DependencyDescription.OnParent(ModuleEntity::class.java) { it.contentRoots.asSequence() })
override fun registerFileSets(entity: ContentRootEntity, registrar: WorkspaceFileSetRegistrar, storage: EntityStorage) {
val directories = Registry.get("ide.workspace.model.relative.paths.to.exclude.automatically").asString()
.split(";").map { it.trim() }.filter { it.isNotEmpty() && it != "." }
if (entity.module.type?.name != "JAVA_MODULE") { // There can be too many java modules in a project. Also, java projects should be covered by ProjectRootEntity
for (dir in directories) {
registrar.registerExcludedRoot(entity.url.append(dir), entity)
}
}
}
}