<commit_before>/*
 * Use of this source code is governed by the MIT license that can be
 * found in the LICENSE file.
 */

package org.rust.cargo.project.model.impl

import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
import com.intellij.execution.RunManager
import com.intellij.ide.impl.isTrusted
import com.intellij.notification.NotificationType
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.application.invokeLater
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.components.*
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ex.ProjectEx
import com.intellij.openapi.roots.ContentEntry
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.roots.ProjectFileIndex
import com.intellij.openapi.roots.ex.ProjectRootManagerEx
import com.intellij.openapi.startup.StartupManager
import com.intellij.openapi.util.EmptyRunnable
import com.intellij.openapi.util.UserDataHolderBase
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager
import com.intellij.ui.GuiUtils
import com.intellij.util.indexing.LightDirectoryIndex
import com.intellij.util.io.exists
import com.intellij.util.io.systemIndependentPath
import org.jdom.Element
import org.jetbrains.annotations.TestOnly
import org.rust.cargo.CargoConstants
import org.rust.cargo.project.model.CargoProject
import org.rust.cargo.project.model.CargoProject.UpdateStatus
import org.rust.cargo.project.model.CargoProjectsService
import org.rust.cargo.project.model.CargoProjectsService.CargoProjectsListener
import org.rust.cargo.project.model.RustcInfo
import org.rust.cargo.project.model.setup
import org.rust.cargo.project.settings.RustProjectSettingsService
import org.rust.cargo.project.settings.RustProjectSettingsService.RustSettingsChangedEvent
import org.rust.cargo.project.settings.RustProjectSettingsService.RustSettingsListener
import org.rust.cargo.project.settings.rustSettings
import org.rust.cargo.project.toolwindow.CargoToolWindow.Companion.initializeToolWindow
import org.rust.cargo.project.workspace.*
import org.rust.cargo.runconfig.command.workingDirectory
import org.rust.cargo.toolchain.RsToolchainBase
import org.rust.cargo.util.AutoInjectedCrates
import org.rust.ide.notifications.showBalloon
import org.rust.ide.security.isNewTrustedProjectApiAvailable
import org.rust.ide.security.whenProjectTrusted
import org.rust.lang.RsFileType
import org.rust.lang.core.macros.macroExpansionManager
import org.rust.openapiext.TaskResult
import org.rust.openapiext.isUnitTestMode
import org.rust.openapiext.modules
import org.rust.openapiext.pathAsPath
import org.rust.stdext.AsyncValue
import org.rust.stdext.applyWithSymlink
import org.rust.stdext.exhaustive
import org.rust.stdext.mapNotNullToSet
import org.rust.taskQueue
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.CompletableFuture
import java.util.concurrent.atomic.AtomicReference


