Click here to Skip to main content
Click here to Skip to main content
Articles » Languages » C# » General » Downloads
 
Add your own
alternative version

CodeDom Assistant

, 21 Sep 2007
Generating CodeDom Code By Parsing C# or VB
codedomassistant_demo.zip
CodeDomAssistant_Demo
CodeDomAssistant.exe
ICSharpCode.NRefactory.dll
RemoteLoader.dll
SciLexer.dll
ScintillaNet.dll
codedomassistant_src.zip
sln.CodeDomAssistant
CodeDomAssistant
bin
Debug
SciLexer.dll
Properties
Settings.settings
NRefactory
NRefactoryASTGenerator
AST
Project
Configuration
Resources
ICSharpCode.NRefactory.snk
Src
Ast
General
Lexer
BuildKeywords.pl
CSharp
Special
VBNet
Parser
CSharp
cs.ATG
Frames
Parser.frame
Scanner.frame
SharpCoco.exe
VBNet
VBNET.ATG
PrettyPrinter
CSharp
VBNet
Visitors
Test
General
Lexer
CSharp
VBNet
Output
CodeDOM
CSharp
VBNet
Parser
Expressions
GlobalScope
Statements
TypeLevel
RemoteLoader
Properties
ScintillaNET
Configuration
Builtin
LexerKeywordListNames
LexerStyleNames
FindReplace
Printing
Properties
Resources
DeleteHS.png
GoToNextMessage - Copy.png
GoToNextMessage.png
GoToPreviousMessage.png
LineColorHS.png
Thumbs.db
ScintillaNET.csproj.vspscc
Snippets
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
//     <version>$Revision: 2035 $</version>
// </file>

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;

namespace ICSharpCode.NRefactory.Ast
{
	public class TypeReference : AbstractNode, INullable, ICloneable
	{
		public static readonly TypeReference StructConstraint = new TypeReference("constraint: struct");
		public static readonly TypeReference ClassConstraint = new TypeReference("constraint: class");
		public static readonly TypeReference NewConstraint = new TypeReference("constraint: new");
		
		string type = "";
		string systemType = "";
		int    pointerNestingLevel;
		int[]  rankSpecifier;
		List<TypeReference> genericTypes = new List<TypeReference>();
		bool isGlobal;
		
		#region Static primitive type list
		static Dictionary<string, string> types   = new Dictionary<string, string>();
		static Dictionary<string, string> vbtypes = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
		static Dictionary<string, string> typesReverse   = new Dictionary<string, string>();
		static Dictionary<string, string> vbtypesReverse = new Dictionary<string, string>();
		
		static TypeReference()
		{
			// C# types
			types.Add("bool",    "System.Boolean");
			types.Add("byte",    "System.Byte");
			types.Add("char",    "System.Char");
			types.Add("decimal", "System.Decimal");
			types.Add("double",  "System.Double");
			types.Add("float",   "System.Single");
			types.Add("int",     "System.Int32");
			types.Add("long",    "System.Int64");
			types.Add("object",  "System.Object");
			types.Add("sbyte",   "System.SByte");
			types.Add("short",   "System.Int16");
			types.Add("string",  "System.String");
			types.Add("uint",    "System.UInt32");
			types.Add("ulong",   "System.UInt64");
			types.Add("ushort",  "System.UInt16");
			types.Add("void",    "System.Void");
			
			// VB.NET types
			vbtypes.Add("Boolean", "System.Boolean");
			vbtypes.Add("Byte",    "System.Byte");
			vbtypes.Add("SByte",   "System.SByte");
			vbtypes.Add("Date",	   "System.DateTime");
			vbtypes.Add("Char",    "System.Char");
			vbtypes.Add("Decimal", "System.Decimal");
			vbtypes.Add("Double",  "System.Double");
			vbtypes.Add("Single",  "System.Single");
			vbtypes.Add("Integer", "System.Int32");
			vbtypes.Add("Long",    "System.Int64");
			vbtypes.Add("UInteger","System.UInt32");
			vbtypes.Add("ULong",   "System.UInt64");
			vbtypes.Add("Object",  "System.Object");
			vbtypes.Add("Short",   "System.Int16");
			vbtypes.Add("UShort",  "System.UInt16");
			vbtypes.Add("String",  "System.String");
			
			foreach (KeyValuePair<string, string> pair in types) {
				typesReverse.Add(pair.Value, pair.Key);
			}
			foreach (KeyValuePair<string, string> pair in vbtypes) {
				vbtypesReverse.Add(pair.Value, pair.Key);
			}
		}
		
		/// <summary>
		/// Gets a shortname=>full name dictionary of C# types.
		/// </summary>
		public static IDictionary<string, string> PrimitiveTypesCSharp {
			get { return types; }
		}
		
		/// <summary>
		/// Gets a shortname=>full name dictionary of VB types.
		/// </summary>
		public static IDictionary<string, string> PrimitiveTypesVB {
			get { return vbtypes; }
		}
		
