IDEA-302307 store ignored projects in workspace model

GitOrigin-RevId: 6870d87b4f8aa97bc0beb903a5e75a2a5c8792fb
This commit is contained in:
Dmitry Kichinsky
2022-12-09 16:38:35 +01:00
committed by intellij-monorepo-bot
parent 2c0d2d085c
commit a04f470dfc
10 changed files with 290 additions and 40 deletions

View File

@@ -5,6 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/gen" isTestSource="false" generated="true" />
<excludeFolder url="file://$MODULE_DIR$/out" />
</content>
<orderEntry type="inheritedJdk" />

View File

@@ -0,0 +1,221 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.maven.importing.workspaceModel
import com.intellij.workspaceModel.storage.EntityInformation
import com.intellij.workspaceModel.storage.EntitySource
import com.intellij.workspaceModel.storage.EntityStorage
import com.intellij.workspaceModel.storage.GeneratedCodeApiVersion
import com.intellij.workspaceModel.storage.GeneratedCodeImplVersion
import com.intellij.workspaceModel.storage.MutableEntityStorage
import com.intellij.workspaceModel.storage.WorkspaceEntity
import com.intellij.workspaceModel.storage.impl.ConnectionId
import com.intellij.workspaceModel.storage.impl.ModifiableWorkspaceEntityBase
import com.intellij.workspaceModel.storage.impl.UsedClassesCollector
import com.intellij.workspaceModel.storage.impl.WorkspaceEntityBase
import com.intellij.workspaceModel.storage.impl.WorkspaceEntityData
import com.intellij.workspaceModel.storage.impl.containers.MutableWorkspaceList
import com.intellij.workspaceModel.storage.impl.containers.toMutableWorkspaceList
@GeneratedCodeApiVersion(1)
@GeneratedCodeImplVersion(1)
open class MavenProjectsTreeSettingsEntityImpl(val dataSource: MavenProjectsTreeSettingsEntityData) : MavenProjectsTreeSettingsEntity, WorkspaceEntityBase() {
companion object {
val connections = listOf<ConnectionId>(
)
}
override val ignoredFilePaths: List<String>
get() = dataSource.ignoredFilePaths
override val entitySource: EntitySource
get() = dataSource.entitySource
override fun connectionIdList(): List<ConnectionId> {
return connections
}
class Builder(result: MavenProjectsTreeSettingsEntityData?) : ModifiableWorkspaceEntityBase<MavenProjectsTreeSettingsEntity, MavenProjectsTreeSettingsEntityData>(
result), MavenProjectsTreeSettingsEntity.Builder {
constructor() : this(MavenProjectsTreeSettingsEntityData())
override fun applyToBuilder(builder: MutableEntityStorage) {
if (this.diff != null) {
if (existsInBuilder(builder)) {
this.diff = builder
return
}
else {
error("Entity MavenProjectsTreeSettingsEntity is already created in a different builder")
}
}
this.diff = builder
this.snapshot = builder
addToBuilder()
this.id = getEntityData().createEntityId()
// After adding entity data to the builder, we need to unbind it and move the control over entity data to builder
// Builder may switch to snapshot at any moment and lock entity data to modification
this.currentEntityData = null
// Process linked entities that are connected without a builder
processLinkedEntities(builder)
checkInitialization() // TODO uncomment and check failed tests
}
fun checkInitialization() {
val _diff = diff
if (!getEntityData().isEntitySourceInitialized()) {
error("Field WorkspaceEntity#entitySource should be initialized")
}
if (!getEntityData().isIgnoredFilePathsInitialized()) {
error("Field MavenProjectsTreeSettingsEntity#ignoredFilePaths should be initialized")
}
}
override fun connectionIdList(): List<ConnectionId> {
return connections
}
override fun afterModification() {
val collection_ignoredFilePaths = getEntityData().ignoredFilePaths
if (collection_ignoredFilePaths is MutableWorkspaceList<*>) {
collection_ignoredFilePaths.cleanModificationUpdateAction()
}
}
// Relabeling code, move information from dataSource to this builder
override fun relabel(dataSource: WorkspaceEntity, parents: Set<WorkspaceEntity>?) {
dataSource as MavenProjectsTreeSettingsEntity
if (this.entitySource != dataSource.entitySource) this.entitySource = dataSource.entitySource
if (this.ignoredFilePaths != dataSource.ignoredFilePaths) this.ignoredFilePaths = dataSource.ignoredFilePaths.toMutableList()
if (parents != null) {
}
}
override var entitySource: EntitySource
get() = getEntityData().entitySource
set(value) {
checkModificationAllowed()
getEntityData(true).entitySource = value
changedProperty.add("entitySource")
}
private val ignoredFilePathsUpdater: (value: List<String>) -> Unit = { value ->
changedProperty.add("ignoredFilePaths")
}
override var ignoredFilePaths: MutableList<String>
get() {
val collection_ignoredFilePaths = getEntityData().ignoredFilePaths
if (collection_ignoredFilePaths !is MutableWorkspaceList) return collection_ignoredFilePaths
if (diff == null || modifiable.get()) {
collection_ignoredFilePaths.setModificationUpdateAction(ignoredFilePathsUpdater)
}
else {
collection_ignoredFilePaths.cleanModificationUpdateAction()
}
return collection_ignoredFilePaths
}
set(value) {
checkModificationAllowed()
getEntityData(true).ignoredFilePaths = value
ignoredFilePathsUpdater.invoke(value)
}
override fun getEntityClass(): Class<MavenProjectsTreeSettingsEntity> = MavenProjectsTreeSettingsEntity::class.java
}
}
class MavenProjectsTreeSettingsEntityData : WorkspaceEntityData<MavenProjectsTreeSettingsEntity>() {
lateinit var ignoredFilePaths: MutableList<String>
fun isIgnoredFilePathsInitialized(): Boolean = ::ignoredFilePaths.isInitialized
override fun wrapAsModifiable(diff: MutableEntityStorage): WorkspaceEntity.Builder<MavenProjectsTreeSettingsEntity> {
val modifiable = MavenProjectsTreeSettingsEntityImpl.Builder(null)
modifiable.diff = diff
modifiable.snapshot = diff
modifiable.id = createEntityId()
return modifiable
}
override fun createEntity(snapshot: EntityStorage): MavenProjectsTreeSettingsEntity {
return getCached(snapshot) {
val entity = MavenProjectsTreeSettingsEntityImpl(this)
entity.snapshot = snapshot
entity.id = createEntityId()
entity
}
}
override fun clone(): MavenProjectsTreeSettingsEntityData {
val clonedEntity = super.clone()
clonedEntity as MavenProjectsTreeSettingsEntityData
clonedEntity.ignoredFilePaths = clonedEntity.ignoredFilePaths.toMutableWorkspaceList()
return clonedEntity
}
override fun getEntityInterface(): Class<out WorkspaceEntity> {
return MavenProjectsTreeSettingsEntity::class.java
}
override fun serialize(ser: EntityInformation.Serializer) {
}
override fun deserialize(de: EntityInformation.Deserializer) {
}
override fun createDetachedEntity(parents: List<WorkspaceEntity>): WorkspaceEntity {
return MavenProjectsTreeSettingsEntity(ignoredFilePaths, entitySource) {
}
}
override fun getRequiredParents(): List<Class<out WorkspaceEntity>> {
val res = mutableListOf<Class<out WorkspaceEntity>>()
return res
}
override fun equals(other: Any?): Boolean {
if (other == null) return false
if (this.javaClass != other.javaClass) return false
other as MavenProjectsTreeSettingsEntityData
if (this.entitySource != other.entitySource) return false
if (this.ignoredFilePaths != other.ignoredFilePaths) return false
return true
}
override fun equalsIgnoringEntitySource(other: Any?): Boolean {
if (other == null) return false
if (this.javaClass != other.javaClass) return false
other as MavenProjectsTreeSettingsEntityData
if (this.ignoredFilePaths != other.ignoredFilePaths) return false
return true
}
override fun hashCode(): Int {
var result = entitySource.hashCode()
result = 31 * result + ignoredFilePaths.hashCode()
return result
}
override fun hashCodeIgnoringEntitySource(): Int {
var result = javaClass.hashCode()
result = 31 * result + ignoredFilePaths.hashCode()
return result
}
override fun collectClassUsagesData(collector: UsedClassesCollector) {
this.ignoredFilePaths?.let { collector.add(it::class.java) }
collector.sameForAllEntities = false
}
}

