blob: f55dbd7bdb04cadbb7c805e7154fc6a15ea510cf [file] [log] [blame]
/*
* Copyright 2006 Sascha Weinreuter
*
* 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 org.intellij.plugins.intelliLang;
import com.intellij.lang.Language;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.undo.GlobalUndoableAction;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.psi.PsiCompiledElement;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiLanguageInjectionHost;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.*;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.intellij.plugins.intelliLang.inject.InjectorUtils;
import org.intellij.plugins.intelliLang.inject.LanguageInjectionConfigBean;
import org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport;
import org.intellij.plugins.intelliLang.inject.config.BaseInjection;
import org.intellij.plugins.intelliLang.inject.config.InjectionPlace;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
/**
* Configuration that holds configured xml tag, attribute and method parameter
* injection settings as well as the annotations to use for injection, pattern
* validation and for substituting non-compile time constant expression.
*
* Making it a service may result in FileContentUtil.reparseFiles at a random loading moment which may cause
* mysterious PSI validity losses
*/
public class Configuration extends SimpleModificationTracker implements PersistentStateComponent<Element>, ModificationTracker {
static final Logger LOG = Logger.getInstance(Configuration.class.getName());
private static final Condition<BaseInjection> LANGUAGE_INJECTION_CONDITION = new Condition<BaseInjection>() {
@Override
public boolean value(BaseInjection o) {
return Language.findLanguageByID(o.getInjectedLanguageId()) != null;
}
};
@State(
name = Configuration.COMPONENT_NAME,
storages = {@Storage( file = StoragePathMacros.APP_CONFIG + "/IntelliLang.xml", scheme = StorageScheme.DIRECTORY_BASED)})
public static class App extends Configuration {
private final List<BaseInjection> myDefaultInjections;
private final AdvancedConfiguration myAdvancedConfiguration;
App() {
myDefaultInjections = loadDefaultInjections();
myAdvancedConfiguration = new AdvancedConfiguration();
}
@Override
public List<BaseInjection> getDefaultInjections() {
return myDefaultInjections;
}
@Override
public AdvancedConfiguration getAdvancedConfiguration() {
return myAdvancedConfiguration;
}
@Override
public void loadState(final Element element) {
myAdvancedConfiguration.loadState(element);
super.loadState(element);
}
@Override
public Element getState() {
final Element element = new Element(COMPONENT_NAME);
myAdvancedConfiguration.writeState(element);
return getState(element);
}
}
@State(
name = Configuration.COMPONENT_NAME,
storages = {
@Storage(file = StoragePathMacros.PROJECT_FILE),
@Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/IntelliLang.xml", scheme = StorageScheme.DIRECTORY_BASED)
})
public static class Prj extends Configuration {
private final Configuration myParentConfiguration;
Prj(final Configuration configuration) {
myParentConfiguration = configuration;
}
@Override
public AdvancedConfiguration getAdvancedConfiguration() {
return myParentConfiguration.getAdvancedConfiguration();
}
@Override
public List<BaseInjection> getDefaultInjections() {
return myParentConfiguration.getDefaultInjections();
}
@Override
protected Collection<BaseInjection> getAllInjections() {
Collection<BaseInjection> injections = super.getAllInjections();
injections.addAll(myParentConfiguration.getAllInjections());
return injections;
}
@NotNull
@Override
public List<BaseInjection> getInjections(final String injectorId) {
return ContainerUtil.concat(myParentConfiguration.getInjections(injectorId), getOwnInjections(injectorId));
}
public Configuration getParentConfiguration() {
return myParentConfiguration;
}
public List<BaseInjection> getOwnInjections(final String injectorId) {
return super.getInjections(injectorId);
}
@Override
public long getModificationCount() {
return super.getModificationCount() + myParentConfiguration.getModificationCount();
}
public boolean replaceInjections(List<? extends BaseInjection> newInjections,
List<? extends BaseInjection> originalInjections,
boolean forceLevel) {
if (!forceLevel && !originalInjections.isEmpty()) {
if (myParentConfiguration.replaceInjections(Collections.<BaseInjection>emptyList(), originalInjections, false)) {
myParentConfiguration.replaceInjections(newInjections, Collections.<BaseInjection>emptyList(), false);
return true;
}
}
return super.replaceInjections(newInjections, originalInjections, forceLevel);
}
}
public enum InstrumentationType {
NONE, ASSERT, EXCEPTION
}
public enum DfaOption {
OFF, RESOLVE, ASSIGNMENTS, DFA
}
@NonNls public static final String COMPONENT_NAME = "LanguageInjectionConfiguration";
// element names
@NonNls private static final String INSTRUMENTATION_TYPE_NAME = "INSTRUMENTATION";
@NonNls private static final String LANGUAGE_ANNOTATION_NAME = "LANGUAGE_ANNOTATION";
@NonNls private static final String PATTERN_ANNOTATION_NAME = "PATTERN_ANNOTATION";
@NonNls private static final String SUBST_ANNOTATION_NAME = "SUBST_ANNOTATION";
@NonNls private static final String RESOLVE_REFERENCES = "RESOLVE_REFERENCES";
@NonNls private static final String LOOK_FOR_VAR_ASSIGNMENTS = "LOOK_FOR_VAR_ASSIGNMENTS";
@NonNls private static final String USE_DFA_IF_AVAILABLE = "USE_DFA_IF_AVAILABLE";
@NonNls private static final String INCLUDE_UNCOMPUTABLES_AS_LITERALS = "INCLUDE_UNCOMPUTABLES_AS_LITERALS";
@NonNls private static final String SOURCE_MODIFICATION_ALLOWED = "SOURCE_MODIFICATION_ALLOWED";
private final Map<String, List<BaseInjection>> myInjections = new ConcurrentFactoryMap<String, List<BaseInjection>>() {
@Override
protected List<BaseInjection> create(final String key) {
return ContainerUtil.createLockFreeCopyOnWriteList();
}
};
protected Collection<BaseInjection> getAllInjections() {
ArrayList<BaseInjection> injections = new ArrayList<BaseInjection>();
for (List<BaseInjection> list : myInjections.values()) {
injections.addAll(list);
}
return injections;
}
private CachedValue<MultiMap<String, BaseInjection>> myInjectionsById = new CachedValueImpl<MultiMap<String, BaseInjection>>(new CachedValueProvider<MultiMap<String, BaseInjection>>() {
@Nullable
@Override
public Result<MultiMap<String, BaseInjection>> compute() {
MultiMap<String, BaseInjection> map = new MultiMap<String, BaseInjection>();
for (BaseInjection injection : getAllInjections()) {
map.putValue(injection.getInjectedLanguageId(), injection);
}
return Result.create(map, Configuration.this);
}
});
public Configuration() {
}
public AdvancedConfiguration getAdvancedConfiguration() {
throw new UnsupportedOperationException("getAdvancedConfiguration should not be called");
}
public void loadState(final Element element) {
myInjections.clear();
final THashMap<String, LanguageInjectionSupport> supports = new THashMap<String, LanguageInjectionSupport>();
for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) {
supports.put(support.getId(), support);
}
for (Element child : element.getChildren("injection")){
final String key = child.getAttributeValue("injector-id");
final LanguageInjectionSupport support = supports.get(key);
final BaseInjection injection = support == null ? new BaseInjection(key) : support.createInjection(child);
injection.loadState(child);
InjectionPlace[] places = dropKnownInvalidPlaces(injection.getInjectionPlaces());
if (places != null) { // not all places were removed
injection.setInjectionPlaces(places);
myInjections.get(key).add(injection);
}
}
importPlaces(getDefaultInjections());
}
@Nullable
private static InjectionPlace[] dropKnownInvalidPlaces(InjectionPlace[] places) {
InjectionPlace[] result = places;
for (InjectionPlace place : places) {
if (place.getText().contains("matches(\"[^${}/\\\\]+\")")) {
result = ArrayUtil.remove(result, place);
}
}
return places.length != 0 && result.length == 0? null : result;
}
private static boolean readBoolean(Element element, String key, boolean defValue) {
final String value = JDOMExternalizerUtil.readField(element, key);
if (value == null) return defValue;
return Boolean.parseBoolean(value);
}
private static List<BaseInjection> loadDefaultInjections() {
final ArrayList<Configuration> cfgList = new ArrayList<Configuration>();
final THashSet<Object> visited = new THashSet<Object>();
for (LanguageInjectionConfigBean configBean : Extensions.getExtensions(LanguageInjectionSupport.CONFIG_EP_NAME)) {
PluginDescriptor descriptor = configBean.getPluginDescriptor();
final ClassLoader loader = descriptor.getPluginClassLoader();
try {
final Enumeration<URL> enumeration = loader.getResources(configBean.getConfigUrl());
if (enumeration == null || !enumeration.hasMoreElements()) {
LOG.warn(descriptor.getPluginId() +": " + configBean.getConfigUrl() + " was not found");
}
else {
while (enumeration.hasMoreElements()) {
URL url = enumeration.nextElement();
if (!visited.add(url.getFile())) continue; // for DEBUG mode
try {
cfgList.add(load(url.openStream()));
}
catch (Exception e) {
LOG.warn(e);
}
}
}
}
catch (Exception e) {
LOG.warn(e);
}
}
final ArrayList<BaseInjection> defaultInjections = new ArrayList<BaseInjection>();
for (String supportId : InjectorUtils.getActiveInjectionSupportIds()) {
for (Configuration cfg : cfgList) {
final List<BaseInjection> imported = cfg.getInjections(supportId);
defaultInjections.addAll(imported);
}
}
return defaultInjections;
}
public Element getState() {
return getState(new Element(COMPONENT_NAME));
}
protected Element getState(final Element element) {
Comparator<BaseInjection> comparator = new Comparator<BaseInjection>() {
public int compare(final BaseInjection o1, final BaseInjection o2) {
return Comparing.compare(o1.getDisplayName(), o2.getDisplayName());
}
};
List<String> injectorIds = new ArrayList<String>(myInjections.keySet());
Collections.sort(injectorIds);
for (String key : injectorIds) {
TreeSet<BaseInjection> injections = new TreeSet<BaseInjection>(comparator);
injections.addAll(myInjections.get(key));
injections.removeAll(getDefaultInjections());
for (BaseInjection injection : injections) {
element.addContent(injection.getState());
}
}
return element;
}
public static Configuration getInstance() {
return ServiceManager.getService(Configuration.class);
}
public static Configuration getProjectInstance(Project project) {
return ServiceManager.getService(project, Configuration.class);
}
public List<BaseInjection> getDefaultInjections() {
return Collections.emptyList();
}
public Collection<BaseInjection> getInjectionsByLanguageId(String languageId) {
return myInjectionsById.getValue().get(languageId);
}
@Nullable
public static Configuration load(final InputStream is) throws IOException, JDOMException {
try {
final Document document = JDOMUtil.loadDocument(is);
final ArrayList<Element> elements = new ArrayList<Element>();
final Element rootElement = document.getRootElement();
final Element state;
if (rootElement.getName().equals(COMPONENT_NAME)) {
state = rootElement;
}
else {
elements.add(rootElement);
//noinspection unchecked
elements.addAll(rootElement.getChildren("component"));
state = ContainerUtil.find(elements, new Condition<Element>() {
public boolean value(final Element element) {
return "component".equals(element.getName()) && COMPONENT_NAME.equals(element.getAttributeValue("name"));
}
});
}
if (state != null) {
final Configuration cfg = new Configuration();
cfg.loadState(state);
return cfg;
}
return null;
}
finally {
is.close();
}
}
private int importPlaces(final List<BaseInjection> injections) {
final Map<String, Set<BaseInjection>> map = ContainerUtil.classify(injections.iterator(), new Convertor<BaseInjection, String>() {
@Override
public String convert(final BaseInjection o) {
return o.getSupportId();
}
});
final ArrayList<BaseInjection> originalInjections = new ArrayList<BaseInjection>();
final ArrayList<BaseInjection> newInjections = new ArrayList<BaseInjection>();
for (String supportId : InjectorUtils.getActiveInjectionSupportIds()) {
final Set<BaseInjection> importingInjections = map.get(supportId);
if (importingInjections == null) continue;
importInjections(getInjections(supportId), importingInjections, originalInjections, newInjections);
}
if (!newInjections.isEmpty()) configurationModified();
replaceInjections(newInjections, originalInjections, true);
return newInjections.size();
}
static void importInjections(final Collection<BaseInjection> existingInjections, final Collection<BaseInjection> importingInjections,
final Collection<BaseInjection> originalInjections, final Collection<BaseInjection> newInjections) {
final MultiValuesMap<InjectionPlace, BaseInjection> placeMap = new MultiValuesMap<InjectionPlace, BaseInjection>();
for (BaseInjection exising : existingInjections) {
for (InjectionPlace place : exising.getInjectionPlaces()) {
placeMap.put(place, exising);
}
}
main: for (BaseInjection other : importingInjections) {
final List<BaseInjection> matchingInjections = ContainerUtil.concat(other.getInjectionPlaces(), new Function<InjectionPlace, Collection<? extends BaseInjection>>() {
public Collection<? extends BaseInjection> fun(final InjectionPlace o) {
final Collection<BaseInjection> collection = placeMap.get(o);
return collection == null? Collections.<BaseInjection>emptyList() : collection;
}
});
if (matchingInjections.isEmpty()) {
newInjections.add(other);
}
else {
BaseInjection existing = null;
for (BaseInjection injection : matchingInjections) {
if (injection.equals(other)) continue main;
if (existing == null && injection.sameLanguageParameters(other)) {
existing = injection;
}
}
if (existing == null) continue main; // skip!! language changed
final BaseInjection newInjection = existing.copy();
newInjection.mergeOriginalPlacesFrom(other, true);
if (!newInjection.equals(existing)) {
originalInjections.add(existing);
newInjections.add(newInjection);
}
}
}
}
private void configurationModified() {
incModificationCount();
}
@Nullable
public BaseInjection findExistingInjection(@NotNull final BaseInjection injection) {
final List<BaseInjection> list = getInjections(injection.getSupportId());
for (BaseInjection cur : list) {
if (cur.intersectsWith(injection)) return cur;
}
return null;
}
public boolean setHostInjectionEnabled(final PsiLanguageInjectionHost host, final Collection<String> languages, final boolean enabled) {
final ArrayList<BaseInjection> originalInjections = new ArrayList<BaseInjection>();
final ArrayList<BaseInjection> newInjections = new ArrayList<BaseInjection>();
for (LanguageInjectionSupport support : InjectorUtils.getActiveInjectionSupports()) {
for (BaseInjection injection : getInjections(support.getId())) {
if (!languages.contains(injection.getInjectedLanguageId())) continue;
boolean replace = false;
final ArrayList<InjectionPlace> newPlaces = new ArrayList<InjectionPlace>();
for (InjectionPlace place : injection.getInjectionPlaces()) {
if (place.isEnabled() != enabled && place.getElementPattern() != null &&
(place.getElementPattern().accepts(host) || place.getElementPattern().accepts(host.getParent()))) {
newPlaces.add(place.enabled(enabled));
replace = true;
}
else newPlaces.add(place);
}
if (replace) {
originalInjections.add(injection);
final BaseInjection newInjection = injection.copy();
newInjection.setInjectionPlaces(newPlaces.toArray(new InjectionPlace[newPlaces.size()]));
newInjections.add(newInjection);
}
}
}
if (!originalInjections.isEmpty()) {
replaceInjectionsWithUndo(host.getProject(), newInjections, originalInjections, Collections.<PsiElement>emptyList());
return true;
}
return false;
}
protected void setInjections(Collection<BaseInjection> injections) {
for (BaseInjection injection : injections) {
myInjections.get(injection.getSupportId()).add(injection);
}
}
/**
* @param injectorId see {@link org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport#getId()}
*/
@NotNull
public List<BaseInjection> getInjections(final String injectorId) {
return Collections.unmodifiableList(myInjections.get(injectorId));
}
public void replaceInjectionsWithUndo(final Project project,
final List<? extends BaseInjection> newInjections,
final List<? extends BaseInjection> originalInjections,
final List<? extends PsiElement> psiElementsToRemove) {
replaceInjectionsWithUndo(project, newInjections, originalInjections, psiElementsToRemove,
new PairProcessor<List<? extends BaseInjection>, List<? extends BaseInjection>>() {
public boolean process(final List<? extends BaseInjection> add,
final List<? extends BaseInjection> remove) {
replaceInjectionsWithUndoInner(add, remove);
if (ContainerUtil.find(add, LANGUAGE_INJECTION_CONDITION) != null || ContainerUtil.find(remove,
LANGUAGE_INJECTION_CONDITION) != null) {
FileContentUtil.reparseOpenedFiles();
}
return true;
}
});
}
protected void replaceInjectionsWithUndoInner(final List<? extends BaseInjection> add, final List<? extends BaseInjection> remove) {
replaceInjections(add, remove, false);
}
public static <T> void replaceInjectionsWithUndo(final Project project, final T add, final T remove,
final List<? extends PsiElement> psiElementsToRemove,
final PairProcessor<T, T> actualProcessor) {
final UndoableAction action = new GlobalUndoableAction() {
public void undo() {
actualProcessor.process(remove, add);
}
public void redo() {
actualProcessor.process(add, remove);
}
};
final List<PsiFile> psiFiles = ContainerUtil.mapNotNull(psiElementsToRemove, new NullableFunction<PsiElement, PsiFile>() {
public PsiFile fun(final PsiElement psiAnnotation) {
return psiAnnotation instanceof PsiCompiledElement ? null : psiAnnotation.getContainingFile();
}
});
new WriteCommandAction.Simple(project, "Language Injection Configuration Update", PsiUtilCore.toPsiFileArray(psiFiles)) {
public void run() {
for (PsiElement annotation : psiElementsToRemove) {
annotation.delete();
}
actualProcessor.process(add, remove);
UndoManager.getInstance(project).undoableActionPerformed(action);
}
@Override
protected UndoConfirmationPolicy getUndoConfirmationPolicy() {
return UndoConfirmationPolicy.REQUEST_CONFIRMATION;
}
}.execute();
}
public boolean replaceInjections(List<? extends BaseInjection> newInjections,
List<? extends BaseInjection> originalInjections,
boolean forceLevel) {
boolean changed = false;
for (BaseInjection injection : originalInjections) {
changed |= myInjections.get(injection.getSupportId()).remove(injection);
}
for (BaseInjection injection : newInjections) {
changed |= myInjections.get(injection.getSupportId()).add(injection);
}
if (changed) {
configurationModified();
}
return changed;
}
public static class AdvancedConfiguration {
// runtime pattern validation instrumentation
@NotNull private InstrumentationType myInstrumentationType = InstrumentationType.ASSERT;
// annotation class names
@NotNull private String myLanguageAnnotation;
@NotNull private String myPatternAnnotation;
@NotNull private String mySubstAnnotation;
private boolean myIncludeUncomputablesAsLiterals;
private DfaOption myDfaOption = DfaOption.RESOLVE;
private boolean mySourceModificationAllowed;
// cached annotation name pairs
private Pair<String, ? extends Set<String>> myLanguageAnnotationPair;
private Pair<String, ? extends Set<String>> myPatternAnnotationPair;
private Pair<String, ? extends Set<String>> mySubstAnnotationPair;
public AdvancedConfiguration() {
setLanguageAnnotation("org.intellij.lang.annotations.Language");
setPatternAnnotation("org.intellij.lang.annotations.Pattern");
setSubstAnnotation("org.intellij.lang.annotations.Subst");
}
public String getLanguageAnnotationClass() {
return myLanguageAnnotation;
}
public String getPatternAnnotationClass() {
return myPatternAnnotation;
}
public String getSubstAnnotationClass() {
return mySubstAnnotation;
}
public void setInstrumentationType(@Nullable String type) {
if (type != null) {
setInstrumentationType(InstrumentationType.valueOf(type));
}
}
public void setInstrumentationType(@NotNull InstrumentationType type) {
myInstrumentationType = type;
}
public void setLanguageAnnotation(@Nullable String languageAnnotation) {
if (languageAnnotation == null) return;
myLanguageAnnotation = languageAnnotation;
myLanguageAnnotationPair = Pair.create(languageAnnotation, Collections.singleton(languageAnnotation));
}
public Pair<String, ? extends Set<String>> getLanguageAnnotationPair() {
return myLanguageAnnotationPair;
}
public void setPatternAnnotation(@Nullable String patternAnnotation) {
if (patternAnnotation == null) return;
myPatternAnnotation = patternAnnotation;
myPatternAnnotationPair = Pair.create(patternAnnotation, Collections.singleton(patternAnnotation));
}
public Pair<String, ? extends Set<String>> getPatternAnnotationPair() {
return myPatternAnnotationPair;
}
public void setSubstAnnotation(@Nullable String substAnnotation) {
if (substAnnotation == null) return;
mySubstAnnotation = substAnnotation;
mySubstAnnotationPair = Pair.create(substAnnotation, Collections.singleton(substAnnotation));
}
public Pair<String, ? extends Set<String>> getSubstAnnotationPair() {
return mySubstAnnotationPair;
}
public boolean isIncludeUncomputablesAsLiterals() {
return myIncludeUncomputablesAsLiterals;
}
public void setIncludeUncomputablesAsLiterals(boolean flag) {
myIncludeUncomputablesAsLiterals = flag;
}
@NotNull
public DfaOption getDfaOption() {
return myDfaOption;
}
public void setDfaOption(@NotNull final DfaOption dfaOption) {
myDfaOption = dfaOption;
}
public boolean isSourceModificationAllowed() {
return mySourceModificationAllowed;
}
public void setSourceModificationAllowed(boolean sourceModificationAllowed) {
mySourceModificationAllowed = sourceModificationAllowed;
}
public InstrumentationType getInstrumentation() {
return myInstrumentationType;
}
private void writeState(final Element element) {
JDOMExternalizerUtil.writeField(element, INSTRUMENTATION_TYPE_NAME, myInstrumentationType.toString());
JDOMExternalizerUtil.writeField(element, LANGUAGE_ANNOTATION_NAME, myLanguageAnnotation);
JDOMExternalizerUtil.writeField(element, PATTERN_ANNOTATION_NAME, myPatternAnnotation);
JDOMExternalizerUtil.writeField(element, SUBST_ANNOTATION_NAME, mySubstAnnotation);
if (myIncludeUncomputablesAsLiterals) {
JDOMExternalizerUtil.writeField(element, INCLUDE_UNCOMPUTABLES_AS_LITERALS, "true");
}
if (mySourceModificationAllowed) {
JDOMExternalizerUtil.writeField(element, SOURCE_MODIFICATION_ALLOWED, "true");
}
switch (myDfaOption) {
case OFF:
break;
case RESOLVE:
JDOMExternalizerUtil.writeField(element, RESOLVE_REFERENCES, Boolean.TRUE.toString());
break;
case ASSIGNMENTS:
JDOMExternalizerUtil.writeField(element, LOOK_FOR_VAR_ASSIGNMENTS, Boolean.TRUE.toString());
break;
case DFA:
JDOMExternalizerUtil.writeField(element, USE_DFA_IF_AVAILABLE, Boolean.TRUE.toString());
break;
}
}
private void loadState(final Element element) {
setInstrumentationType(JDOMExternalizerUtil.readField(element, INSTRUMENTATION_TYPE_NAME));
setLanguageAnnotation(JDOMExternalizerUtil.readField(element, LANGUAGE_ANNOTATION_NAME));
setPatternAnnotation(JDOMExternalizerUtil.readField(element, PATTERN_ANNOTATION_NAME));
setSubstAnnotation(JDOMExternalizerUtil.readField(element, SUBST_ANNOTATION_NAME));
if (readBoolean(element, RESOLVE_REFERENCES, true)) {
setDfaOption(DfaOption.RESOLVE);
}
if (readBoolean(element, LOOK_FOR_VAR_ASSIGNMENTS, false)) {
setDfaOption(DfaOption.ASSIGNMENTS);
}
if (readBoolean(element, USE_DFA_IF_AVAILABLE, false)) {
setDfaOption(DfaOption.DFA);
}
setIncludeUncomputablesAsLiterals(readBoolean(element, INCLUDE_UNCOMPUTABLES_AS_LITERALS, false));
setSourceModificationAllowed(readBoolean(element, SOURCE_MODIFICATION_ALLOWED, false));
}
}
}