		/// <summary>
		/// Gets a full name=>shortname dictionary of C# types.
		/// </summary>
		public static IDictionary<string, string> PrimitiveTypesCSharpReverse {
			get { return typesReverse; }
		}
		
		/// <summary>
		/// Gets a full name=>shortname dictionary of VB types.
		/// </summary>
		public static IDictionary<string, string> PrimitiveTypesVBReverse {
			get { return vbtypesReverse; }
		}
		
		
		static string GetSystemType(string type)
		{
			if (types == null) return type;
			
			string systemType;
			if (types.TryGetValue(type, out systemType)) {
				return systemType;
			}
			if (vbtypes.TryGetValue(type, out systemType)) {
				return systemType;
			}
			return type;
		}
		#endregion
		
		object ICloneable.Clone()
		{
			return this.Clone();
		}
		
		public virtual TypeReference Clone()
		{
			TypeReference c = new TypeReference(type, systemType);
			CopyFields(this, c);
			return c;
		}
		
		/// <summary>
		/// Copies the pointerNestingLevel, RankSpecifier, GenericTypes and IsGlobal flag
		/// from <paramref name="from"/> to <paramref name="to"/>.
		/// </summary>
		/// <remarks>
		/// If <paramref name="to"/> already contains generics, the new generics are appended to the list.
		/// </remarks>
		protected static void CopyFields(TypeReference from, TypeReference to)
		{
			to.pointerNestingLevel = from.pointerNestingLevel;
			if (from.rankSpecifier != null) {
				to.rankSpecifier = (int[])from.rankSpecifier.Clone();
			}
			foreach (TypeReference r in from.genericTypes) {
				to.genericTypes.Add(r.Clone());
			}
			to.isGlobal = from.isGlobal;
		}
		
		public string Type {
			get {
				return type;
			}
			set {
				Debug.Assert(value != null);
				type = value;
				systemType = GetSystemType(type);
			}
		}
		
		/// <summary>
		/// Removes the last identifier from the type.
		/// e.g. "System.String.Length" becomes "System.String" or
		/// "System.Collections.IEnumerable(of string).Current" becomes "System.Collections.IEnumerable(of string)"
		/// This is used for explicit interface implementation in VB.
		/// </summary>
		public static string StripLastIdentifierFromType(ref TypeReference tr)
		{
			if (tr is InnerClassTypeReference && ((InnerClassTypeReference)tr).Type.IndexOf('.') < 0) {
				string ident = ((InnerClassTypeReference)tr).Type;
				tr = ((InnerClassTypeReference)tr).BaseType;
				return ident;
			} else {
				int pos = tr.Type.LastIndexOf('.');
				if (pos < 0)
					return tr.Type;
				string ident = tr.Type.Substring(pos + 1);
				tr.Type = tr.Type.Substring(0, pos);
				return ident;
			}
		}
		
		public string SystemType {
			get {
				return systemType;
			}
		}
		
		public int PointerNestingLevel {
			get {
				return pointerNestingLevel;
			}
			set {
				pointerNestingLevel = value;
			}
		}
		
		/// <summary>
		/// The rank of the array type.
		/// For "object[]", this is { 0 }; for "object[,]", it is {1}.
		/// For "object[,][,,][]", it is {1, 2, 0}.
		/// For non-array types, this property is null or {}.
		/// </summary>
		public int[] RankSpecifier {
			get {
				return rankSpecifier;
			}
			set {
				rankSpecifier = value;
			}
		}
		
		public List<TypeReference> GenericTypes {
			get {
				return genericTypes;
			}
		}
		
		public bool IsArrayType {
			get {
				return rankSpecifier != null && rankSpecifier.Length > 0;
			}
		}
		
		public static TypeReference CheckNull(TypeReference typeReference)
		{
			return typeReference ?? NullTypeReference.Instance;
		}
		
		public static NullTypeReference Null {
			get {
				return NullTypeReference.Instance;
			}
		}
		
		public virtual bool IsNull {
			get {
				return false;
			}
		}
		
		/// <summary>
		/// Gets/Sets if the type reference had a "global::" prefix.
		/// </summary>
		public bool IsGlobal {
			get {
				return isGlobal;
			}
			set {
				isGlobal = value;
			}
		}
		
		public TypeReference(string type)
		{
			this.Type = type;
		}
		
		public TypeReference(string type, string systemType)
		{
			this.type       = type;
			this.systemType = systemType;
		}
		
		public TypeReference(string type, List<TypeReference> genericTypes) : this(type)
		{
			if (genericTypes != null) {
				this.genericTypes = genericTypes;
			}
		}
		
		public TypeReference(string type, int[] rankSpecifier) : this(type, 0, rankSpecifier)
		{
		}
		
		public TypeReference(string type, int pointerNestingLevel, int[] rankSpecifier) : this(type, pointerNestingLevel, rankSpecifier, null)
		{
		}
		
