mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
[externalSystem] SourceFolderManagerImpl is a project service
GitOrigin-RevId: d85162ebcfdab24bfdddd671d1e94e9cd8695ad7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
63f819bc5b
commit
117f72d8a2
@@ -11,8 +11,8 @@ import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
|
||||
@ApiStatus.Experimental
|
||||
public interface SourceFolderManager {
|
||||
|
||||
static SourceFolderManager getInstance(@NotNull Project project) {
|
||||
return project.getComponent(SourceFolderManager.class);
|
||||
static @NotNull SourceFolderManager getInstance(@NotNull Project project) {
|
||||
return project.getService(SourceFolderManager.class);
|
||||
}
|
||||
|
||||
void setSourceFolderPackagePrefix(@NotNull String url, @Nullable String packagePrefix);
|
||||
@@ -22,4 +22,7 @@ public interface SourceFolderManager {
|
||||
void addSourceFolder(@NotNull Module module, @NotNull String url, @NotNull JpsModuleSourceRootType<?> type);
|
||||
|
||||
void removeSourceFolders(@NotNull Module module);
|
||||
|
||||
@ApiStatus.Internal
|
||||
void rescanAndUpdateSourceFolders();
|
||||
}
|
||||
|
||||
@@ -2,10 +2,4 @@
|
||||
<xi:include href="ExternalSystemExtensionPoints.xml"/>
|
||||
<xi:include href="ExternalSystemExtensions.xml"/>
|
||||
<xi:include href="ExternalSystemActions.xml"/>
|
||||
<project-components>
|
||||
<component>
|
||||
<interface-class>com.intellij.openapi.externalSystem.service.project.manage.SourceFolderManager</interface-class>
|
||||
<implementation-class>com.intellij.openapi.externalSystem.service.project.manage.SourceFolderManagerImpl</implementation-class>
|
||||
</component>
|
||||
</project-components>
|
||||
</idea-plugin>
|
||||
@@ -14,7 +14,7 @@
|
||||
implementation="com.intellij.openapi.externalSystem.service.notification.ExternalSystemNotificationExtensionImpl"/>
|
||||
|
||||
<module.workingDirectoryProvider
|
||||
implementation="com.intellij.openapi.externalSystem.service.project.ExternalSystemWorkingDirectoryProvider"/>
|
||||
implementation="com.intellij.openapi.externalSystem.service.project.ExternalSystemWorkingDirectoryProvider"/>
|
||||
<applicationService serviceInterface="com.intellij.openapi.externalSystem.util.environment.Environment"
|
||||
serviceImplementation="com.intellij.openapi.externalSystem.util.environment.SystemEnvironment"/>
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
<search.optionContributor
|
||||
implementation="com.intellij.openapi.externalSystem.service.settings.ExternalSystemGroupSearchableContributor"/>
|
||||
|
||||
<projectService serviceInterface="com.intellij.openapi.externalSystem.service.project.manage.SourceFolderManager"
|
||||
serviceImplementation="com.intellij.openapi.externalSystem.service.project.manage.SourceFolderManagerImpl"/>
|
||||
|
||||
<!--Auto-reload-->
|
||||
<projectService serviceInterface="com.intellij.openapi.externalSystem.autoimport.ExternalSystemProjectTracker"
|
||||
serviceImplementation="com.intellij.openapi.externalSystem.autoimport.AutoImportProjectTracker"/>
|
||||
@@ -136,6 +139,12 @@
|
||||
<listener class="com.intellij.openapi.externalSystem.service.project.ExternalSystemTrustedListener"
|
||||
topic="com.intellij.ide.impl.TrustStateListener"
|
||||
activeInHeadlessMode="false" activeInTestMode="false"/>
|
||||
<listener class="com.intellij.openapi.externalSystem.service.project.manage.SourceFolderManagerImpl$BulkFileListenerImpl"
|
||||
topic="com.intellij.openapi.vfs.newvfs.BulkFileListener"
|
||||
activeInHeadlessMode="true" activeInTestMode="true"/>
|
||||
<listener class="com.intellij.openapi.externalSystem.service.project.manage.SourceFolderManagerImpl$ModuleListenerImpl"
|
||||
topic="com.intellij.openapi.project.ModuleListener"
|
||||
activeInHeadlessMode="true" activeInTestMode="true"/>
|
||||
</applicationListeners>
|
||||
</idea-plugin>
|
||||
|
||||
|
||||
@@ -3,21 +3,25 @@ package com.intellij.openapi.externalSystem.service.project.manage
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.thisLogger
|
||||
import com.intellij.openapi.extensions.ExtensionNotApplicableException
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.ProjectPostStartupActivity
|
||||
|
||||
private class ReprocessContentRootDataActivity : ProjectPostStartupActivity {
|
||||
override suspend fun execute(project: Project) {
|
||||
|
||||
init {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||
return
|
||||
throw ExtensionNotApplicableException.create()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun execute(project: Project) {
|
||||
if (ExternalSystemUtil.isNewProject(project)) {
|
||||
thisLogger().info("Ignored reprocess of content root data service for new projects")
|
||||
return
|
||||
}
|
||||
|
||||
val instance = SourceFolderManager.getInstance(project) as SourceFolderManagerImpl
|
||||
instance.rescanAndUpdateSourceFolders()
|
||||
SourceFolderManager.getInstance(project).rescanAndUpdateSourceFolders()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.externalSystem.service.project.manage
|
||||
|
||||
import com.intellij.ProjectTopics
|
||||
import com.intellij.ide.projectView.actions.MarkRootActionBase
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
@@ -15,6 +14,7 @@ import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.ModuleListener
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.roots.ModifiableRootModel
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.roots.SourceFolder
|
||||
@@ -44,8 +44,11 @@ import org.jetbrains.jps.model.java.JavaSourceRootType
|
||||
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
|
||||
import java.util.concurrent.Future
|
||||
|
||||
@State(name = "sourceFolderManager", storages = [Storage(StoragePathMacros.CACHE_FILE)])
|
||||
class SourceFolderManagerImpl(private val project: Project) : SourceFolderManager, Disposable, PersistentStateComponent<SourceFolderManagerState> {
|
||||
@State(name = "sourceFolderManager", storages = [Storage(StoragePathMacros.CACHE_FILE)])
|
||||
class SourceFolderManagerImpl(private val project: Project) : SourceFolderManager,
|
||||
PersistentStateComponent<SourceFolderManagerState>,
|
||||
Disposable {
|
||||
|
||||
private val moduleNamesToSourceFolderState: MultiMap<String, SourceFolderModelState> = MultiMap.create()
|
||||
private var isDisposed = false
|
||||
private val mutex = Any()
|
||||
@@ -124,51 +127,69 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage
|
||||
val sourceFolders: MutableSet<String> = CollectionFactory.createFilePathSet()
|
||||
)
|
||||
|
||||
init {
|
||||
project.messageBus.connect().subscribe(VirtualFileManager.VFS_CHANGES, object : BulkFileListener {
|
||||
override fun after(events: List<VFileEvent>) {
|
||||
val sourceFoldersToChange = HashMap<Module, ArrayList<Pair<VirtualFile, SourceFolderModel>>>()
|
||||
val virtualFileManager = VirtualFileManager.getInstance()
|
||||
@Suppress("unused") // todo fix warning
|
||||
private class BulkFileListenerImpl : BulkFileListener {
|
||||
|
||||
for (event in events) {
|
||||
if (event !is VFileCreateEvent) {
|
||||
continue
|
||||
}
|
||||
val allDescendantValues = synchronized(mutex) { sourceFolders.getAllDescendantValues(VfsUtilCore.pathToUrl(event.path)) }
|
||||
for (sourceFolder in allDescendantValues) {
|
||||
val sourceFolderFile = virtualFileManager.refreshAndFindFileByUrl(sourceFolder.url)
|
||||
if (sourceFolderFile != null && sourceFolderFile.isValid) {
|
||||
sourceFoldersToChange.computeIfAbsent(sourceFolder.module) { ArrayList() }.add(Pair(event.file!!, sourceFolder))
|
||||
removeSourceFolder(sourceFolder.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
override fun after(events: List<VFileEvent>) {
|
||||
val fileCreateEvents = events.filterIsInstance<VFileCreateEvent>()
|
||||
if (fileCreateEvents.isEmpty()) return
|
||||
|
||||
val application = ApplicationManager.getApplication()
|
||||
val future = project.coroutineScope.async { updateSourceFolders(sourceFoldersToChange) }.asCompletableFuture()
|
||||
if (application.isUnitTestMode) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread()
|
||||
operationsStates.removeIf { it.isDone }
|
||||
operationsStates.add(future)
|
||||
}
|
||||
for (project in ProjectManager.getInstance().openProjects) {
|
||||
(SourceFolderManager.getInstance(project) as SourceFolderManagerImpl).filesCreated(fileCreateEvents)
|
||||
}
|
||||
})
|
||||
|
||||
project.messageBus.connect().subscribe(ProjectTopics.MODULES, object : ModuleListener {
|
||||
override fun modulesAdded(project: Project, modules: List<Module>) {
|
||||
synchronized(mutex) {
|
||||
for (module in modules) {
|
||||
moduleNamesToSourceFolderState[module.name].forEach {
|
||||
loadSourceFolderState(it, module)
|
||||
}
|
||||
moduleNamesToSourceFolderState.remove(module.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun rescanAndUpdateSourceFolders() {
|
||||
|
||||
@Suppress("unused") // todo fix warning
|
||||
private class ModuleListenerImpl : ModuleListener {
|
||||
|
||||
override fun modulesAdded(project: Project, modules: List<Module>) {
|
||||
(SourceFolderManager.getInstance(project) as SourceFolderManagerImpl).modulesAdded(modules)
|
||||
}
|
||||
}
|
||||
|
||||
private fun filesCreated(fileCreateEvents: List<VFileCreateEvent>) {
|
||||
val sourceFoldersToChange = mutableMapOf<Module, ArrayList<Pair<VirtualFile, SourceFolderModel>>>()
|
||||
val virtualFileManager = VirtualFileManager.getInstance()
|
||||
|
||||
for (event in fileCreateEvents) {
|
||||
val allDescendantValues = synchronized(mutex) {
|
||||
sourceFolders.getAllDescendantValues(VfsUtilCore.pathToUrl(event.path))
|
||||
}
|
||||
|
||||
for (sourceFolder in allDescendantValues) {
|
||||
val sourceFolderFile = virtualFileManager.refreshAndFindFileByUrl(sourceFolder.url)
|
||||
if (sourceFolderFile != null && sourceFolderFile.isValid) {
|
||||
sourceFoldersToChange.computeIfAbsent(sourceFolder.module) { ArrayList() }.add(Pair(event.file!!, sourceFolder))
|
||||
removeSourceFolder(sourceFolder.url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val application = ApplicationManager.getApplication()
|
||||
val future = project.coroutineScope.async {
|
||||
updateSourceFolders(sourceFoldersToChange)
|
||||
}.asCompletableFuture()
|
||||
|
||||
if (application.isUnitTestMode) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread()
|
||||
operationsStates.removeIf { it.isDone }
|
||||
operationsStates.add(future)
|
||||
}
|
||||
}
|
||||
|
||||
private fun modulesAdded(modules: List<Module>) {
|
||||
synchronized(mutex) {
|
||||
for (module in modules) {
|
||||
moduleNamesToSourceFolderState.remove(module.name)!!.forEach {
|
||||
loadSourceFolderState(it, module)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun rescanAndUpdateSourceFolders() {
|
||||
val sourceFoldersToChange = HashMap<Module, ArrayList<Pair<VirtualFile, SourceFolderModel>>>()
|
||||
val virtualFileManager = VirtualFileManager.getInstance()
|
||||
|
||||
@@ -254,6 +275,10 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage
|
||||
sourceFolders = PathPrefixTreeMap()
|
||||
sourceFoldersByModule = HashMap()
|
||||
|
||||
if (state.sourceFolders.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val moduleManager = ModuleManager.getInstance(project)
|
||||
|
||||
state.sourceFolders.forEach { model ->
|
||||
|
||||
Reference in New Issue
Block a user