Files
MicrosoftIris/UIX/Microsoft/Iris/Markup/Validation/ValidateProperty.cs
T
2022-03-03 08:14:05 -06:00

359 lines
17 KiB
C#

// Decompiled with JetBrains decompiler
// Type: Microsoft.Iris.Markup.Validation.ValidateProperty
// Assembly: UIX, Version=4.8.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217
// MVID: A56C6C9D-B7F6-46A9-8BDE-B3D9B8D60B11
// Assembly location: C:\Program Files\Zune\UIX.dll
using Microsoft.Iris.Library;
using Microsoft.Iris.Markup.UIX;
namespace Microsoft.Iris.Markup.Validation
{
internal class ValidateProperty : Microsoft.Iris.Markup.Validation.Validate
{
public const string c_requiredValue = "$Required";
public const string c_overrideProperty = "Override";
private string _propertyName;
private ValidateObject _value;
private bool _multipleValueProperty;
private int _valueCount;
private ValueApplyMode _valueApplyMode;
private PropertyAttribute _propertyAttributeList;
private bool _allowPropertyAttributes;
private PropertySchema _foundProperty;
private int _foundPropertyIndex;
private int _foundPropertyTypeIndex;
private bool _isPseudo;
private bool _shouldSkipDictionaryAddIfContains;
private ValidateProperty _next;
public ValidateProperty(SourceMarkupLoader owner, string propertyName, int line, int column)
: this(owner, propertyName, null, line, column)
{
}
public ValidateProperty(
SourceMarkupLoader owner,
string propertyName,
ValidateObject value,
int line,
int column)
: base(owner, line, column)
{
_propertyName = propertyName;
_value = value;
}
public string PropertyName => _propertyName;
public ValidateObject Value
{
get => _value;
set => _value = value;
}
public PropertyAttribute PropertyAttributeList => _propertyAttributeList;
public void AllowPropertyAttributes() => _allowPropertyAttributes = true;
public ValidateProperty Next
{
get => _next;
set => _next = value;
}
public void AppendToEnd(ValidateProperty item)
{
ValidateProperty validateProperty = this;
while (validateProperty.Next != null)
validateProperty = validateProperty.Next;
validateProperty.Next = item;
}
public void AddValue(ValidateObject value)
{
if (_value == null)
_value = value;
else if (_value is ValidateObjectTag && value is ValidateObjectTag)
_value.AppendToEnd(value);
else if (_value is ValidateCode && value is ValidateCode)
_value.AppendToEnd(value);
else
ReportError("Property '{0}' cannot contain both object-tag and script block values", _propertyName);
}
public void AddAttribute(PropertyAttribute attribute)
{
attribute.Next = _propertyAttributeList;
_propertyAttributeList = attribute;
}
public void Validate(ValidateObjectTag targetObject, ValidateContext context)
{
TypeSchema objectType = targetObject.ObjectType;
if (_propertyName == "Override" && ValidateOverrideProperty(targetObject, context))
return;
string name = _propertyName;
int length = _propertyName.IndexOf('.');
if (length >= 0 && _propertyName.Length > length + 1 && _propertyName.Substring(0, length) == targetObject.TypeIdentifier.TypeName)
name = _propertyName.Substring(length + 1);
_foundProperty = objectType.FindPropertyDeep(name);
if (_foundProperty == null)
{
if (_propertyName == "Name")
ValidateNameProperty(true, targetObject, context);
else if (_propertyName == targetObject.TypeIdentifier.TypeName)
ValidatePseudoConstructionProperty(targetObject, context);
else
ReportError("Property '{0}' does not exist on '{1}'", _propertyName, objectType.Name);
}
else
{
if (_propertyName == "Name")
ValidateNameProperty(false, targetObject, context);
UpdateFoundProperty(_foundProperty);
if (_propertyAttributeList != null && !_allowPropertyAttributes)
ReportError("Property attributes are not supported on property '{0}'", _propertyName);
if (IsCodeValue && ((ValidateCode)_value).Next != null)
{
ReportError("Property '{0}' does not support multi-value script blocks", _propertyName);
}
else
{
bool flag1 = DictionarySchema.Type.IsAssignableFrom(_foundProperty.PropertyType);
bool flag2 = ListSchema.Type.IsAssignableFrom(_foundProperty.PropertyType);
_multipleValueProperty = flag1 || flag2;
bool flag3 = IsObjectTagValue && ((ValidateObjectTag)_value).Next != null;
if (!_multipleValueProperty && flag3)
{
ReportError("Property '{0}' does not support multiple values (property type is '{1}')", _propertyName, _foundProperty.PropertyType.Name);
}
else
{
context.NotifyPropertyScopeEnter(this);
try
{
if (!_multipleValueProperty)
{
if (_value == null)
{
ReportError("Property '{0}' requires a value to be provided", _propertyName);
return;
}
_valueCount = 1;
_valueApplyMode = ValueApplyMode.SingleValueSet;
_value.Validate(new TypeRestriction(_foundProperty.PropertyType, _foundProperty.AlternateType), context);
if (_value.HasErrors)
{
MarkHasErrors();
return;
}
if (_foundProperty.RangeValidator != null && IsFromStringValue)
{
Result result = _foundProperty.RangeValidator(((ValidateFromString)_value).FromStringInstance);
if (result.Failed)
ReportError(result.Error);
}
}
else
{
TypeSchema primary = _foundProperty.AlternateType ?? ObjectSchema.Type;
_valueApplyMode = !flag1 ? ValueApplyMode.MultiValueList : ValueApplyMode.MultiValueDictionary;
if (_foundProperty.CanWrite && _foundProperty.PropertyType.HasDefaultConstructor)
_valueApplyMode |= ValueApplyMode.CollectionPopulateAndSet;
else
_valueApplyMode |= ValueApplyMode.CollectionAdd;
for (ValidateObject validateObject = _value; validateObject != null; validateObject = validateObject.ObjectSourceType != ObjectSourceType.ObjectTag ? null : (ValidateObject)((ValidateObjectTag)validateObject).Next)
{
++_valueCount;
TypeRestriction typeRestriction = !flag3 ? new TypeRestriction(primary, _foundProperty.PropertyType) : new TypeRestriction(primary);
validateObject.Validate(typeRestriction, context);
if (validateObject.HasErrors)
{
MarkHasErrors();
}
else
{
if (!flag3 && _foundProperty.PropertyType.IsAssignableFrom(validateObject.ObjectType))
{
bool flag4 = true;
if (flag1)
{
if (validateObject.ObjectSourceType == ObjectSourceType.ObjectTag && ((ValidateObjectTag)validateObject).Name != null)
flag4 = false;
}
else if (!_foundProperty.CanWrite)
flag4 = false;
if (flag4)
{
_valueApplyMode = ValueApplyMode.SingleValueSet;
break;
}
}
if (validateObject.ObjectSourceType != ObjectSourceType.ObjectTag)
{
ReportError("Collection property '{0}' may only have multiple values specified in expanded form", _propertyName);
break;
}
if ((_valueApplyMode & ValueApplyMode.MultiValueDictionary) != ValueApplyMode.SingleValueSet && ((ValidateObjectTag)validateObject).Name == null)
ReportError("Dictionary property '{0}' requires all values be named", _propertyName);
}
}
}
if (_valueApplyMode == ValueApplyMode.SingleValueSet)
{
if (_foundProperty.CanWrite)
return;
ReportError("Property '{0}' does not support setting", _foundProperty.Name);
}
else
{
if (_foundProperty.CanRead)
return;
ReportError("Property '{0}' must support reading to retrieve its collection for multiple value adds", _foundProperty.Name);
}
}
finally
{
context.NotifyPropertyScopeExit(this);
}
}
}
}
}
private void ValidateNameProperty(
bool isPseudo,
ValidateObjectTag targetObject,
ValidateContext context)
{
if (isPseudo)
MarkAsPseudo();
if (!IsFromStringValue)
{
ReportError("Property '{0}' does not support expanded value syntax", _propertyName);
}
else
{
ValidateFromString validateFromString = (ValidateFromString)_value;
validateFromString.Validate(new TypeRestriction(StringSchema.Type), context);
if (validateFromString.HasErrors)
MarkHasErrors();
else
targetObject.Name = validateFromString.FromString;
}
}
private void ValidatePseudoConstructionProperty(
ValidateObjectTag targetObject,
ValidateContext context)
{
bool flag = false;
MarkAsPseudo();
if (IsObjectTagValue && ((ValidateObjectTag)_value).Next != null)
{
ReportError("Property '{0}' does not support multiple values (property type is '{1}')", _propertyName, targetObject.ObjectType.Name);
}
else
{
if (IsFromStringValue && ((ValidateFromString)_value).FromString == "$Required")
{
flag = true;
targetObject.PropertyIsRequiredForCreation = flag;
}
if (flag)
return;
_value.Validate(new TypeRestriction(targetObject.ObjectType, TypeSchemaDefinition.Type), context);
if (_value.HasErrors)
MarkHasErrors();
else if (targetObject.ObjectType.IsAssignableFrom(_value.ObjectType))
targetObject.IndirectedObject = _value;
else
targetObject.DynamicConstructionType = _value;
}
}
private bool ValidateOverrideProperty(ValidateObjectTag targetObject, ValidateContext context)
{
if (context.ActiveSymbolScope != SymbolOrigin.Properties)
return false;
bool result;
if (IsFromStringValue && bool.TryParse(((ValidateFromString)_value).FromString, out result))
{
if (targetObject.PropertySchemaExport != null && context.Owner.TypeExport != null)
{
PropertySchema propertySchema = null;
if (context.Owner.TypeExport.MarkupTypeBase != null)
propertySchema = context.Owner.TypeExport.MarkupTypeBase.FindPropertyDeep(targetObject.PropertySchemaExport.Name);
if (result && propertySchema == null)
ReportError("Property '{0}' was specified as Override='true' but no property was found to override", targetObject.PropertySchemaExport.Name);
else if (!result && propertySchema != null)
ReportError("Property '{0}' was specified as Override='false' but a base property was found", targetObject.PropertySchemaExport.Name);
}
}
else
ReportError("Property '{0}' must be Boolean 'true' or 'false'", "Override");
MarkAsPseudo();
return true;
}
public bool IsPseudo => _isPseudo;
public void MarkAsPseudo() => _isPseudo = true;
public void RepurposeProperty(string newName, PropertyAttribute newAttributes)
{
_propertyName = newName;
_propertyAttributeList = newAttributes;
}
public bool IsObjectTagValue => _value != null && _value.ObjectSourceType == ObjectSourceType.ObjectTag;
public bool IsFromStringValue => _value != null && _value.ObjectSourceType == ObjectSourceType.FromString;
public bool IsCodeValue => _value != null && _value.ObjectSourceType == ObjectSourceType.Code;
public bool IsExpressionValue => _value != null && _value.ObjectSourceType == ObjectSourceType.Expression;
public void UpdateFoundProperty(PropertySchema newFoundProperty)
{
_foundProperty = newFoundProperty;
_foundPropertyIndex = Owner.TrackImportedProperty(_foundProperty);
_foundPropertyTypeIndex = Owner.TrackImportedType(_foundProperty.PropertyType);
}
public PropertySchema FoundProperty => _foundProperty;
public int FoundPropertyIndex => _foundPropertyIndex;
public int FoundPropertyTypeIndex => _foundPropertyTypeIndex;
public int ValueCount => _valueCount;
public bool ShouldSkipDictionaryAddIfContains
{
get => _shouldSkipDictionaryAddIfContains;
set => _shouldSkipDictionaryAddIfContains = value;
}
public ValueApplyMode ValueApplyMode => _valueApplyMode;
public void ReversePropertyValues()
{
ValidateObjectTag next;
for (ValidateObjectTag validateObjectTag = (ValidateObjectTag)_value; validateObjectTag != null; validateObjectTag = next)
{
next = validateObjectTag.Next;
validateObjectTag.Next = null;
if (validateObjectTag != _value)
{
validateObjectTag.Next = (ValidateObjectTag)_value;
_value = validateObjectTag;
}
}
}
public override string ToString() => _value != null ? string.Format("{0} = {1}", _propertyName, _value.ToString()) : "Unavailable";
}
}