/// <summary> /// Gets the common base types for all specializations. /// </summary> /// <param name="factory">The user type factory.</param> private string[] GetCommonBaseTypesForAllSpecializations(UserTypeFactory factory) { // If we don't have specializations, we cannot continue if (!SpecializedTypes.Any()) { return(null); } // Do this for every template argument string[] results = new string[NumberOfTemplateArguments]; for (int i = 0; i < NumberOfTemplateArguments; i++) { // Get all specializations for current template argument Symbol[] specializedSymbols = SpecializedTypes.Select(r => r.templateArgumentsAsSymbols[i]).ToArray(); TypeOfSpecializationType specializationType = TypeOfSpecializationType.Unmatched; UserType commonType = null; foreach (Symbol type in specializedSymbols) { // Check base type if (type.Tag == Dia2Lib.SymTagEnum.SymTagBaseType || type.Tag == Dia2Lib.SymTagEnum.SymTagEnum) { if (type.Name != "void") { specializationType = TypeOfSpecializationType.Anything; break; } else { specializationType = TypeOfSpecializationType.Variable; continue; } } // Check pointer, array and function types, they inherit Variable if (type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType || type.Tag == Dia2Lib.SymTagEnum.SymTagArrayType || type.Tag == Dia2Lib.SymTagEnum.SymTagFunctionType) { specializationType = TypeOfSpecializationType.Variable; continue; } if (type.Tag != Dia2Lib.SymTagEnum.SymTagUDT) { throw new NotImplementedException("Unexpected symbol type " + type.Tag + ". Symbol name: " + type.Name); } // Check if type has user type UserType userType = type.UserType; if (userType == null) { // TODO: This shouldn't happen specializationType = TypeOfSpecializationType.Variable; continue; } if (specializationType == TypeOfSpecializationType.Variable) { continue; } // If user type is template, get parent template type (one that describes all specializations) var templateType = userType as TemplateUserType; if (templateType != null) { userType = templateType.TemplateType; } if (specializationType == TypeOfSpecializationType.Unmatched) { specializationType = TypeOfSpecializationType.UserType; commonType = userType; continue; } // Try to find common type for commonType and userType var commonTypeBases = ExtractAllBaseClasses(commonType); var userTypeBases = ExtractAllBaseClasses(userType); bool found = false; foreach (var ct in commonTypeBases) { foreach (var ut in userTypeBases) { if (ut == ct) { found = true; commonType = ut; break; } } if (found) { break; } } if (!found) { specializationType = TypeOfSpecializationType.Variable; } } // Save result based on specialization type string userTypeName = null; var templateCommonType = commonType as TemplateUserType; switch (specializationType) { case TypeOfSpecializationType.Anything: userTypeName = null; break; case TypeOfSpecializationType.Variable: userTypeName = "Variable"; break; case TypeOfSpecializationType.UserType: if (templateCommonType != null) { // Common specialization is template type. In order to use it, we need to take specialization from this type // and not the one that engine picked up as generalization. UserType templateArgumentUserType = templateArgumentsAsUserTypes[i]; List <UserType> baseClasses = ExtractAllBaseClasses(templateArgumentUserType); foreach (UserType baseClass in baseClasses) { TemplateUserType templateBaseClass = baseClass as TemplateUserType; if (templateBaseClass != null && templateCommonType == templateBaseClass.TemplateType) { templateCommonType = templateBaseClass; break; } } // In order to use template as specialization, we need to have all arguments coming from our template arguments. // If not, we cannot trust them and should continue with the base classes. var tree = new TemplateTypeTree(templateCommonType, factory); bool ok = true; do { // Check if all arguments are coming from our template arguments. ok = true; foreach (var args in tree.SpecializedArguments) { if (args != null) { foreach (var arg in args) { if (!(arg is TemplateArgumentTreeType) && !(arg is UserTypeTree && ((UserTypeTree)arg).UserType is TemplateArgumentUserType)) { ok = false; break; } } } } if (!ok) { // Find base class that we should continue with UserType nextBaseClass = null; Symbol symbol = templateCommonType.Symbol; while (nextBaseClass == null) { if (symbol.BaseClasses == null || symbol.BaseClasses.Length == 0) { // We have finished all break; } if (symbol.BaseClasses.Length > 1) { // We cannot match common type with multi-inheritance break; } symbol = symbol.BaseClasses[0]; nextBaseClass = symbol?.UserType; } // No base class, use Variable if (nextBaseClass == null) { userTypeName = "Variable"; break; } else if (nextBaseClass is TemplateUserType) { // Base class is template, continue with checks templateCommonType = (TemplateUserType)nextBaseClass; tree = new TemplateTypeTree(templateCommonType, factory); } else { // Base class is not template, so we can stop testing it. userTypeName = nextBaseClass.FullClassName; break; } } }while (!ok); // All checks passed for this template user type, use it. if (ok) { userTypeName = tree.GetTypeString(); } } else { userTypeName = commonType.FullClassName; } break; case TypeOfSpecializationType.Unmatched: default: throw new NotImplementedException("Unexpected specialization type " + specializationType + " for template type " + ClassName); } results[i] = userTypeName; } return(results); }
/// <summary> /// Gets the common base types for all specializations. /// </summary> /// <param name="factory">The user type factory.</param> private string[] GetCommonBaseTypesForAllSpecializations(UserTypeFactory factory) { // If we don't have specializations, we cannot continue if (!SpecializedTypes.Any()) { return(null); } // Do this for every template argument string[] results = new string[NumberOfTemplateArguments]; for (int i = 0; i < NumberOfTemplateArguments; i++) { // Get all specializations for current template argument Symbol[] specializedSymbols = SpecializedTypes.Select(r => r.templateArgumentsAsSymbols[i]).ToArray(); TypeOfSpecializationType specializationType = TypeOfSpecializationType.Unmatched; UserType commonType = null; foreach (Symbol type in specializedSymbols) { // Check base type if (type.Tag == Dia2Lib.SymTagEnum.SymTagBaseType || type.Tag == Dia2Lib.SymTagEnum.SymTagEnum) { if (type.Name != "void") { specializationType = TypeOfSpecializationType.Anything; break; } else { specializationType = TypeOfSpecializationType.Variable; continue; } } // Check pointer, array and function types, they inherit Variable if (type.Tag == Dia2Lib.SymTagEnum.SymTagPointerType || type.Tag == Dia2Lib.SymTagEnum.SymTagArrayType || type.Tag == Dia2Lib.SymTagEnum.SymTagFunctionType) { specializationType = TypeOfSpecializationType.Variable; continue; } if (type.Tag != Dia2Lib.SymTagEnum.SymTagUDT) { throw new NotImplementedException("Unexpected symbol type " + type.Tag + ". Symbol name: " + type.Name); } // Check if type has user type UserType userType = type.UserType; if (userType == null) { // TODO: This shouldn't happen //specializationType = TypeOfSpecializationType.Variable; //continue; throw new Exception("This should never happen"); } if (specializationType == TypeOfSpecializationType.Variable) { continue; } // If user type is template, get parent template type (one that describes all specializations) var templateType = userType as TemplateUserType; if (templateType != null) { userType = templateType.TemplateType; } if (specializationType == TypeOfSpecializationType.Unmatched) { specializationType = TypeOfSpecializationType.UserType; commonType = userType; continue; } // Try to find common type for commonType and userType var commonTypeBases = ExtractAllBaseClasses(commonType); var userTypeBases = ExtractAllBaseClasses(userType); bool found = false; foreach (var ct in commonTypeBases) { foreach (var ut in userTypeBases) { if (ut == ct) { found = true; commonType = ut; break; } } if (found) { break; } } if (!found) { specializationType = TypeOfSpecializationType.Variable; } } // Save result based on specialization type string userTypeName; var templateCommonType = commonType as TemplateUserType; switch (specializationType) { case TypeOfSpecializationType.Anything: userTypeName = null; break; case TypeOfSpecializationType.Variable: userTypeName = "Variable"; break; case TypeOfSpecializationType.UserType: if (templateCommonType != null) { userTypeName = new TemplateTypeTree(templateCommonType, factory).GetTypeString(); } else { userTypeName = commonType.FullClassName; } break; case TypeOfSpecializationType.Unmatched: default: throw new NotImplementedException("Unexpected specialization type " + specializationType + " for template type " + ClassName); } results[i] = userTypeName; } return(results); }