mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
notifications for unknown macros
This commit is contained in:
@@ -131,7 +131,7 @@ public class GenerationOptionsImpl extends GenerationOptions {
|
||||
if (myMacroReplacementMap.size() == 0) {
|
||||
return path; // optimization
|
||||
}
|
||||
return myMacroReplacementMap.substitute(path, SystemInfo.isFileSystemCaseSensitive, null);
|
||||
return myMacroReplacementMap.substitute(path, SystemInfo.isFileSystemCaseSensitive);
|
||||
}
|
||||
|
||||
public String getPropertyRefForUrl(String url) {
|
||||
|
||||
@@ -40,7 +40,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -87,13 +86,8 @@ public class ExistingModuleLoader extends ModuleBuilder {
|
||||
usedMacros.remove("$" + PathMacrosImpl.MODULE_DIR_MACRO_NAME + "$");
|
||||
usedMacros.removeAll(definedMacros);
|
||||
|
||||
final HashMap<String, String> map = new HashMap<String, String>();
|
||||
for (String v : usedMacros) {
|
||||
map.put(v, null);
|
||||
}
|
||||
|
||||
if (usedMacros.size() > 0) {
|
||||
final boolean ok = ProjectMacrosUtil.showMacrosConfigurationDialog(current, map);
|
||||
final boolean ok = ProjectMacrosUtil.showMacrosConfigurationDialog(current, usedMacros);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ public abstract class ModuleTestCase extends IdeaTestCase {
|
||||
final ProjectImpl project = (ProjectImpl)myProject;
|
||||
project.setOptimiseTestLoadSpeed(false);
|
||||
final ModuleRootManagerImpl moduleRootManager = (ModuleRootManagerImpl)ModuleRootManager.getInstance(module);
|
||||
module.getStateStore().initComponent(moduleRootManager);
|
||||
module.getStateStore().initComponent(moduleRootManager, false);
|
||||
project.setOptimiseTestLoadSpeed(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ public class ConversionContextImpl implements ConversionContext {
|
||||
List<File> files = new ArrayList<File>();
|
||||
for (Element module : JDomConvertingUtil.getChildren(modules, ModuleManagerImpl.ELEMENT_MODULE)) {
|
||||
String filePath = module.getAttributeValue(ModuleManagerImpl.ATTRIBUTE_FILEPATH);
|
||||
filePath = macros.substitute(filePath, true, null);
|
||||
filePath = macros.substitute(filePath, true);
|
||||
files.add(new File(FileUtil.toSystemDependentName(filePath)));
|
||||
}
|
||||
return files.toArray(new File[files.size()]);
|
||||
|
||||
+55
-5
@@ -1,14 +1,20 @@
|
||||
package com.intellij.openapi.components.impl.stores;
|
||||
|
||||
import com.intellij.notification.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.PathMacroManager;
|
||||
import com.intellij.openapi.components.PathMacroSubstitutor;
|
||||
import com.intellij.openapi.components.StateStorage;
|
||||
import com.intellij.openapi.components.TrackingPathMacroSubstitutor;
|
||||
import com.intellij.openapi.components.impl.ComponentManagerImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleTypeManager;
|
||||
import com.intellij.openapi.module.impl.ModuleImpl;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ex.ProjectEx;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jdom.Attribute;
|
||||
@@ -17,12 +23,10 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
|
||||
public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IModuleStore {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.ModuleStoreImpl");
|
||||
@@ -45,7 +49,32 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM
|
||||
return storage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String initComponent(@NotNull Object component, boolean service) {
|
||||
final String componentName = super.initComponent(component, service);
|
||||
|
||||
if (!ApplicationManager.getApplication().isHeadlessEnvironment() && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
if (service && componentName != null) {
|
||||
final TrackingPathMacroSubstitutor substitutor = getStateStorageManager().getMacroSubstitutor();
|
||||
if (substitutor != null) {
|
||||
final Collection<String> macros = substitutor.getUnknownMacros(componentName);
|
||||
if (!macros.isEmpty()) {
|
||||
Notifications.Bus.notify(new Notification("Load Error", "Error loading component",
|
||||
String.format("<p>Undefined Path Variables: <i>%s</i>. <a href=\"\">Fix it!</a></p>",
|
||||
StringUtil.join(macros, ", ")), NotificationType.ERROR,
|
||||
new NotificationListener() {
|
||||
public void hyperlinkUpdate(@NotNull Notification notification,
|
||||
@NotNull HyperlinkEvent event) {
|
||||
myModule.checkUnknownMacros(myModule.getProject(), notification);
|
||||
}
|
||||
}), NotificationDisplayType.STICKY_BALLOON, myModule.getProject());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return componentName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() throws IOException, StateStorage.StateStorageException {
|
||||
@@ -54,8 +83,29 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM
|
||||
final ModuleFileData storageData = getMainStorageData();
|
||||
final String moduleTypeId = storageData.myOptions.get(ModuleImpl.ELEMENT_TYPE);
|
||||
myModule.setModuleType(ModuleTypeManager.getInstance().findByID(moduleTypeId));
|
||||
}
|
||||
|
||||
if (ApplicationManager.getApplication().isHeadlessEnvironment() || ApplicationManager.getApplication().isUnitTestMode()) return;
|
||||
|
||||
final TrackingPathMacroSubstitutor substitutor = getStateStorageManager().getMacroSubstitutor();
|
||||
if (substitutor != null) {
|
||||
final Collection<String> macros = substitutor.getUnknownMacros(null);
|
||||
if (!macros.isEmpty()) {
|
||||
final Project project = myModule.getProject();
|
||||
StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() {
|
||||
public void run() {
|
||||
Notifications.Bus.notify(new Notification("Load Error", String.format("Error loading module '%s':", myModule.getName()),
|
||||
String.format(
|
||||
"<p>Undefined Path Variable(s): <i>%s</i>. <a href=\"\">Fix it!</a></p>",
|
||||
StringUtil.join(macros, ", ")), NotificationType.ERROR, new NotificationListener() {
|
||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
myModule.checkUnknownMacros(myModule.getProject(), notification);
|
||||
}
|
||||
}), NotificationDisplayType.STICKY_BALLOON, project);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ModuleFileData getMainStorageData() throws StateStorage.StateStorageException {
|
||||
return (ModuleFileData)super.getMainStorageData();
|
||||
|
||||
+5
-5
@@ -21,19 +21,19 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl {
|
||||
super(project);
|
||||
}
|
||||
|
||||
protected void reinitComponents(final Set<String> componentNames) {
|
||||
super.reinitComponents(componentNames);
|
||||
public void reinitComponents(final Set<String> componentNames, final boolean reloadData) {
|
||||
super.reinitComponents(componentNames, reloadData);
|
||||
|
||||
for (Module module : getPersistentModules()) {
|
||||
((ComponentStoreImpl)((ModuleImpl)module).getStateStore()).reinitComponents(componentNames);
|
||||
((ModuleImpl)module).getStateStore().reinitComponents(componentNames, reloadData);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isReloadPossible(final Set<String> componentNames) {
|
||||
public boolean isReloadPossible(final Set<String> componentNames) {
|
||||
if (!super.isReloadPossible(componentNames)) return false;
|
||||
|
||||
for (Module module : getPersistentModules()) {
|
||||
if (!((ComponentStoreImpl)((ModuleImpl)module).getStateStore()).isReloadPossible(componentNames)) return false;
|
||||
if (!((ModuleImpl)module).getStateStore().isReloadPossible(componentNames)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+3
-6
@@ -106,11 +106,8 @@ public class ClasspathStorage implements StateStorage {
|
||||
model.dispose();
|
||||
}
|
||||
}
|
||||
final HashMap<String, String> map = new HashMap<String, String>();
|
||||
for (String v : macros) {
|
||||
map.put(v, null);
|
||||
}
|
||||
final boolean macrosOk = ProjectMacrosUtil.checkMacros(module.getProject(), map);
|
||||
|
||||
final boolean macrosOk = ProjectMacrosUtil.checkMacros(module.getProject(), macros);
|
||||
PathMacroManager.getInstance(module).expandPaths(element);
|
||||
ModuleRootManagerImpl.ModuleRootManagerState moduleRootManagerState = new ModuleRootManagerImpl.ModuleRootManagerState();
|
||||
moduleRootManagerState.readExternal(element);
|
||||
@@ -128,7 +125,7 @@ public class ClasspathStorage implements StateStorage {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasState(final Object component, final String componentName, final Class<?> aClass)
|
||||
public boolean hasState(final Object component, final String componentName, final Class<?> aClass, final boolean reloadData)
|
||||
throws StateStorageException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public interface StateStorage {
|
||||
|
||||
@Nullable
|
||||
<T> T getState(final Object component, final String componentName, Class<T> stateClass, @Nullable T mergeInto) throws StateStorageException;
|
||||
boolean hasState(final Object component, final String componentName, final Class<?> aClass) throws StateStorageException;
|
||||
boolean hasState(final Object component, final String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException;
|
||||
|
||||
@NotNull
|
||||
ExternalizationSession startExternalization();
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public interface StorageAnnotationsDefaultValues {
|
||||
throw new UnsupportedOperationException("Method getState is not supported in " + getClass());
|
||||
}
|
||||
|
||||
public boolean hasState(final Object component, final String componentName, final Class<?> aClass) throws StateStorageException {
|
||||
public boolean hasState(final Object component, final String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException {
|
||||
throw new UnsupportedOperationException("Method hasState not implemented in " + getClass());
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -26,11 +26,11 @@ public class PathMacrosCollector extends PathMacroMap {
|
||||
|
||||
public static Set<String> getMacroNames(Element root) {
|
||||
final PathMacrosCollector collector = new PathMacrosCollector();
|
||||
collector.substitute(root, true, null);
|
||||
collector.substitute(root, true);
|
||||
return new HashSet<String>(collector.myMacroMap.keySet());
|
||||
}
|
||||
|
||||
public String substitute(String text, boolean caseSensitive, final Set<String> usedMacros) {
|
||||
public String substitute(String text, boolean caseSensitive) {
|
||||
myMatcher.reset(text);
|
||||
while (myMatcher.find()) {
|
||||
final String macroName = myMatcher.group(1);
|
||||
+6
-35
@@ -51,10 +51,10 @@ public class ReplacePathToMacroMap extends PathMacroMap {
|
||||
}
|
||||
}
|
||||
|
||||
public String substitute(String text, boolean caseSensitive, final Set<String> usedMacros) {
|
||||
public String substitute(String text, boolean caseSensitive) {
|
||||
for (final String path : getPathIndex()) {
|
||||
final String macro = get(path);
|
||||
text = replacePathMacro(text, path, macro, caseSensitive, usedMacros);
|
||||
text = replacePathMacro(text, path, macro, caseSensitive);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@@ -62,8 +62,7 @@ public class ReplacePathToMacroMap extends PathMacroMap {
|
||||
private static String replacePathMacro(String text,
|
||||
String path,
|
||||
final String macro,
|
||||
boolean caseSensitive,
|
||||
final Set<String> usedMacros) {
|
||||
boolean caseSensitive) {
|
||||
if (text.length() < path.length() || path.length() == 0) {
|
||||
return text;
|
||||
}
|
||||
@@ -93,7 +92,6 @@ public class ReplacePathToMacroMap extends PathMacroMap {
|
||||
|
||||
newText.append(macro);
|
||||
newText.append(text.substring(endOfOccurence));
|
||||
logUsage(macro, usedMacros);
|
||||
|
||||
return newText.toString();
|
||||
}
|
||||
@@ -103,10 +101,10 @@ public class ReplacePathToMacroMap extends PathMacroMap {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String substituteRecursively(String text, final boolean caseSensitive, final Set<String> usedMacros) {
|
||||
public String substituteRecursively(String text, final boolean caseSensitive) {
|
||||
for (final String path : getPathIndex()) {
|
||||
final String macro = get(path);
|
||||
text = replacePathMacroRecursively(text, path, macro, caseSensitive, usedMacros);
|
||||
text = replacePathMacroRecursively(text, path, macro, caseSensitive);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
@@ -114,8 +112,7 @@ public class ReplacePathToMacroMap extends PathMacroMap {
|
||||
private static String replacePathMacroRecursively(String text,
|
||||
String path,
|
||||
final String macro,
|
||||
boolean caseSensitive,
|
||||
final Set<String> usedMacros) {
|
||||
boolean caseSensitive) {
|
||||
if (text.length() < path.length()) {
|
||||
return text;
|
||||
}
|
||||
@@ -151,7 +148,6 @@ public class ReplacePathToMacroMap extends PathMacroMap {
|
||||
else {
|
||||
newText.append(text.substring(i, occurrenceOfPath));
|
||||
newText.append(macro);
|
||||
logUsage(macro, usedMacros);
|
||||
i = occurrenceOfPath + path.length();
|
||||
}
|
||||
}
|
||||
@@ -162,31 +158,6 @@ public class ReplacePathToMacroMap extends PathMacroMap {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void logUsage(String macroReplacement, final Set<String> usedMacros) {
|
||||
if (usedMacros == null) return;
|
||||
|
||||
int idx = 0;
|
||||
for (String protocol : PROTOCOLS) {
|
||||
if (StringUtil.startsWithConcatenationOf(macroReplacement, protocol, "://")) {
|
||||
idx = protocol.length() + 3;
|
||||
}
|
||||
else if (StringUtil.startsWithConcatenationOf(macroReplacement, protocol, ":/")) {
|
||||
idx = protocol.length() + 2;
|
||||
}
|
||||
else if (StringUtil.startsWithConcatenationOf(macroReplacement, protocol, ":")) {
|
||||
idx = protocol.length() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
macroReplacement = macroReplacement.substring(idx);
|
||||
if (macroReplacement.length() >= 2 && macroReplacement.startsWith("$") && macroReplacement.endsWith("$")) {
|
||||
macroReplacement = macroReplacement.substring(1, macroReplacement.length() - 1);
|
||||
}
|
||||
|
||||
usedMacros.add(macroReplacement);
|
||||
}
|
||||
|
||||
public List<String> getPathIndex() {
|
||||
if (myPathsIndex == null || myPathsIndex.size() != size()) {
|
||||
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ import com.intellij.openapi.options.ConfigurationException;
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author dsl
|
||||
@@ -24,7 +24,7 @@ public class PathMacroListEditor {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public PathMacroListEditor(Map<String, String> undefinedMacroNames) {
|
||||
public PathMacroListEditor(final Collection<String> undefinedMacroNames) {
|
||||
myPathMacroTable = undefinedMacroNames != null ? new PathMacroTable(undefinedMacroNames) : new PathMacroTable();
|
||||
myScrollPane.setViewportView(myPathMacroTable);
|
||||
myAddButton.addActionListener(new ActionListener() {
|
||||
|
||||
+3
-3
@@ -33,13 +33,13 @@ public class PathMacroTable extends Table {
|
||||
}
|
||||
};
|
||||
|
||||
private final Map<String, String> myUndefinedMacroNames;
|
||||
private final Collection<String> myUndefinedMacroNames;
|
||||
|
||||
public PathMacroTable() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public PathMacroTable(Map<String, String> undefinedMacroNames) {
|
||||
public PathMacroTable(final Collection<String> undefinedMacroNames) {
|
||||
myUndefinedMacroNames = undefinedMacroNames;
|
||||
setModel(myTableModel);
|
||||
TableColumn column = getColumnModel().getColumn(NAME_COLUMN);
|
||||
@@ -147,7 +147,7 @@ public class PathMacroTable extends Table {
|
||||
}
|
||||
|
||||
if (myUndefinedMacroNames != null) {
|
||||
for (String undefinedMacroName : myUndefinedMacroNames.keySet()) {
|
||||
for (String undefinedMacroName : myUndefinedMacroNames) {
|
||||
macros.add(new Pair<String, String>(undefinedMacroName, ""));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -7,7 +7,6 @@ package com.intellij.openapi.components;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -19,7 +18,7 @@ public class ExpandMacroToPathMap extends PathMacroMap {
|
||||
put("$" + macroName + "$", quotePath(path));
|
||||
}
|
||||
|
||||
public String substitute(String text, boolean caseSensitive, final Set<String> usedMacros) {
|
||||
public String substitute(String text, boolean caseSensitive) {
|
||||
for (Map.Entry<String, String> entry : entries()) {
|
||||
// when replacing macros with actual paths the replace utility may be used as always 'case-sensitive'
|
||||
// for case-insensitive file systems there will be no unnecesary toLowerCase() transforms.
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.jdom.Attribute;
|
||||
import org.jdom.Comment;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.Text;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -41,34 +40,22 @@ public abstract class PathMacroMap {
|
||||
myMacroMap.put(fromText, toText);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"WeakerAccess"})
|
||||
public abstract String substitute(String text, boolean caseSensitive, @Nullable final Set<String> usedMacros);
|
||||
public abstract String substitute(String text, boolean caseSensitive);
|
||||
|
||||
public final void substitute(Element e, boolean caseSensitive, @Nullable final Set<String> usedMacros) {
|
||||
substitute(e, caseSensitive, usedMacros, false);
|
||||
public final void substitute(Element e, boolean caseSensitive) {
|
||||
substitute(e, caseSensitive, false);
|
||||
}
|
||||
|
||||
public final void substitute(Element e, boolean caseSensitive, @Nullable final Set<String> usedMacros, final boolean recursively) {
|
||||
public final void substitute(Element e, boolean caseSensitive, final boolean recursively) {
|
||||
List content = e.getContent();
|
||||
for (Object child : content) {
|
||||
if (child instanceof Element) {
|
||||
Element element = (Element)child;
|
||||
|
||||
//mike
|
||||
//dirty hack: do not substitute macroses in path macroses declarations.
|
||||
//I can't find a way to disable macro saving in one component (yet).
|
||||
|
||||
if (element.getName().equals("macro") &&
|
||||
element.getAttributes().size() == 2 &&
|
||||
element.getAttributeValue("name") != null &&
|
||||
element.getAttributeValue("value") != null &&
|
||||
element.getChildren().isEmpty()) continue;
|
||||
|
||||
substitute(element, caseSensitive, usedMacros, recursively);
|
||||
substitute(element, caseSensitive, recursively);
|
||||
}
|
||||
else if (child instanceof Text) {
|
||||
Text t = (Text)child;
|
||||
t.setText(recursively ? substituteRecursively(t.getText(), caseSensitive, usedMacros) : substitute(t.getText(), caseSensitive, usedMacros));
|
||||
t.setText(recursively ? substituteRecursively(t.getText(), caseSensitive) : substitute(t.getText(), caseSensitive));
|
||||
}
|
||||
else if (child instanceof Comment) {
|
||||
/*do not substitute in comments
|
||||
@@ -84,12 +71,15 @@ public abstract class PathMacroMap {
|
||||
List attributes = e.getAttributes();
|
||||
for (final Object attribute1 : attributes) {
|
||||
Attribute attribute = (Attribute)attribute1;
|
||||
attribute.setValue(recursively? substituteRecursively(attribute.getValue(), caseSensitive, usedMacros) : substitute(attribute.getValue(), caseSensitive, usedMacros));
|
||||
final String value = recursively
|
||||
? substituteRecursively(attribute.getValue(), caseSensitive)
|
||||
: substitute(attribute.getValue(), caseSensitive);
|
||||
attribute.setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
public String substituteRecursively(String text, boolean caseSensitive, Set<String> usedMacros) {
|
||||
return substitute(text, caseSensitive, usedMacros);
|
||||
public String substituteRecursively(String text, boolean caseSensitive) {
|
||||
return substitute(text, caseSensitive);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
|
||||
+7
-2
@@ -1,9 +1,14 @@
|
||||
package com.intellij.openapi.components;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
public interface TrackingPathMacroSubstitutor extends PathMacroSubstitutor {
|
||||
Set<String> getUsedMacros();
|
||||
Collection<String> getUnknownMacros(@Nullable String componentName);
|
||||
Collection<String> getComponents(final Collection<String> macros);
|
||||
void addUnknownMacros(String componentName, Collection<String> unknownMacros);
|
||||
void invalidateUnknownMacros(Set<String> macros);
|
||||
void reset();
|
||||
void reset(Set<String> usedMacros);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.intellij.openapi.components.ex;
|
||||
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.openapi.components.ComponentConfig;
|
||||
import com.intellij.openapi.components.ComponentManager;
|
||||
import com.intellij.openapi.components.impl.stores.IComponentStore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -25,4 +28,6 @@ public interface ComponentManagerEx extends ComponentManager {
|
||||
void registerComponent(ComponentConfig config, IdeaPluginDescriptor pluginDescriptor);
|
||||
|
||||
IComponentStore getComponentStore();
|
||||
|
||||
void checkUnknownMacros(@NotNull Project project, @NotNull Notification notification);
|
||||
}
|
||||
|
||||
+68
-25
@@ -7,12 +7,11 @@ import com.intellij.openapi.components.ExpandMacroToPathMap;
|
||||
import com.intellij.openapi.components.PathMacroManager;
|
||||
import com.intellij.openapi.components.TrackingPathMacroSubstitutor;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.util.containers.FactoryMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class BasePathMacroManager extends PathMacroManager {
|
||||
private PathMacrosImpl myPathMacros;
|
||||
@@ -49,28 +48,28 @@ public class BasePathMacroManager extends PathMacroManager {
|
||||
}
|
||||
|
||||
public TrackingPathMacroSubstitutor createTrackingSubstitutor() {
|
||||
return new MyTrackingPathMacroSubstitutor(new HashSet<String>());
|
||||
return new MyTrackingPathMacroSubstitutor();
|
||||
}
|
||||
|
||||
public String expandPath(final String path) {
|
||||
return getExpandMacroMap().substitute(path, SystemInfo.isFileSystemCaseSensitive, null);
|
||||
return getExpandMacroMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
|
||||
}
|
||||
|
||||
public String collapsePath(final String path) {
|
||||
return getReplacePathMap().substitute(path, SystemInfo.isFileSystemCaseSensitive, null);
|
||||
return getReplacePathMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
|
||||
}
|
||||
|
||||
public void collapsePathsRecursively(final Element element) {
|
||||
getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive, null, true);
|
||||
getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive, true);
|
||||
}
|
||||
|
||||
public void expandPaths(final Element element) {
|
||||
getExpandMacroMap().substitute(element, SystemInfo.isFileSystemCaseSensitive, null);
|
||||
getExpandMacroMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
|
||||
}
|
||||
|
||||
|
||||
public void collapsePaths(final Element element) {
|
||||
getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive, null);
|
||||
getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
|
||||
}
|
||||
|
||||
public PathMacrosImpl getPathMacros() {
|
||||
@@ -88,43 +87,87 @@ public class BasePathMacroManager extends PathMacroManager {
|
||||
}
|
||||
|
||||
private class MyTrackingPathMacroSubstitutor implements TrackingPathMacroSubstitutor {
|
||||
private final Set<String> myUsedMacros;
|
||||
private final Map<String, Set<String>> myMacroToComponentNames = new FactoryMap<String, Set<String>>() {
|
||||
@Override
|
||||
protected Set<String> create(String key) {
|
||||
return new HashSet<String>();
|
||||
}
|
||||
};
|
||||
|
||||
public MyTrackingPathMacroSubstitutor(final Set<String> usedMacros) {
|
||||
myUsedMacros = usedMacros;
|
||||
}
|
||||
private final Map<String, Set<String>> myComponentNameToMacros = new FactoryMap<String, Set<String>>() {
|
||||
@Override
|
||||
protected Set<String> create(String key) {
|
||||
return new HashSet<String>();
|
||||
}
|
||||
};
|
||||
|
||||
public Set<String> getUsedMacros() {
|
||||
return Collections.unmodifiableSet(myUsedMacros);
|
||||
public MyTrackingPathMacroSubstitutor() {
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
myUsedMacros.clear();
|
||||
myMacroToComponentNames.clear();
|
||||
myComponentNameToMacros.clear();
|
||||
}
|
||||
|
||||
public String expandPath(final String path) {
|
||||
return getExpandMacroMap().substitute(path, SystemInfo.isFileSystemCaseSensitive, myUsedMacros);
|
||||
return getExpandMacroMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
|
||||
}
|
||||
|
||||
public String collapsePath(final String path) {
|
||||
return getReplacePathMap().substitute(path, SystemInfo.isFileSystemCaseSensitive, myUsedMacros);
|
||||
return getReplacePathMap().substitute(path, SystemInfo.isFileSystemCaseSensitive);
|
||||
}
|
||||
|
||||
public void expandPaths(final Element element) {
|
||||
getExpandMacroMap().substitute(element, SystemInfo.isFileSystemCaseSensitive, myUsedMacros);
|
||||
getExpandMacroMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
|
||||
}
|
||||
|
||||
public void collapsePaths(final Element element) {
|
||||
getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive, myUsedMacros);
|
||||
}
|
||||
|
||||
public void reset(final Set<String> usedMacros) {
|
||||
reset();
|
||||
myUsedMacros.addAll(usedMacros);
|
||||
getReplacePathMap().substitute(element, SystemInfo.isFileSystemCaseSensitive);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return getExpandMacroMap().hashCode();
|
||||
}
|
||||
|
||||
public void invalidateUnknownMacros(final Set<String> macros) {
|
||||
for (final String macro : macros) {
|
||||
final Set<String> components = myMacroToComponentNames.get(macro);
|
||||
for (final String component : components) {
|
||||
myComponentNameToMacros.remove(component);
|
||||
}
|
||||
|
||||
myMacroToComponentNames.remove(macro);
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<String> getComponents(final Collection<String> macros) {
|
||||
final Set<String> result = new HashSet<String>();
|
||||
for (String macro : myMacroToComponentNames.keySet()) {
|
||||
if (macros.contains(macro)) {
|
||||
result.addAll(myMacroToComponentNames.get(macro));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Collection<String> getUnknownMacros(final String componentName) {
|
||||
if (componentName == null) {
|
||||
return Collections.unmodifiableSet(myMacroToComponentNames.keySet());
|
||||
} else {
|
||||
return Collections.unmodifiableSet(myComponentNameToMacros.get(componentName));
|
||||
}
|
||||
}
|
||||
|
||||
public void addUnknownMacros(final String componentName, final Collection<String> unknownMacros) {
|
||||
if (unknownMacros.isEmpty()) return;
|
||||
|
||||
for (String unknownMacro : unknownMacros) {
|
||||
final Set<String> stringList = myMacroToComponentNames.get(unknownMacro);
|
||||
stringList.add(componentName);
|
||||
}
|
||||
|
||||
myComponentNameToMacros.get(componentName).addAll(unknownMacros);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+49
-8
@@ -2,19 +2,22 @@ package com.intellij.openapi.components.impl;
|
||||
|
||||
import com.intellij.diagnostic.PluginException;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathMacros;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
|
||||
import com.intellij.openapi.components.BaseComponent;
|
||||
import com.intellij.openapi.components.ComponentConfig;
|
||||
import com.intellij.openapi.components.ComponentManager;
|
||||
import com.intellij.openapi.components.StateStorage;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.components.ex.ComponentManagerEx;
|
||||
import com.intellij.openapi.components.impl.stores.IComponentStore;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx;
|
||||
import com.intellij.openapi.project.impl.ProjectMacrosUtil;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
@@ -34,9 +37,7 @@ import org.picocontainer.defaults.ConstructorInjectionComponentAdapter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author mike
|
||||
@@ -217,7 +218,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
}
|
||||
|
||||
try {
|
||||
getStateStore().initComponent(component);
|
||||
getStateStore().initComponent(component, false);
|
||||
if (component instanceof BaseComponent) {
|
||||
((BaseComponent)component).initComponent();
|
||||
}
|
||||
@@ -233,6 +234,46 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements
|
||||
}
|
||||
}
|
||||
|
||||
public void checkUnknownMacros(@NotNull final Project project, @NotNull final Notification notification) {
|
||||
final IComponentStore stateStore = getStateStore();
|
||||
final TrackingPathMacroSubstitutor substitutor = stateStore.getStateStorageManager().getMacroSubstitutor();
|
||||
if (substitutor != null) {
|
||||
final Collection<String> macros = substitutor.getUnknownMacros(null);
|
||||
if (!macros.isEmpty()) {
|
||||
if (ProjectMacrosUtil.checkMacros(project, new HashSet<String>(macros))) {
|
||||
final PathMacros pathMacros = PathMacros.getInstance();
|
||||
boolean expire = true;
|
||||
final Set<String> macros2invalidate = new HashSet<String>(macros);
|
||||
for (Iterator it = macros2invalidate.iterator(); it.hasNext();) {
|
||||
final String macro = (String)it.next();
|
||||
if (null == pathMacros.getValue(macro)) {
|
||||
it.remove();
|
||||
expire = false;
|
||||
}
|
||||
}
|
||||
|
||||
final Set<String> components = new HashSet<String>(substitutor.getComponents(macros2invalidate));
|
||||
if (stateStore.isReloadPossible(components)) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
stateStore.reinitComponents(components, true);
|
||||
}
|
||||
});
|
||||
|
||||
substitutor.invalidateUnknownMacros(macros2invalidate);
|
||||
if (expire) notification.expire();
|
||||
}
|
||||
else {
|
||||
if (Messages.showYesNoDialog(project, "Component could not be reloaded. Reload project?", "Configuration changed",
|
||||
Messages.getQuestionIcon()) == 0) {
|
||||
ProjectManagerEx.getInstanceEx().reloadProject(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleInitComponentError(final Throwable ex, final boolean fatal, final String componentClassName) {
|
||||
LOG.error(ex);
|
||||
}
|
||||
|
||||
+4
-2
@@ -116,12 +116,14 @@ public class ServiceManagerImpl implements BaseComponent {
|
||||
});
|
||||
}
|
||||
|
||||
private Object initializeInstance(final PicoContainer container) {
|
||||
protected Object initializeInstance(final PicoContainer container) {
|
||||
final Object serviceInstance = getDelegate().getComponentInstance(container);
|
||||
if (serviceInstance instanceof Disposable) {
|
||||
Disposer.register(myComponentManager, (Disposable)serviceInstance);
|
||||
}
|
||||
myComponentManager.getComponentStore().initComponent(serviceInstance);
|
||||
|
||||
myComponentManager.getComponentStore().initComponent(serviceInstance, true);
|
||||
|
||||
return serviceInstance;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -120,7 +120,7 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto
|
||||
|
||||
try {
|
||||
doReload(changedFiles, componentNames);
|
||||
reinitComponents(componentNames);
|
||||
reinitComponents(componentNames, false);
|
||||
}
|
||||
finally {
|
||||
myApplication.getMessageBus().syncPublisher(BatchUpdateListener.TOPIC).onBatchUpdateFinished();
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ abstract class BaseFileConfigurableStoreImpl extends ComponentStoreImpl {
|
||||
}
|
||||
|
||||
public BaseStorageData getMainStorageData() throws StateStorage.StateStorageException {
|
||||
return (BaseStorageData) getMainStorage().getStorageData();
|
||||
return (BaseStorageData) getMainStorage().getStorageData(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+22
-14
@@ -47,25 +47,26 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
throw new UnsupportedOperationException("Method getDefaultsStorage is not supported in " + getClass());
|
||||
}
|
||||
|
||||
public void initComponent(@NotNull final Object component) {
|
||||
public String initComponent(@NotNull final Object component, final boolean service) {
|
||||
boolean isSerializable = component instanceof JDOMExternalizable ||
|
||||
component instanceof PersistentStateComponent ||
|
||||
component instanceof SettingsSavingComponent;
|
||||
|
||||
if (!isSerializable) return;
|
||||
if (!isSerializable) return null;
|
||||
|
||||
if (component instanceof SettingsSavingComponent) {
|
||||
SettingsSavingComponent settingsSavingComponent = (SettingsSavingComponent)component;
|
||||
mySettingsSavingComponents.add(settingsSavingComponent);
|
||||
}
|
||||
|
||||
final String[] componentName = {null};
|
||||
final Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
if (component instanceof PersistentStateComponent) {
|
||||
initPersistentComponent((PersistentStateComponent<?>)component);
|
||||
componentName[0] = initPersistentComponent((PersistentStateComponent<?>)component, false);
|
||||
}
|
||||
else if (component instanceof JDOMExternalizable) {
|
||||
initJdomExternalizable((JDOMExternalizable)component);
|
||||
componentName[0] = initJdomExternalizable((JDOMExternalizable)component);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -77,6 +78,8 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
else {
|
||||
applicationEx.runReadAction(r);
|
||||
}
|
||||
|
||||
return componentName[0];
|
||||
}
|
||||
|
||||
public boolean isSaving() {
|
||||
@@ -146,22 +149,23 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
session.setStateInOldStorage(component, componentName, component);
|
||||
}
|
||||
|
||||
void initJdomExternalizable(@NotNull JDOMExternalizable component) {
|
||||
@Nullable
|
||||
String initJdomExternalizable(@NotNull JDOMExternalizable component) {
|
||||
final String componentName = getComponentName(component);
|
||||
|
||||
myComponents.put(componentName, component);
|
||||
|
||||
if (optimizeTestLoading()) return;
|
||||
if (optimizeTestLoading()) return componentName;
|
||||
|
||||
loadJdomDefaults(component, componentName);
|
||||
|
||||
Element element = null;
|
||||
StateStorage stateStorage = getOldStorage(component, componentName, StateStorageOperation.READ);
|
||||
|
||||
if (stateStorage == null) return;
|
||||
if (stateStorage == null) return null;
|
||||
element = getJdomState(component, componentName, stateStorage);
|
||||
|
||||
if (element == null) return;
|
||||
if (element == null) return null;
|
||||
|
||||
try {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
@@ -172,6 +176,8 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
catch (InvalidDataException e) {
|
||||
throw new InvalidComponentDataException(e);
|
||||
}
|
||||
|
||||
return componentName;
|
||||
}
|
||||
|
||||
private static String getComponentName(@NotNull final JDOMExternalizable component) {
|
||||
@@ -216,7 +222,7 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
return defaultsStorage.getState(component, componentName, Element.class, null);
|
||||
}
|
||||
|
||||
private <T> void initPersistentComponent(@NotNull final PersistentStateComponent<T> component) {
|
||||
private <T> String initPersistentComponent(@NotNull final PersistentStateComponent<T> component, final boolean reloadData) {
|
||||
final String name = getComponentName(component);
|
||||
|
||||
RoamingType roamingTypeFromComponent = getRoamingType(component);
|
||||
@@ -226,7 +232,7 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
}
|
||||
|
||||
myComponents.put(name, component);
|
||||
if (optimizeTestLoading()) return;
|
||||
if (optimizeTestLoading()) return name;
|
||||
|
||||
Class<T> stateClass = getComponentStateClass(component);
|
||||
|
||||
@@ -242,13 +248,15 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
|
||||
for (Storage storageSpec : storageSpecs) {
|
||||
StateStorage stateStorage = getStateStorage(storageSpec);
|
||||
if (stateStorage == null || !stateStorage.hasState(component, name, stateClass)) continue;
|
||||
if (stateStorage == null || !stateStorage.hasState(component, name, stateClass, reloadData)) continue;
|
||||
state = stateStorage.getState(component, name, stateClass, state);
|
||||
}
|
||||
|
||||
if (state != null) {
|
||||
component.loadState(state);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
private static RoamingType getRoamingType(final PersistentStateComponent component) {
|
||||
@@ -455,7 +463,7 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
|
||||
}
|
||||
|
||||
protected boolean isReloadPossible(final Set<String> componentNames) {
|
||||
public boolean isReloadPossible(final Set<String> componentNames) {
|
||||
for (String componentName : componentNames) {
|
||||
final Object component = myComponents.get(componentName);
|
||||
|
||||
@@ -470,11 +478,11 @@ abstract class ComponentStoreImpl implements IComponentStore {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void reinitComponents(final Set<String> componentNames) {
|
||||
public void reinitComponents(final Set<String> componentNames, final boolean reloadData) {
|
||||
for (String componentName : componentNames) {
|
||||
final PersistentStateComponent component = (PersistentStateComponent)myComponents.get(componentName);
|
||||
if (component != null) {
|
||||
initPersistentComponent(component);
|
||||
initPersistentComponent(component, reloadData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -94,6 +94,11 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl {
|
||||
throw new UnsupportedOperationException("Method addMacro not implemented in " + getClass());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TrackingPathMacroSubstitutor getMacroSubstitutor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public StateStorage getStateStorage(@NotNull Storage storageSpec) throws StateStorage.StateStorageException {
|
||||
return storage;
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ class DefaultsStateStorage implements StateStorage {
|
||||
return DefaultStateSerializer.deserializeState(getState(component, componentName), stateClass, mergeInto);
|
||||
}
|
||||
|
||||
public boolean hasState(final Object component, final String componentName, final Class<?> aClass) throws StateStorageException {
|
||||
public boolean hasState(final Object component, final String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException {
|
||||
final URL url = DecodeDefaultsUtil.getDefaults(component, componentName);
|
||||
return url != null;
|
||||
}
|
||||
|
||||
+5
-4
@@ -1,5 +1,6 @@
|
||||
package com.intellij.openapi.components.impl.stores;
|
||||
|
||||
import com.intellij.application.options.PathMacrosCollector;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.StateSplitter;
|
||||
@@ -146,6 +147,9 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
|
||||
|
||||
if (myPathMacroSubstitutor != null) {
|
||||
myPathMacroSubstitutor.expandPaths(element);
|
||||
|
||||
final Set<String> unknownMacros = PathMacrosCollector.getMacroNames(element);
|
||||
myPathMacroSubstitutor.addUnknownMacros(componentName, unknownMacros);
|
||||
}
|
||||
|
||||
storageData.put(componentName, file, element, true);
|
||||
@@ -162,7 +166,7 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
|
||||
public boolean hasState(final Object component, final String componentName, final Class<?> aClass) throws StateStorageException {
|
||||
public boolean hasState(final Object component, final String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException {
|
||||
if (!myDir.exists()) return false;
|
||||
return true;
|
||||
}
|
||||
@@ -432,13 +436,10 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
private class MyExternalizationSession implements ExternalizationSession {
|
||||
private final TrackingPathMacroSubstitutor myPathMacroSubstitutor;
|
||||
private final MyStorageData myStorageData;
|
||||
|
||||
private MyExternalizationSession(final TrackingPathMacroSubstitutor pathMacroSubstitutor, final MyStorageData storageData) {
|
||||
myStorageData = storageData;
|
||||
myPathMacroSubstitutor = pathMacroSubstitutor;
|
||||
myPathMacroSubstitutor.reset();
|
||||
}
|
||||
|
||||
public void setState(final Object component, final String componentName, final Object state, final Storage storageSpec)
|
||||
|
||||
+6
-1
@@ -12,7 +12,12 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface IComponentStore {
|
||||
void initComponent(Object component);
|
||||
@Nullable
|
||||
String initComponent(Object component, boolean service);
|
||||
void reinitComponents(Set<String> componentNames, boolean reloadData);
|
||||
boolean isReloadPossible(Set<String> componentNames);
|
||||
|
||||
|
||||
void load() throws IOException, StateStorage.StateStorageException;
|
||||
boolean isSaving();
|
||||
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ class ProjectStateStorageManager extends StateStorageManagerImpl {
|
||||
|
||||
StateStorage storage = getFileStateStorage(name);
|
||||
|
||||
if (operation == StateStorageOperation.READ && storage != null && workspace && !storage.hasState(component, componentName, Element.class)) {
|
||||
if (operation == StateStorageOperation.READ && storage != null && workspace && !storage.hasState(component, componentName, Element.class, false)) {
|
||||
name = "$" + ProjectStoreImpl.PROJECT_FILE_MACRO + "$";
|
||||
}
|
||||
|
||||
|
||||
+33
-1
@@ -3,9 +3,11 @@ package com.intellij.openapi.components.impl.stores;
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.ide.highlighter.ProjectFileType;
|
||||
import com.intellij.ide.highlighter.WorkspaceFileType;
|
||||
import com.intellij.notification.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.components.ex.ComponentManagerEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.help.HelpManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -19,6 +21,7 @@ import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
@@ -32,12 +35,14 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -137,6 +142,33 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
|
||||
return myProject.isOptimiseTestLoadSpeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String initComponent(@NotNull Object component, boolean service) {
|
||||
final String componentName = super.initComponent(component, service);
|
||||
|
||||
if (!ApplicationManager.getApplication().isHeadlessEnvironment() && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
if (service && componentName != null && myProject.isInitialized()) {
|
||||
final TrackingPathMacroSubstitutor substitutor = getStateStorageManager().getMacroSubstitutor();
|
||||
if (substitutor != null) {
|
||||
final Collection<String> macros = substitutor.getUnknownMacros(componentName);
|
||||
if (!macros.isEmpty()) {
|
||||
Notifications.Bus.notify(new Notification("Load Error", "Error loading component",
|
||||
String.format("<p>Undefined Path Variables: <i>%s</i>. <a href=\"\">Fix it!</a></p>",
|
||||
StringUtil.join(macros, ", ")), NotificationType.ERROR,
|
||||
new NotificationListener() {
|
||||
public void hyperlinkUpdate(@NotNull Notification notification,
|
||||
@NotNull HyperlinkEvent event) {
|
||||
((ComponentManagerEx)myProject).checkUnknownMacros(myProject, notification);
|
||||
}
|
||||
}), NotificationDisplayType.STICKY_BALLOON, myProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return componentName;
|
||||
}
|
||||
|
||||
public void setProjectFilePath(final String filePath) {
|
||||
if (filePath == null) {
|
||||
return;
|
||||
@@ -595,7 +627,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
|
||||
|
||||
try {
|
||||
doReload(changedFiles, componentNames);
|
||||
reinitComponents(componentNames);
|
||||
reinitComponents(componentNames, false);
|
||||
}
|
||||
finally {
|
||||
myProject.getMessageBus().syncPublisher(BatchUpdateListener.TOPIC).onBatchUpdateFinished();
|
||||
|
||||
+3
-4
@@ -1,9 +1,6 @@
|
||||
package com.intellij.openapi.components.impl.stores;
|
||||
|
||||
import com.intellij.openapi.components.RoamingType;
|
||||
import com.intellij.openapi.components.StateStorage;
|
||||
import com.intellij.openapi.components.StateStorageOperation;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.options.StreamProvider;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -20,6 +17,8 @@ import java.util.Set;
|
||||
*/
|
||||
public interface StateStorageManager {
|
||||
void addMacro(String macro, String expansion);
|
||||
@Nullable
|
||||
TrackingPathMacroSubstitutor getMacroSubstitutor();
|
||||
|
||||
@Nullable
|
||||
StateStorage getStateStorage(@NotNull Storage storageSpec) throws StateStorage.StateStorageException;
|
||||
|
||||
+5
@@ -59,6 +59,11 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public TrackingPathMacroSubstitutor getMacroSubstitutor() {
|
||||
return myPathMacroSubstitutor;
|
||||
}
|
||||
|
||||
public synchronized void addMacro(String macro, String expansion) {
|
||||
myMacros.put("$" + macro + "$", expansion);
|
||||
}
|
||||
|
||||
+19
-14
@@ -1,5 +1,6 @@
|
||||
package com.intellij.openapi.components.impl.stores;
|
||||
|
||||
import com.intellij.application.options.PathMacrosCollector;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -102,7 +103,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
|
||||
@Nullable
|
||||
public synchronized Element getState(final String componentName) throws StateStorageException {
|
||||
final StorageData storageData = getStorageData();
|
||||
final StorageData storageData = getStorageData(false);
|
||||
final Element state = storageData.getState(componentName);
|
||||
|
||||
|
||||
@@ -117,8 +118,8 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
return state;
|
||||
}
|
||||
|
||||
public boolean hasState(final Object component, final String componentName, final Class<?> aClass) throws StateStorageException {
|
||||
final StorageData storageData = getStorageData();
|
||||
public boolean hasState(final Object component, final String componentName, final Class<?> aClass, final boolean reloadData) throws StateStorageException {
|
||||
final StorageData storageData = getStorageData(reloadData);
|
||||
return storageData.hasState(componentName);
|
||||
}
|
||||
|
||||
@@ -129,8 +130,8 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected StorageData getStorageData() throws StateStorageException {
|
||||
if (myLoadedData != null) return myLoadedData;
|
||||
protected StorageData getStorageData(final boolean reloadData) throws StateStorageException {
|
||||
if (myLoadedData != null && !reloadData) return myLoadedData;
|
||||
|
||||
myLoadedData = loadData(true, myListener);
|
||||
|
||||
@@ -178,7 +179,6 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
protected void loadState(final StorageData result, final Element element) throws StateStorageException {
|
||||
// TODO: notification should be created here
|
||||
if (myPathMacroSubstitutor != null) {
|
||||
myPathMacroSubstitutor.expandPaths(element);
|
||||
}
|
||||
@@ -187,6 +187,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
|
||||
try {
|
||||
result.load(element);
|
||||
result.checkUnknownMacros(myPathMacroSubstitutor);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new StateStorageException(e);
|
||||
@@ -211,7 +212,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
@NotNull
|
||||
public ExternalizationSession startExternalization() {
|
||||
try {
|
||||
final ExternalizationSession session = new MyExternalizationSession(getStorageData().clone(), myListener);
|
||||
final ExternalizationSession session = new MyExternalizationSession(getStorageData(false).clone(), myListener);
|
||||
|
||||
mySession = session;
|
||||
return session;
|
||||
@@ -305,17 +306,13 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
protected Document getDocument(StorageData data) {
|
||||
|
||||
final Element element = data.save();
|
||||
|
||||
if (myPathMacroSubstitutor != null) {
|
||||
Set<String> usedMacros = myPathMacroSubstitutor.getUsedMacros();
|
||||
try {
|
||||
myPathMacroSubstitutor.reset();
|
||||
myPathMacroSubstitutor.collapsePaths(element);
|
||||
}
|
||||
finally {
|
||||
myPathMacroSubstitutor.reset(usedMacros);
|
||||
} finally {
|
||||
myPathMacroSubstitutor.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,7 +460,6 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
myDocumentToSave = new Document(element);
|
||||
|
||||
if (myPathMacroSubstitutor != null) {
|
||||
myPathMacroSubstitutor.reset();
|
||||
myPathMacroSubstitutor.collapsePaths(element);
|
||||
}
|
||||
|
||||
@@ -697,6 +693,15 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
public boolean hasState(final String componentName) {
|
||||
return myComponentStates.containsKey(componentName);
|
||||
}
|
||||
|
||||
public void checkUnknownMacros(TrackingPathMacroSubstitutor pathMacroSubstitutor) {
|
||||
for (String componentName : myComponentStates.keySet()) {
|
||||
final Set<String> unknownMacros = PathMacrosCollector.getMacroNames(myComponentStates.get(componentName));
|
||||
if (!unknownMacros.isEmpty()) {
|
||||
pathMacroSubstitutor.addUnknownMacros(componentName, unknownMacros);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void resetData(){
|
||||
|
||||
@@ -25,11 +25,11 @@ public class ProjectMacrosUtil {
|
||||
private ProjectMacrosUtil() {
|
||||
}
|
||||
|
||||
public static boolean showMacrosConfigurationDialog(Project project, final Map<String, String> undefinedMacros) {
|
||||
public static boolean showMacrosConfigurationDialog(Project project, final Collection<String> undefinedMacros) {
|
||||
final String text = ProjectBundle.message("project.load.undefined.path.variables.message");
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
if (application.isHeadlessEnvironment() || application.isUnitTestMode()) {
|
||||
throw new RuntimeException(text + ": " + StringUtil.join(undefinedMacros.keySet(), ", "));
|
||||
throw new RuntimeException(text + ": " + StringUtil.join(undefinedMacros, ", "));
|
||||
}
|
||||
final UndefinedMacrosConfigurable configurable =
|
||||
new UndefinedMacrosConfigurable(text, undefinedMacros);
|
||||
@@ -47,13 +47,13 @@ public class ProjectMacrosUtil {
|
||||
return editor.isOK();
|
||||
}
|
||||
|
||||
public static boolean checkMacros(final Project project, final Map<String, String> usedMacros) {
|
||||
public static boolean checkMacros(final Project project, final Set<String> usedMacros) {
|
||||
final Set<String> defined = getDefinedMacros();
|
||||
usedMacros.keySet().removeAll(defined);
|
||||
usedMacros.removeAll(defined);
|
||||
|
||||
// try to lookup values in System properties
|
||||
@NonNls final String pathMacroSystemPrefix = "path.macro.";
|
||||
for (Iterator it = usedMacros.keySet().iterator(); it.hasNext();) {
|
||||
for (Iterator it = usedMacros.iterator(); it.hasNext();) {
|
||||
final String macro = (String)it.next();
|
||||
final String value = System.getProperty(pathMacroSystemPrefix + macro, null);
|
||||
if (value != null) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.intellij.ide.AppLifecycleListener;
|
||||
import com.intellij.ide.highlighter.WorkspaceFileType;
|
||||
import com.intellij.ide.impl.ProjectUtil;
|
||||
import com.intellij.ide.startup.impl.StartupManagerImpl;
|
||||
import com.intellij.notification.*;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
@@ -13,6 +14,8 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.application.impl.ApplicationImpl;
|
||||
import com.intellij.openapi.components.ExportableApplicationComponent;
|
||||
import com.intellij.openapi.components.StateStorage;
|
||||
import com.intellij.openapi.components.TrackingPathMacroSubstitutor;
|
||||
import com.intellij.openapi.components.ex.ComponentManagerEx;
|
||||
import com.intellij.openapi.components.impl.stores.IComponentStore;
|
||||
import com.intellij.openapi.components.impl.stores.IProjectStore;
|
||||
import com.intellij.openapi.components.impl.stores.XmlElementStorage;
|
||||
@@ -31,6 +34,7 @@ import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileEvent;
|
||||
@@ -51,6 +55,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
@@ -376,6 +381,30 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt
|
||||
|
||||
startupManager.runPostStartupActivities();
|
||||
|
||||
if (!ApplicationManager.getApplication().isHeadlessEnvironment() && !ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
// should be invoked last
|
||||
StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() {
|
||||
public void run() {
|
||||
final TrackingPathMacroSubstitutor macroSubstitutor =
|
||||
((ProjectEx)project).getStateStore().getStateStorageManager().getMacroSubstitutor();
|
||||
if (macroSubstitutor != null) {
|
||||
final Collection<String> macros = macroSubstitutor.getUnknownMacros(null);
|
||||
if (!macros.isEmpty()) {
|
||||
Notifications.Bus.notify(new Notification("Load Error", "Error loading project",
|
||||
String.format("<p>Undefined Path Variables: %s. <a href=\"\">Fix it!</a></p>",
|
||||
StringUtil.join(macros, ", ")), NotificationType.ERROR,
|
||||
new NotificationListener() {
|
||||
public void hyperlinkUpdate(@NotNull Notification notification,
|
||||
@NotNull HyperlinkEvent event) {
|
||||
((ComponentManagerEx)project).checkUnknownMacros(project, notification);
|
||||
}
|
||||
}), NotificationDisplayType.STICKY_BALLOON, project);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -14,7 +14,7 @@ import com.intellij.ui.IdeBorderFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -23,9 +23,9 @@ import java.util.Map;
|
||||
public class UndefinedMacrosConfigurable implements Configurable{
|
||||
private PathMacroListEditor myEditor;
|
||||
private final String myText;
|
||||
private final Map<String, String> myUndefinedMacroNames;
|
||||
private final Collection<String> myUndefinedMacroNames;
|
||||
|
||||
public UndefinedMacrosConfigurable(String text, Map<String, String> undefinedMacroNames) {
|
||||
public UndefinedMacrosConfigurable(String text, Collection<String> undefinedMacroNames) {
|
||||
myText = text;
|
||||
myUndefinedMacroNames = undefinedMacroNames;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.intellij.mock;
|
||||
|
||||
import com.intellij.application.options.ReplacePathToMacroMap;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ExpandMacroToPathMap;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
@@ -23,6 +24,9 @@ public class MockProject extends MockComponentManager implements ProjectEx {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void checkMacros(Notification notification, @Nullable String componentName) {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PomModel getModel() {
|
||||
return ServiceManager.getService(this, PomModel.class);
|
||||
|
||||
@@ -33,6 +33,14 @@ public class MockProjectStore implements IProjectStore {
|
||||
throw new UnsupportedOperationException("Method setProjectFilePath is not yet implemented in " + getClass().getName());
|
||||
}
|
||||
|
||||
public void reinitComponents(Set<String> componentNames, boolean reloadData) {
|
||||
throw new UnsupportedOperationException("Method reinitComponents is not yet implemented in " + getClass().getName());
|
||||
}
|
||||
|
||||
public boolean isReloadPossible(Set<String> componentNames) {
|
||||
throw new UnsupportedOperationException("Method isReloadPossible is not yet implemented in " + getClass().getName());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VirtualFile getProjectBaseDir() {
|
||||
throw new UnsupportedOperationException("Method getProjectBaseDir is not yet implemented in " + getClass().getName());
|
||||
@@ -95,7 +103,7 @@ public class MockProjectStore implements IProjectStore {
|
||||
throw new UnsupportedOperationException("Method initStore is not yet implemented in " + getClass().getName());
|
||||
}
|
||||
|
||||
public void initComponent(Object component) {
|
||||
public String initComponent(Object component, final boolean service) {
|
||||
throw new UnsupportedOperationException("Method initComponent is not yet implemented in " + getClass().getName());
|
||||
}
|
||||
|
||||
|
||||
+1
-6
@@ -155,12 +155,7 @@ public class EclipseImportBuilder extends ProjectImportBuilder<String> implement
|
||||
return false;
|
||||
}
|
||||
|
||||
final HashMap<String, String> map = new HashMap<String, String>();
|
||||
for (String v : variables) {
|
||||
map.put(v, null);
|
||||
}
|
||||
|
||||
if (!ProjectMacrosUtil.checkMacros(dstProject, map)) {
|
||||
if (!ProjectMacrosUtil.checkMacros(dstProject, variables)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -292,7 +292,7 @@ public class ExternalResourceManagerImpl extends ExternalResourceManagerEx imple
|
||||
public void readExternal(Element element) throws InvalidDataException {
|
||||
final ExpandMacroToPathMap macroExpands = new ExpandMacroToPathMap();
|
||||
myPathMacros.addMacroExpands(macroExpands);
|
||||
macroExpands.substitute(element, SystemInfo.isFileSystemCaseSensitive, null);
|
||||
macroExpands.substitute(element, SystemInfo.isFileSystemCaseSensitive);
|
||||
|
||||
myModificationCount++;
|
||||
for (final Object o1 : element.getChildren(RESOURCE_ELEMENT)) {
|
||||
@@ -329,7 +329,7 @@ public class ExternalResourceManagerImpl extends ExternalResourceManagerEx imple
|
||||
|
||||
final ReplacePathToMacroMap macroReplacements = new ReplacePathToMacroMap();
|
||||
PathMacrosImpl.getInstanceEx().addMacroReplacements(macroReplacements);
|
||||
macroReplacements.substitute(element, SystemInfo.isFileSystemCaseSensitive, null);
|
||||
macroReplacements.substitute(element, SystemInfo.isFileSystemCaseSensitive);
|
||||
}
|
||||
|
||||
public void addExternalResourceListener(ExternalResourceListener listener) {
|
||||
|
||||
Reference in New Issue
Block a user