using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Text; using JetBrains.Metadata.Reader.API; using JetBrains.Util.DataStructures; using MbUnit.ReSharperRunner.Helper; namespace MbUnit.ReSharperRunner.Explorer { internal class AssemblyHelper { public string[] GetChildNames(IMetadataMethod method) { List childNames = new List(); IMetadataCustomAttribute[] attributes = GetAttributesFromType(method, AttributesNames.RowAttributeName); foreach (IMetadataCustomAttribute attribute in attributes) { if (attribute.UsedConstructor.Parameters.Length > 0) { childNames.Add(GetChildMethodName(method, attribute)); } } return childNames.ToArray(); } public bool HasChildTest(IMetadataEntity method) { IMetadataCustomAttribute[] attributes = GetAttributesFromType(method, AttributesNames.RowAttributeName); foreach (IMetadataCustomAttribute attribute in attributes) { if (attribute.UsedConstructor.Parameters.Length > 0) { return true; } } return false; } private static string GetChildMethodName(IMetadataMethod method, IMetadataCustomAttribute attribute) { StringBuilder sb = new StringBuilder(); sb.Append(method.Name); sb.Append("("); int parameterCount = 0; var methodParameters = method.Parameters; AppendParameters(sb, methodParameters, attribute.ConstructorArguments, ref parameterCount); sb.Append(")"); return sb.ToString(); } private static void AppendParameters(StringBuilder sb, IMetadataParameter[] methodParameters, IEnumerable arguments, ref int parameterCount) { foreach (var argument in arguments) { if (argument == null) { if (parameterCount > 0) { sb.Append(","); } sb.Append(""); parameterCount++; } else { if (argument.GetType().IsArray) { AppendParameters(sb, methodParameters, (IEnumerable) argument, ref parameterCount); } else { if (parameterCount > 0) { sb.Append(","); } var added = false; if (parameterCount < methodParameters.Length) { var parameter = methodParameters[parameterCount]; var theType = parameter.Type as IMetadataClassType; if (theType != null) { foreach (var field in theType.Type.GetFields()) { var value = field.GetLiteralValue(); if (value != null && value.Equals(argument)) { added = true; sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", field.Name); continue; } } } } if (!added) sb.AppendFormat(CultureInfo.InvariantCulture, "{0}", argument); parameterCount++; } } } } public string GetMethodName(IMetadataMethod method) { StringBuilder sb = new StringBuilder(); sb.Append(method.Name); sb.Append("("); for (int i = 0; i < method.Parameters.Length; i++) { IMetadataParameter parameter = method.Parameters[i]; if (i > 0) { sb.Append(","); } sb.Append(parameter.Type.PresentableName); sb.Append(" "); sb.Append(parameter.Name); } sb.Append(")"); return sb.ToString(); } public string GetTestName(IMetadataEntity method) { IMetadataTypeInfo fixtureType = GetAttributeFromType(method, AttributesNames.TestBaseAttributeName); return GetShortTypeName(fixtureType); } public string GetTestFixtureName(IMetadataEntity type) { IMetadataTypeInfo fixtureType = GetAttributeFromType(type, AttributesNames.TestFixtureBaseAttributeName); return GetShortTypeName(fixtureType); } public bool IsTestFixture(IMetadataTypeInfo typeInfo) { if (!typeInfo.IsAbstract || typeInfo.IsPublic) { return HasAttributeFromType(typeInfo, AttributesNames.TestFixtureBaseAttributeName); } return false; } public bool IsTestMethod(IMetadataMethod method) { if ((method.IsStatic || method.IsAbstract || !method.IsPublic)) { return false; } if (!method.ReturnValue.Type.PresentableName.StartsWith("System.Void")) { return false; } return HasAttributeFromType(method, AttributesNames.TestBaseAttributeName); } public IMetadataCustomAttribute[] GetAttributesFromType(IMetadataEntity typeInfo, string typeName) { List attributes = new List(); foreach (IMetadataCustomAttribute customAttribute in typeInfo.CustomAttributes) { IMetadataTypeInfo type = GetIfAttributeIsFromType(customAttribute, typeName); if (type != null) { attributes.Add(customAttribute); } } return attributes.ToArray(); } public void CollectTestFixtureCategories(IMetadataEntity typeInfo, ref List categories) { CollectCategoriesForType(typeInfo, categories, AttributesNames.FixtureCategoryAttributeName); CollectCategoriesForType(typeInfo, categories, AttributesNames.TestCategoryAttributeName); } public void CollectTestMethodCategories(IMetadataEntity typeInfo, ref List categories) { CollectCategoriesForType(typeInfo, categories, AttributesNames.TestCategoryAttributeName); } private void CollectCategoriesForType(IMetadataEntity typeInfo, ICollection categories, string typeName) { foreach (IMetadataCustomAttribute attribute in GetAttributesFromType(typeInfo, typeName)) { if (attribute.UsedConstructor != null && attribute.UsedConstructor.Parameters.Length != 0) { foreach (object argument in attribute.ConstructorArguments) { if (argument.GetType().IsArray) { object[] args = (object[]) argument; foreach (object arg in args) { if (arg is string && !categories.Contains((string) arg)) { categories.Add((string) arg); } } } else { if (argument is string && !categories.Contains((string) argument)) { categories.Add((string) argument); } } } } } } public IMetadataTypeInfo GetAttributeFromType(IMetadataEntity typeInfo, string typeName) { foreach (IMetadataCustomAttribute customAttribute in typeInfo.CustomAttributes) { if (customAttribute.UsedConstructor != null) { IMetadataTypeInfo type = GetIfAttributeIsFromType(customAttribute, typeName); if (type != null) { return type; } } } return null; } public IMetadataTypeInfo GetIfAttributeIsFromType(IMetadataCustomAttribute customAttribute, string typeName) { Stack types = new Stack(); if (customAttribute.UsedConstructor == null) { return null; } IMetadataTypeInfo mainType = customAttribute.UsedConstructor.DeclaringType; types.Push(mainType); while (types.Count > 0) { IMetadataTypeInfo type = types.Pop(); if (type.FullyQualifiedName.Equals(typeName)) { return mainType; } else if (type.Base != null) { types.Push(type.Base.Type); } } return null; } public bool HasAttributeFromType(IMetadataEntity typeInfo, string typeName) { return GetAttributeFromType(typeInfo, typeName) != null; } public List GetAllTestMethods(IMetadataTypeInfo typeInfo) { List list = new List(); OneToListMap map = new OneToListMap(); while (typeInfo != null) { foreach (IMetadataMethod method in typeInfo.GetMethods()) { if (IsTestMethod(method)) { if (map.ContainsKey(GetMethodName(method)) && method.IsVirtual) { bool hasOverride = false; foreach (IMetadataMethod metadataMethod in map[GetMethodName(method)]) { if (metadataMethod.IsVirtual && !metadataMethod.IsNewSlot) { hasOverride = true; } } if (hasOverride) { goto DontAddMethod; } } map.AddValue(GetMethodName(method), method); list.Add(method); DontAddMethod: ; } } IMetadataClassType baseType = typeInfo.Base; typeInfo = (baseType != null) ? baseType.Type : null; } return list; } public string GetAttributeName(IMetadataCustomAttribute attribute) { IMetadataMethod constructor = attribute.UsedConstructor; if (constructor == null) { return null; } IMetadataTypeInfo declaringType = constructor.DeclaringType; if (declaringType == null) { return null; } return declaringType.FullyQualifiedName; } public string GetShortTypeName(IMetadataTypeInfo fixtureType) { return StringHelper.GetShortTypeName(fixtureType.FullyQualifiedName); } } }