Click here to Skip to main content
15,897,518 members
Articles / Programming Languages / Forth.NET

DocMounter 2: A tool to build VS.NET documentation (now with Sandcastle)

,
Rate me:
Please Sign up or sign in to vote.
4.94/5 (29 votes)
15 Nov 2010GPL314 min read 139.8K   1.4K   99  
Tool for creating MS Visual Studio documentation files - XML Summaries, HxS/MSHC help solutions and manuals.
using System;
using System.Text;
using System.Reflection;

namespace TenTec.Utils
{
	internal class XmlHelpNameManager
	{
		#region Consts

		private const string cTypePrefix = "T:";

		private const string cFieldPrefix = "F:";

		private const string cMethodPrefix = "M:";

		private const string cEventPrefix = "E:";

		private const string cPropertyPrefix = "P:";

		private const string cNamespacePrefix = "N:";

		private const char cDelimiter = '.';

		private const char cNestedDelimiter = '+';

		private const char cPeriodSubstitute = '#';

		#endregion

		#region Methods

		public static string Get(string @namespace)
		{
			return cNamespacePrefix + @namespace;
		}

		public static string Get(MemberInfo member)
		{
			StringBuilder myResult = new StringBuilder();

			switch (member.MemberType)
			{
				case System.Reflection.MemberTypes.TypeInfo:
					myResult.Append(cTypePrefix);
					break;
				case System.Reflection.MemberTypes.NestedType:
					myResult.Append(cTypePrefix);
					break;
				case System.Reflection.MemberTypes.Event:
					myResult.Append(cEventPrefix);
					break;
				case System.Reflection.MemberTypes.Field:
					myResult.Append(cFieldPrefix);
					break;
				case System.Reflection.MemberTypes.Constructor:
				case System.Reflection.MemberTypes.Method:
					myResult.Append(cMethodPrefix);
					break;
				case System.Reflection.MemberTypes.Property:
					myResult.Append(cPropertyPrefix);
					break;
			}
			
			if(member.DeclaringType != null)
			{
				myResult.Append(member.DeclaringType.FullName);
				myResult.Append(cDelimiter);
			}
			else
			{
				Type myType = member as Type;
				if(myType != null && myType.Namespace != null)
				{
					myResult.Append(myType.Namespace);
					myResult.Append(cDelimiter);
				}
			}

			myResult.Append(member.Name.Replace(cDelimiter, cPeriodSubstitute));
			myResult.Replace(cNestedDelimiter, cDelimiter);

			if (
				member.MemberType == System.Reflection.MemberTypes.Method ||
				member.MemberType == System.Reflection.MemberTypes.Constructor)
			{
				MethodBase lvMethodBase = (member as MethodBase);

				if (lvMethodBase.IsGenericMethod)
					myResult.Append(GetMethodGenericParamsDefinition(lvMethodBase));

				myResult.Append(GetMethodParametersString(lvMethodBase.GetParameters()));
			}
			else if (member.MemberType == System.Reflection.MemberTypes.Property)
			{
				myResult.Append(GetMethodParametersString(ReflectionManager.GetParameters(member as PropertyInfo)));
			}
			return myResult.ToString();
		}

		private static string GetMethodGenericParamsDefinition(MethodBase method)
		{
			if (method == null)
				throw new ArgumentNullException("XmlHelpNameManager.GetMethodGenericParamsDefinition(method)");

			if (!method.ContainsGenericParameters)
				return string.Empty;

			int myGenericParamsCount = method.GetGenericArguments().Length;

			return ConstsXmlHelp.cGenericMethodParameterPrefix + myGenericParamsCount.ToString();
		}

		public static string GetTypeName(string fullName)
		{
			if(fullName == null)
				throw new ArgumentNullException("XmlHelpNameManager.GetTypeName(fullName)");

			if(fullName.Length == 0)
				throw new ArgumentNullException("XmlHelpNameManager.GetTypeName(fullName)");

			fullName = fullName.Replace(cNestedDelimiter, cDelimiter);

			return cTypePrefix + fullName;			
		}

		private static string GetMethodParametersString(ParameterInfo[] parameters)
		{
			StringBuilder myString;
			if(parameters.Length > 0)
			{
				myString = new StringBuilder(ConstsXmlHelp.cOpenBracket);  
				for(int i = 0; i < parameters.Length; i++)
				{
					ParameterInfo myInfo = parameters[i];
					myString.Append(GetFullName(myInfo.ParameterType));
					if(i+1 < parameters.Length)
						myString.Append(ConstsXmlHelp.cParameterDelimeter);
				}
				myString.Append(ConstsXmlHelp.cCloseBracket);
				return myString.ToString();
			}
			return String.Empty;
		}

