Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into weigl/key-javaparser3
Browse files Browse the repository at this point in the history
* origin/main: (25 commits)
  bug fix
  applying spotless
  Configurable enabled keys for JML condition evaluation
  Spotless cleanups
  Fix selection highlight for OSS node child
  Remove unnecessary checks for correct change as listener is now registered correctly only for changes of interest
  Make usage of PropertyChangeListeners working (addendum to previous commit)
  Reduce number of sequentview updates
  Remove duplicate update of sequentview
  USe refactorings from #3369 but preserve non-local filter semantics for proof tree view
  MainWindow updates sequent view after settings change for pretty printing
  Minor clean up to slightly simplify complexity of path selection in ProofTreeView
  Fix problem with closed subtree filter
  Fix node filter selection display in popup dialoh and some refactoring
  Restore correct node selection and remove unused fields from GUIProofTreeModel
  Store ProofTreeViewSettings per proof outside model and restore all settings upon switching
  Fix update of proof tree in case of filter changes (fixes #3367)
  applying spotless
  Bump com.miglayout:miglayout-swing from 11.2 to 11.3
  Configurable enabled keys for JML condition evaluation
  ...

# Conflicts:
#	key.ui/build.gradle
  • Loading branch information
wadoon committed Dec 29, 2023
2 parents a1581bf + 5dc944b commit 8fb85f9
Show file tree
Hide file tree
Showing 36 changed files with 506 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void readSettings(Configuration props) {
if (cat == null)
return;
propertyEntries.forEach(it -> {
final var value = cat.get(it.getKey());
final var value = it.fromObject(cat.get(it.getKey()));
if (value != null) {
properties.put(it.getKey(), value);
}
Expand All @@ -127,39 +127,45 @@ public void writeSettings(Configuration props) {
}

protected PropertyEntry<Double> createDoubleProperty(String key, double defValue) {
PropertyEntry<Double> pe = new DefaultPropertyEntry<>(key, defValue, parseDouble);
PropertyEntry<Double> pe =
new DefaultPropertyEntry<>(key, defValue, parseDouble, (it) -> (double) it);
propertyEntries.add(pe);
return pe;
}

protected PropertyEntry<Integer> createIntegerProperty(String key, int defValue) {
PropertyEntry<Integer> pe = new DefaultPropertyEntry<>(key, defValue, parseInt);
PropertyEntry<Integer> pe = new DefaultPropertyEntry<>(key, defValue, parseInt,
(it) -> Math.toIntExact((Long) it));
propertyEntries.add(pe);
return pe;
}

protected PropertyEntry<Float> createFloatProperty(String key, float defValue) {
PropertyEntry<Float> pe = new DefaultPropertyEntry<>(key, defValue, parseFloat);
PropertyEntry<Float> pe =
new DefaultPropertyEntry<>(key, defValue, parseFloat, (it) -> (float) (double) it);
propertyEntries.add(pe);
return pe;
}

protected PropertyEntry<String> createStringProperty(String key, String defValue) {
PropertyEntry<String> pe = new DefaultPropertyEntry<>(key, defValue, id -> id);
PropertyEntry<String> pe =
new DefaultPropertyEntry<>(key, defValue, id -> id, Object::toString);
propertyEntries.add(pe);
return pe;
}

protected PropertyEntry<Boolean> createBooleanProperty(String key, boolean defValue) {
PropertyEntry<Boolean> pe = new DefaultPropertyEntry<>(key, defValue, parseBoolean);
PropertyEntry<Boolean> pe =
new DefaultPropertyEntry<>(key, defValue, parseBoolean, (it) -> (Boolean) it);
propertyEntries.add(pe);
return pe;
}

protected PropertyEntry<Set<String>> createStringSetProperty(String key, String defValue) {
PropertyEntry<Set<String>> pe = new DefaultPropertyEntry<>(key, parseStringSet(defValue),
AbstractPropertiesSettings::parseStringSet,
AbstractPropertiesSettings::stringSetToString);
AbstractPropertiesSettings::stringSetToString,
(it) -> new LinkedHashSet<>((Collection<String>) it));
propertyEntries.add(pe);
return pe;
}
Expand All @@ -175,7 +181,7 @@ protected PropertyEntry<List<String>> createStringListProperty(@NonNull String k
@Nullable String defValue) {
PropertyEntry<List<String>> pe = new DefaultPropertyEntry<>(key, parseStringList(defValue),
AbstractPropertiesSettings::parseStringList,
AbstractPropertiesSettings::stringListToString);
AbstractPropertiesSettings::stringListToString, it -> (List<String>) it);
propertyEntries.add(pe);
return pe;
}
Expand All @@ -195,6 +201,8 @@ default void update() {
}

String value();

T fromObject(@Nullable Object o);
}


Expand All @@ -204,16 +212,20 @@ class DefaultPropertyEntry<T> implements PropertyEntry<T> {
private final Function<String, T> convert;
private final Function<T, String> toString;

private DefaultPropertyEntry(String key, T defaultValue, Function<String, T> convert) {
this(key, defaultValue, convert, Objects::toString);
private final Function<Object, T> fromObject;

private DefaultPropertyEntry(String key, T defaultValue, Function<String, T> convert,
Function<Object, T> fromObject) {
this(key, defaultValue, convert, Objects::toString, fromObject);
}

private DefaultPropertyEntry(String key, T defaultValue, Function<String, T> convert,
Function<T, String> toString) {
Function<T, String> toString, Function<Object, T> fromObject) {
this.key = key;
this.defaultValue = defaultValue;
this.convert = convert;
this.toString = toString;
this.fromObject = fromObject;
}

@Override
Expand Down Expand Up @@ -255,5 +267,10 @@ public String value() {
return toString.apply(v);
}
}

@Override
public T fromObject(@Nullable Object o) {
return fromObject.apply(o);
}
}
}
206 changes: 206 additions & 0 deletions key.core/src/main/java/de/uka/ilkd/key/settings/FeatureSettings.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/* This file is part of KeY - https://key-project.org
* KeY is licensed under the GNU General Public License Version 2
* SPDX-License-Identifier: GPL-2.0-only */
package de.uka.ilkd.key.settings;

import java.util.*;
import java.util.function.Consumer;

import org.jspecify.annotations.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Feature flags for the selected and deselected of experimental features.
* <p>
* In the old days of KeY, we used to have {@code --experimental} flag, which was a bad idea.
* You cannot control which feature you want to activate.
* Instead, you are getting the full load of fun(ctionality). This class allows you to have more
* fine-grained feature flags by defining feature flags which are controllable by the user.
*
* @author Alexander Weigl
* @version 1 (04.12.23)
*/
public class FeatureSettings extends AbstractSettings {
private static final Logger LOGGER = LoggerFactory.getLogger(FeatureSettings.class);
private static final String CATEGORY = "Feature";

/**
* unstored, set by {@code --experimental}
*/
private boolean activateAll = false;

/**
* persistent list of activated features
*/
private final Set<String> activatedFeatures = new TreeSet<>();

public FeatureSettings() {
readFromSystemProperties();
}

public static boolean isFeatureActivated(Feature f) {
return ProofIndependentSettings.DEFAULT_INSTANCE.getFeatureSettings().isActivated(f);
}

public static boolean isFeatureActivated(String s) {
return ProofIndependentSettings.DEFAULT_INSTANCE.getFeatureSettings().isActivated(s);
}

/**
* Helper function for notification on feature flag changes.
*
* @param feature the feature to be listening on
* @param update a callback function which gets informed on changes with the new value
*/
public static void on(Feature feature, Consumer<Boolean> update) {
ProofIndependentSettings.DEFAULT_INSTANCE.getFeatureSettings().addPropertyChangeListener(
feature.id, evt -> update.accept((Boolean) evt.getNewValue()));
}

/**
* Helper function for notification on feature flag changes which also calls the consumer.
*
* @param feature the feature to be listening on
* @param update a callback function which gets informed on changes with the new value
*/
public static void onAndActivate(Feature feature, Consumer<Boolean> update) {
on(feature, update);
update.accept(isFeatureActivated(feature));
}

/**
* Use the system properties ({@code -P FEATURE:XXX=true} to activate a feature from the command
* line.
*/
private void readFromSystemProperties() {
var prefix = CATEGORY.toUpperCase() + ":";
for (Map.Entry<Object, Object> entries : System.getProperties().entrySet()) {
final var s = entries.getKey().toString();
if (s.startsWith(prefix) && isTrue(entries.getValue())) {
final var feature = s.substring(prefix.length());
activate(feature);
LOGGER.info("Activate feature: {}", feature);
}
}
}

/**
* Checks if the given {@code value} represents something like to true.
*
* @return true, if {@code value} feels like a feature activation.
*/
private boolean isTrue(Object value) {
return switch (value.toString().toLowerCase()) {
case "true", "yes", "on" -> true;
default -> false;
};
}

@Override
public void readSettings(Properties props) {
activatedFeatures.clear();
var prefix = "[" + CATEGORY + "]";
for (Map.Entry<Object, Object> entries : props.entrySet()) {
final var s = entries.getKey().toString();
if (s.startsWith(prefix) && isTrue(entries.getValue())) {
final var feature = s.substring(prefix.length());
activate(feature);
LOGGER.info("Activate feature: {}", feature);
}
}
}

@Override
public void writeSettings(Properties props) {
var prefix = "[" + CATEGORY + "]";
for (String activatedFeature : activatedFeatures) {
props.put(prefix + activatedFeature, "true");
}
}

@Override
public void readSettings(@NonNull Configuration props) {
activatedFeatures.clear();
for (String s : props.getStringList(CATEGORY)) {
activate(s);
}
}

@Override
public void writeSettings(@NonNull Configuration props) {
props.set(CATEGORY, activatedFeatures.stream().toList());
}

public boolean isActivated(Feature f) {
return isActivated(f.id);
}

private boolean isActivated(String id) {
if (activateAll)
return true;
return activatedFeatures.contains(id);
}

/**
* Activates the given feature {@code f}.
*/
public void activate(Feature f) {
activate(f.id);
}

/**
* Activates the given feature by {@code id}.
*/
private void activate(String id) {
if (!isActivated(id)) {
activatedFeatures.add(id);
firePropertyChange(id, false, isActivated(id));
}
}

/**
* Deactivates the given feature {@code f}.
*/
public void deactivate(Feature f) {
deactivate(f.id);
}

/**
* Deactivates the given feature by {@code id}.
*/
private void deactivate(String id) {
if (isActivated(id)) {
firePropertyChange(id, true, isActivated(id));
activatedFeatures.remove(id);
}
}

public void setActivateAll(boolean b) {
activateAll = b;
}

public boolean isActivateAll() {
return activateAll;
}

public static Feature createFeature(String id) {
return createFeature(id, "", true);
}

public static Feature createFeature(String id, String doc) {
return new Feature(id, doc, true);
}

public static Feature createFeature(String id, String doc, boolean restartRequired) {
return new Feature(id, doc, restartRequired);
}

public record Feature(String id, String documentation, boolean restartRequired) {
public static final List<Feature> FEATURES = new ArrayList<>();

public Feature {
FEATURES.add(this);
}
}
}
Loading

0 comments on commit 8fb85f9

Please sign in to comment.