[project structure] avoid unnecessary creation of ModifiableRootModel in ModuleConfigurationState

This commit introduces ModuleConfigurationState::getCurrentRootModel method which can be used if we need to just read the current state of the model and don't need to modify it, and explicit 'getModifiableRootModel' method. The old 'getRootModel' method is deprecated and all its usages are replaced by usages of one of the new methods. This way we avoid creating unnecessary instances of ModifiableRootModel to improve performance and avoid exceptions (EA-251419) which may happen if ModifiableRootModel is created during commit (when ClasspathPanelImpl creates modifiable model to update the table during processing 'rootsChanged').

GitOrigin-RevId: 4cbd410ed6039a5ee652d2585bdeee429baf7df7
This commit is contained in:
Nikolay Chashnikov
2021-01-30 03:29:42 +03:00
committed by intellij-monorepo-bot
parent ea4b95e631
commit 804cff19da
19 changed files with 73 additions and 34 deletions

View File

@@ -125,7 +125,7 @@ public class ClasspathEditor extends ModuleElementsEditor implements ModuleRootL
}
private ModifiableRootModel getModifiableModel() {
return getState().getRootModel();
return getState().getModifiableRootModel();
}
public void selectOrderEntry(@NotNull final OrderEntry entry) {
@@ -190,7 +190,7 @@ public class ClasspathEditor extends ModuleElementsEditor implements ModuleRootL
}
private @NlsContexts.Label String getModuleClasspathFormat() {
@NlsSafe final String type = ClassPathStorageUtil.getStorageType(myState.getRootModel().getModule());
@NlsSafe final String type = ClassPathStorageUtil.getStorageType(myState.getCurrentRootModel().getModule());
return type;
}
@@ -201,13 +201,13 @@ public class ClasspathEditor extends ModuleElementsEditor implements ModuleRootL
public void canApply() throws ConfigurationException {
ClasspathStorageProvider provider = ClasspathStorage.getProvider(getSelectedClasspathFormat());
if (provider != null) {
provider.assertCompatible(myState.getRootModel());
provider.assertCompatible(myState.getCurrentRootModel());
}
}
private void apply() throws ConfigurationException {
canApply();
ClasspathStorage.setStorageType(myState.getRootModel(), getSelectedClasspathFormat());
ClasspathStorage.setStorageType(myState.getCurrentRootModel(), getSelectedClasspathFormat());
}
}

View File

