IDEA-133480 Eclipse integration: .iml content is not reduced on setting Dependencies Storage Format = Eclipse

This commit is contained in:
Vladimir Krivosheev
2015-03-03 18:05:42 +01:00
parent 19b5bc5896
commit 1cfaad1bcc
6 changed files with 114 additions and 67 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.impl.storage.ClassPathStorageUtil;
import com.intellij.openapi.roots.impl.storage.ClasspathStorage;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
@@ -27,30 +28,29 @@ import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
@State(
name = "NewModuleRootManager",
storages = {
@Storage(id = ClassPathStorageUtil.DEFAULT_STORAGE, file = StoragePathMacros.MODULE_FILE),
@Storage(file = StoragePathMacros.MODULE_FILE),
@Storage(id = ClasspathStorage.SPECIAL_STORAGE, storageClass = ClasspathStorage.class)
},
storageChooser = ModuleRootManagerComponent.StorageChooser.class
}
)
public class ModuleRootManagerComponent extends ModuleRootManagerImpl implements
PersistentStateComponent<ModuleRootManagerImpl.ModuleRootManagerState> {
PersistentStateComponent<ModuleRootManagerImpl.ModuleRootManagerState>,
StateStorageChooserEx {
public ModuleRootManagerComponent(Module module,
ProjectRootManagerImpl projectRootManager,
VirtualFilePointerManager filePointerManager) {
super(module, projectRootManager, filePointerManager);
}
static class StorageChooser implements StateStorageChooser<ModuleRootManagerImpl> {
@Override
public Storage[] selectStorages(Storage[] storages, ModuleRootManagerImpl moduleRootManager, final StateStorageOperation operation) {
boolean isDefaultStorageType = ClassPathStorageUtil.isDefaultStorage(moduleRootManager.getModule());
String id = isDefaultStorageType ? ClassPathStorageUtil.DEFAULT_STORAGE : ClasspathStorage.SPECIAL_STORAGE;
for (Storage storage : storages) {
if (storage.id().equals(id)) {
return new Storage[]{storage};
}
}
throw new IllegalArgumentException();
@NotNull
@Override
public Resolution getResolution(@NotNull Storage storage, @NotNull StateStorageOperation operation) {
boolean isEffectiveStorage = storage.id().equals(ClassPathStorageUtil.isDefaultStorage(getModule()) ? ClassPathStorageUtil.DEFAULT_STORAGE : ClasspathStorage.SPECIAL_STORAGE);
if (operation == StateStorageOperation.READ) {
return isEffectiveStorage ? Resolution.DO : Resolution.SKIP;
}
else {
// IDEA-133480 Eclipse integration: .iml content is not reduced on setting Dependencies Storage Format = Eclipse
return isEffectiveStorage ? Resolution.DO : (storage.id().equals(ClassPathStorageUtil.DEFAULT_STORAGE) ? Resolution.CLEAR : Resolution.SKIP);
}
}
}
@@ -19,6 +19,7 @@ import com.intellij.openapi.application.*;
import com.intellij.openapi.application.ex.DecodeDefaultsUtil;
import com.intellij.openapi.components.*;
import com.intellij.openapi.components.StateStorage.SaveSession;
import com.intellij.openapi.components.StateStorageChooserEx.Resolution;
import com.intellij.openapi.components.impl.ComponentManagerImpl;
import com.intellij.openapi.components.impl.stores.StateStorageManager.ExternalizationSession;
import com.intellij.openapi.components.store.ReadOnlyModificationException;
@@ -301,7 +302,13 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable {
T state = stateSpec.defaultStateAsResource() ? getDefaultState(component, name, stateClass) : null;
Storage[] storageSpecs = getComponentStorageSpecs(component, stateSpec, StateStorageOperation.READ);
StateStorageChooserEx stateStorageChooser = component instanceof StateStorageChooserEx ? (StateStorageChooserEx)component : null;
for (Storage storageSpec : storageSpecs) {
Resolution resolution = stateStorageChooser == null ? Resolution.DO : stateStorageChooser.getResolution(storageSpec, StateStorageOperation.READ);
if (resolution == Resolution.SKIP) {
continue;
}
StateStorage stateStorage = getStateStorageManager().getStateStorage(storageSpec);
if (stateStorage != null && (stateStorage.hasState(component, name, stateClass, reloadData) ||
(changedStorages != null && changedStorages.contains(stateStorage)))) {
@@ -353,64 +360,67 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable {
}
@NotNull
protected <T> Storage[] getComponentStorageSpecs(@NotNull PersistentStateComponent<T> persistentStateComponent,
@NotNull State stateSpec,
@NotNull StateStorageOperation operation) {
protected <T> Storage[] getComponentStorageSpecs(@NotNull PersistentStateComponent<T> component,
@NotNull State stateSpec,
@NotNull StateStorageOperation operation) {
Storage[] storages = stateSpec.storages();
if (storages.length == 1) {
return storages;
}
assert storages.length > 0;
StateStorageChooser<PersistentStateComponent<T>> storageChooser;
Class<? extends StateStorageChooser> storageChooserClass = stateSpec.storageChooser();
if (storageChooserClass == StateStorageChooser.class) {
StateStorageChooser<PersistentStateComponent<?>> defaultStateStorageChooser = getDefaultStateStorageChooser();
if (defaultStateStorageChooser == null) {
int actualStorageCount = 0;
for (Storage storage : storages) {
if (!storage.deprecated()) {
actualStorageCount++;
}
}
if (storageChooserClass != StateStorageChooser.class) {
//noinspection unchecked
storageChooser = ReflectionUtil.newInstance(storageChooserClass);
return storageChooser.selectStorages(storages, component, operation);
}
if (actualStorageCount > 1) {
LOG.error("State chooser not specified for: " + persistentStateComponent.getClass());
}
StateStorageChooser<PersistentStateComponent<?>> defaultStateStorageChooser = getDefaultStateStorageChooser();
if (defaultStateStorageChooser != null) {
return defaultStateStorageChooser.selectStorages(storages, component, operation);
}
if (!storages[0].deprecated()) {
boolean othersAreDeprecated = true;
for (int i = 1; i < storages.length; i++) {
if (!storages[i].deprecated()) {
othersAreDeprecated = false;
break;
}
}
if (component instanceof StateStorageChooserEx) {
return storages;
}
if (othersAreDeprecated) {
return storages;
}
}
Storage[] sorted = Arrays.copyOf(storages, storages.length);
Arrays.sort(sorted, new Comparator<Storage>() {
@Override
public int compare(Storage o1, Storage o2) {
int w1 = o1.deprecated() ? 1 : 0;
int w2 = o2.deprecated() ? 1 : 0;
return w1 - w2;
}
});
return sorted;
}
else {
return defaultStateStorageChooser.selectStorages(storages, persistentStateComponent, operation);
int actualStorageCount = 0;
for (Storage storage : storages) {
if (!storage.deprecated()) {
actualStorageCount++;
}
}
else {
@SuppressWarnings("unchecked")
StateStorageChooser<PersistentStateComponent<T>> storageChooser = ReflectionUtil.newInstance(storageChooserClass);
return storageChooser.selectStorages(storages, persistentStateComponent, operation);
if (actualStorageCount > 1) {
LOG.error("State chooser not specified for: " + component.getClass());
}
if (!storages[0].deprecated()) {
boolean othersAreDeprecated = true;
for (int i = 1; i < storages.length; i++) {
if (!storages[i].deprecated()) {
othersAreDeprecated = false;
break;
}
}
if (othersAreDeprecated) {
return storages;
}
}
Storage[] sorted = Arrays.copyOf(storages, storages.length);
Arrays.sort(sorted, new Comparator<Storage>() {
@Override
public int compare(Storage o1, Storage o2) {
int w1 = o1.deprecated() ? 1 : 0;
int w2 = o2.deprecated() ? 1 : 0;
return w1 - w2;
}
});
return sorted;
}
protected boolean optimizeTestLoading() {
@@ -503,6 +503,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
}
private final StateStorageChooser<PersistentStateComponent<?>> myStateStorageChooser = new StateStorageChooser<PersistentStateComponent<?>>() {
@NotNull
@Override
public Storage[] selectStorages(@NotNull Storage[] storages, @NotNull PersistentStateComponent<?> component, @NotNull StateStorageOperation operation) {
if (operation == StateStorageOperation.READ) {
@@ -561,12 +562,12 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
@NotNull
@Override
protected <T> Storage[] getComponentStorageSpecs(@NotNull PersistentStateComponent<T> persistentStateComponent,
protected <T> Storage[] getComponentStorageSpecs(@NotNull PersistentStateComponent<T> component,
@NotNull State stateSpec,
@NotNull StateStorageOperation operation) {
// if we create project from default, component state written not to own storage file, but to project file,
// we don't have time to fix it properly, so, ancient hack restored.
Storage[] result = super.getComponentStorageSpecs(persistentStateComponent, stateSpec, operation);
Storage[] result = super.getComponentStorageSpecs(component, stateSpec, operation);
// don't add fake storage if project file storage already listed, otherwise data will be deleted on write (because of "deprecated")
for (Storage storage : result) {
if (storage.file().equals(StoragePathMacros.PROJECT_FILE)) {
@@ -20,6 +20,7 @@ import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
import com.intellij.openapi.components.StateStorage.SaveSession;
import com.intellij.openapi.components.StateStorageChooserEx.Resolution;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.Disposer;
@@ -290,12 +291,18 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
@Override
public void setState(@NotNull Storage[] storageSpecs, @NotNull Object component, @NotNull String componentName, @NotNull Object state) {
StateStorageChooserEx stateStorageChooser = component instanceof StateStorageChooserEx ? (StateStorageChooserEx)component : null;
for (Storage storageSpec : storageSpecs) {
Resolution resolution = stateStorageChooser == null ? Resolution.DO : stateStorageChooser.getResolution(storageSpec, StateStorageOperation.WRITE);
if (resolution == Resolution.SKIP) {
continue;
}
StateStorage stateStorage = getStateStorage(storageSpec);
StateStorage.ExternalizationSession session = getExternalizationSession(stateStorage);
if (session != null) {
// empty element as null state, so, will be deleted
session.setState(component, componentName, storageSpec.deprecated() ? new Element("empty") : state, storageSpec);
session.setState(component, componentName, storageSpec.deprecated() || resolution == Resolution.CLEAR ? new Element("empty") : state, storageSpec);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.components;
import org.jetbrains.annotations.NotNull;
public interface StateStorageChooser<T> {
Storage[] selectStorages(Storage[] storages, T component, final StateStorageOperation operation);
@NotNull
Storage[] selectStorages(Storage[] storages, T component, @NotNull StateStorageOperation operation);
}
@@ -0,0 +1,27 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.components;
import org.jetbrains.annotations.NotNull;
public interface StateStorageChooserEx {
enum Resolution {
DO, SKIP, CLEAR
}
@NotNull
Resolution getResolution(@NotNull Storage storage, @NotNull StateStorageOperation operation);
}