private static string GetObjectsNotEqualToReferenceObject( this ModelType modelType) { var unequalSet = new List <string>(); var objectNotEqualToReferenceObjectCodeSnippet = typeof(EqualityGeneration).GetCodeTemplate(modelType.ClassifiedHierarchyKind, CodeTemplateKind.TestSnippet, KeyMethodKinds.Generated, CodeSnippetKind.EquatableTestFieldsObjectNotEqualToReferenceObject); foreach (var property in modelType.PropertiesOfConcern) { if (modelType.IsAbstractBase) { var cast = modelType.DeclaresProperty(property) ? string.Empty : Invariant($"({modelType.TypeNameInCodeString})"); var code = objectNotEqualToReferenceObjectCodeSnippet .Replace(Tokens.PropertyNameToken, property.Name) .Replace(Tokens.CastToken, cast); unequalSet.Add(code); } else { if (!modelType.IsMissingCorrespondingConstructorParameter(property)) { var propertiesCode = modelType.PropertiesOfConcern.Select(_ => { var propertyOfConcern = modelType.CaseInsensitivePropertyNameToPropertyOfConcernMap[_.Name]; var referenceProperty = modelType.CastIfConstructorParameterIsOfDifferentType(propertyOfConcern) + "ReferenceObjectForEquatableTestScenarios." + _.Name; var dummyObject = modelType.CastIfConstructorParameterIsOfDifferentType(propertyOfConcern) + objectNotEqualToReferenceObjectCodeSnippet.Replace(Tokens.PropertyNameToken, property.Name); var memberCode = _.Name != property.Name ? referenceProperty : dummyObject; return(new MemberCode(_.Name, memberCode)); }).ToList(); var code = modelType.GenerateModelInstantiation(propertiesCode, parameterPaddingLength: 32); unequalSet.Add(code); } } } var result = unequalSet.Any() ? Environment.NewLine + " " + string.Join("," + Environment.NewLine + " ", unequalSet) + "," : string.Empty; return(result); }
private static string GenerateDeepCloneWithCode( this ModelType modelType) { var deepCloneWithMethods = new List <string>(); foreach (var property in modelType.PropertiesOfConcern) { if (modelType.IsAbstractBase && (!modelType.DeclaresProperty(property))) { continue; } var propertiesCode = modelType.PropertiesOfConcern.Select(_ => { var referenceItemCloned = _.PropertyType.GenerateCloningLogicCodeForType("this." + _.Name); var code = _.Name == property.Name ? property.ToParameterName() : referenceItemCloned; code = modelType.CastIfConstructorParameterIsOfDifferentType(_) + code; return(new MemberCode(_.Name, code)); }).ToList(); var deepCloneWithModelInstantiationCode = modelType.GenerateModelInstantiation(propertiesCode, parameterPaddingLength: 33); var effectiveHierarchyKind = (modelType.HierarchyKind == HierarchyKind.ConcreteInherited) && modelType.DeclaresProperty(property) ? HierarchyKind.Standalone : modelType.HierarchyKind; var deepCloneWithMethodTemplate = modelType.IsMissingCorrespondingConstructorParameter(property) ? typeof(CloningGeneration).GetCodeTemplate(modelType.HierarchyKind, CodeTemplateKind.ModelSnippet, modelType.DeepCloneKeyMethodKinds, CodeSnippetKind.DeepCloneWithThrows) : typeof(CloningGeneration).GetCodeTemplate(effectiveHierarchyKind, CodeTemplateKind.ModelSnippet, modelType.DeepCloneKeyMethodKinds, CodeSnippetKind.DeepCloneWith); var deepCloneWithMethod = deepCloneWithMethodTemplate .Replace(Tokens.ModelTypeNameInCodeToken, modelType.TypeNameInCodeString) .Replace(Tokens.ModelTypeNameInXmlDocToken, modelType.TypeNameInXmlDocString) .Replace(Tokens.ModelAncestorTypeNameToken, property.DeclaringType.ToStringReadable()) .Replace(Tokens.PropertyNameToken, property.Name) .Replace(Tokens.ParameterNameToken, property.ToParameterName()) .Replace(Tokens.ParameterNameInXmlDocToken, property.ToParameterName(forXmlDoc: true)) .Replace(Tokens.PropertyTypeNameToken, property.PropertyType.ToStringReadable()) .Replace(Tokens.DeepCloneWithModelInstantiationToken, deepCloneWithModelInstantiationCode); deepCloneWithMethods.Add(deepCloneWithMethod); } var result = deepCloneWithMethods.Any() ? Environment.NewLine + Environment.NewLine + string.Join(Environment.NewLine + Environment.NewLine, deepCloneWithMethods) : string.Empty; result = result .Replace(Tokens.DeepCloneWithCodeAnalysisSuppressionsToken, typeof(CloningGeneration).GetCodeTemplate(CodeTemplateKind.ModelSnippet, KeyMethodKinds.Both, CodeSnippetKind.DeepCloneWithCodeAnalysisSuppressions)); return(result); }
private static string GetEqualityTestFieldsForGeneratedEquality( this ModelType modelType, KeyMethodKinds keyMethodKinds, CodeSnippetKind codeSnippetKind) { var codeTemplate = typeof(EqualityGeneration).GetCodeTemplate(modelType.ClassifiedHierarchyKind, CodeTemplateKind.TestSnippet, keyMethodKinds, codeSnippetKind); var objectsThatDeriveFromScenarioTypeButAreNotOfSameTypeAsReferenceObject = (modelType.ExampleConcreteDerivativeTypeNamesInCodeStrings.Count() >= 2) ? Environment.NewLine + typeof(EqualityGeneration).GetCodeTemplate(modelType.ClassifiedHierarchyKind, CodeTemplateKind.TestSnippet, keyMethodKinds, CodeSnippetKind.EquatableTestFieldsScenarioTypeDerivativeThatIsNotSameTypeAsReferenceObject, throwIfDoesNotExist: false) : string.Empty; var objectsEqualToButNotTheSameAsReferenceObjectMemberCode = modelType.PropertiesOfConcern .Select(_ => { var propertyOfConcern = modelType.CaseInsensitivePropertyNameToPropertyOfConcernMap[_.Name]; var referenceProperty = modelType.CastIfConstructorParameterIsOfDifferentType(propertyOfConcern) + "ReferenceObjectForEquatableTestScenarios." + _.Name; return(new MemberCode(_.Name, referenceProperty)); }) .ToList(); var objectsEqualToButNotTheSameAsReferenceObject = modelType.GenerateModelInstantiation(objectsEqualToButNotTheSameAsReferenceObjectMemberCode, parameterPaddingLength: 32); var objectsNotEqualToReferenceObject = modelType.GetObjectsNotEqualToReferenceObject(); var dummyAncestorConcreteDerivatives = modelType.ExampleAncestorConcreteDerivativeTypeNamesInCodeStrings.Any() ? Environment.NewLine + " " + modelType.ExampleAncestorConcreteDerivativeTypeNamesInCodeStrings.Select(_ => _.GenerateDummyConstructionCodeForType() + ",").ToDelimitedString(Environment.NewLine + " ") : string.Empty; var result = codeTemplate .Replace(Tokens.ScenarioTypeDerivativeThatIsNotSameTypeAsReferenceObjectToken, objectsThatDeriveFromScenarioTypeButAreNotOfSameTypeAsReferenceObject) .Replace(Tokens.ObjectsEqualToButNotTheSameAsReferenceObjectToken, objectsEqualToButNotTheSameAsReferenceObject) .Replace(Tokens.ObjectsNotEqualToReferenceObjectToken, objectsNotEqualToReferenceObject) .Replace(Tokens.ModelTypeNameInCodeToken, modelType.TypeNameInCodeString) .Replace(Tokens.DummyAncestorConcreteDerivativesToken, dummyAncestorConcreteDerivatives) .Replace(Tokens.CommentOutToken, modelType.RequiresDeepCloning ? string.Empty : "// "); return(result); }
private static string GenerateDeepCloneCode( this ModelType modelType) { var deepCloneCodeForEachProperty = modelType .PropertiesOfConcern .Select(_ => new MemberCode(_.Name, Invariant($"{modelType.CastIfConstructorParameterIsOfDifferentType(_)}{_.PropertyType.GenerateCloningLogicCodeForType("this." + _.Name)}"))) .ToList(); var result = modelType.GenerateModelInstantiation(deepCloneCodeForEachProperty, parameterPaddingLength: 33); return(result); }
public static string GenerateConstructorTestFields( this ModelType modelType) { new { modelType }.AsArg().Must().NotBeNull(); if ((modelType.Constructor == null) || modelType.Constructor.IsDefaultConstructor()) { return(null); } var argumentValidationScenarios = new List <string>(); var parameters = modelType.Constructor.GetParameters(); var referenceObjectDummyCode = "var referenceObject = A.Dummy<[model-type-name-in-code-here]>();" + Environment.NewLine + Environment.NewLine + " "; foreach (var parameter in parameters.Where(_ => !_.ParameterType.IsValueType)) { var referenceObjectUsed = false; var parametersCode = parameters.Select(_ => { var propertyOfConcern = modelType.CaseInsensitivePropertyNameToPropertyOfConcernMap[_.Name]; var referenceObject = modelType.CastIfConstructorParameterIsOfDifferentType(propertyOfConcern) + "referenceObject." + _.ToPropertyName(); string code; if (_.Name == parameter.Name) { code = "null"; } else { code = referenceObject; referenceObjectUsed = true; } return(new MemberCode(_.Name, code)); }).ToList(); var objectInstantiationCode = modelType.GenerateModelInstantiation(parametersCode, parameterPaddingLength: 45); var scenario = typeof(ConstructingGeneration).GetCodeTemplate(CodeTemplateKind.TestSnippet, KeyMethodKinds.Both, CodeSnippetKind.ConstructorArgumentValidationScenarioNullObject) .Replace(Tokens.ReferenceObjectToken, referenceObjectUsed ? referenceObjectDummyCode : null) .Replace(Tokens.ModelTypeNameInCodeToken, modelType.TypeNameInCodeString) .Replace(Tokens.ParameterNameToken, parameter.Name) .Replace(Tokens.ConstructObjectToken, objectInstantiationCode); argumentValidationScenarios.Add(scenario); if (parameter.ParameterType == typeof(string)) { referenceObjectUsed = false; var stringParameterCode = parameters.Select(_ => { var propertyOfConcern = modelType.CaseInsensitivePropertyNameToPropertyOfConcernMap[_.Name]; var referenceProperty = modelType.CastIfConstructorParameterIsOfDifferentType(propertyOfConcern) + "referenceObject." + _.ToPropertyName(); string code; if (_.Name == parameter.Name) { code = "Invariant($\" {Environment.NewLine} \")"; } else { code = referenceProperty; referenceObjectUsed = true; } return(new MemberCode(_.Name, code)); }).ToList(); objectInstantiationCode = modelType.GenerateModelInstantiation(stringParameterCode, parameterPaddingLength: 45); scenario = typeof(ConstructingGeneration).GetCodeTemplate(CodeTemplateKind.TestSnippet, KeyMethodKinds.Both, CodeSnippetKind.ConstructorArgumentValidationScenarioWhiteSpaceString) .Replace(Tokens.ReferenceObjectToken, referenceObjectUsed ? referenceObjectDummyCode : null) .Replace(Tokens.ModelTypeNameInCodeToken, modelType.TypeNameInCodeString) .Replace(Tokens.ParameterNameToken, parameter.Name) .Replace(Tokens.ConstructObjectToken, objectInstantiationCode); argumentValidationScenarios.Add(scenario); } if (parameter.ParameterType.IsClosedSystemCollectionType() || parameter.ParameterType.IsArray) { // add test for empty collection or array referenceObjectUsed = false; var collectionParameterCode = parameters.Select(_ => { var propertyOfConcern = modelType.CaseInsensitivePropertyNameToPropertyOfConcernMap[_.Name]; var referenceProperty = modelType.CastIfConstructorParameterIsOfDifferentType(propertyOfConcern) + "referenceObject." + _.ToPropertyName(); string code; if (_.Name == parameter.Name) { code = parameter.ParameterType.GenerateSystemTypeInstantiationCode(); } else { code = referenceProperty; referenceObjectUsed = true; } return(new MemberCode(_.Name, code)); }).ToList(); objectInstantiationCode = modelType.GenerateModelInstantiation(collectionParameterCode, parameterPaddingLength: 45); scenario = typeof(ConstructingGeneration).GetCodeTemplate(CodeTemplateKind.TestSnippet, KeyMethodKinds.Both, CodeSnippetKind.ConstructorArgumentValidationScenarioEmptyEnumerable) .Replace(Tokens.ReferenceObjectToken, referenceObjectUsed ? referenceObjectDummyCode : null) .Replace(Tokens.ModelTypeNameInCodeToken, modelType.TypeNameInCodeString) .Replace(Tokens.ParameterNameToken, parameter.Name) .Replace(Tokens.ConstructObjectToken, objectInstantiationCode); argumentValidationScenarios.Add(scenario); // add test for collection or array containing null element // we are specifically EXCLUDING nullable types here var elementType = parameter.ParameterType.IsArray ? parameter.ParameterType.GetElementType() : parameter.ParameterType.GetClosedSystemCollectionElementType(); // ReSharper disable once PossibleNullReferenceException if (!elementType.IsValueType) { collectionParameterCode = parameters.Select(_ => { var propertyOfConcern = modelType.CaseInsensitivePropertyNameToPropertyOfConcernMap[_.Name]; var referenceProperty = modelType.CastIfConstructorParameterIsOfDifferentType(propertyOfConcern) + "referenceObject." + _.ToPropertyName(); if (_.Name == parameter.Name) { referenceProperty = Invariant($"new {elementType.ToStringReadable()}[0].Concat({referenceProperty}).Concat(new {elementType.ToStringReadable()}[] {{ null }}).Concat({referenceProperty})"); referenceProperty = parameter.ParameterType.IsArray ? referenceProperty + ".ToArray()" : referenceProperty + ".ToList()"; if (parameter.ParameterType.IsGenericType && ((parameter.ParameterType.GetGenericTypeDefinition() == typeof(Collection <>)) || (parameter.ParameterType.GetGenericTypeDefinition() == typeof(ReadOnlyCollection <>)))) { referenceProperty = parameter.ParameterType.GenerateSystemTypeInstantiationCode(referenceProperty); } } return(new MemberCode(_.Name, referenceProperty)); }).ToList(); objectInstantiationCode = modelType.GenerateModelInstantiation(collectionParameterCode, parameterPaddingLength: 45); scenario = typeof(ConstructingGeneration).GetCodeTemplate(CodeTemplateKind.TestSnippet, KeyMethodKinds.Both, CodeSnippetKind.ConstructorArgumentValidationScenarioEnumerableWithNullElement) .Replace(Tokens.ModelTypeNameInCodeToken, modelType.TypeNameInCodeString) .Replace(Tokens.ParameterNameToken, parameter.Name) .Replace(Tokens.ConstructObjectToken, objectInstantiationCode); argumentValidationScenarios.Add(scenario); } } if (parameter.ParameterType.IsClosedSystemDictionaryType()) { // add test for empty dictionary referenceObjectUsed = false; var dictionaryParameterCode = parameters.Select(_ => { var propertyOfConcern = modelType.CaseInsensitivePropertyNameToPropertyOfConcernMap[_.Name]; var referenceProperty = modelType.CastIfConstructorParameterIsOfDifferentType(propertyOfConcern) + "referenceObject." + _.ToPropertyName(); string code; if (_.Name == parameter.Name) { code = parameter.ParameterType.GenerateSystemTypeInstantiationCode(); } else { code = referenceProperty; referenceObjectUsed = true; } return(new MemberCode(_.Name, code)); }).ToList(); objectInstantiationCode = modelType.GenerateModelInstantiation(dictionaryParameterCode, parameterPaddingLength: 45); scenario = typeof(ConstructingGeneration).GetCodeTemplate(CodeTemplateKind.TestSnippet, KeyMethodKinds.Both, CodeSnippetKind.ConstructorArgumentValidationScenarioEmptyDictionary) .Replace(Tokens.ReferenceObjectToken, referenceObjectUsed ? referenceObjectDummyCode : null) .Replace(Tokens.ModelTypeNameInCodeToken, modelType.TypeNameInCodeString) .Replace(Tokens.ParameterNameToken, parameter.Name) .Replace(Tokens.ConstructObjectToken, objectInstantiationCode); argumentValidationScenarios.Add(scenario); // add test for dictionary containing null value // we are specifically EXCLUDING nullable types here var valueType = parameter.ParameterType.GetClosedSystemDictionaryValueType(); if (!valueType.IsValueType) { dictionaryParameterCode = parameters.Select(_ => { var propertyOfConcern = modelType.CaseInsensitivePropertyNameToPropertyOfConcernMap[_.Name]; var referenceProperty = modelType.CastIfConstructorParameterIsOfDifferentType(propertyOfConcern) + "referenceObject." + _.ToPropertyName(); if (_.Name == parameter.Name) { referenceProperty = "dictionaryWithNullValue"; if (parameter.ParameterType.IsGenericType && ((parameter.ParameterType.GetGenericTypeDefinition() == typeof(ReadOnlyDictionary <,>)) || (parameter.ParameterType.GetGenericTypeDefinition() == typeof(ConcurrentDictionary <,>)))) { referenceProperty = parameter.ParameterType.GenerateSystemTypeInstantiationCode(referenceProperty); } } return(new MemberCode(_.Name, referenceProperty)); }).ToList(); var setDictionaryValueToNullCode = Invariant($"var dictionaryWithNullValue = referenceObject.{parameter.ToPropertyName()}.ToDictionary(_ => _.Key, _ => _.Value);"); objectInstantiationCode = modelType.GenerateModelInstantiation(dictionaryParameterCode, parameterPaddingLength: 45); scenario = typeof(ConstructingGeneration).GetCodeTemplate(CodeTemplateKind.TestSnippet, KeyMethodKinds.Both, CodeSnippetKind.ConstructorArgumentValidationScenarioDictionaryWithNullValue) .Replace(Tokens.SetDictionaryValueToNullToken, setDictionaryValueToNullCode) .Replace(Tokens.ModelTypeNameInCodeToken, modelType.TypeNameInCodeString) .Replace(Tokens.ParameterNameToken, parameter.Name) .Replace(Tokens.ConstructObjectToken, objectInstantiationCode); argumentValidationScenarios.Add(scenario); } } } var propertyAssignmentScenarios = new List <string>(); foreach (var parameter in parameters) { var parameterCode = parameters .Select(_ => { var propertyOfConcern = modelType.CaseInsensitivePropertyNameToPropertyOfConcernMap[_.Name]; var referenceProperty = modelType.CastIfConstructorParameterIsOfDifferentType(propertyOfConcern) + "referenceObject." + _.ToPropertyName(); return(new MemberCode(_.Name, referenceProperty)); }) .ToList(); var newObjectCode = modelType.GenerateModelInstantiation(parameterCode, parameterPaddingLength: 54); var scenario = typeof(ConstructingGeneration).GetCodeTemplate(CodeTemplateKind.TestSnippet, KeyMethodKinds.Both, CodeSnippetKind.ConstructorParameterAssignmentScenario) .Replace(Tokens.ModelTypeNameInCodeToken, modelType.TypeNameInCodeString) .Replace(Tokens.PropertyNameToken, parameter.ToPropertyName()) .Replace(Tokens.ParameterNameToken, parameter.Name) .Replace(Tokens.ConstructObjectToken, newObjectCode); propertyAssignmentScenarios.Add(scenario); } var argumentValidationScenariosCode = argumentValidationScenarios.Any() ? Environment.NewLine + string.Join(Environment.NewLine, argumentValidationScenarios) : string.Empty; var propertyAssignmentScenariosCode = propertyAssignmentScenarios.Any() ? Environment.NewLine + string.Join(Environment.NewLine, propertyAssignmentScenarios) : string.Empty; var result = typeof(ConstructingGeneration).GetCodeTemplate(modelType.ClassifiedHierarchyKind, CodeTemplateKind.TestSnippet, KeyMethodKinds.Both, CodeSnippetKind.ConstructorTestFields) .Replace(Tokens.ModelTypeNameInCodeToken, modelType.TypeNameInCodeString) .Replace(Tokens.ConstructorArgumentValidationTestScenariosToken, argumentValidationScenariosCode) .Replace(Tokens.ConstructorPropertyAssignmentTestScenariosToken, propertyAssignmentScenariosCode); return(result); }