@@ -17,7 +17,6 @@ package com.intellij.openapi.roots.ui.configuration;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleConfigurationEditor;
import com.intellij.openapi.roots.ModifiableRootModel;
/**
* @author Eugene Zhuravlev
@@ -25,8 +24,7 @@ import com.intellij.openapi.roots.ModifiableRootModel;
public class DefaultModuleConfigurationEditorFactoryImpl extends DefaultModuleConfigurationEditorFactory {
@Override
public ModuleConfigurationEditor createModuleContentRootsEditor(ModuleConfigurationState state) {
final ModifiableRootModel rootModel = state.getRootModel();
final Module module = rootModel.getModule();
final Module module = state.getCurrentRootModel().getModule();
final String moduleName = module.getName();
return new ContentEntriesEditor(moduleName, state);
}

View File

@@ -19,7 +19,6 @@ import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleConfigurationEditor;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.roots.ModifiableRootModel;
import java.util.ArrayList;
import java.util.List;
@@ -27,8 +26,7 @@ import java.util.List;
public class DefaultModuleEditorsProvider implements ModuleConfigurationEditorProvider {
@Override
public ModuleConfigurationEditor[] createEditors(ModuleConfigurationState state) {
ModifiableRootModel rootModel = state.getRootModel();
Module module = rootModel.getModule();
Module module = state.getCurrentRootModel().getModule();
if (!(ModuleType.get(module) instanceof JavaModuleType)) {
return ModuleConfigurationEditor.EMPTY;
}

View File

@@ -218,10 +218,15 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable {
public ModuleConfigurationState createModuleConfigurationState() {
return new ModuleConfigurationStateImpl(myProject, myModulesProvider) {
@Override
public ModifiableRootModel getRootModel() {
public ModifiableRootModel getModifiableRootModel() {
return getModifiableRootModelProxy();
}
@Override
public ModuleRootModel getCurrentRootModel() {
return ModuleEditor.this.getRootModel();
}
@Override
public FacetsProvider getFacetsProvider() {
return getFacetsConfigurator();

View File

@@ -62,7 +62,7 @@ class AnalyzeModuleDependencyAction extends AnAction {
List<GlobalSearchScope> scopes = new ArrayList<>(additionalScopes.keySet());
scopes.add(mainScope);
new AnalyzeDependenciesOnSpecifiedTargetHandler(myPanel.getProject(), new AnalysisScope(myPanel.getModuleConfigurationState().getRootModel().getModule()),
new AnalyzeDependenciesOnSpecifiedTargetHandler(myPanel.getProject(), new AnalysisScope(myPanel.getModuleConfigurationState().getCurrentRootModel().getModule()),
GlobalSearchScope.union(scopes.toArray(GlobalSearchScope.EMPTY_ARRAY))) {
@Override
protected boolean shouldShowDependenciesPanel(List<? extends DependenciesBuilder> builders) {

View File

@@ -513,7 +513,7 @@ public final class ClasspathPanelImpl extends JPanel implements ClasspathPanel {
@Override
public ModifiableRootModel getRootModel() {
return myState.getRootModel();
return myState.getModifiableRootModel();
}
@Override

View File

@@ -18,7 +18,6 @@ package com.intellij.openapi.roots.ui.configuration.classpath;
import com.intellij.ide.JavaUiBundle;
import com.intellij.openapi.roots.DependencyScope;
import com.intellij.openapi.roots.JdkOrderEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationState;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
@@ -106,12 +105,8 @@ class ClasspathTableModel extends ListTableModel<ClasspathTableItem<?>> implemen
return new RowSorter.SortKey(1, SortOrder.UNSORTED);
}
private ModifiableRootModel getModel() {
return myState.getRootModel();
}
public void init() {
final OrderEntry[] orderEntries = getModel().getOrderEntries();
final OrderEntry[] orderEntries = myState.getCurrentRootModel().getOrderEntries();
boolean hasJdkOrderEntry = false;
List<ClasspathTableItem<?>> items = new ArrayList<>();
for (final OrderEntry orderEntry : orderEntries) {
@@ -130,7 +125,7 @@ class ClasspathTableModel extends ListTableModel<ClasspathTableItem<?>> implemen
public void exchangeRows(int idx1, int idx2) {
super.exchangeRows(idx1, idx2);
List<OrderEntry> entries = getEntries();
myState.getRootModel().rearrangeOrderEntries(entries.toArray(OrderEntry.EMPTY_ARRAY));
myState.getModifiableRootModel().rearrangeOrderEntries(entries.toArray(OrderEntry.EMPTY_ARRAY));
}
public void clear() {

View File

@@ -116,7 +116,8 @@ class InlineModuleDependencyActionTest : JavaModuleTestCase() {
private fun setUpClasspathPanel(modifiableRootModel: ModifiableRootModel, entryToSelect: ModuleOrderEntry): ClasspathPanelImpl {
val moduleConfigurationState = object : ModuleConfigurationStateImpl(project, ModulesProvider.EMPTY_MODULES_PROVIDER) {
override fun getRootModel(): ModifiableRootModel = modifiableRootModel
override fun getModifiableRootModel(): ModifiableRootModel = modifiableRootModel
override fun getCurrentRootModel(): ModuleRootModel = modifiableRootModel
}
return ClasspathPanelImpl(moduleConfigurationState).apply { selectOrderEntry(entryToSelect) }
}

View File

@@ -8,6 +8,7 @@ import com.intellij.openapi.module.impl.ModuleConfigurationStateImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.testFramework.LightPlatformTestCase;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -35,7 +36,12 @@ public class ClasspathEditorTest extends LightPlatformTestCase {
ClasspathEditor e = new ClasspathEditor(new ModuleConfigurationStateImpl(project, new DefaultModulesProvider(project)) {
@Override
public @NotNull ModifiableRootModel getRootModel() {
public ModifiableRootModel getModifiableRootModel() {
return uiRootModel;
}
@Override
public ModuleRootModel getCurrentRootModel() {
return uiRootModel;
}
});

View File

@@ -17,13 +17,33 @@ package com.intellij.openapi.roots.ui.configuration;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.util.UserDataHolder;
import org.jetbrains.annotations.NotNull;
public interface ModuleConfigurationState extends UserDataHolder {
ModulesProvider getModulesProvider();
FacetsProvider getFacetsProvider();
ModifiableRootModel getRootModel();
/**
* Returns an instance which can be used to modify the module configuration
*/
ModifiableRootModel getModifiableRootModel();
/**
* Returns the actual state of the module configuration
*/
ModuleRootModel getCurrentRootModel();
@NotNull
Project getProject();
/**
* @deprecated use {@link #getModifiableRootModel()}} if you need to modify the model and use {@link #getCurrentRootModel()} if you just
* need to read the current state
*/
@Deprecated
default ModifiableRootModel getRootModel() {
return getModifiableRootModel();
}
}

