fix "IDEA-221944 Deadlock on opening second project" and support preloading for proje...
[idea/community.git] / platform / lang-impl / src / com / intellij / openapi / roots / impl / ModuleRootManagerComponent.java
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.openapi.roots.impl;
3
4 import com.intellij.openapi.components.*;
5 import com.intellij.openapi.module.Module;
6 import com.intellij.openapi.module.impl.ModuleEx;
7 import com.intellij.openapi.roots.impl.libraries.LibraryTableBase;
8 import com.intellij.openapi.roots.impl.storage.ClassPathStorageUtil;
9 import com.intellij.openapi.roots.impl.storage.ClasspathStorage;
10 import com.intellij.openapi.roots.libraries.LibraryTable;
11 import com.intellij.openapi.util.registry.Registry;
12 import com.intellij.util.SmartList;
13 import org.jetbrains.annotations.NotNull;
14 import org.jetbrains.annotations.TestOnly;
15
16 import java.util.List;
17
18 /**
19  * @author yole
20  */
21 @State(
22   name = "NewModuleRootManager",
23   storages = {
24     @Storage(StoragePathMacros.MODULE_FILE),
25     @Storage(storageClass = ClasspathStorage.class)
26   },
27   // will be changed only on actual user change, so, to speed up module loading, disable
28   useLoadedStateAsExisting = false
29 )
30 public class ModuleRootManagerComponent extends ModuleRootManagerImpl implements
31                                                                       PersistentStateComponentWithModificationTracker<ModuleRootManagerImpl.ModuleRootManagerState>,
32                                                                       StateStorageChooserEx {
33   public ModuleRootManagerComponent(Module module) {
34     super(module);
35   }
36
37   @NotNull
38   @Override
39   public Resolution getResolution(@NotNull Storage storage, @NotNull StateStorageOperation operation) {
40     boolean isClasspathStorage = storage.storageClass() == ClasspathStorage.class;
41     boolean isEffectiveStorage = ClassPathStorageUtil.isClasspathStorage(getModule()) == isClasspathStorage;
42     if (operation == StateStorageOperation.READ) {
43       return isEffectiveStorage ? Resolution.DO : Resolution.SKIP;
44     }
45     else {
46       // IDEA-133480 Eclipse integration: .iml content is not reduced on setting Dependencies Storage Format = Eclipse
47       // We clear any storage except eclipse (because we must not clear shared files).
48       // Currently there is only one known non-default storage - ExternalProjectStorage.
49       return isEffectiveStorage ? Resolution.DO : isClasspathStorage ? Resolution.SKIP : Resolution.CLEAR;
50     }
51   }
52
53   @Override
54   public long getStateModificationCount() {
55     Module module = getModule();
56     if (!module.isLoaded() || !(module instanceof ModuleEx)) {
57       return myModificationTracker.getModificationCount();
58     }
59
60     final long[] result = {myModificationTracker.getModificationCount()};
61     result[0] += ((ModuleEx)module).getOptionsModificationCount();
62     final List<String> handledLibraryTables = new SmartList<>();
63     getRootModel().orderEntries().forEachLibrary(library -> {
64       LibraryTable table = library.getTable();
65       if (table instanceof LibraryTableBase && !handledLibraryTables.contains(table.getTableLevel())) {
66         handledLibraryTables.add(table.getTableLevel());
67         long count = ((LibraryTableBase)table).getStateModificationCount();
68         if (count > 0 && Registry.is("store.track.module.root.manager.changes", false)) {
69           LOG.error("modification count changed due to library  " + library.getName() + " change (" + count + "), module " + getModule().getName());
70         }
71         result[0] += count;
72       }
73       return true;
74     });
75     return result[0] + myRootModel.getStateModificationCount();
76   }
77
78   @Override
79   @TestOnly
80   public long getModificationCountForTests() {
81     return getStateModificationCount();
82   }
83 }