		private static string GetFullName(Type type)
		{
			#region Check whether the type an element type

			if (type.HasElementType)
			{
				string lvElementTypeName = GetFullName(type.GetElementType());
				if (type.IsByRef) // Check whether it is a by-reference type (ref or out parameter)
					return lvElementTypeName + ConstsXmlHelp.cPointerSuffix;
				if (type.IsArray)
					return lvElementTypeName + GetArrayTypeSuffix(type);					
			}
			
			#endregion

			#region Check whether it is a generic parameter. If so, return its name

			if (type.IsGenericParameter)
			{
				if (type.DeclaringMethod == null)
					return ConstsXmlHelp.cGenericTypeParameterPrexif + type.GenericParameterPosition.ToString();
				else
					return ConstsXmlHelp.cGenericMethodParameterPrefix + type.GenericParameterPosition.ToString();
			} 

			#endregion

			#region Get the name prefix (namespace or nested type full name)

			string myPrefix;
			if (type.IsNested)
				myPrefix = GetFullName(type.DeclaringType);
			else
				myPrefix = type.Namespace; 

			#endregion

			#region Change the generic closed constructed type declaration (replace '`' with {...}) and return it

			if (type.IsGenericType)
			{
				int lvIndexOfTypeGenericParameterPrefix = type.Name.LastIndexOf(ConstsXmlHelp.cGenericTypeParameterPrexif);
				return
					myPrefix + ConstsXmlHelp.cDelimiter +
					type.Name.Substring(0, lvIndexOfTypeGenericParameterPrefix) +
					GetGenericClosedConstructedTypeArgumentsString(type);
			}
			
			#endregion

			return myPrefix + ConstsXmlHelp.cDelimiter + type.Name;
		}

		/// <summary>
		/// Returns the suffix which should be added to the element type name 
		/// of the specified array ([0:,0:,...]).
		/// </summary>
		private static string GetArrayTypeSuffix(Type type)
		{
			if (type == null)
				throw new ArgumentNullException("XmlHelpNameManager.GetArrayTypeSuffix(type)");

			if (!type.IsArray)
				throw new ArgumentException("XmlHelpNameManager.GetArrayTypeSuffix(type)");

			StringBuilder myResult = new StringBuilder();

			myResult.Append(ConstsXmlHelp.cOpenSquareBrackets);

			int lvArrayRank = type.GetArrayRank();

			if (lvArrayRank > 1)
			{
				myResult.Append(ConstsXmlHelp.cArrayLowerBoundAndSize);
				for (int myArrayDimension = 1; myArrayDimension < lvArrayRank; myArrayDimension++)
				{
					myResult.Append(ConstsXmlHelp.cArrayDimensionDelimeter);
					myResult.Append(ConstsXmlHelp.cArrayLowerBoundAndSize);
				}
			}

			myResult.Append(ConstsXmlHelp.cCloseSquareBrackets);

			return myResult.ToString();
		}

		private static string GetGenericClosedConstructedTypeArgumentsString(Type type)
		{
			if (type == null)
				throw new ArgumentNullException("XmlHelpNameManager.GetGenericClosedConstructedTypeArgumentsString(type)");

			Type[] myArgumentTypes = type.GetGenericArguments();

			StringBuilder lvResult = new StringBuilder();

			lvResult.Append(ConstsXmlHelp.cGenericMethodParameterArgumentListStart);

			foreach (Type myArgumentType in myArgumentTypes)
			{
				if (myArgumentType.IsGenericParameter)
				{
					if (myArgumentType.DeclaringType != null && myArgumentType.DeclaringType != type)
					{
						#region Check whether the current argument type is declared in a nesting type

						bool lvIsArgumentTypeDeclaredInNestingType = false;
						Type lvNestingType = type.DeclaringType;
						while (lvNestingType != null)
						{
							if (lvNestingType == myArgumentType.DeclaringType)
							{
								lvIsArgumentTypeDeclaredInNestingType = true;
								break;
							}

							lvNestingType = lvNestingType.DeclaringType;
						} 

						#endregion

						if (lvIsArgumentTypeDeclaredInNestingType)
							continue;
					}
				}

				if (lvResult.Length > ConstsXmlHelp.cGenericMethodParameterArgumentListStart.Length)
					lvResult.Append(ConstsXmlHelp.cParameterDelimeter);

				lvResult.Append(GetFullName(myArgumentType));
			}

			lvResult.Append(ConstsXmlHelp.cGenericMethodParameterArgumentListEnd);

			return lvResult.ToString();
		}

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer (Senior)
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Written By
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.
This is a Organisation

2 members

Comments and Discussions