/// <summary> /// Gets the type tree for the specified field. /// </summary> /// <param name="field">The field.</param> /// <param name="factory">The user type factory.</param> /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param> /// <param name="bitLength">Number of bits used for this symbol.</param> protected override TypeTree GetFieldTypeTree(SymbolField field, UserTypeFactory factory, bool extractingBaseClass, int bitLength = 0) { // Do not match specializations when getting type for base class. if (extractingBaseClass || NumberOfTemplateArguments == 0) { return(GetSymbolTypeTree(field.Type, factory, bitLength)); } // Check field in all specializations var specializedFields = SpecializedTypes.Select(r => new Tuple <TemplateUserType, SymbolField>(r, r.Symbol.Fields.FirstOrDefault(q => q.Name == field.Name))).ToArray(); if (specializedFields.Any(r => r.Item2 == null)) { // TODO: Incorrect bucketization. Field does not exist in all specialization. return(GetSymbolTypeTree(field.Type, factory, bitLength)); } if (specializedFields.All(r => r.Item2.Type.Name == field.Type.Name)) { // There is no specialization, all types across the specializations are the same. return(GetSymbolTypeTree(field.Type, factory, bitLength)); } // Try to get type tree TypeTree result = GetSymbolTypeTree(field.Type, factory, bitLength); return(FixTypeTree(result, field.Type, factory)); }
/// <summary> /// Gets the name of the property based on the field name. /// </summary> /// <param name="field">The field.</param> /// <param name="userType">The user type owning the field.</param> /// <returns>The name of the property.</returns> public static string GetPropertyName(SymbolField field, UserType userType) { if (!string.IsNullOrEmpty(field.PropertyName)) { return(field.PropertyName); } string fieldName = field.Name; // Check if field name is the same as owner type name if (fieldName == userType.Symbol.Name) // TODO: Check if this should be userType.ConstructorName { // Property name cannot be equal to the class name return(string.Format("_{0}", fieldName)); } // Check if field name is the same as any inner type name foreach (string className in userType.InnerTypes.Select(r => r.ClassName)) // TODO: Check if this should be r.ConstructorName { if (fieldName == className) { // Property name cannot be equal to the class name return(string.Format("_{0}", fieldName)); } } fieldName = fieldName.Replace("::", "_"); switch (fieldName) { case "lock": case "base": case "params": case "enum": case "in": case "object": case "event": case "string": case "fixed": case "internal": case "out": case "override": case "virtual": case "namespace": case "public": case "private": case "decimal": return(string.Format("_{0}", fieldName)); default: break; } return(fieldName); }
/// <summary> /// Gets the type tree for the specified field. /// </summary> /// <param name="field">The field.</param> /// <param name="factory">The user type factory.</param> /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param> /// <param name="bitLength">Number of bits used for this symbol.</param> protected override TypeTree GetFieldTypeTree(SymbolField field, UserTypeFactory factory, bool extractingBaseClass, int bitLength = 0) { // Do not match specializations when getting type for base class. if (extractingBaseClass || NumberOfTemplateArguments == 0) { return(GetSymbolTypeTree(field.Type, factory, bitLength)); } // Check field in all specializations var specializedFields = SpecializedTypes.Select(r => new Tuple <TemplateUserType, SymbolField>(r, r.Symbol.Fields.FirstOrDefault(q => q.Name == field.Name))).ToArray(); if (specializedFields.Any(r => r.Item2 == null)) { // TODO: Incorrect bucketization. Field does not exist in all specialization. return(GetSymbolTypeTree(field.Type, factory, bitLength)); } if (specializedFields.All(r => r.Item2.Type.Name == field.Type.Name)) { // There is no specialization, all types across the specializations are the same. return(GetSymbolTypeTree(field.Type, factory, bitLength)); } // Try to get type tree TypeTree result = GetSymbolTypeTree(field.Type, factory, bitLength); if (result is BasicTypeTree) { // Basic type tree is not challenged against template arguments, so try to do that. UserType basicUserType; if (CreateFactory(factory).GetUserType(field.Type, out basicUserType)) { TypeTree tree = UserTypeTree.Create(basicUserType, factory); if (tree != null) { return(tree); } } // Failed to match the type // TODO: Look for typedeclared. Class is using different types than in template specialization. We cannot support it right now. return(new VariableTypeTree()); } return(result); }
/// <summary> /// Generates user type field based on the specified symbol field and all other fields that are prepared for this function. /// Do not use this function directly, unless you are calling it from overridden function. /// </summary> /// <param name="field">The symbol field.</param> /// <param name="fieldType">The field tree type.</param> /// <param name="factory">The user type factory.</param> /// <param name="simpleFieldValue">The code foe "simple field value" used when creating transformation.</param> /// <param name="gettingField">The code for getting field variable.</param> /// <param name="isStatic">if set to <c>true</c> generated field should be static.</param> /// <param name="generationFlags">The user type generation flags.</param> /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param> protected override UserTypeField ExtractFieldInternal(SymbolField field, TypeTree fieldType, UserTypeFactory factory, string simpleFieldValue, string gettingField, bool isStatic, UserTypeGenerationFlags generationFlags, bool extractingBaseClass) { // Physical code generation make sense only for non-static fields if (!isStatic) { bool lazyCacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.LazyCacheUserTypeFields); bool cacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheUserTypeFields); bool cacheStaticUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheStaticUserTypeFields); string constructorText = ""; string fieldName = field.Name; string fieldTypeString = fieldType.GetTypeString(); BasicTypeTree baseType = fieldType as BasicTypeTree; ArrayTypeTree codeArrayType = fieldType as ArrayTypeTree; UserTypeTree userType = fieldType as UserTypeTree; TransformationTypeTree transformationType = fieldType as TransformationTypeTree; bool isEmbedded = field.Type.Tag != CodeTypeTag.Pointer; // Specialization for basic types if (baseType != null) { if (baseType.BasicType == "string") { int charSize = field.Type.ElementType.Size; constructorText = string.Format("ReadString(GetCodeType().Module.Process, ReadPointer(memoryBuffer, memoryBufferOffset + {0}, {1}), {2})", field.Offset, field.Type.Size, charSize); } else if (baseType.BasicType != "NakedPointer") { if (field.LocationType == LocationType.BitField) { constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, field.Size, field.BitPosition); } else { constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1})", baseType.GetTypeString().UppercaseFirst(), field.Offset); } } } // Specialization for arrays else if (codeArrayType != null) { if (codeArrayType.ElementType is BasicTypeTree) { baseType = (BasicTypeTree)codeArrayType.ElementType; if (baseType != null && baseType.BasicType != "string" && baseType.BasicType != "NakedPointer") { int arraySize = field.Type.Size; int elementSize = field.Type.ElementType.Size; if (baseType.BasicType == "char") { constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize, elementSize); } else { constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize); } fieldTypeString = baseType.GetTypeString() + "[]"; } } } // Specialization for user types else if (userType != null && !extractingBaseClass) { if (!(userType.UserType is EnumUserType)) { string thisClassCodeType; if (IsTypeUsingStaticCodeType(this)) { thisClassCodeType = ClassCodeType; } else { thisClassCodeType = "thisClass.Value.GetCodeType()"; usedThisClass = true; } // Check if type is embedded if (!isEmbedded) { // If user type is not embedded, we do have pointer inside of our memory buffer that we can read directly if (IsTypeUsingStaticCodeType(this)) { constructorText = string.Format("ReadPointer<{0}>({4}, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size, ClassCodeType); } else { constructorText = string.Format("ReadPointer<{0}>(thisClass, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size); usedThisClass = true; } // Do downcasting if field has vtable if (userType.UserType.Symbol.HasVTable() && userType.UserType.DerivedClasses.Count > 0) { constructorText += ".DowncastObject()"; } } else { // If user type is embedded, we can reuse memory buffer that we already have in this class string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset); string fieldCodeType = string.Format("{0}.GetClassFieldType(\"{1}\")", thisClassCodeType, fieldName); if (IsTypeUsingStaticCodeType(userType.UserType)) { fieldCodeType = string.Format("{0}.{1}", userType.UserType.FullClassName, ClassCodeType); } else if (IsTypeUsingStaticCodeType(this)) { fieldCodeType = AddFieldCodeType(fieldName); } constructorText = string.Format("new {0}(memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress, {2}, {3}, \"{4}\")", fieldTypeString, field.Offset, fieldCodeType, fieldAddress, fieldName); } } else { // TODO: This is enum. Read how much enum base type is big and just cast to enum type... } } // Specialization for transformations else if (transformationType != null) { if (!isEmbedded) { string thisClassCodeType; if (IsTypeUsingStaticCodeType(this)) { thisClassCodeType = ClassCodeType; } else { thisClassCodeType = "thisClass.Value.GetCodeType()"; usedThisClass = true; } string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset); string fieldVariable = string.Format("Variable.CreateNoCast({0}.GetClassFieldType(\"{1}\"), {2}, \"{1}\")", thisClassCodeType, fieldName, fieldAddress); if (transformationType.Transformation.Transformation.HasPhysicalConstructor) { fieldVariable = string.Format("{0}, memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress", fieldVariable, field.Offset); } simpleFieldValue = fieldVariable; constructorText = string.Format("new {0}({1})", fieldTypeString, fieldVariable); } } // If we found suitable physical representation, generate the field if (!string.IsNullOrEmpty(constructorText)) { return new UserTypeField() { ConstructorText = constructorText, FieldName = "_" + fieldName, FieldType = fieldTypeString, FieldTypeInfoComment = string.Format("// {0} {1};", field.Type.Name, fieldName), PropertyName = UserTypeField.GetPropertyName(field, this), Static = isStatic, UseUserMember = lazyCacheUserTypeFields, CacheResult = cacheUserTypeFields || (isStatic && cacheStaticUserTypeFields), SimpleFieldValue = simpleFieldValue, } } ; } return(base.ExtractFieldInternal(field, fieldType, factory, simpleFieldValue, gettingField, isStatic, generationFlags, extractingBaseClass)); }
private void OnRequestBrowse(SymbolField sender) => ParameterSelector.ShowParameterSelector(_sym.ParameterDefinition.Parameter, sender);
/// <summary> /// Generates user type field based on the specified symbol field and all other fields that are prepared for this function. /// Do not use this function directly, unless you are calling it from overridden function. /// </summary> /// <param name="field">The symbol field.</param> /// <param name="fieldType">The field tree type.</param> /// <param name="factory">The user type factory.</param> /// <param name="simpleFieldValue">The code foe "simple field value" used when creating transformation.</param> /// <param name="gettingField">The code for getting field variable.</param> /// <param name="isStatic">if set to <c>true</c> generated field should be static.</param> /// <param name="generationFlags">The user type generation flags.</param> /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param> protected override UserTypeField ExtractFieldInternal(SymbolField field, TypeTree fieldType, UserTypeFactory factory, string simpleFieldValue, string gettingField, bool isStatic, UserTypeGenerationFlags generationFlags, bool extractingBaseClass) { // Physical code generation make sense only for non-static fields if (!isStatic) { bool lazyCacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.LazyCacheUserTypeFields); bool cacheUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheUserTypeFields); bool cacheStaticUserTypeFields = generationFlags.HasFlag(UserTypeGenerationFlags.CacheStaticUserTypeFields); string constructorText = ""; string fieldName = field.Name; string fieldTypeString = fieldType.GetTypeString(); BasicTypeTree baseType = fieldType as BasicTypeTree; ArrayTypeTree codeArrayType = fieldType as ArrayTypeTree; UserTypeTree userType = fieldType as UserTypeTree; TransformationTypeTree transformationType = fieldType as TransformationTypeTree; bool isEmbedded = field.Type.Tag != SymTagEnum.SymTagPointerType; // Specialization for basic types if (baseType != null) { if (baseType.BasicType == "string") { int charSize = field.Type.ElementType.Size; constructorText = string.Format("ReadString(GetCodeType().Module.Process, ReadPointer(memoryBuffer, memoryBufferOffset + {0}, {1}), {2})", field.Offset, field.Type.Size, charSize); } else if (baseType.BasicType != "NakedPointer") { if (field.LocationType == LocationType.BitField) constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, field.Size, field.BitPosition); else constructorText = string.Format("Read{0}(memoryBuffer, memoryBufferOffset + {1})", baseType.GetTypeString().UppercaseFirst(), field.Offset); } } // Specialization for arrays else if (codeArrayType != null) { if (codeArrayType.ElementType is BasicTypeTree) { baseType = (BasicTypeTree)codeArrayType.ElementType; if (baseType != null && baseType.BasicType != "string" && baseType.BasicType != "NakedPointer") { int arraySize = field.Type.Size; int elementSize = field.Type.ElementType.Size; if (baseType.BasicType == "char") constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2}, {3})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize, elementSize); else constructorText = string.Format("Read{0}Array(memoryBuffer, memoryBufferOffset + {1}, {2})", baseType.GetTypeString().UppercaseFirst(), field.Offset, arraySize / elementSize); fieldTypeString = baseType.GetTypeString() + "[]"; } } } // Specialization for user types else if (userType != null && !extractingBaseClass) { if (!(userType.UserType is EnumUserType)) { string thisClassCodeType; if (IsTypeUsingStaticCodeType(this)) thisClassCodeType = ClassCodeType; else { thisClassCodeType = "thisClass.Value.GetCodeType()"; usedThisClass = true; } // Check if type is embedded if (!isEmbedded) { // If user type is not embedded, we do have pointer inside of our memory buffer that we can read directly if (IsTypeUsingStaticCodeType(this)) constructorText = string.Format("ReadPointer<{0}>({4}, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size, ClassCodeType); else { constructorText = string.Format("ReadPointer<{0}>(thisClass, \"{1}\", memoryBuffer, memoryBufferOffset + {2}, {3})", fieldTypeString, fieldName, field.Offset, field.Type.Size); usedThisClass = true; } // Do downcasting if field has vtable if (userType.UserType.Symbol.HasVTable() && userType.UserType.DerivedClasses.Count > 0) constructorText += ".DowncastObject()"; } else { // If user type is embedded, we can reuse memory buffer that we already have in this class string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset); string fieldCodeType = string.Format("{0}.GetClassFieldType(\"{1}\")", thisClassCodeType, fieldName); if (IsTypeUsingStaticCodeType(userType.UserType)) { fieldCodeType = string.Format("{0}.{1}", userType.UserType.FullClassName, ClassCodeType); } else if (IsTypeUsingStaticCodeType(this)) { fieldCodeType = AddFieldCodeType(fieldName); } constructorText = string.Format("new {0}(memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress, {2}, {3}, \"{4}\")", fieldTypeString, field.Offset, fieldCodeType, fieldAddress, fieldName); } } else { // TODO: This is enum. Read how much enum base type is big and just cast to enum type... } } // Specialization for transformations else if (transformationType != null) { if (!isEmbedded) { string thisClassCodeType; if (IsTypeUsingStaticCodeType(this)) thisClassCodeType = ClassCodeType; else { thisClassCodeType = "thisClass.Value.GetCodeType()"; usedThisClass = true; } string fieldAddress = string.Format("memoryBufferAddress + (ulong)(memoryBufferOffset + {0})", field.Offset); string fieldVariable = string.Format("Variable.CreateNoCast({0}.GetClassFieldType(\"{1}\"), {2}, \"{1}\")", thisClassCodeType, fieldName, fieldAddress); if (transformationType.Transformation.Transformation.HasPhysicalConstructor) { fieldVariable = string.Format("{0}, memoryBuffer, memoryBufferOffset + {1}, memoryBufferAddress", fieldVariable, field.Offset); } simpleFieldValue = fieldVariable; constructorText = string.Format("new {0}({1})", fieldTypeString, fieldVariable); } } // If we found suitable physical representation, generate the field if (!string.IsNullOrEmpty(constructorText)) return new UserTypeField() { ConstructorText = constructorText, FieldName = "_" + fieldName, FieldType = fieldTypeString, FieldTypeInfoComment = string.Format("// {0} {1};", field.Type.Name, fieldName), PropertyName = UserTypeField.GetPropertyName(fieldName, this), Static = isStatic, UseUserMember = lazyCacheUserTypeFields, CacheResult = cacheUserTypeFields || (isStatic && cacheStaticUserTypeFields), SimpleFieldValue = simpleFieldValue, }; } return base.ExtractFieldInternal(field, fieldType, factory, simpleFieldValue, gettingField, isStatic, generationFlags, extractingBaseClass); }
/// <summary> /// Gets the type tree for the specified field. /// </summary> /// <param name="field">The field.</param> /// <param name="factory">The user type factory.</param> /// <param name="extractingBaseClass">if set to <c>true</c> user type field is being generated for getting base class.</param> /// <param name="bitLength">Number of bits used for this symbol.</param> protected override TypeTree GetFieldTypeTree(SymbolField field, UserTypeFactory factory, bool extractingBaseClass, int bitLength = 0) { // Do not match specializations when getting type for base class. if (extractingBaseClass || NumberOfTemplateArguments == 0) return GetSymbolTypeTree(field.Type, factory, bitLength); // Check field in all specializations var specializedFields = SpecializedTypes.Select(r => new Tuple<TemplateUserType, SymbolField>(r, r.Symbol.Fields.FirstOrDefault(q => q.Name == field.Name))).ToArray(); if (specializedFields.Any(r => r.Item2 == null)) { // TODO: Incorrect bucketization. Field does not exist in all specialization. return GetSymbolTypeTree(field.Type, factory, bitLength); } if (specializedFields.All(r => r.Item2.Type.Name == field.Type.Name)) { // There is no specialization, all types across the specializations are the same. return GetSymbolTypeTree(field.Type, factory, bitLength); } // Try to get type tree TypeTree result = GetSymbolTypeTree(field.Type, factory, bitLength); if (result is BasicTypeTree) { // Basic type tree is not challenged against template arguments, so try to do that. UserType basicUserType; if (CreateFactory(factory).GetUserType(field.Type, out basicUserType)) { TypeTree tree = UserTypeTree.Create(basicUserType, factory); if (tree != null) { return tree; } } // Failed to match the type // TODO: Look for typedeclared. Class is using different types than in template specialization. We cannot support it right now. return new VariableTypeTree(); } return result; }
private void OnRequestBrowse(SymbolField sender) { ParameterSelector.ShowParameterSelector(_sym.ParameterDefinition.Parameter, sender); }
/// <summary> /// Try to generate fields based on the Hungarian notation used in class fields. /// </summary> /// <param name="fixName">Function that generated unique field names with desire to keep existing name.</param> protected virtual IEnumerable <HungarianArrayUserTypeMember> GenerateHungarianNotationFields(Func <string, string> fixName) { // TODO: Add comments to this function and expand XML documentation comment const string CounterPrefix = "m_c"; const string PointerPrefix = "m_p"; const string ArrayPrefix = "m_rg"; SymbolField[] fields = Symbol.Fields; IEnumerable <SymbolField> counterFields = fields.Where(r => r.Name.StartsWith(CounterPrefix)); Dictionary <SymbolField, SymbolField> userTypesArrays = new Dictionary <SymbolField, SymbolField>(); foreach (SymbolField counterField in counterFields) { if (counterField.Type.BasicType != BasicType.UInt && counterField.Type.BasicType != BasicType.Int && counterField.Type.BasicType != BasicType.Long && counterField.Type.BasicType != BasicType.ULong) { continue; } if (counterField.Type.Tag == CodeTypeTag.Enum) { continue; } string counterNameSurfix = counterField.Name.Substring(CounterPrefix.Length); if (string.IsNullOrEmpty(counterNameSurfix)) { continue; } foreach (SymbolField pointerField in fields.Where(r => (r.Name.StartsWith(PointerPrefix) || r.Name.StartsWith(ArrayPrefix)) && r.Name.EndsWith(counterNameSurfix))) { if ((counterField.IsStatic) != (pointerField.IsStatic)) { continue; } if (pointerField.Type.Tag != CodeTypeTag.Pointer) { continue; } if (userTypesArrays.ContainsKey(pointerField)) { if (userTypesArrays[pointerField].Name.Length > counterField.Name.Length) { continue; } } userTypesArrays[pointerField] = counterField; } } foreach (var userTypeArray in userTypesArrays) { SymbolField pointerField = userTypeArray.Key; SymbolField counterField = userTypeArray.Value; TypeInstance fieldType = Factory.GetSymbolTypeInstance(this, pointerField.Type); if (fieldType is ArrayTypeInstance) { continue; } if (fieldType is PointerTypeInstance fieldTypeCodePointer) { fieldType = fieldTypeCodePointer.ElementType; } yield return(new HungarianArrayUserTypeMember() { AccessLevel = AccessLevel.Public, Name = fixName(CodeNaming.FixUserNaming(pointerField.Name + "Array")), Type = new ArrayTypeInstance(fieldType), UserType = this, PointerFieldName = pointerField.Name, CounterFieldName = counterField.Name, }); } }