View File

@@ -22,13 +22,12 @@ interface MavenProjectImporter {
fun createImporter(project: Project,
projectsTree: MavenProjectsTree,
projectsToImportWithChanges: Map<MavenProject, MavenProjectChanges>,
newlyIgnoredProjects: Collection<MavenProject>,
importModuleGroupsRequired: Boolean,
modelsProvider: IdeModifiableModelsProvider,
importingSettings: MavenImportingSettings,
previewModule: Module?,
importingActivity: StructuredIdeActivity): MavenProjectImporter {
val importer = createImporter(project, projectsTree, projectsToImportWithChanges, newlyIgnoredProjects,
val importer = createImporter(project, projectsTree, projectsToImportWithChanges,
importModuleGroupsRequired, modelsProvider, importingSettings, previewModule)
return object : MavenProjectImporter {
override fun importProject(): List<MavenProjectsProcessorTask>? {
@@ -56,13 +55,12 @@ interface MavenProjectImporter {
private fun createImporter(project: Project,
projectsTree: MavenProjectsTree,
projectsToImportWithChanges: Map<MavenProject, MavenProjectChanges>,
newlyIgnoredProjects: Collection<MavenProject>,
importModuleGroupsRequired: Boolean,
modelsProvider: IdeModifiableModelsProvider,
importingSettings: MavenImportingSettings,
previewModule: Module?): MavenProjectImporter {
if (isImportToWorkspaceModelEnabled(project)) {
return WorkspaceProjectImporter(projectsTree, projectsToImportWithChanges, newlyIgnoredProjects,
return WorkspaceProjectImporter(projectsTree, projectsToImportWithChanges,
importingSettings, modelsProvider, project)
}
@@ -73,7 +71,6 @@ interface MavenProjectImporter {
return MavenProjectLegacyImporter(project, projectsTree,
projectsToImportWithChanges,
newlyIgnoredProjects,
importModuleGroupsRequired,
modelsProvider, importingSettings,
previewModule)

View File

@@ -50,18 +50,15 @@ class MavenProjectLegacyImporter extends MavenProjectImporterLegacyBase {
private final Map<MavenProject, Module> myMavenProjectToModule = new HashMap<>();
private final Map<MavenProject, String> myMavenProjectToModuleName = new HashMap<>();
private final Map<MavenProject, String> myMavenProjectToModulePath = new HashMap<>();
private final Collection<MavenProject> myNewlyIgnoredProjects;
MavenProjectLegacyImporter(@NotNull Project p,
@NotNull MavenProjectsTree projectsTree,
@NotNull Map<MavenProject, MavenProjectChanges> projectsToImportWithChanges,
@NotNull Collection<MavenProject> newlyIgnoredProjects,
boolean importModuleGroupsRequired,
@NotNull IdeModifiableModelsProvider modelsProvider,
@NotNull MavenImportingSettings importingSettings,
@Nullable Module previewModule) {
super(p, projectsTree, importingSettings, projectsToImportWithChanges, modelsProvider);
myNewlyIgnoredProjects = newlyIgnoredProjects;
myFileToModuleMapping = getFileToModuleMapping(p, previewModule, modelsProvider);
myImportModuleGroupsRequired = importModuleGroupsRequired;
myPreviewModule = previewModule;
@@ -284,11 +281,6 @@ class MavenProjectLegacyImporter extends MavenProjectImporterLegacyBase {
if (obsoleteModules.isEmpty()) {
return false;
}
var myNewlyIgnoredModules = ContainerUtil.map(myNewlyIgnoredProjects, mavenProject -> myMavenProjectToModule.get(mavenProject));
// don't ask about module deletion if it was explicitly deleted by the user in project view or project structure
if (myNewlyIgnoredModules.containsAll(obsoleteModules)) {
return true;
}
if (!ApplicationManager.getApplication().isHeadlessEnvironment() || MavenUtil.isMavenUnitTestModeEnabled()) {
final int[] result = new int[1];
MavenUtil.invokeAndWait(myProject, myModelsProvider.getModalityStateForQuestionDialogs(),

View File

@@ -60,7 +60,6 @@ var WORKSPACE_IMPORTER_SKIP_FAST_APPLY_ATTEMPTS_ONCE = false
internal class WorkspaceProjectImporter(
private val myProjectsTree: MavenProjectsTree,
private val projectsToImportWithChanges: Map<MavenProject, MavenProjectChanges>,
private val newlyIgnoredProjects: Collection<MavenProject>,
private val myImportingSettings: MavenImportingSettings,
private val myModifiableModelsProvider: IdeModifiableModelsProvider,
private val myProject: Project
@@ -73,7 +72,7 @@ internal class WorkspaceProjectImporter(
val storageBeforeImport = WorkspaceModel.getInstance(myProject).entityStorage.current
var (hasChanges, projectToImport) = collectProjectsAndChanges(storageBeforeImport, projectsToImportWithChanges)
var (hasChanges, projectToImport, ignoredFilePaths) = collectProjectsAndChanges(storageBeforeImport, projectsToImportWithChanges)
val externalStorageManager = myProject.getService(ExternalStorageConfigurationManager::class.java)
if (!externalStorageManager.isEnabled) {
@@ -100,6 +99,8 @@ internal class WorkspaceProjectImporter(
val mavenProjectToModuleName = buildModuleNameMap(projectToImport)
val builder = MutableEntityStorage.create()
builder.addEntity(MavenProjectsTreeSettingsEntity(ignoredFilePaths, MavenProjectsTreeEntitySource))
val contextData = UserDataHolderBase()
val projectsWithModuleEntities = stats.recordPhase(MavenImportCollector.WORKSPACE_POPULATE_PHASE) {
@@ -136,7 +137,8 @@ internal class WorkspaceProjectImporter(
}
private fun collectProjectsAndChanges(storageBeforeImport: EntityStorage,
originalProjectsChanges: Map<MavenProject, MavenProjectChanges>): Pair<Boolean, Map<MavenProject, MavenProjectChanges>> {
originalProjectsChanges: Map<MavenProject, MavenProjectChanges>):
Triple<Boolean, Map<MavenProject, MavenProjectChanges>, List<String>> {
val projectFilesFromPreviousImport = readMavenExternalSystemData(storageBeforeImport)
.mapTo(FileCollectionFactory.createCanonicalFilePathSet()) { it.mavenProjectFilePath }
@@ -147,13 +149,17 @@ internal class WorkspaceProjectImporter(
if (newProjectToImport) MavenProjectChanges.ALL else originalProjectsChanges.getOrDefault(it, MavenProjectChanges.NONE)
}
var hasChanges = allProjectToImport.values.any { it.hasChanges() } || !newlyIgnoredProjects.isEmpty()
val ignoredFilePaths = myProjectsTree.ignoredFilesPaths
var hasChanges = allProjectToImport.values.any { it.hasChanges() }
if (!hasChanges) {
// check for a situation, when we have a newly ignored project, but no other changes
val listOfProjectChanged = allProjectToImport.size != projectFilesFromPreviousImport.size
hasChanges = listOfProjectChanged
val mavenProjectsTreeSettingsEntity = storageBeforeImport.entities(MavenProjectsTreeSettingsEntity::class.java).firstOrNull()
val storedIgnoredFilePaths = mavenProjectsTreeSettingsEntity?.ignoredFilePaths ?: listOf()
val ignoredProjectsChanged = storedIgnoredFilePaths != ignoredFilePaths
hasChanges = ignoredProjectsChanged
}
return hasChanges to allProjectToImport
return Triple(hasChanges, allProjectToImport, ignoredFilePaths)
}
private fun buildModuleNameMap(projectToImport: Map<MavenProject, MavenProjectChanges>): HashMap<MavenProject, String> {
@@ -293,6 +299,8 @@ internal class WorkspaceProjectImporter(
currentStorage.replaceBySource({ isMavenEntity(it) }, newStorage)
currentStorage.replaceBySource({ it is MavenProjectsTreeEntitySource }, newStorage)
// Now we have some modules with duplicating content roots. One content root existed before and another one exported from maven.
// We need to move source roots and excludes from existing content roots to the exported content roots and remove (obsolete) existing.
modulesWithDuplicatingRoots.asSequence()

View File

@@ -0,0 +1,42 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.maven.importing.workspaceModel
import com.intellij.workspaceModel.storage.EntitySource
import com.intellij.workspaceModel.storage.GeneratedCodeApiVersion
import com.intellij.workspaceModel.storage.MutableEntityStorage
import com.intellij.workspaceModel.storage.WorkspaceEntity
import com.intellij.workspaceModel.storage.impl.containers.toMutableWorkspaceList
import org.jetbrains.deft.ObjBuilder
import org.jetbrains.deft.Type
object MavenProjectsTreeEntitySource : EntitySource
interface MavenProjectsTreeSettingsEntity: WorkspaceEntity {
val ignoredFilePaths: List<String>
//region generated code
@GeneratedCodeApiVersion(1)
interface Builder : MavenProjectsTreeSettingsEntity, WorkspaceEntity.Builder<MavenProjectsTreeSettingsEntity>, ObjBuilder<MavenProjectsTreeSettingsEntity> {
override var entitySource: EntitySource
override var ignoredFilePaths: MutableList<String>
}
companion object : Type<MavenProjectsTreeSettingsEntity, Builder>() {
operator fun invoke(ignoredFilePaths: List<String>,
entitySource: EntitySource,
init: (Builder.() -> Unit)? = null): MavenProjectsTreeSettingsEntity {
val builder = builder()
builder.ignoredFilePaths = ignoredFilePaths.toMutableWorkspaceList()
builder.entitySource = entitySource
init?.invoke(builder)
return builder
}
}
//endregion
}
//region generated code
fun MutableEntityStorage.modifyEntity(entity: MavenProjectsTreeSettingsEntity,
modification: MavenProjectsTreeSettingsEntity.Builder.() -> Unit) = modifyEntity(
MavenProjectsTreeSettingsEntity.Builder::class.java, entity, modification)
//endregion

View File

@@ -110,8 +110,6 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
private MavenMergingUpdateQueue myImportingQueue;
private final Object myImportingDataLock = new Object();
private final Map<MavenProject, MavenProjectChanges> myProjectsToImport = new LinkedHashMap<>();
private final Collection<MavenProject> myProjectsScheduledToIgnore = new HashSet<>();
private final Set<MavenProject> myProjectsToResolve = new LinkedHashSet<>();
private boolean myImportModuleGroupsRequired = false;
@@ -884,13 +882,6 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
return myProjectsTree.isIgnored(project);
}
public void scheduleMavenProjectsToIgnore(@NotNull Set<MavenProject> mavenProjects) {
if (mavenProjects.isEmpty()) return;
myProjectsScheduledToIgnore.addAll(mavenProjects);
importProjects();
}
public Set<MavenRemoteRepository> getRemoteRepositories() {
Set<MavenRemoteRepository> result = new HashSet<>();
for (MavenProject each : getProjects()) {
@@ -1384,13 +1375,10 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
public List<Module> importProjects(final IdeModifiableModelsProvider modelsProvider) {
final Map<MavenProject, MavenProjectChanges> projectsToImportWithChanges;
final List <MavenProject> projectsScheduledToIgnore;
final boolean importModuleGroupsRequired;
synchronized (myImportingDataLock) {
projectsToImportWithChanges = Collections.unmodifiableMap(new LinkedHashMap<>(myProjectsToImport));
myProjectsToImport.clear();
projectsScheduledToIgnore = Collections.unmodifiableList(new ArrayList<>(myProjectsScheduledToIgnore));
myProjectsScheduledToIgnore.clear();
importModuleGroupsRequired = myImportModuleGroupsRequired;
myImportModuleGroupsRequired = false;
}
@@ -1403,9 +1391,8 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
Collections.singletonList(ProjectImportCollector.TASK_CLASS.with(MavenImportStats.ImportingTaskOld.class))
);
try {
myProjectsTree.setIgnoredState(projectsScheduledToIgnore, true, true);
MavenProjectImporter projectImporter = MavenProjectImporter.createImporter(
myProject, myProjectsTree, projectsToImportWithChanges, projectsScheduledToIgnore, importModuleGroupsRequired,
myProject, myProjectsTree, projectsToImportWithChanges, importModuleGroupsRequired,
modelsProvider, getImportingSettings(), myPreviewModule, activity
);
importer.set(projectImporter);

View File

@@ -10,7 +10,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
/**
@@ -21,7 +21,7 @@ public class MavenModuleDeleteProvider extends ModuleDeleteProvider {
protected void doDetachModules(@NotNull Project project,
Module @Nullable [] modules,
@Nullable List<? extends UnloadedModuleDescription> unloadedModules) {
var mavenProjectsToIgnore = new HashSet<MavenProject>();
var mavenProjectsToIgnore = new ArrayList<MavenProject>();
var projectsManager = MavenProjectsManager.getInstance(project);
if (null != modules) {
for (var module : modules) {
@@ -34,6 +34,6 @@ public class MavenModuleDeleteProvider extends ModuleDeleteProvider {
super.doDetachModules(project, modules, unloadedModules);
projectsManager.scheduleMavenProjectsToIgnore(mavenProjectsToIgnore);
projectsManager.setIgnoredState(mavenProjectsToIgnore, true);
}
}

View File

@@ -290,7 +290,7 @@ class MavenImportFlow {
val projectImporter = MavenProjectImporter.createImporter(context.project, context.readContext.projectsTree,
context.projectsToImport.map {
it to MavenProjectChanges.ALL
}.toMap(), emptySet(),
}.toMap(),
context.initialContext.importingSettings.isCreateModuleGroups,
modelsProvider, context.initialContext.importingSettings,
context.initialContext.previewModule, importingActivity)

View File

@@ -7,12 +7,14 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureEx
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MavenModuleStructureExtension extends ModuleStructureExtension {
private final Set<Module> myModulesToRemove = new HashSet<>();
private final Set<MavenProject> myMavenProjectsToIgnore = new HashSet<>();
private final List<MavenProject> myMavenProjectsToIgnore = new ArrayList<>();
private MavenProjectsManager myMavenProjectsManager = null;
@Override
@@ -42,7 +44,7 @@ public class MavenModuleStructureExtension extends ModuleStructureExtension {
@Override
public void disposeUIResources() {
if (null != myMavenProjectsManager) {
myMavenProjectsManager.scheduleMavenProjectsToIgnore(myMavenProjectsToIgnore);
myMavenProjectsManager.setIgnoredState(myMavenProjectsToIgnore, true);
}
myModulesToRemove.clear();