View File

@@ -22,7 +22,7 @@ import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationState;
public class WebModuleConfigurationEditorProvider implements ModuleConfigurationEditorProvider {
@Override
public ModuleConfigurationEditor[] createEditors(final ModuleConfigurationState state) {
Module module = state.getRootModel().getModule();
Module module = state.getCurrentRootModel().getModule();
if (!ModuleTypeWithWebFeatures.isAvailable(module)) {
return ModuleConfigurationEditor.EMPTY;
}

View File

@@ -18,12 +18,12 @@ package com.intellij.openapi.module.impl;
import com.intellij.facet.impl.DefaultFacetsProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.ui.configuration.FacetsProvider;
import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationState;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.UserDataHolderBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ModuleConfigurationStateImpl extends UserDataHolderBase implements ModuleConfigurationState {
private final ModulesProvider myProvider;
@@ -45,8 +45,12 @@ public class ModuleConfigurationStateImpl extends UserDataHolderBase implements
}
@Override
@Nullable
public ModifiableRootModel getRootModel() {
public ModifiableRootModel getModifiableRootModel() {
return null;
}
@Override
public ModuleRootModel getCurrentRootModel() {
return null;
}

View File

@@ -112,7 +112,7 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor {
@Override
protected ModifiableRootModel getModel() {
return myState.getRootModel();
return myState.getModifiableRootModel();
}
@Override

View File

@@ -59,7 +59,7 @@ public abstract class ModuleElementsEditor implements ModuleConfigurationEditor
}
protected ModifiableRootModel getModel() {
return myState.getRootModel();
return myState.getModifiableRootModel();
}
@NotNull

View File

@@ -25,6 +25,7 @@ import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
@@ -70,7 +71,12 @@ public class PlatformContentEntriesConfigurable implements Configurable {
final ModuleConfigurationStateImpl moduleConfigurationState =
new ModuleConfigurationStateImpl(myModule.getProject(), new DefaultModulesProvider(myModule.getProject())) {
@Override
public ModifiableRootModel getRootModel() {
public ModifiableRootModel getModifiableRootModel() {
return myModifiableModel;
}
@Override
public ModuleRootModel getCurrentRootModel() {
return myModifiableModel;
}
};

View File

@@ -53,7 +53,7 @@ public class PluginModuleBuildConfEditor implements ModuleConfigurationEditor {
@NonNls private static final String MANIFEST_MF = "manifest.mf";
public PluginModuleBuildConfEditor(ModuleConfigurationState state) {
myModule = state.getRootModel().getModule();
myModule = state.getCurrentRootModel().getModule();
myBuildProperties = PluginBuildConfiguration.getInstance(myModule);
}

View File

@@ -16,7 +16,7 @@ public class PluginModuleEditorsProvider implements ModuleConfigurationEditorPro
@Override
public ModuleConfigurationEditor[] createEditors(ModuleConfigurationState state) {
final Module module = state.getRootModel().getModule();
final Module module = state.getCurrentRootModel().getModule();
if (ModuleType.get(module) != PluginModuleType.getInstance()) return ModuleConfigurationEditor.EMPTY;
final DefaultModuleConfigurationEditorFactory editorFactory = DefaultModuleConfigurationEditorFactory.getInstance();

View File

@@ -25,6 +25,7 @@ import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider;
import com.intellij.openapi.roots.ui.configuration.FacetsProvider;
import com.jetbrains.python.PyBundle;
@@ -69,7 +70,12 @@ public class PyContentEntriesModuleConfigurable extends SearchableConfigurable.P
final ModuleConfigurationStateImpl moduleConfigurationState =
new ModuleConfigurationStateImpl(myModule.getProject(), new DefaultModulesProvider(myModule.getProject())) {
@Override
public ModifiableRootModel getRootModel() {
public ModifiableRootModel getModifiableRootModel() {
return myModifiableModel;
}
@Override
public ModuleRootModel getCurrentRootModel() {
return myModifiableModel;
}

View File

@@ -18,7 +18,7 @@ import java.util.List;
public class PythonModuleConfigurationEditorProvider implements ModuleConfigurationEditorProvider {
@Override
public ModuleConfigurationEditor[] createEditors(final ModuleConfigurationState state) {
final Module module = state.getRootModel().getModule();
final Module module = state.getCurrentRootModel().getModule();
if (!(ModuleType.get(module) instanceof PythonModuleType)) return ModuleConfigurationEditor.EMPTY;
final DefaultModuleConfigurationEditorFactory editorFactory = DefaultModuleConfigurationEditorFactory.getInstance();
final List<ModuleConfigurationEditor> editors = new ArrayList<>();