Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Resolving Symbolic References in a CodeDOM (Part 7)

, 2 Dec 2012
Resolving symbolic references in a CodeDOM.
Nova.0.6.exe.zip
Nova.0.6.zip
Nova.CLI
Properties
Nova.CodeDOM
CodeDOM
Annotations
Base
Comments
Base
DocComments
CodeRef
Base
List
Name
Base
Other
Simple
CompilerDirectives
Base
Conditionals
Base
Messages
Base
Pragmas
Base
Symbols
Base
Base
Interfaces
Expressions
AnonymousMethods
Base
Operators
Base
Binary
Arithmetic
Base
Assignment
Base
Bitwise
Base
Conditional
Relational
Base
Shift
Base
Other
Base
Unary
Base
Other
References
Base
GotoTargets
Base
Methods
Namespaces
Other
Properties
Types
Base
Variables
Base
Projects
Assemblies
Namespaces
References
Base
Statements
Base
Conditionals
Base
Exceptions
Generics
Constraints
Base
Iterators
Base
Jumps
Loops
Methods
OperatorDecls
Miscellaneous
Namespaces
Properties
Base
Events
Types
Base
Variables
Base
Parsing
Base
Properties
Rendering
Resolving
Utilities
Mono.Cecil
Reflection
Nova.Examples
Properties
Nova.Studio
Images
About.png
Configuration.png
EditCopy.png
EditCut.png
EditDelete.png
EditPaste.png
EditRedo.png
EditUndo.png
Error.png
Exit.png
FileNew.png
FileOpen.png
FileSave.png
FileSaveAll.png
FileSaveAs.png
Find.png
Help.png
Info.png
Logo.png
Options.png
Print.png
PrintPreview.png
Properties.png
Todo.png
Warning.png
Objects.ico
Properties
Settings.settings
Nova.Test
Properties
Nova.UI
CodeDOM
Annotations
Base
Comments
Base
DocComments
CodeRef
Base
List
Name
Base
Other
Simple
CompilerDirectives
Base
Conditionals
Base
Messages
Base
Pragmas
Base
Symbols
Base
Base
Expressions
AnonymousMethods
Base
Operators
Base
Binary
Arithmetic
Base
Assignment
Base
Bitwise
Base
Conditional
Relational
Base
Shift
Base
Other
Base
Unary
Base
Other
References
Base
GotoTargets
Base
Methods
Namespaces
Other
Properties
Types
Base
Variables
Base
Projects
Namespaces
References
Base
Statements
Base
Conditionals
Base
Exceptions
Generics
Constraints
Base
Iterators
Base
Jumps
Loops
Methods
OperatorDecls
Miscellaneous
Namespaces
Properties
Base
Events
Types
Base
Variables
Base
Properties
Resolving
Utilties
// 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)

About the Author

KenBeckett
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).

| Advertise | Privacy | Mobile
Web03 | 2.8.140709.1 | Last Updated 2 Dec 2012
Article Copyright 2012 by KenBeckett
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid