Click here to Skip to main content
15,879,239 members
Articles / Programming Languages / C#

Resolving Symbolic References in a CodeDOM (Part 7)

Rate me:
Please Sign up or sign in to vote.
4.75/5 (6 votes)
2 Dec 2012CDDL12 min read 19.4K   509   14  
Resolving symbolic references in a CodeDOM.
// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php

using System;
using System.Collections;
using System.Reflection;
using Mono.Cecil;

namespace Nova.CodeDOM
{
    /// <summary>
    /// Represents a group of types (<see cref="TypeDecl"/>s and/or <see cref="TypeDefinition"/>s/<see cref="Type"/>s)
    /// and/or <see cref="Namespace"/>s, with the same name (the contained objects are of type 'object').
    /// </summary>
    /// <remarks>
    /// In valid code, a <see cref="NamespaceTypeGroup"/> should contain only <see cref="TypeDecl"/>s and/or <see cref="TypeDefinition"/>s/<see cref="Type"/>s
    /// with the same name (the types being a combination of a non-generic type and/or generic types with the same name but different
    /// numbers of type parameters).  The two types of objects can be mixed due to external types existing in the same namespace as types
    /// declared in the current <see cref="Solution"/>.  Normally, <see cref="Namespace"/>s shouldn't be involved, since types aren't
    /// allowed to have the same name as a child namespace in the same parent namespace (but they could collide with a <see cref="TypeDecl"/>
    /// in a <see cref="Project"/> that contains invalid code).
    /// </remarks>
    public class NamespaceTypeGroup : INamedCodeObject, ICollection
    {
        #region /* FIELDS */

        /// <summary>
        /// The list of type objects with the same name.
        /// </summary>
        protected ArrayList _list = new ArrayList();

        #endregion

        #region /* CONSTRUCTORS */

        /// <summary>
        /// Create an empty <see cref="NamespaceTypeGroup"/>.
        /// </summary>
        public NamespaceTypeGroup()
        { }

        /// <summary>
        /// Create a <see cref="NamespaceTypeGroup"/>, adding the specified object to it.
        /// </summary>
        public NamespaceTypeGroup(object obj)
        {
            Add(obj);
        }

        #endregion

        #region /* PROPERTIES */

        /// <summary>
        /// The name of the <see cref="NamespaceTypeGroup"/>.
        /// </summary>
        public string Name
        {
            get
            {
                object obj;
                lock (this)
                    obj = _list[0];
                string name;
                if (obj is INamedCodeObject)
                    name = ((INamedCodeObject)obj).Name;
                else if (obj is IMemberDefinition)
                    name = ((IMemberDefinition)obj).Name;
                else if (obj is MemberInfo)
                    name = ((MemberInfo)obj).Name;
                else
                    name = null;
                return name;
            }
        }

        /// <summary>
        /// The descriptive category of the code object.
        /// </summary>
        public string Category
        {
            get { return "ambiguity"; }
        }

        /// <summary>
        /// The number of items in the group.
        /// </summary>
        public int Count
        {
            get
            {
                int count;
                lock (this)
                    count = _list.Count;
                return count;
            }
        }

        /// <summary>
        /// Get the first item in the group.
        /// </summary>
        public object First
        {
            get
            {
                object item;
                lock (this)
                    item = _list[0];
                return item;
            }
        }

        /// <summary>
        /// True if access to the <see cref="ICollection"/> is synchronized.
        /// </summary>
        public bool IsSynchronized
        {
            get { return true; }
        }

        /// <summary>
        /// Gets an object that can be used to synchronize access to the <see cref="ICollection"/>.
        /// </summary>
        public object SyncRoot
        {
            get { return this; }
        }

        #endregion

        #region /* METHODS */

        /// <summary>
        /// Add the specified <see cref="Namespace"/> to the group.
        /// </summary>
        public void Add(Namespace @namespace)
        {
            Add((object)@namespace);
        }

        /// <summary>
        /// Add the specified <see cref="TypeDecl"/> to the group.
        /// </summary>
        public void Add(TypeDecl typeDecl)
        {
            Add((object)typeDecl);
        }

        /// <summary>
        /// Add the specified <see cref="Type"/> to the group.
        /// </summary>
        public void Add(Type type)
        {
            Add((object)type);
        }

        /// <summary>
        /// Add the specified <see cref="TypeDefinition"/> to the group.
        /// </summary>
        public void Add(TypeDefinition typeDefinition)
        {
            Add((object)typeDefinition);
        }

        /// <summary>
        /// Add an object to the group.
        /// </summary>
        /// <param name="obj">The <see cref="TypeDecl"/>, <see cref="TypeDefinition"/>/<see cref="Type"/>, or <see cref="Namespace"/> object being added.</param>
        public void Add(object obj)
        {
            if (obj is IEnumerable)
                AddRange((IEnumerable)obj);
            else if (obj != null)
            {
                lock (this)
                    _list.Add(obj);
            }
        }

        protected void AddRange(IEnumerable collection)
        {
            if (collection != null)
            {
                // Call the Add method for each member, allowing for nested
                // arrays and/or collections.
                foreach (object obj in collection)
                    Add(obj);
            }
        }

        /// <summary>
        /// This method is not supported for this type.
        /// </summary>
        public SymbolicRef CreateRef(bool isFirstOnLine)
        {
            throw new Exception("Can't create a reference to a NamespaceTypeGroup!");
        }

        /// <summary>
        /// This method is not supported for this type.
        /// </summary>
        public SymbolicRef CreateRef()
        {
            return CreateRef(false);
        }

        /// <summary>
        /// Remove all items from the group.
        /// </summary>
        public void Clear()
        {
            lock (this)
                _list.Clear();
        }

        /// <summary>
        /// Copy the objects in the group to the specified array, starting at the specified offset.
        /// </summary>
        /// <param name="array">The array to copy into.</param>
        /// <param name="index">The starting index in the array.</param>
        public virtual void CopyTo(Array array, int index)
        {
            if (array == null)
                throw new ArgumentNullException("array", "Null array reference");
            if (index < 0)
                throw new ArgumentOutOfRangeException("index", "Index is out of range");
            if (array.Rank > 1)
                throw new ArgumentException("Array is multi-dimensional", "array");

            lock (this)
            {
                foreach (object obj in this)
                    array.SetValue(obj, index++);
            }
        }

        /// <summary>
        /// Check if the group contains the specified code object.
        /// </summary>
        /// <param name="obj">The code object being searched for.</param>
        /// <returns>True if the group contains the object, otherwise false.</returns>
        public bool Contains(object obj)
        {
            bool contains;
            lock (this)
                contains = _list.Contains(obj);
            return contains;
        }

        /// <summary>
        /// Get an enumerator for the objects in the group.
        /// </summary>
        public IEnumerator GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        /// <summary>
        /// Remove the specified object from the group.
        /// </summary>
        public void Remove(object obj)
        {
            lock (this)
                _list.Remove(obj);
        }

        /// <summary>
        /// Remove the object at the specified index from the group.
        /// </summary>
        public void RemoveAt(int index)
        {
            lock (this)
                _list.RemoveAt(index);
        }

        /// <summary>
        /// Get the object in the group at the specified index.
        /// </summary>
        public object this[int index]
        {
            get
            {
                object obj;
                lock (this)
                    obj = _list[index];
                return obj;
            }
        }

        /// <summary>
        /// This method shouldn't be called on this type.
        /// </summary>
        public void AddToDictionary(NamedCodeObjectDictionary dictionary)
        {
            throw new Exception("Can't add a NamespaceTypeGroup to a NamedCodeObjectDictionary!");
        }

        /// <summary>
        /// This method shouldn't be called on this type.
        /// </summary>
        public void RemoveFromDictionary(NamedCodeObjectDictionary dictionary)
        {
            throw new Exception("Can't remove a NamespaceTypeGroup from a NamedCodeObjectDictionary!");
        }

        /// <summary>
        /// This method always returns null for this type.
        /// </summary>
        public T FindParent<T>() where T : CodeObject
        {
            return null;
        }

        /// <summary>
        /// Get the full name of the <see cref="INamedCodeObject"/>, including any namespace name.
        /// </summary>
        public string GetFullName(bool descriptive)
        {
            return Name;
        }

        /// <summary>
        /// Get the full name of the <see cref="INamedCodeObject"/>, including any namespace name.
        /// </summary>
        public string GetFullName()
        {
            return Name;
        }

        #endregion

        #region /* STATIC METHODS */

        /// <summary>
        /// Add a source object or group to a target object or group, converting the target into a group if necessary.
        /// </summary>
        /// <param name="target">The target object or group.</param>
        /// <param name="source">The source object or group.</param>
        public static void Add(ref object target, object source)
        {
            if (target == null)
            {
                if (source is ICollection)
                {
                    if (((ICollection)source).Count > 0)
                        target = new NamespaceTypeGroup(source);
                }
                else
                    target = source;
            }
            else if (source != null && !(source is ICollection && ((ICollection)source).Count == 0))
            {
                if (!(target is NamespaceTypeGroup))
                    target = new NamespaceTypeGroup(target);
                ((NamespaceTypeGroup)target).Add(source);
            }
        }

        /// <summary>
        /// Add a source object or group to a target object or group, converting the target into a group if necessary.
        /// </summary>
        /// <param name="target">The target object or group.</param>
        /// <param name="source">The source object or group.</param>
        public static void Add(ref INamedCodeObject target, INamedCodeObject source)
        {
            if (target == null)
            {
                if (source is NamespaceTypeGroup)
                    target = new NamespaceTypeGroup(source);
                else
                    target = source;
            }
            else if (source != null)
            {
                if (!(target is NamespaceTypeGroup))
                    target = new NamespaceTypeGroup(target);
                ((NamespaceTypeGroup)target).Add(source);
            }
        }

        #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 Common Development and Distribution License (CDDL)


Written By
Software Developer (Senior)
United States United States
I've been writing software since the late 70's, currently focusing mainly on C#.NET. I also like to travel around the world, and I own a Chocolate Factory (sadly, none of my employees are oompa loompas).

Comments and Discussions