		public TypeReference(string type, int pointerNestingLevel, int[] rankSpecifier, List<TypeReference> genericTypes)
		{
			Debug.Assert(type != null);
			this.type = type;
			this.systemType = GetSystemType(type);
			this.pointerNestingLevel = pointerNestingLevel;
			this.rankSpecifier = rankSpecifier;
			if (genericTypes != null) {
				this.genericTypes = genericTypes;
			}
		}
		
		protected TypeReference()
		{}
		
		public override object AcceptVisitor(IAstVisitor visitor, object data)
		{
			return visitor.VisitTypeReference(this, data);
		}
		
		public override string ToString()
		{
			StringBuilder b = new StringBuilder(type);
			if (genericTypes != null && genericTypes.Count > 0) {
				b.Append('<');
				for (int i = 0; i < genericTypes.Count; i++) {
					if (i > 0) b.Append(',');
					b.Append(genericTypes[i].ToString());
				}
				b.Append('>');
			}
			if (pointerNestingLevel > 0) {
				b.Append('*', pointerNestingLevel);
			}
			if (IsArrayType) {
				foreach (int rank in rankSpecifier) {
					b.Append('[');
					if (rank < 0)
						b.Append('`', -rank);
					else
						b.Append(',', rank);
					b.Append(']');
				}
			}
			return b.ToString();
		}
		
		public static bool AreEqualReferences(TypeReference a, TypeReference b)
		{
			if (a == b) return true;
			if (a == null || b == null) return false;
			if (a is InnerClassTypeReference) a = ((InnerClassTypeReference)a).CombineToNormalTypeReference();
			if (b is InnerClassTypeReference) b = ((InnerClassTypeReference)b).CombineToNormalTypeReference();
			if (a.systemType != b.systemType) return false;
			if (a.pointerNestingLevel != b.pointerNestingLevel) return false;
			if (a.IsArrayType != b.IsArrayType) return false;
			if (a.IsArrayType) {
				if (a.rankSpecifier.Length != b.rankSpecifier.Length) return false;
				for (int i = 0; i < a.rankSpecifier.Length; i++) {
					if (a.rankSpecifier[i] != b.rankSpecifier[i]) return false;
				}
			}
			if (a.genericTypes.Count != b.genericTypes.Count) return false;
			for (int i = 0; i < a.genericTypes.Count; i++) {
				if (!AreEqualReferences(a.genericTypes[i], b.genericTypes[i]))
					return false;
			}
			return true;
		}
	}

	public class NullTypeReference : TypeReference
	{
		static NullTypeReference nullTypeReference = new NullTypeReference();
		public override bool IsNull {
			get {
				return true;
			}
		}
		public override object AcceptVisitor(IAstVisitor visitor, object data)
		{
			return null;
		}
		public static NullTypeReference Instance {
			get {
				return nullTypeReference;
			}
		}
		NullTypeReference() {}
		public override string ToString()
		{
			return String.Format("[NullTypeReference]");
		}
	}

	/// <summary>
	/// We need this special type reference for cases like
	/// OuterClass(Of T1).InnerClass(Of T2) (in expression or type context)
	/// or Dictionary(Of String, NamespaceStruct).KeyCollection (in type context, otherwise it's a
	/// MemberReferenceExpression)
	/// </summary>
	public class InnerClassTypeReference: TypeReference
	{
		TypeReference baseType;
		
		public TypeReference BaseType {
			get { return baseType; }
			set { baseType = value; }
		}
		
		public override TypeReference Clone()
		{
			InnerClassTypeReference c = new InnerClassTypeReference(baseType.Clone(), Type, GenericTypes);
			CopyFields(this, c);
			return c;
		}
		
		public InnerClassTypeReference(TypeReference outerClass, string innerType, List<TypeReference> innerGenericTypes)
			: base(innerType, innerGenericTypes)
		{
			this.baseType = outerClass;
		}
		
		public override object AcceptVisitor(IAstVisitor visitor, object data)
		{
			return visitor.VisitInnerClassTypeReference(this, data);
		}
		
		/// <summary>
		/// Creates a type reference where all type parameters are specified for the innermost class.
		/// Namespace.OuterClass(of string).InnerClass(of integer).InnerInnerClass
		/// becomes Namespace.OuterClass.InnerClass.InnerInnerClass(of string, integer)
		/// </summary>
		public TypeReference CombineToNormalTypeReference()
		{
			TypeReference tr = (baseType is InnerClassTypeReference)
				? ((InnerClassTypeReference)baseType).CombineToNormalTypeReference()
				: baseType.Clone();
			CopyFields(this, tr);
			tr.Type += "." + Type;
			return tr;
		}
		
		public override string ToString()
		{
			return "[InnerClassTypeReference: (" + baseType.ToString() + ")." + base.ToString() + "]";
		}
	}
}

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

raygilbert
Web Developer
Australia Australia
No Biography provided

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 21 Sep 2007
Article Copyright 2007 by raygilbert
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid