mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Conditions - Move to new paths API (WIP)
This commit is contained in:
parent
a2759d007e
commit
da132fa4e9
@ -50,6 +50,6 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="a">The parameter on the left side of the expression</param>
|
/// <param name="a">The parameter on the left side of the expression</param>
|
||||||
/// <param name="b">The parameter on the right side of the expression</param>
|
/// <param name="b">The parameter on the right side of the expression</param>
|
||||||
public abstract bool Evaluate(object a, object b);
|
public abstract bool Evaluate(object? a, object? b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,7 +2,6 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.DataModelExpansions;
|
||||||
using Artemis.Storage.Entities.Profile.Abstract;
|
using Artemis.Storage.Entities.Profile.Abstract;
|
||||||
using Artemis.Storage.Entities.Profile.Conditions;
|
using Artemis.Storage.Entities.Profile.Conditions;
|
||||||
@ -37,37 +36,27 @@ namespace Artemis.Core
|
|||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DataModelConditionListEntity Entity { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the list operator
|
/// Gets or sets the list operator
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ListOperator ListOperator { get; set; }
|
public ListOperator ListOperator { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the path of the list property
|
||||||
|
/// </summary>
|
||||||
|
public DataModelPath? ListPath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the type of the content of the list this predicate is evaluated on
|
/// Gets the type of the content of the list this predicate is evaluated on
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Type ListType { get; set; }
|
public Type? ListType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets whether the list contains primitives
|
/// Gets whether the list contains primitives
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsPrimitiveList { get; set; }
|
public bool IsPrimitiveList { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
internal DataModelConditionListEntity Entity { get; set; }
|
||||||
/// Gets the currently used instance of the list data model
|
|
||||||
/// </summary>
|
|
||||||
public DataModel ListDataModel { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the path of the list property in the <see cref="ListDataModel" />
|
|
||||||
/// </summary>
|
|
||||||
public string ListPropertyPath { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the compiled function that accesses the list this condition evaluates on
|
|
||||||
/// </summary>
|
|
||||||
public Func<object, IList> CompiledListAccessor { get; private set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Evaluate()
|
public override bool Evaluate()
|
||||||
@ -75,10 +64,10 @@ namespace Artemis.Core
|
|||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DataModelConditionList");
|
throw new ObjectDisposedException("DataModelConditionList");
|
||||||
|
|
||||||
if (CompiledListAccessor == null)
|
if (ListPath == null || !ListPath.IsValid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return EvaluateObject(CompiledListAccessor(ListDataModel));
|
return EvaluateObject(ListPath.GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -86,7 +75,7 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataModel">The data model of the list</param>
|
/// <param name="dataModel">The data model of the list</param>
|
||||||
/// <param name="path">The path pointing to the list inside the list</param>
|
/// <param name="path">The path pointing to the list inside the list</param>
|
||||||
public void UpdateList(DataModel dataModel, string path)
|
public void UpdateList(DataModel? dataModel, string? path)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DataModelConditionList");
|
throw new ObjectDisposedException("DataModelConditionList");
|
||||||
@ -96,17 +85,23 @@ namespace Artemis.Core
|
|||||||
if (dataModel == null && path != null)
|
if (dataModel == null && path != null)
|
||||||
throw new ArtemisCoreException("If path is provided, a data model is also required");
|
throw new ArtemisCoreException("If path is provided, a data model is also required");
|
||||||
|
|
||||||
if (dataModel != null)
|
ListPath?.Dispose();
|
||||||
|
if (dataModel != null && path != null)
|
||||||
{
|
{
|
||||||
Type listType = dataModel.GetListTypeAtPath(path);
|
DataModelPath newPath = new DataModelPath(dataModel, path);
|
||||||
if (listType == null)
|
if (!newPath.IsValid)
|
||||||
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a list at path '{path}'");
|
throw new ArtemisCoreException($"New left path '{newPath}' is invalid");
|
||||||
|
Type listType = newPath.GetPropertyType()!;
|
||||||
|
if (!typeof(IList).IsAssignableFrom(listType))
|
||||||
|
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a list at path '{newPath}'");
|
||||||
|
|
||||||
ListType = listType;
|
ListType = listType;
|
||||||
IsPrimitiveList = listType.IsPrimitive || listType.IsEnum || listType == typeof(string);
|
IsPrimitiveList = listType.IsPrimitive || listType.IsEnum || listType == typeof(string);
|
||||||
|
}
|
||||||
ListDataModel = dataModel;
|
else
|
||||||
ListPropertyPath = path;
|
{
|
||||||
|
ListPath = null;
|
||||||
|
ListType = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the old root group that was tied to the old data model
|
// Remove the old root group that was tied to the old data model
|
||||||
@ -118,7 +113,6 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
// Create a new root group
|
// Create a new root group
|
||||||
AddChild(new DataModelConditionGroup(this));
|
AddChild(new DataModelConditionGroup(this));
|
||||||
CreateExpression();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
@ -128,8 +122,7 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
|
ListPath?.Dispose();
|
||||||
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
|
|
||||||
|
|
||||||
foreach (DataModelConditionPart child in Children)
|
foreach (DataModelConditionPart child in Children)
|
||||||
child.Dispose();
|
child.Dispose();
|
||||||
@ -139,7 +132,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
internal override bool EvaluateObject(object target)
|
internal override bool EvaluateObject(object? target)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DataModelConditionList");
|
throw new ObjectDisposedException("DataModelConditionList");
|
||||||
@ -163,11 +156,8 @@ namespace Artemis.Core
|
|||||||
internal override void Save()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
// Target list
|
// Target list
|
||||||
if (ListDataModel != null)
|
ListPath?.Save();
|
||||||
{
|
Entity.ListPath = ListPath?.Entity;
|
||||||
Entity.ListDataModelGuid = ListDataModel.PluginInfo.Guid;
|
|
||||||
Entity.ListPropertyPath = ListPropertyPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operator
|
// Operator
|
||||||
Entity.ListOperator = (int) ListOperator;
|
Entity.ListOperator = (int) ListOperator;
|
||||||
@ -186,80 +176,27 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void Initialize()
|
internal void Initialize()
|
||||||
{
|
{
|
||||||
DataModelStore.DataModelAdded += DataModelStoreOnDataModelAdded;
|
if (Entity.ListPath == null)
|
||||||
DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
|
|
||||||
if (Entity.ListDataModelGuid == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get the data model ...
|
// Ensure the list path is valid and points to a list
|
||||||
DataModel dataModel = DataModelStore.Get(Entity.ListDataModelGuid.Value)?.DataModel;
|
DataModelPath listPath = new DataModelPath(null, Entity.ListPath);
|
||||||
if (dataModel == null)
|
if (!listPath.IsValid || !typeof(IList).IsAssignableFrom(listPath.GetPropertyType()))
|
||||||
return;
|
|
||||||
// ... and ensure the path is valid
|
|
||||||
Type listType = dataModel.GetListTypeAtPath(Entity.ListPropertyPath);
|
|
||||||
if (listType == null)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ListType = listType;
|
ListPath = listPath;
|
||||||
IsPrimitiveList = listType.IsPrimitive || listType.IsEnum || listType == typeof(string);
|
|
||||||
ListDataModel = dataModel;
|
|
||||||
ListPropertyPath = Entity.ListPropertyPath;
|
|
||||||
|
|
||||||
CreateExpression();
|
|
||||||
|
|
||||||
if (ListDataModel == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// There should only be one child and it should be a group
|
// There should only be one child and it should be a group
|
||||||
if (Entity.Children.SingleOrDefault() is DataModelConditionGroupEntity rootGroup)
|
if (Entity.Children.SingleOrDefault() is DataModelConditionGroupEntity rootGroup)
|
||||||
|
{
|
||||||
AddChild(new DataModelConditionGroup(this, rootGroup));
|
AddChild(new DataModelConditionGroup(this, rootGroup));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Entity.Children.Clear();
|
Entity.Children.Clear();
|
||||||
AddChild(new DataModelConditionGroup(this));
|
AddChild(new DataModelConditionGroup(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateExpression()
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
throw new ObjectDisposedException("DataModelConditionList");
|
|
||||||
|
|
||||||
ParameterExpression parameter = Expression.Parameter(typeof(object), "listDataModel");
|
|
||||||
Expression accessor = ListPropertyPath.Split('.').Aggregate<string, Expression>(
|
|
||||||
Expression.Convert(parameter, ListDataModel.GetType()),
|
|
||||||
Expression.Property
|
|
||||||
);
|
|
||||||
accessor = Expression.Convert(accessor, typeof(IList));
|
|
||||||
|
|
||||||
Expression<Func<object, IList>> lambda = Expression.Lambda<Func<object, IList>>(accessor, parameter);
|
|
||||||
CompiledListAccessor = lambda.Compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region Event handlers
|
|
||||||
|
|
||||||
private void DataModelStoreOnDataModelAdded(object sender, DataModelStoreEvent e)
|
|
||||||
{
|
|
||||||
DataModel dataModel = e.Registration.DataModel;
|
|
||||||
if (dataModel.PluginInfo.Guid == Entity.ListDataModelGuid && dataModel.ContainsPath(Entity.ListPropertyPath))
|
|
||||||
{
|
|
||||||
ListDataModel = dataModel;
|
|
||||||
ListPropertyPath = Entity.ListPropertyPath;
|
|
||||||
CreateExpression();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DataModelStoreOnDataModelRemoved(object sender, DataModelStoreEvent e)
|
|
||||||
{
|
|
||||||
if (ListDataModel != e.Registration.DataModel)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ListDataModel = null;
|
|
||||||
CompiledListAccessor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.DataModelExpansions;
|
||||||
using Artemis.Storage.Entities.Profile.Abstract;
|
using Artemis.Storage.Entities.Profile.Abstract;
|
||||||
using Artemis.Storage.Entities.Profile.Conditions;
|
using Artemis.Storage.Entities.Profile.Conditions;
|
||||||
@ -45,36 +43,23 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the operator
|
/// Gets the operator
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ConditionOperator Operator { get; private set; }
|
public ConditionOperator? Operator { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the currently used instance of the left data model
|
/// Gets the path of the left property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataModel LeftDataModel { get; private set; }
|
public DataModelPath? LeftPath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the path of the left property in the <see cref="LeftDataModel" />
|
/// Gets the path of the right property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LeftPropertyPath { get; private set; }
|
public DataModelPath? RightPath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the currently used instance of the right data model
|
|
||||||
/// </summary>
|
|
||||||
public DataModel RightDataModel { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the path of the right property in the <see cref="RightDataModel" />
|
|
||||||
/// </summary>
|
|
||||||
public string RightPropertyPath { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the right static value, only used it <see cref="PredicateType" /> is
|
/// Gets the right static value, only used it <see cref="PredicateType" /> is
|
||||||
/// <see cref="ProfileRightSideType.Static" />
|
/// <see cref="ProfileRightSideType.Static" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object RightStaticValue { get; private set; }
|
public object? RightStaticValue { get; private set; }
|
||||||
|
|
||||||
public Func<object, object> LeftSideAccessor { get; set; }
|
|
||||||
public Func<object, object> RightSideAccessor { get; set; }
|
|
||||||
|
|
||||||
internal DataModelConditionPredicateEntity Entity { get; set; }
|
internal DataModelConditionPredicateEntity Entity { get; set; }
|
||||||
|
|
||||||
@ -83,26 +68,28 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataModel">The data model of the left side value</param>
|
/// <param name="dataModel">The data model of the left side value</param>
|
||||||
/// <param name="path">The path pointing to the left side value inside the data model</param>
|
/// <param name="path">The path pointing to the left side value inside the data model</param>
|
||||||
public void UpdateLeftSide(DataModel dataModel, string path)
|
public void UpdateLeftSide(DataModel? dataModel, string? path)
|
||||||
{
|
{
|
||||||
if (dataModel != null && path == null)
|
if (dataModel != null && path == null)
|
||||||
throw new ArtemisCoreException("If a data model is provided, a path is also required");
|
throw new ArtemisCoreException("If a data model is provided, a path is also required");
|
||||||
if (dataModel == null && path != null)
|
if (dataModel == null && path != null)
|
||||||
throw new ArtemisCoreException("If path is provided, a data model is also required");
|
throw new ArtemisCoreException("If path is provided, a data model is also required");
|
||||||
|
|
||||||
if (dataModel != null)
|
LeftPath?.Dispose();
|
||||||
|
if (dataModel != null && path != null)
|
||||||
{
|
{
|
||||||
if (!dataModel.ContainsPath(path))
|
DataModelPath newPath = new DataModelPath(dataModel, path);
|
||||||
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a property at path '{path}'");
|
if (!newPath.IsValid)
|
||||||
|
throw new ArtemisCoreException($"New left path '{newPath}' is invalid");
|
||||||
|
LeftPath = newPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LeftPath = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
LeftDataModel = dataModel;
|
|
||||||
LeftPropertyPath = path;
|
|
||||||
|
|
||||||
ValidateOperator();
|
ValidateOperator();
|
||||||
ValidateRightSide();
|
ValidateRightSide();
|
||||||
|
|
||||||
CreateAccessors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -110,44 +97,48 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataModel">The data model of the right side value</param>
|
/// <param name="dataModel">The data model of the right side value</param>
|
||||||
/// <param name="path">The path pointing to the right side value inside the data model</param>
|
/// <param name="path">The path pointing to the right side value inside the data model</param>
|
||||||
public void UpdateRightSide(DataModel dataModel, string path)
|
public void UpdateRightSide(DataModel? dataModel, string? path)
|
||||||
{
|
{
|
||||||
if (dataModel != null && path == null)
|
if (dataModel != null && path == null)
|
||||||
throw new ArtemisCoreException("If a data model is provided, a path is also required");
|
throw new ArtemisCoreException("If a data model is provided, a path is also required");
|
||||||
if (dataModel == null && path != null)
|
if (dataModel == null && path != null)
|
||||||
throw new ArtemisCoreException("If path is provided, a data model is also required");
|
throw new ArtemisCoreException("If path is provided, a data model is also required");
|
||||||
|
|
||||||
if (dataModel != null)
|
RightPath?.Dispose();
|
||||||
|
if (dataModel != null && path != null)
|
||||||
{
|
{
|
||||||
if (!dataModel.ContainsPath(path))
|
DataModelPath newPath = new DataModelPath(dataModel, path);
|
||||||
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a property at path '{path}'");
|
if (!newPath.IsValid)
|
||||||
|
throw new ArtemisCoreException($"New right path '{newPath}' is invalid");
|
||||||
|
RightPath = newPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RightPath = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
PredicateType = ProfileRightSideType.Dynamic;
|
PredicateType = ProfileRightSideType.Dynamic;
|
||||||
RightDataModel = dataModel;
|
|
||||||
RightPropertyPath = path;
|
|
||||||
|
|
||||||
CreateAccessors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the right side of the predicate, makes the predicate static and re-compiles the expression
|
/// Updates the right side of the predicate, makes the predicate static and re-compiles the expression
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="staticValue">The right side value to use</param>
|
/// <param name="staticValue">The right side value to use</param>
|
||||||
public void UpdateRightSide(object staticValue)
|
public void UpdateRightSide(object? staticValue)
|
||||||
{
|
{
|
||||||
PredicateType = ProfileRightSideType.Static;
|
PredicateType = ProfileRightSideType.Static;
|
||||||
RightDataModel = null;
|
RightPath?.Dispose();
|
||||||
RightPropertyPath = null;
|
RightPath = null;
|
||||||
|
|
||||||
// If the left side is empty simply apply the value, any validation will wait
|
// If the left side is empty simply apply the value, any validation will wait
|
||||||
if (LeftDataModel == null)
|
if (LeftPath == null || !LeftPath.IsValid)
|
||||||
{
|
{
|
||||||
RightStaticValue = staticValue;
|
RightStaticValue = staticValue;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type leftSideType = LeftDataModel.GetTypeAtPath(LeftPropertyPath);
|
// If the left path is valid we can expect a type
|
||||||
|
Type leftSideType = LeftPath.GetPropertyType()!;
|
||||||
|
|
||||||
// If not null ensure the types match and if not, convert it
|
// If not null ensure the types match and if not, convert it
|
||||||
if (staticValue != null && staticValue.GetType() == leftSideType)
|
if (staticValue != null && staticValue.GetType() == leftSideType)
|
||||||
@ -159,63 +150,77 @@ namespace Artemis.Core
|
|||||||
RightStaticValue = Activator.CreateInstance(leftSideType);
|
RightStaticValue = Activator.CreateInstance(leftSideType);
|
||||||
else
|
else
|
||||||
RightStaticValue = null;
|
RightStaticValue = null;
|
||||||
|
|
||||||
CreateAccessors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the operator of the predicate and re-compiles the expression
|
/// Updates the operator of the predicate and re-compiles the expression
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="conditionOperator"></param>
|
/// <param name="conditionOperator"></param>
|
||||||
public void UpdateOperator(ConditionOperator conditionOperator)
|
public void UpdateOperator(ConditionOperator? conditionOperator)
|
||||||
{
|
{
|
||||||
// Calling CreateExpression will clear compiled expressions
|
// Calling CreateExpression will clear compiled expressions
|
||||||
if (conditionOperator == null)
|
if (conditionOperator == null)
|
||||||
{
|
{
|
||||||
Operator = null;
|
Operator = null;
|
||||||
CreateAccessors();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No need to clear compiled expressions, without a left data model they are already null
|
// No need to clear compiled expressions, without a left data model they are already null
|
||||||
if (LeftDataModel == null)
|
if (LeftPath == null || !LeftPath.IsValid)
|
||||||
{
|
{
|
||||||
Operator = conditionOperator;
|
Operator = conditionOperator;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type leftType = LeftDataModel.GetTypeAtPath(LeftPropertyPath);
|
Type leftType = LeftPath.GetPropertyType()!;
|
||||||
if (!conditionOperator.SupportsType(leftType))
|
if (!conditionOperator.SupportsType(leftType))
|
||||||
{
|
|
||||||
throw new ArtemisCoreException($"Cannot apply operator {conditionOperator.GetType().Name} to this predicate because " +
|
throw new ArtemisCoreException($"Cannot apply operator {conditionOperator.GetType().Name} to this predicate because " +
|
||||||
$"it does not support left side type {leftType.Name}");
|
$"it does not support left side type {leftType.Name}");
|
||||||
}
|
|
||||||
|
|
||||||
Operator = conditionOperator;
|
Operator = conditionOperator;
|
||||||
CreateAccessors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Evaluate()
|
public override bool Evaluate()
|
||||||
{
|
{
|
||||||
if (Operator == null || LeftSideAccessor == null || PredicateType != ProfileRightSideType.Static && RightSideAccessor == null)
|
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Compare with a static value
|
// Compare with a static value
|
||||||
if (PredicateType == ProfileRightSideType.Static)
|
if (PredicateType == ProfileRightSideType.Static)
|
||||||
{
|
{
|
||||||
object leftSideValue = LeftSideAccessor(LeftDataModel);
|
object? leftSideValue = LeftPath.GetValue();
|
||||||
if (leftSideValue.GetType().IsValueType && RightStaticValue == null)
|
if (leftSideValue != null && leftSideValue.GetType().IsValueType && RightStaticValue == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return Operator.Evaluate(leftSideValue, RightStaticValue);
|
return Operator.Evaluate(leftSideValue, RightStaticValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare with dynamic values
|
if (RightPath == null || !RightPath.IsValid)
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic)
|
return false;
|
||||||
return Operator.Evaluate(LeftSideAccessor(LeftDataModel), RightSideAccessor(RightDataModel));
|
|
||||||
|
|
||||||
return false;
|
// Compare with dynamic values
|
||||||
|
return Operator.Evaluate(LeftPath.GetValue(), RightPath.GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (PredicateType == ProfileRightSideType.Dynamic)
|
||||||
|
return $"[Dynamic] {LeftPath} {Operator.Description} {RightPath}";
|
||||||
|
return $"[Static] {LeftPath} {Operator.Description} {RightStaticValue}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
|
||||||
|
ConditionOperatorStore.ConditionOperatorRemoved -= ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||||
|
|
||||||
|
LeftPath?.Dispose();
|
||||||
|
RightPath?.Dispose();
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -224,22 +229,15 @@ namespace Artemis.Core
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic)
|
|
||||||
return $"[Dynamic] {LeftPropertyPath} {Operator.Description} {RightPropertyPath}";
|
|
||||||
return $"[Static] {LeftPropertyPath} {Operator.Description} {RightStaticValue}";
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override void Save()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
Entity.PredicateType = (int) PredicateType;
|
Entity.PredicateType = (int) PredicateType;
|
||||||
Entity.LeftDataModelGuid = LeftDataModel?.PluginInfo?.Guid;
|
|
||||||
Entity.LeftPropertyPath = LeftPropertyPath;
|
|
||||||
|
|
||||||
Entity.RightDataModelGuid = RightDataModel?.PluginInfo?.Guid;
|
LeftPath?.Save();
|
||||||
Entity.RightPropertyPath = RightPropertyPath;
|
Entity.LeftPath = LeftPath?.Entity;
|
||||||
|
RightPath?.Save();
|
||||||
|
Entity.RightPath = RightPath?.Entity;
|
||||||
|
|
||||||
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
||||||
|
|
||||||
Entity.OperatorPluginGuid = Operator?.PluginInfo?.Guid;
|
Entity.OperatorPluginGuid = Operator?.PluginInfo?.Guid;
|
||||||
@ -248,44 +246,32 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void Initialize()
|
internal void Initialize()
|
||||||
{
|
{
|
||||||
DataModelStore.DataModelAdded += DataModelStoreOnDataModelAdded;
|
|
||||||
DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
|
|
||||||
ConditionOperatorStore.ConditionOperatorAdded += ConditionOperatorStoreOnConditionOperatorAdded;
|
ConditionOperatorStore.ConditionOperatorAdded += ConditionOperatorStoreOnConditionOperatorAdded;
|
||||||
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||||
|
|
||||||
// Left side
|
// Left side
|
||||||
if (Entity.LeftDataModelGuid != null)
|
if (Entity.LeftPath != null) LeftPath = new DataModelPath(null, Entity.LeftPath);
|
||||||
{
|
|
||||||
DataModel dataModel = DataModelStore.Get(Entity.LeftDataModelGuid.Value)?.DataModel;
|
|
||||||
if (dataModel != null && dataModel.ContainsPath(Entity.LeftPropertyPath))
|
|
||||||
UpdateLeftSide(dataModel, Entity.LeftPropertyPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Operator
|
// Operator
|
||||||
if (Entity.OperatorPluginGuid != null)
|
if (Entity.OperatorPluginGuid != null)
|
||||||
{
|
{
|
||||||
ConditionOperator conditionOperator = ConditionOperatorStore.Get(Entity.OperatorPluginGuid.Value, Entity.OperatorType)?.ConditionOperator;
|
ConditionOperator? conditionOperator = ConditionOperatorStore.Get(Entity.OperatorPluginGuid.Value, Entity.OperatorType)?.ConditionOperator;
|
||||||
if (conditionOperator != null)
|
if (conditionOperator != null)
|
||||||
UpdateOperator(conditionOperator);
|
UpdateOperator(conditionOperator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right side dynamic
|
// Right side dynamic
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightDataModelGuid != null)
|
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPath != null)
|
||||||
{
|
RightPath = new DataModelPath(null, Entity.RightPath);
|
||||||
DataModel dataModel = DataModelStore.Get(Entity.RightDataModelGuid.Value)?.DataModel;
|
|
||||||
if (dataModel != null && dataModel.ContainsPath(Entity.RightPropertyPath))
|
|
||||||
UpdateRightSide(dataModel, Entity.RightPropertyPath);
|
|
||||||
}
|
|
||||||
// Right side static
|
// Right side static
|
||||||
else if (PredicateType == ProfileRightSideType.Static && Entity.RightStaticValue != null)
|
else if (PredicateType == ProfileRightSideType.Static && Entity.RightStaticValue != null)
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (LeftDataModel != null)
|
if (LeftPath != null && LeftPath.IsValid)
|
||||||
{
|
{
|
||||||
// Use the left side type so JSON.NET has a better idea what to do
|
// Use the left side type so JSON.NET has a better idea what to do
|
||||||
Type leftSideType = LeftDataModel.GetTypeAtPath(LeftPropertyPath);
|
Type leftSideType = LeftPath.GetPropertyType()!;
|
||||||
object rightSideValue;
|
object? rightSideValue;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -311,7 +297,6 @@ namespace Artemis.Core
|
|||||||
// ignored
|
// ignored
|
||||||
// TODO: Some logging would be nice
|
// TODO: Some logging would be nice
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override DataModelConditionPartEntity GetEntity()
|
internal override DataModelConditionPartEntity GetEntity()
|
||||||
@ -319,119 +304,47 @@ namespace Artemis.Core
|
|||||||
return Entity;
|
return Entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateAccessors()
|
|
||||||
{
|
|
||||||
if (Operator == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If the operator does not support a right side, create a static expression because the right side will simply be null
|
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic && Operator.SupportsRightSide)
|
|
||||||
CreateDynamicAccessors();
|
|
||||||
else
|
|
||||||
CreateStaticExpression();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ValidateOperator()
|
private void ValidateOperator()
|
||||||
{
|
{
|
||||||
if (LeftDataModel == null || Operator == null)
|
if (LeftPath == null || !LeftPath.IsValid || Operator == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Type leftType = LeftDataModel.GetTypeAtPath(LeftPropertyPath);
|
Type leftType = LeftPath.GetPropertyType()!;
|
||||||
if (!Operator.SupportsType(leftType))
|
if (!Operator.SupportsType(leftType))
|
||||||
Operator = null;
|
Operator = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateRightSide()
|
private void ValidateRightSide()
|
||||||
{
|
{
|
||||||
Type leftSideType = LeftDataModel.GetTypeAtPath(LeftPropertyPath);
|
Type? leftType = LeftPath?.GetPropertyType();
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic)
|
if (PredicateType == ProfileRightSideType.Dynamic)
|
||||||
{
|
{
|
||||||
if (RightDataModel == null)
|
if (RightPath == null || !RightPath.IsValid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Type rightSideType = RightDataModel.GetTypeAtPath(RightPropertyPath);
|
Type rightSideType = RightPath.GetPropertyType()!;
|
||||||
if (!leftSideType.IsCastableFrom(rightSideType))
|
if (leftType != null && !leftType.IsCastableFrom(rightSideType))
|
||||||
UpdateRightSide(null, null);
|
UpdateRightSide(null, null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (RightStaticValue != null && leftSideType.IsCastableFrom(RightStaticValue.GetType()))
|
if (RightStaticValue != null && (leftType == null || leftType.IsCastableFrom(RightStaticValue.GetType())))
|
||||||
UpdateRightSide(RightStaticValue);
|
UpdateRightSide(RightStaticValue);
|
||||||
else
|
else
|
||||||
UpdateRightSide(null);
|
UpdateRightSide(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateDynamicAccessors()
|
|
||||||
{
|
|
||||||
if (LeftDataModel == null || RightDataModel == null || Operator == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Expression leftSideAccessor = ExpressionUtilities.CreateDataModelAccessor(LeftDataModel, LeftPropertyPath, "left", out ParameterExpression leftSideParameter);
|
|
||||||
Expression rightSideAccessor = ExpressionUtilities.CreateDataModelAccessor(RightDataModel, RightPropertyPath, "right", out ParameterExpression rightSideParameter);
|
|
||||||
|
|
||||||
// A conversion may be required if the types differ
|
|
||||||
// This can cause issues if the DataModelConditionOperator wasn't accurate in it's supported types but that is not a concern here
|
|
||||||
if (rightSideAccessor.Type != leftSideAccessor.Type)
|
|
||||||
rightSideAccessor = Expression.Convert(rightSideAccessor, leftSideAccessor.Type);
|
|
||||||
|
|
||||||
LeftSideAccessor = Expression.Lambda<Func<object, object>>(leftSideAccessor, leftSideParameter).Compile();
|
|
||||||
RightSideAccessor = Expression.Lambda<Func<object, object>>(rightSideAccessor, rightSideParameter).Compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateStaticExpression()
|
|
||||||
{
|
|
||||||
if (LeftDataModel == null || Operator == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
UnaryExpression leftSideAccessor = Expression.Convert(
|
|
||||||
ExpressionUtilities.CreateDataModelAccessor(LeftDataModel, LeftPropertyPath, "left", out ParameterExpression leftSideParameter),
|
|
||||||
typeof(object)
|
|
||||||
);
|
|
||||||
|
|
||||||
// If the left side is a value type but the input is empty, this isn't a valid expression
|
|
||||||
if (leftSideAccessor.Type.IsValueType && RightStaticValue == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LeftSideAccessor = Expression.Lambda<Func<object, object>>(leftSideAccessor, leftSideParameter).Compile();
|
|
||||||
RightSideAccessor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#region Event handlers
|
#region Event handlers
|
||||||
|
|
||||||
private void DataModelStoreOnDataModelAdded(object sender, DataModelStoreEvent e)
|
private void ConditionOperatorStoreOnConditionOperatorAdded(object? sender, ConditionOperatorStoreEvent e)
|
||||||
{
|
|
||||||
DataModel dataModel = e.Registration.DataModel;
|
|
||||||
if (dataModel.PluginInfo.Guid == Entity.LeftDataModelGuid && dataModel.ContainsPath(Entity.LeftPropertyPath))
|
|
||||||
UpdateLeftSide(dataModel, Entity.LeftPropertyPath);
|
|
||||||
if (dataModel.PluginInfo.Guid == Entity.RightDataModelGuid && dataModel.ContainsPath(Entity.RightPropertyPath))
|
|
||||||
UpdateRightSide(dataModel, Entity.RightPropertyPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DataModelStoreOnDataModelRemoved(object sender, DataModelStoreEvent e)
|
|
||||||
{
|
|
||||||
if (LeftDataModel == e.Registration.DataModel)
|
|
||||||
{
|
|
||||||
LeftSideAccessor = null;
|
|
||||||
LeftDataModel = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RightDataModel == e.Registration.DataModel)
|
|
||||||
{
|
|
||||||
RightSideAccessor = null;
|
|
||||||
RightDataModel = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConditionOperatorStoreOnConditionOperatorAdded(object sender, ConditionOperatorStoreEvent e)
|
|
||||||
{
|
{
|
||||||
ConditionOperator conditionOperator = e.Registration.ConditionOperator;
|
ConditionOperator conditionOperator = e.Registration.ConditionOperator;
|
||||||
if (Entity.OperatorPluginGuid == conditionOperator.PluginInfo.Guid && Entity.OperatorType == conditionOperator.GetType().Name)
|
if (Entity.OperatorPluginGuid == conditionOperator.PluginInfo.Guid && Entity.OperatorType == conditionOperator.GetType().Name)
|
||||||
UpdateOperator(conditionOperator);
|
UpdateOperator(conditionOperator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConditionOperatorStoreOnConditionOperatorRemoved(object sender, ConditionOperatorStoreEvent e)
|
private void ConditionOperatorStoreOnConditionOperatorRemoved(object? sender, ConditionOperatorStoreEvent e)
|
||||||
{
|
{
|
||||||
if (e.Registration.ConditionOperator != Operator)
|
if (e.Registration.ConditionOperator != Operator)
|
||||||
return;
|
return;
|
||||||
@ -440,16 +353,5 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
|
|
||||||
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
|
|
||||||
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
|
|
||||||
ConditionOperatorStore.ConditionOperatorRemoved -= ConditionOperatorStoreOnConditionOperatorRemoved;
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ namespace Artemis.Core
|
|||||||
SubscribeToDataModelStore();
|
SubscribeToDataModelStore();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DataModelPath(object target, DataModelPathEntity entity)
|
internal DataModelPath(object? target, DataModelPathEntity entity)
|
||||||
{
|
{
|
||||||
Target = target!;
|
Target = target!;
|
||||||
Path = entity.Path;
|
Path = entity.Path;
|
||||||
|
|||||||
@ -11,9 +11,7 @@ namespace Artemis.Storage.Entities.Profile.Conditions
|
|||||||
Children = new List<DataModelConditionPartEntity>();
|
Children = new List<DataModelConditionPartEntity>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guid? ListDataModelGuid { get; set; }
|
public DataModelPathEntity ListPath { get; set; }
|
||||||
public string ListPropertyPath { get; set; }
|
|
||||||
|
|
||||||
public int ListOperator { get; set; }
|
public int ListOperator { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6,16 +6,14 @@ namespace Artemis.Storage.Entities.Profile.Conditions
|
|||||||
public class DataModelConditionPredicateEntity : DataModelConditionPartEntity
|
public class DataModelConditionPredicateEntity : DataModelConditionPartEntity
|
||||||
{
|
{
|
||||||
public int PredicateType { get; set; }
|
public int PredicateType { get; set; }
|
||||||
public Guid? LeftDataModelGuid { get; set; }
|
public DataModelPathEntity LeftPath { get; set; }
|
||||||
public string LeftPropertyPath { get; set; }
|
public DataModelPathEntity RightPath { get; set; }
|
||||||
|
|
||||||
public Guid? RightDataModelGuid { get; set; }
|
|
||||||
public string RightPropertyPath { get; set; }
|
|
||||||
|
|
||||||
public string OperatorType { get; set; }
|
public string OperatorType { get; set; }
|
||||||
public Guid? OperatorPluginGuid { get; set; }
|
public Guid? OperatorPluginGuid { get; set; }
|
||||||
|
|
||||||
// Stored as a string to be able to control serialization and deserialization ourselves
|
// Stored as a string to be able to control serialization and deserialization ourselves
|
||||||
public string RightStaticValue { get; set; }
|
public string RightStaticValue { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,7 +50,7 @@
|
|||||||
</Entry.SortBy>
|
</Entry.SortBy>
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry DisplayName="All other members" />
|
<Entry DisplayName="All other members" />
|
||||||
<Entry DisplayName="Test Methods" Priority="100">
|
<Entry Priority="100" DisplayName="Test Methods">
|
||||||
<Entry.Match>
|
<Entry.Match>
|
||||||
<And>
|
<And>
|
||||||
<Kind Is="Method" />
|
<Kind Is="Method" />
|
||||||
@ -97,7 +97,7 @@
|
|||||||
</Entry.Match>
|
</Entry.Match>
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry DisplayName="All other members" />
|
<Entry DisplayName="All other members" />
|
||||||
<Entry DisplayName="Test Methods" Priority="100">
|
<Entry Priority="100" DisplayName="Test Methods">
|
||||||
<Entry.Match>
|
<Entry.Match>
|
||||||
<And>
|
<And>
|
||||||
<Kind Is="Method" />
|
<Kind Is="Method" />
|
||||||
@ -112,7 +112,7 @@
|
|||||||
</Entry>
|
</Entry>
|
||||||
</TypePattern>
|
</TypePattern>
|
||||||
<TypePattern DisplayName="Default Pattern">
|
<TypePattern DisplayName="Default Pattern">
|
||||||
<Entry DisplayName="Public Delegates" Priority="100">
|
<Entry Priority="100" DisplayName="Public Delegates">
|
||||||
<Entry.Match>
|
<Entry.Match>
|
||||||
<And>
|
<And>
|
||||||
<Access Is="Public" />
|
<Access Is="Public" />
|
||||||
@ -123,7 +123,7 @@
|
|||||||
<Name />
|
<Name />
|
||||||
</Entry.SortBy>
|
</Entry.SortBy>
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry DisplayName="Public Enums" Priority="100">
|
<Entry Priority="100" DisplayName="Public Enums">
|
||||||
<Entry.Match>
|
<Entry.Match>
|
||||||
<And>
|
<And>
|
||||||
<Access Is="Public" />
|
<Access Is="Public" />
|
||||||
@ -191,7 +191,7 @@
|
|||||||
<Kind Is="Type" />
|
<Kind Is="Type" />
|
||||||
</Entry.Match>
|
</Entry.Match>
|
||||||
</Entry>
|
</Entry>
|
||||||
<Entry DisplayName="Interface Implementations" Priority="100">
|
<Entry Priority="100" DisplayName="Interface Implementations">
|
||||||
<Entry.Match>
|
<Entry.Match>
|
||||||
<And>
|
<And>
|
||||||
<Kind Is="Member" />
|
<Kind Is="Member" />
|
||||||
@ -206,4 +206,9 @@
|
|||||||
</Patterns></s:String>
|
</Patterns></s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FElsewhere/@EntryIndexedValue">ERROR</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FElsewhere/@EntryIndexedValue">ERROR</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">ERROR</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">ERROR</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">ERROR</s:String></wpf:ResourceDictionary>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">ERROR</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
Loading…
x
Reference in New Issue
Block a user