@State(name = "CargoProjects", storages = [
    Storage(StoragePathMacros.WORKSPACE_FILE),
    Storage("misc.xml", deprecated = true)
])
open class CargoProjectsServiceImpl(
    final override val project: Project
) : CargoProjectsService, PersistentStateComponent<Element>, Disposable {
    init {
        with(project.messageBus.connect()) {
            if (!isUnitTestMode) {
                subscribe(VirtualFileManager.VFS_CHANGES, CargoTomlWatcher(this@CargoProjectsServiceImpl, fun() {
                    if (!project.rustSettings.autoUpdateEnabled) return
                    refreshAllProjects()
                }))
            }

            subscribe(RustProjectSettingsService.RUST_SETTINGS_TOPIC, object : RustSettingsListener {
                override fun rustSettingsChanged(e: RustSettingsChangedEvent) {
                    if (e.affectsCargoMetadata) {
                        refreshAllProjects()
                    }
                }
            })

            subscribe(CargoProjectsService.CARGO_PROJECTS_TOPIC, CargoProjectsListener { _, _ ->
                StartupManager.getInstance(project).runAfterOpened {
                    GuiUtils.invokeLaterIfNeeded({
                        initializeToolWindow(project)
                    }, ModalityState.NON_MODAL)
                }
            })
        }
        // BACKCOMPAT: 2021.3. Just declare `com.intellij.ide.impl.TrustStateListener`
        //  instead of `org.rust.ide.security.RsTrustChangeNotifier`
        if (isNewTrustedProjectApiAvailable) {
            @Suppress("LeakingThis")
            whenProjectTrusted(this) {
                refreshAllProjects()
            }
        }
    }

    /**<commit_msg>Don't perform cargo refresh when another IDE project become trusted<commit_after>/*
 * Use of this source code is governed by the MIT license that can be
 * found in the LICENSE file.
 */

package org.rust.cargo.project.model.impl

import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
import com.intellij.execution.RunManager
import com.intellij.ide.impl.isTrusted
import com.intellij.notification.NotificationType
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.application.invokeLater
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.components.*
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ex.ProjectEx
import com.intellij.openapi.roots.ContentEntry
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.roots.ProjectFileIndex
import com.intellij.openapi.roots.ex.ProjectRootManagerEx
import com.intellij.openapi.startup.StartupManager
import com.intellij.openapi.util.EmptyRunnable
import com.intellij.openapi.util.UserDataHolderBase
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager
import com.intellij.ui.GuiUtils
import com.intellij.util.indexing.LightDirectoryIndex
import com.intellij.util.io.exists
import com.intellij.util.io.systemIndependentPath
import org.jdom.Element
import org.jetbrains.annotations.TestOnly
import org.rust.cargo.CargoConstants
import org.rust.cargo.project.model.CargoProject
import org.rust.cargo.project.model.CargoProject.UpdateStatus
import org.rust.cargo.project.model.CargoProjectsService
import org.rust.cargo.project.model.CargoProjectsService.CargoProjectsListener
import org.rust.cargo.project.model.RustcInfo
import org.rust.cargo.project.model.setup
import org.rust.cargo.project.settings.RustProjectSettingsService
import org.rust.cargo.project.settings.RustProjectSettingsService.RustSettingsChangedEvent
import org.rust.cargo.project.settings.RustProjectSettingsService.RustSettingsListener
import org.rust.cargo.project.settings.rustSettings
import org.rust.cargo.project.toolwindow.CargoToolWindow.Companion.initializeToolWindow
import org.rust.cargo.project.workspace.*
import org.rust.cargo.runconfig.command.workingDirectory
import org.rust.cargo.toolchain.RsToolchainBase
import org.rust.cargo.util.AutoInjectedCrates
import org.rust.ide.notifications.showBalloon
import org.rust.ide.security.isNewTrustedProjectApiAvailable
import org.rust.ide.security.whenProjectTrusted
import org.rust.lang.RsFileType
import org.rust.lang.core.macros.macroExpansionManager
import org.rust.openapiext.TaskResult
import org.rust.openapiext.isUnitTestMode
import org.rust.openapiext.modules
import org.rust.openapiext.pathAsPath
import org.rust.stdext.AsyncValue
import org.rust.stdext.applyWithSymlink
import org.rust.stdext.exhaustive
import org.rust.stdext.mapNotNullToSet
import org.rust.taskQueue
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.CompletableFuture
import java.util.concurrent.atomic.AtomicReference


@State(name = "CargoProjects", storages = [
    Storage(StoragePathMacros.WORKSPACE_FILE),
    Storage("misc.xml", deprecated = true)
])
open class CargoProjectsServiceImpl(
    final override val project: Project
) : CargoProjectsService, PersistentStateComponent<Element>, Disposable {
    init {
        with(project.messageBus.connect()) {
            if (!isUnitTestMode) {
                subscribe(VirtualFileManager.VFS_CHANGES, CargoTomlWatcher(this@CargoProjectsServiceImpl, fun() {
                    if (!project.rustSettings.autoUpdateEnabled) return
                    refreshAllProjects()
                }))
            }

            subscribe(RustProjectSettingsService.RUST_SETTINGS_TOPIC, object : RustSettingsListener {
                override fun rustSettingsChanged(e: RustSettingsChangedEvent) {
                    if (e.affectsCargoMetadata) {
                        refreshAllProjects()
                    }
                }
            })

            subscribe(CargoProjectsService.CARGO_PROJECTS_TOPIC, CargoProjectsListener { _, _ ->
                StartupManager.getInstance(project).runAfterOpened {
                    GuiUtils.invokeLaterIfNeeded({
                        initializeToolWindow(project)
                    }, ModalityState.NON_MODAL)
                }
            })
        }
        // BACKCOMPAT: 2021.3. Just declare `com.intellij.ide.impl.TrustStateListener`
        //  instead of `org.rust.ide.security.RsTrustChangeNotifier`
        if (isNewTrustedProjectApiAvailable) {
            @Suppress("LeakingThis")
            whenProjectTrusted(this) {
                if (it == project) {
                    refreshAllProjects()
                }
            }
        }
    }

    /**
{'fraction_non_alphanumeric': 0.08390197020663143, 'fraction_numerical': 0.0009610764055742432, 'mean_word_length': 3.894637817497648, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4941142', 'n_tokens_mistral': 3159, 'n_tokens_neox': 3044, 'n_words': 444}