Exemple #1
0
        /// <summary>
        /// Initializes a new instance of the ClassBase class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="type">
        /// The element type.
        /// </param>
        /// <param name="name">
        /// The name of this element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="typeConstraints">
        /// The list of type constraints on the element.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal ClassBase(
            CsDocument document,
            CsElement parent,
            ElementType type,
            string name,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            ICollection <TypeParameterConstraintClause> typeConstraints,
            bool unsafeCode,
            bool generated)
            : base(document, parent, type, name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.Ignore(document, parent, type, name, header, attributes, declaration, typeConstraints, unsafeCode, generated);

            this.typeConstraints = typeConstraints;

            // Set the parent of the type constraint clauses.
            if (typeConstraints != null)
            {
                Debug.Assert(typeConstraints.IsReadOnly, "The typeconstraints collection should be read-only.");

                foreach (TypeParameterConstraintClause constraint in typeConstraints)
                {
                    constraint.ParentElement = this;
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Initializes a new instance of the Property class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="returnType">
        /// The property return type.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Property(
            CsDocument document, 
            CsElement parent, 
            XmlHeader header, 
            ICollection<Attribute> attributes, 
            Declaration declaration, 
            TypeToken returnType, 
            bool unsafeCode, 
            bool generated)
            : base(document, parent, ElementType.Property, "property " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.AssertNotNull(returnType, "returnType");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.returnType = returnType;

            // If this is an explicit interface member implementation and our access modifier
            // is currently set to private because we don't have one, then it should be public instead.
            if (this.Declaration.Name.IndexOf(".", StringComparison.Ordinal) > -1 && !this.Declaration.Name.StartsWith("this.", StringComparison.Ordinal))
            {
                this.Declaration.AccessModifierType = AccessModifierType.Public;
            }
        }
Exemple #3
0
        /// <summary>
        /// Initializes a new instance of the Property class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="returnType">
        /// The property return type.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Property(
            CsDocument document,
            CsElement parent,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            TypeToken returnType,
            bool unsafeCode,
            bool generated)
            : base(document, parent, ElementType.Property, "property " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.AssertNotNull(returnType, "returnType");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.returnType = returnType;

            // If this is an explicit interface member implementation and our access modifier
            // is currently set to private because we don't have one, then it should be public instead.
            if (this.Declaration.Name.IndexOf(".", StringComparison.Ordinal) > -1 && !this.Declaration.Name.StartsWith("this.", StringComparison.Ordinal))
            {
                this.Declaration.AccessModifierType = AccessModifierType.Public;
            }
        }
Exemple #4
0
        /// <summary>
        /// Initializes a new instance of the Field class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="fieldType">
        /// The type of the field.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Field(
            CsDocument document,
            CsElement parent,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            TypeToken fieldType,
            bool unsafeCode,
            bool generated)
            : base(document, parent, ElementType.Field, "field " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.AssertNotNull(fieldType, "fieldType");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.type = fieldType;

            // Determine whether the item is const /readonly / static.
            this.isConst    = this.Declaration.ContainsModifier(CsTokenType.Const);
            this.isReadOnly = this.Declaration.ContainsModifier(CsTokenType.Readonly);
            this.isStatic   = this.Declaration.ContainsModifier(CsTokenType.Static);
        }
Exemple #5
0
        /// <summary>
        /// Initializes a new instance of the Event class.
        /// </summary>
        /// <param name="document">
        /// The document that contains this element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="eventHandlerType">
        /// The type of the event handler.
        /// </param>
        /// <param name="eventDeclarators">
        /// Declarators for the event.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Event(
            CsDocument document,
            CsElement parent,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            TypeToken eventHandlerType,
            ICollection <EventDeclaratorExpression> eventDeclarators,
            bool unsafeCode,
            bool generated)
            : base(document, parent, ElementType.Event, "event " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.AssertNotNull(eventHandlerType, "eventHandlerType");
            Param.AssertNotNull(eventDeclarators, "eventDeclarators");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.eventHandlerType = eventHandlerType;
            this.eventDeclarators = eventDeclarators;

            foreach (EventDeclaratorExpression expression in this.eventDeclarators)
            {
                this.AddExpression(expression);
                expression.ParentEvent = this;
            }
        }
Exemple #6
0
        /// <summary>
        /// Initializes a new instance of the Accessor class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="accessorType">
        /// The type of the accessor.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Accessor(
            CsDocument document, 
            CsElement parent, 
            AccessorType accessorType, 
            XmlHeader header, 
            ICollection<Attribute> attributes, 
            Declaration declaration, 
            bool unsafeCode, 
            bool generated)
            : base(document, parent, ElementType.Accessor, declaration.Name + " accessor", header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(accessorType);
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.accessorType = accessorType;

            // Make sure the type and name match.
            Debug.Assert(
                (accessorType == AccessorType.Get && declaration.Name == "get") || (accessorType == AccessorType.Set && declaration.Name == "set")
                || (accessorType == AccessorType.Add && declaration.Name == "add") || (accessorType == AccessorType.Remove && declaration.Name == "remove"), 
                "The accessor type does not match its name.");

            this.FillDetails(parent);
        }
Exemple #7
0
        /// <summary>
        /// Initializes a new instance of the Accessor class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="accessorType">
        /// The type of the accessor.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Accessor(
            CsDocument document,
            CsElement parent,
            AccessorType accessorType,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            bool unsafeCode,
            bool generated)
            : base(document, parent, ElementType.Accessor, declaration.Name + " accessor", header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(accessorType);
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.accessorType = accessorType;

            // Make sure the type and name match.
            Debug.Assert(
                (accessorType == AccessorType.Get && declaration.Name == "get") || (accessorType == AccessorType.Set && declaration.Name == "set") ||
                (accessorType == AccessorType.Add && declaration.Name == "add") || (accessorType == AccessorType.Remove && declaration.Name == "remove"),
                "The accessor type does not match its name.");

            this.FillDetails(parent);
        }
 /// <summary>
 /// Initializes a new instance of the Class class.
 /// </summary>
 /// <param name="document">
 /// The document that contains the element.
 /// </param>
 /// <param name="parent">
 /// The parent of the element.
 /// </param>
 /// <param name="header">
 /// The Xml header for this element.
 /// </param>
 /// <param name="attributes">
 /// The list of attributes attached to this element.
 /// </param>
 /// <param name="declaration">
 /// The declaration code for this element.
 /// </param>
 /// <param name="typeConstraints">
 /// The list of type constraints on the class, if any.
 /// </param>
 /// <param name="unsafeCode">
 /// Indicates whether the element resides within a block of unsafe code.
 /// </param>
 /// <param name="generated">
 /// Indicates whether the code element was generated or written by hand.
 /// </param>
 internal Class(
     CsDocument document, 
     CsElement parent, 
     XmlHeader header, 
     ICollection<Attribute> attributes, 
     Declaration declaration, 
     ICollection<TypeParameterConstraintClause> typeConstraints, 
     bool unsafeCode, 
     bool generated)
     : base(document, parent, ElementType.Class, "class " + declaration.Name, header, attributes, declaration, typeConstraints, unsafeCode, generated)
 {
     Param.Ignore(document, parent, header, attributes, declaration, typeConstraints, unsafeCode, generated);
 }
Exemple #9
0
 /// <summary>
 /// Initializes a new instance of the Class class.
 /// </summary>
 /// <param name="document">
 /// The document that contains the element.
 /// </param>
 /// <param name="parent">
 /// The parent of the element.
 /// </param>
 /// <param name="header">
 /// The Xml header for this element.
 /// </param>
 /// <param name="attributes">
 /// The list of attributes attached to this element.
 /// </param>
 /// <param name="declaration">
 /// The declaration code for this element.
 /// </param>
 /// <param name="typeConstraints">
 /// The list of type constraints on the class, if any.
 /// </param>
 /// <param name="unsafeCode">
 /// Indicates whether the element resides within a block of unsafe code.
 /// </param>
 /// <param name="generated">
 /// Indicates whether the code element was generated or written by hand.
 /// </param>
 internal Class(
     CsDocument document,
     CsElement parent,
     XmlHeader header,
     ICollection <Attribute> attributes,
     Declaration declaration,
     ICollection <TypeParameterConstraintClause> typeConstraints,
     bool unsafeCode,
     bool generated)
     : base(document, parent, ElementType.Class, "class " + declaration.Name, header, attributes, declaration, typeConstraints, unsafeCode, generated)
 {
     Param.Ignore(document, parent, header, attributes, declaration, typeConstraints, unsafeCode, generated);
 }
Exemple #10
0
 /// <summary>
 /// Initializes a new instance of the Namespace class.
 /// </summary>
 /// <param name="document">
 /// The document that contains the element.
 /// </param>
 /// <param name="parent">
 /// The parent of the element.
 /// </param>
 /// <param name="type">
 /// The element type.
 /// </param>
 /// <param name="name">
 /// The name of this element.
 /// </param>
 /// <param name="header">
 /// The Xml header for this element.
 /// </param>
 /// <param name="attributes">
 /// The list of attributes attached to this element.
 /// </param>
 /// <param name="declaration">
 /// The declaration code for this element.
 /// </param>
 /// <param name="unsafeCode">
 /// Indicates whether the element resides within a block of unsafe code.
 /// </param>
 /// <param name="generated">
 /// Indicates whether the code element was generated or written by hand.
 /// </param>
 internal Namespace(
     CsDocument document,
     CsElement parent,
     ElementType type,
     string name,
     XmlHeader header,
     ICollection <Attribute> attributes,
     Declaration declaration,
     bool unsafeCode,
     bool generated)
     : base(document, parent, type, name, header, attributes, declaration, unsafeCode, generated)
 {
     Param.Ignore(document, parent, type, name, header, attributes, declaration, unsafeCode, generated);
 }
Exemple #11
0
        /// <summary>
        /// Initializes a new instance of the Destructor class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Destructor(
            CsDocument document, CsElement parent, XmlHeader header, ICollection<Attribute> attributes, Declaration declaration, bool unsafeCode, bool generated)
            : base(document, parent, ElementType.Destructor, "destructor " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            // Static destructors are always public.
            if (this.Declaration.ContainsModifier(CsTokenType.Static))
            {
                this.Declaration.AccessModifierType = AccessModifierType.Public;
            }
        }
Exemple #12
0
        /// <summary>
        /// Initializes a new instance of the Destructor class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Destructor(
            CsDocument document, CsElement parent, XmlHeader header, ICollection <Attribute> attributes, Declaration declaration, bool unsafeCode, bool generated)
            : base(document, parent, ElementType.Destructor, "destructor " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            // Static destructors are always public.
            if (this.Declaration.ContainsModifier(CsTokenType.Static))
            {
                this.Declaration.AccessModifierType = AccessModifierType.Public;
            }
        }
Exemple #13
0
        /// <summary>
        /// Initializes a new instance of the Delegate class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="returnType">
        /// The return type.
        /// </param>
        /// <param name="parameters">
        /// The parameters to the delegate.
        /// </param>
        /// <param name="typeConstraints">
        /// The list of type constraints on the element.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether this is generated code.
        /// </param>
        internal Delegate(
            CsDocument document,
            CsElement parent,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            TypeToken returnType,
            IList <Parameter> parameters,
            ICollection <TypeParameterConstraintClause> typeConstraints,
            bool unsafeCode,
            bool generated)
            : base(document, parent, ElementType.Delegate, "delegate " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.AssertNotNull(returnType, "returnType");
            Param.AssertNotNull(parameters, "parameters");
            Param.Ignore(typeConstraints);
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.returnType      = returnType;
            this.typeConstraints = typeConstraints;
            this.parameters      = parameters;

            Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only.");

            // Add the qualifications
            this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName);

            // Set the parent of the type constraint clauses.
            if (typeConstraints != null)
            {
                Debug.Assert(typeConstraints.IsReadOnly, "The collection of type constraints should be read-only.");

                foreach (TypeParameterConstraintClause constraint in typeConstraints)
                {
                    constraint.ParentElement = this;
                }
            }
        }
Exemple #14
0
        /// <summary>
        /// Initializes a new instance of the <see cref="EnumItem"/> class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="initialization">
        /// The initialization expression, if there is one.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal EnumItem(
            CsDocument document, 
            Enum parent, 
            XmlHeader header, 
            ICollection<Attribute> attributes, 
            Declaration declaration, 
            Expression initialization, 
            bool unsafeCode, 
            bool generated)
            : base(document, parent, ElementType.EnumItem, "enum item " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.Ignore(document, parent, header, attributes, declaration, initialization, unsafeCode, generated);

            this.initialization = initialization;
            if (this.initialization != null)
            {
                this.AddExpression(this.initialization);
            }
        }
Exemple #15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="EnumItem"/> class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="initialization">
        /// The initialization expression, if there is one.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal EnumItem(
            CsDocument document,
            Enum parent,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            Expression initialization,
            bool unsafeCode,
            bool generated)
            : base(document, parent, ElementType.EnumItem, "enum item " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.Ignore(document, parent, header, attributes, declaration, initialization, unsafeCode, generated);

            this.initialization = initialization;
            if (this.initialization != null)
            {
                this.AddExpression(this.initialization);
            }
        }
Exemple #16
0
        /// <summary>
        /// Initializes a new instance of the Constructor class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="parameters">
        /// The parameters to the constructor.
        /// </param>
        /// <param name="initializerExpression">
        /// The constructor initializer, if there is one.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Constructor(
            CsDocument document,
            CsElement parent,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            IList <Parameter> parameters,
            MethodInvocationExpression initializerExpression,
            bool unsafeCode,
            bool generated)
            : base(document, parent, ElementType.Constructor, "constructor " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.AssertNotNull(parameters, "parameters");
            Param.Ignore(initializerExpression);
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            // Static constructors are treated as private and handled as a special case for ordering.
            if (this.Declaration.ContainsModifier(CsTokenType.Static))
            {
                this.Declaration.AccessModifierType = AccessModifierType.Private;
            }

            this.parameters = parameters;
            Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only.");

            // Add the qualifications
            this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName);

            // If there is an initializer expression, add it to the statement list for this constructor.
            if (initializerExpression != null)
            {
                this.initializer = initializerExpression;

                ConstructorInitializerStatement initializerStatement = new ConstructorInitializerStatement(initializerExpression.Tokens, initializerExpression);
                this.AddStatement(initializerStatement);
            }
        }
        /// <summary>
        /// Initializes a new instance of the Constructor class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="parameters">
        /// The parameters to the constructor.
        /// </param>
        /// <param name="initializerExpression">
        /// The constructor initializer, if there is one.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Constructor(
            CsDocument document, 
            CsElement parent, 
            XmlHeader header, 
            ICollection<Attribute> attributes, 
            Declaration declaration, 
            IList<Parameter> parameters, 
            MethodInvocationExpression initializerExpression, 
            bool unsafeCode, 
            bool generated)
            : base(document, parent, ElementType.Constructor, "constructor " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.AssertNotNull(parameters, "parameters");
            Param.Ignore(initializerExpression);
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            // Static constructors are treated as private and handled as a special case for ordering.
            if (this.Declaration.ContainsModifier(CsTokenType.Static))
            {
                this.Declaration.AccessModifierType = AccessModifierType.Private;
            }

            this.parameters = parameters;
            Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only.");

            // Add the qualifications
            this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName);

            // If there is an initializer expression, add it to the statement list for this constructor.
            if (initializerExpression != null)
            {
                this.initializer = initializerExpression;

                ConstructorInitializerStatement initializerStatement = new ConstructorInitializerStatement(initializerExpression.Tokens, initializerExpression);
                this.AddStatement(initializerStatement);
            }
        }
Exemple #18
0
        /// <summary>
        /// Initializes a new instance of the Indexer class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="returnType">
        /// The return type of the indexer.
        /// </param>
        /// <param name="parameters">
        /// The parameters to the indexer.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Indexer(
            CsDocument document,
            CsElement parent,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            TypeToken returnType,
            IList <Parameter> parameters,
            bool unsafeCode,
            bool generated)
            : base(document, parent, ElementType.Indexer, "indexer " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.Ignore(returnType);
            Param.AssertNotNull(parameters, "parameters");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.returnType = returnType;
            this.parameters = parameters;

            Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only.");

            // Add the qualifications
            this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName);

            // If this is an explicit interface member implementation and our access modifier
            // is currently set to private because we don't have one, then it should be public instead.
            if (this.Declaration.Name.IndexOf(".", StringComparison.Ordinal) > -1 && !this.Declaration.Name.StartsWith("this.", StringComparison.Ordinal))
            {
                this.Declaration.AccessModifierType = AccessModifierType.Public;
            }
        }
        /// <summary>
        /// Parses and returns a namespace.
        /// </summary>
        /// <param name="parent">
        /// The parent of the namespace.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="partialElements">
        /// The collection of partial elements found while parsing the files.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Namespace ParseNamespace(
            CsElement parent,
            Reference<ICodePart> elementReference,
            Dictionary<string, List<CsElement>> partialElements,
            bool unsafeCode,
            bool generated,
            XmlHeader xmlHeader,
            ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.AssertNotNull(partialElements, "partialElements");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            // Add the namespace token.
            Node<CsToken> firstToken = this.tokens.InsertLast(this.GetToken(CsTokenType.Namespace, SymbolType.Namespace, elementReference));

            // Add the namespace name token.
            CsToken name = this.GetElementNameToken(elementReference, unsafeCode);
            this.tokens.Add(name);

            // Create the declaration.
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstToken, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Namespace, AccessModifierType.Public);

            // Create the namespace.
            Namespace @namespace = new Namespace(this.document, parent, xmlHeader, attributes, declaration, unsafeCode, generated);
            elementReference.Target = @namespace;

            // Parse the body of the namespace.
            this.ParseElementContainer(@namespace, elementReference, partialElements, unsafeCode);

            return @namespace;
        }
        /// <summary>
        /// Initializes a new instance of the Field class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="fieldType">
        /// The type of the field.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Field(
            CsDocument document, 
            CsElement parent, 
            XmlHeader header, 
            ICollection<Attribute> attributes, 
            Declaration declaration, 
            TypeToken fieldType, 
            bool unsafeCode, 
            bool generated)
            : base(document, parent, ElementType.Field, "field " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.AssertNotNull(fieldType, "fieldType");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.type = fieldType;

            // Determine whether the item is const /readonly / static.
            this.isConst = this.Declaration.ContainsModifier(CsTokenType.Const);
            this.isReadOnly = this.Declaration.ContainsModifier(CsTokenType.Readonly);
            this.isStatic = this.Declaration.ContainsModifier(CsTokenType.Static);
        }
Exemple #21
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Enum"/> class.
 /// </summary>
 /// <param name="document">
 /// The document that contains the element.
 /// </param>
 /// <param name="parent">
 /// The parent of the element.
 /// </param>
 /// <param name="header">
 /// The Xml header for this element.
 /// </param>
 /// <param name="attributes">
 /// The list of attributes attached to this element.
 /// </param>
 /// <param name="declaration">
 /// The declaration code for this element.
 /// </param>
 /// <param name="unsafeCode">
 /// Indicates whether the element resides within a block of unsafe code.
 /// </param>
 /// <param name="generated">
 /// Indicates whether the code element was generated or written by hand.
 /// </param>
 internal Enum(
     CsDocument document, CsElement parent, XmlHeader header, ICollection <Attribute> attributes, Declaration declaration, bool unsafeCode, bool generated)
     : base(document, parent, ElementType.Enum, "enum " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
 {
     Param.Ignore(document, parent, header, attributes, declaration, unsafeCode, generated);
 }
        /// <summary>
        /// Loads the header text for the element into a document and returns it.
        /// </summary>
        /// <param name="element">
        /// The element containing the header.
        /// </param>
        /// <param name="header">
        /// The header to load.
        /// </param>
        /// <param name="lineNumber">
        /// The line number that the header begins on.
        /// </param>
        /// <param name="rawDocs">
        /// Returns the docs with whitespace and newlines left in place.
        /// </param>
        /// <param name="formattedDocs">
        /// Returns the docs with newlines filtered out.
        /// </param>
        private void LoadHeaderIntoDocuments(CsElement element, XmlHeader header, int lineNumber, out XmlDocument rawDocs, out XmlDocument formattedDocs)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(header, "header");
            Param.AssertGreaterThanZero(lineNumber, "lineNumber");

            rawDocs = new XmlDocument();

            try
            {
                string correctxml = "<root>" + header.RawText + "</root>";
                rawDocs.LoadXml(correctxml);
                formattedDocs = FormatXmlDocument(rawDocs);
            }
            catch (XmlException xmlex)
            {
                this.AddViolation(element, lineNumber, Rules.DocumentationMustContainValidXml, xmlex.Message);
                rawDocs = formattedDocs = null;
            }
        }
Exemple #23
0
        /// <summary>
        /// Initializes a new instance of the CsElement class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="type">
        /// The element type.
        /// </param>
        /// <param name="name">
        /// The name of this element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element is unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the element was generated or written by hand.
        /// </param>
        internal CsElement(
            CsDocument document,
            CsElement parent,
            ElementType type,
            string name,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            bool unsafeCode,
            bool generated)
            : base(CodePartType.Element)
        {
            Param.AssertNotNull(document, "document");
            Param.Ignore(parent);
            Param.Ignore(type);
            Param.AssertNotNull(name, "name");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.Ignore(declaration);
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.document = document;
            if (this.document == null)
            {
                throw new ArgumentException(Strings.DocumentMustBeCsDocument, "document");
            }

            if (parent != null && parent.Document != document)
            {
                throw new ArgumentException(Strings.ElementMustBeInParentsDocument, "parent");
            }

            this.type        = type;
            this.name        = CodeLexer.DecodeEscapedText(name, true);
            this.header      = header;
            this.attributes  = attributes;
            this.declaration = declaration;
            this.unsafeCode  = unsafeCode;
            this.generated   = generated;

            if (!unsafeCode && this.declaration.ContainsModifier(CsTokenType.Unsafe))
            {
                this.unsafeCode = true;
            }

            // Fill in the element reference in the header object.
            if (this.header != null)
            {
                Debug.Assert(this.header.Element == null, "The header element should not be empty.");
                this.header.Element = this;
            }

            // Fill in the element reference in the attributes list items.
            if (this.attributes != null)
            {
                Debug.Assert(this.attributes.IsReadOnly, "The attributes collection should be read-only.");

                foreach (Attribute attribute in this.attributes)
                {
                    Debug.Assert(attribute.Element == null, "The attribute element should not be empty");
                    attribute.Element = this;
                }
            }

            // Set the fully qualified base name
            if (parent != null)
            {
                this.fullyQualifiedBase = parent.FullyQualifiedName;
                this.MergeAccess(parent.ActualAccess);
            }
            else
            {
                if (this.declaration != null)
                {
                    this.actualAccess = this.declaration.AccessModifierType;
                }
                else
                {
                    this.actualAccess = AccessModifierType.Public;
                }
            }

            // Set the fully qualified name
            this.fullyQualifiedName = this.fullyQualifiedBase;
            if (this.declaration != null && this.declaration.Name != null && this.declaration.Name.Length > 0)
            {
                if (this.fullyQualifiedBase != null && this.fullyQualifiedBase.Length > 0)
                {
                    this.fullyQualifiedName += ".";
                }

                int index = this.declaration.Name.LastIndexOf("\\", StringComparison.Ordinal);
                if (index != -1)
                {
                    this.fullyQualifiedName += this.declaration.Name.Substring(index + 1, this.declaration.Name.Length - index - 1);
                }
                else
                {
                    this.fullyQualifiedName += this.declaration.Name;
                }

                index = this.fullyQualifiedName.IndexOf(".cs.", StringComparison.OrdinalIgnoreCase);
                if (-1 == index)
                {
                    this.fullNamespaceName = this.fullyQualifiedName;
                }
                else
                {
                    this.fullNamespaceName = this.fullyQualifiedName.Substring(index + 4, this.fullyQualifiedName.Length - index - 4);
                }
            }

            // There is only one type of element which is allowed to have a token
            // list consisting of nothing other than whitespace, newlines, etc.,
            // which is the document root. This happens if you have a document which
            // contains nothing other than whitespace. Due to this we do not want to
            // trim down the token list for the root element, but we do want to for
            // all other types of elements.
            if (type == ElementType.Root)
            {
                this.TrimTokens = false;
            }
        }
        /// <summary>
        /// Checks to make sure that the slashes in in the Xml header are followed by a space.
        /// </summary>
        /// <param name="header">
        /// The Xml header token.
        /// </param>
        private void CheckXmlHeaderComment(XmlHeader header)
        {
            Param.AssertNotNull(header, "header");

            for (Node<CsToken> tokenNode = header.ChildTokens.First; tokenNode != null; tokenNode = tokenNode.Next)
            {
                CsToken token = tokenNode.Value;

                if (token.CsTokenType == CsTokenType.XmlHeaderLine)
                {
                    if (token.Text.Length > 3)
                    {
                        if (token.Text[3] != ' ' && token.Text[3] != '\t' && token.Text[3] != '/' && token.Text[2] != '\n' && token.Text[2] != '\r')
                        {
                            // The header line does not start with any spaces.
                            this.AddViolation(tokenNode.Value.FindParentElement(), token.Location, Rules.DocumentationLinesMustBeginWithSingleSpace);
                        }
                        else if (token.Text.Length > 4 && (token.Text[4] == ' ' || token.Text[4] == '\t'))
                        {
                            // The header line starts with more than one space. This is only allowed when the 
                            // header line is not the first or last line in the header.
                            bool error = true;
                            for (Node<CsToken> previous = tokenNode.Previous; previous != null; previous = previous.Previous)
                            {
                                if (previous.Value.CsTokenType == CsTokenType.XmlHeaderLine)
                                {
                                    for (Node<CsToken> next = tokenNode.Next; next != null; next = next.Next)
                                    {
                                        if (next.Value.CsTokenType == CsTokenType.XmlHeaderLine)
                                        {
                                            error = false;
                                            break;
                                        }
                                    }

                                    break;
                                }
                            }

                            if (error)
                            {
                                this.AddViolation(token.FindParentElement(), token.Location, Rules.DocumentationLinesMustBeginWithSingleSpace);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Parses and returns a delegate.
        /// </summary>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Delegate ParseDelegate(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // The access defaults to public for a top-level element, or private for a nested element.
            AccessModifierType accessModifier = AccessModifierType.Public;
            if (parent.ElementType == ElementType.Class || parent.ElementType == ElementType.Struct)
            {
                accessModifier = AccessModifierType.Private;
            }

            // Get the modifiers and access.
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, DelegateModifiers);

            unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe);

            // Get the delegate keyword.
            this.tokens.Add(this.GetToken(CsTokenType.Delegate, SymbolType.Delegate, elementReference));

            // Get the return type.
            TypeToken returnType = this.GetTypeToken(elementReference, unsafeCode, true);
            this.tokens.Add(returnType);

            // Get the name of the delegate.
            CsToken name = this.GetElementNameToken(elementReference, unsafeCode);
            this.tokens.Add(name);

            // Get the parameter list.
            IList<Parameter> parameters = this.ParseParameterList(elementReference, unsafeCode, SymbolType.OpenParenthesis);

            // Check whether there are any type constraint clauses.
            ICollection<TypeParameterConstraintClause> typeConstraints = null;
            Symbol symbol = this.GetNextSymbol(elementReference);
            if (symbol.Text == "where")
            {
                typeConstraints = this.ParseTypeConstraintClauses(elementReference, unsafeCode);
            }

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Delegate, accessModifier, modifiers);

            // Get the closing semicolon.
            this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference));

            Delegate element = new Delegate(this.document, parent, xmlHeader, attributes, declaration, returnType, parameters, typeConstraints, unsafeCode, generated);

            elementReference.Target = element;
            return element;
        }
        /// <summary>
        /// Parses and returns a destructor.
        /// </summary>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Destructor ParseDestructor(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // Get the modifiers and access.
            AccessModifierType accessModifier = AccessModifierType.Private;
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, DestructorModifiers);

            unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe);

            // Move past the tilde symbol.
            this.tokens.Add(this.GetToken(CsTokenType.DestructorTilde, SymbolType.Tilde, elementReference));

            // Get the name of the destructor.
            CsToken nameToken = this.GetElementNameToken(elementReference, unsafeCode);
            this.tokens.Add(nameToken);

            string destructorName = "~" + nameToken.Text;

            // Get the opening and closing parenthesis.
            Bracket openingParenthesis = this.GetBracketToken(CsTokenType.OpenParenthesis, SymbolType.OpenParenthesis, elementReference);
            Node<CsToken> openingParenthesisNode = this.tokens.InsertLast(openingParenthesis);

            Bracket closingParenthesis = this.GetBracketToken(CsTokenType.CloseParenthesis, SymbolType.CloseParenthesis, elementReference);
            Node<CsToken> closingParenthesisNode = this.tokens.InsertLast(closingParenthesis);

            openingParenthesis.MatchingBracketNode = closingParenthesisNode;
            closingParenthesis.MatchingBracketNode = openingParenthesisNode;

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, destructorName, ElementType.Destructor, accessModifier, modifiers);

            Destructor destructor = new Destructor(this.document, parent, xmlHeader, attributes, declaration, unsafeCode, generated);
            elementReference.Target = destructor;

            // If the destructor is extern, it will not have a body.
            if (modifiers.ContainsKey(CsTokenType.Extern))
            {
                // Get the closing semicolon.
                this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference));
            }
            else
            {
                // Get the body.
                this.ParseStatementContainer(destructor, true, unsafeCode);
            }

            return destructor;
        }
        /// <summary>
        /// Initializes a new instance of the Method class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="returnType">
        /// The method's return type.
        /// </param>
        /// <param name="parameters">
        /// The parameters to the method.
        /// </param>
        /// <param name="typeConstraints">
        /// The list of type constraints on the element.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Method(
            CsDocument document, 
            CsElement parent, 
            XmlHeader header, 
            ICollection<Attribute> attributes, 
            Declaration declaration, 
            TypeToken returnType, 
            IList<Parameter> parameters, 
            ICollection<TypeParameterConstraintClause> typeConstraints, 
            bool unsafeCode, 
            bool generated)
            : base(document, parent, ElementType.Method, "method " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.Ignore(returnType);
            Param.AssertNotNull(parameters, "parameters");
            Param.Ignore(typeConstraints);
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            Debug.Assert(
                returnType != null || declaration.ContainsModifier(CsTokenType.Explicit, CsTokenType.Implicit), 
                "A method's return type can only be null in an explicit or implicit operator overload method.");

            this.returnType = returnType;
            this.parameters = parameters;
            this.typeConstraints = typeConstraints;

            Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only.");

            // Determine whether this is an extension method. The method must be static.
            if (this.parameters.Count > 0 && this.Declaration.ContainsModifier(CsTokenType.Static))
            {
                // Look at this first parameter. Since the parameters collection is not an indexable list, the 
                // easiest way to do this is to foreach through the parameter list and break after the first one.
                foreach (Parameter parameter in this.parameters)
                {
                    if ((parameter.Modifiers & ParameterModifiers.This) != 0)
                    {
                        this.extensionMethod = true;
                    }

                    break;
                }
            }

            // Add the qualifications.
            this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName);

            // If this is an explicit interface member implementation and our access modifier
            // is currently set to private because we don't have one, then it should be public instead.
            if (this.Declaration.Name.IndexOf(".", StringComparison.Ordinal) > -1 && !this.Declaration.Name.StartsWith("this.", StringComparison.Ordinal))
            {
                this.Declaration.AccessModifierType = AccessModifierType.Public;
            }

            // Set the parent of the type constraint clauses.
            if (typeConstraints != null)
            {
                foreach (TypeParameterConstraintClause constraint in typeConstraints)
                {
                    constraint.ParentElement = this;
                }
            }
        }
        /// <summary>
        /// Parses and returns a constructor.
        /// </summary>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Constructor ParseConstructor(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // Get the modifiers and access.
            AccessModifierType accessModifier = AccessModifierType.Private;
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, ConstructorModifiers);

            unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe);

            // Get the name of the constructor.
            CsToken name = this.GetElementNameToken(elementReference, unsafeCode);
            this.tokens.Add(name);

            // Get the parameter list.
            IList<Parameter> parameters = this.ParseParameterList(elementReference, unsafeCode, SymbolType.OpenParenthesis);

            // Get the constructor initializer if there is one.
            MethodInvocationExpression constructorInitializer = null;

            Symbol symbol = this.GetNextSymbol(elementReference);
            if (symbol.SymbolType == SymbolType.Colon)
            {
                this.tokens.Add(this.GetToken(CsTokenType.BaseColon, SymbolType.Colon, elementReference));

                // The next symbol must be the keyword base or this.
                symbol = this.GetNextSymbol(elementReference);
                if (symbol.SymbolType != SymbolType.This && symbol.SymbolType != SymbolType.Base)
                {
                    throw this.CreateSyntaxException();
                }

                Reference<ICodePart> initializerNameExpressionReference = new Reference<ICodePart>();
                Node<CsToken> initializerNameTokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Other, symbol.SymbolType, initializerNameExpressionReference));

                // Get the name expression.
                LiteralExpression initializerNameExpression = new LiteralExpression(this.tokens, initializerNameTokenNode);
                initializerNameExpressionReference.Target = initializerNameExpression;

                // Get the initializer expression.
                constructorInitializer = this.GetMethodInvocationExpression(initializerNameExpression, ExpressionPrecedence.None, unsafeCode);
            }

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Constructor, accessModifier, modifiers);

            Constructor constructor = new Constructor(
                this.document, parent, xmlHeader, attributes, declaration, parameters, constructorInitializer, unsafeCode, generated);

            elementReference.Target = constructor;

            // If the constructor is extern, it will not have a body.
            if (modifiers.ContainsKey(CsTokenType.Extern))
            {
                // Get the closing semicolon.
                this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference));
            }
            else
            {
                // Get the body.
                this.ParseStatementContainer(constructor, true, unsafeCode);
            }

            return constructor;
        }
        /// <summary>
        /// Parses and returns a property, indexer, or event accessor.
        /// </summary>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Accessor ParseAccessor(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // Get the modifiers and access.
            AccessModifierType accessModifier = AccessModifierType.Private;
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, null);

            // Get the accessor type token.
            AccessorType accessorType = AccessorType.Get;
            CsToken accessorName = null;

            Symbol symbol = this.GetNextSymbol(elementReference);
            if (symbol.Text == "get")
            {
                accessorName = this.GetToken(CsTokenType.Get, SymbolType.Other, elementReference);

                if (parent.ElementType != ElementType.Property && parent.ElementType != ElementType.Indexer)
                {
                    throw this.CreateSyntaxException();
                }
            }
            else if (symbol.Text == "set")
            {
                accessorType = AccessorType.Set;
                accessorName = this.GetToken(CsTokenType.Set, SymbolType.Other, elementReference);

                if (parent.ElementType != ElementType.Property && parent.ElementType != ElementType.Indexer)
                {
                    throw this.CreateSyntaxException();
                }
            }
            else if (symbol.Text == "add")
            {
                accessorType = AccessorType.Add;
                accessorName = this.GetToken(CsTokenType.Add, SymbolType.Other, elementReference);

                if (parent.ElementType != ElementType.Event)
                {
                    throw this.CreateSyntaxException();
                }
            }
            else if (symbol.Text == "remove")
            {
                accessorType = AccessorType.Remove;
                accessorName = this.GetToken(CsTokenType.Remove, SymbolType.Other, elementReference);

                if (parent.ElementType != ElementType.Event)
                {
                    throw this.CreateSyntaxException();
                }
            }
            else
            {
                throw this.CreateSyntaxException();
            }

            this.tokens.Add(accessorName);

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, accessorName.Text, ElementType.Accessor, accessModifier, modifiers);

            Accessor accessor = new Accessor(this.document, parent, accessorType, xmlHeader, attributes, declaration, unsafeCode, generated);
            elementReference.Target = accessor;

            // Get the method body.
            this.ParseStatementContainer(accessor, true, unsafeCode);

            return accessor;
        }
        /// <summary>
        /// Moves past whitespace, comments, preprocessors and xml headers up to the start of the next element.
        /// </summary>
        /// <param name="element">
        /// The parent element.
        /// </param>
        /// <param name="parentElementReference">
        /// A reference to the parent element.
        /// </param>
        /// <param name="childElementReference">
        /// A reference to the child element about to be created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is unsafe.
        /// </param>
        /// <param name="xmlHeader">
        /// Returns the xml header, if any.
        /// </param>
        /// <param name="attributes">
        /// Returns the list of attributes, if any.
        /// </param>
        private void MoveToElementDeclaration(
            CsElement element,
            Reference<ICodePart> parentElementReference,
            Reference<ICodePart> childElementReference,
            bool unsafeCode,
            out XmlHeader xmlHeader,
            out ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parentElementReference, "parentElementReference");
            Param.AssertNotNull(childElementReference, "childElementReference");
            Param.Ignore(unsafeCode);

            // Initialize the out parameters.
            xmlHeader = null;

            List<Attribute> tempAttributes = new List<Attribute>();

            SkipSymbols skip = SkipSymbols.All;
            skip &= ~SkipSymbols.XmlHeader;

            Reference<ICodePart> currentElementReference = parentElementReference;

            // Loop past any comments, whitespace, preprocessor statements, xml headers, and element attributes. Keep
            // going until we get to the element itself.
            bool loop = true;
            Symbol symbol = this.GetNextSymbol(skip, currentElementReference, true);
            while (symbol != null && loop)
            {
                switch (symbol.SymbolType)
                {
                    case SymbolType.XmlHeaderLine:

                        // Get the xml header.
                        currentElementReference = childElementReference;
                        xmlHeader = this.GetXmlHeader(childElementReference);
                        if (xmlHeader == null)
                        {
                            throw new SyntaxException(this.document.SourceCode, symbol.LineNumber);
                        }

                        // Add the header to the document.
                        this.tokens.Add(xmlHeader);
                        break;

                    case SymbolType.OpenSquareBracket:

                        // Need to see if its an assembly attribute.
                        // If it is don't process it here.
                        ElementType? nextElementType = this.GetElementType(element, unsafeCode);

                        if (nextElementType == ElementType.AssemblyOrModuleAttribute)
                        {
                            loop = false;
                        }
                        else
                        {
                            // Get the attribute statement.
                            currentElementReference = childElementReference;
                            Attribute attribute = this.GetAttribute(childElementReference, unsafeCode);
                            if (attribute == null)
                            {
                                throw new SyntaxException(this.document.SourceCode, symbol.LineNumber);
                            }

                            tempAttributes.Add(attribute);

                            // Add the attribute to the document.
                            this.tokens.Add(attribute);
                        }

                        break;

                    default:

                        // This must be the start of the element.
                        loop = false;
                        break;
                }

                symbol = this.GetNextSymbol(skip, currentElementReference, true);
            }

            // Set the attributes as a read-only collection.
            attributes = tempAttributes.ToArray();
        }
        /// <summary>
        /// Gets an xml header.
        /// </summary>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <returns>
        /// Returns the header or null if there is no header.
        /// </returns>
        private XmlHeader GetXmlHeader(Reference<ICodePart> elementReference)
        {
            Param.AssertNotNull(elementReference, "elementReference");

            // Get the first symbol and make sure it is the right type.
            int index = 1;
            Symbol firstSymbol = this.symbols.Peek(index);
            Debug.Assert(firstSymbol != null && firstSymbol.SymbolType == SymbolType.XmlHeaderLine, "Expected an xml documentation header line");

            // Marks the end of the header.
            int end = -1;
            int endOfLineCount = 0;

            Reference<ICodePart> xmlHeaderReference = new Reference<ICodePart>();

            // Loop until the entire header is found.
            Symbol symbol = firstSymbol;
            while (symbol != null)
            {
                if (symbol.SymbolType == SymbolType.XmlHeaderLine)
                {
                    // This type of token belongs in the header.
                    end = index;
                    endOfLineCount = 0;
                }
                else if (symbol.SymbolType == SymbolType.EndOfLine)
                {
                    if (++endOfLineCount > 1)
                    {
                        // If there are two newlines in a row, this is the
                        // end of the Xml header.
                        break;
                    }
                }
                else if (symbol.SymbolType == SymbolType.WhiteSpace || symbol.SymbolType == SymbolType.SingleLineComment)
                {
                    endOfLineCount = 0;
                }
                else
                {
                    // This is the end of the header.
                    break;
                }

                // Advance the index and get the next symbol.
                symbol = this.symbols.Peek(++index);
            }

            // Make sure we've advanced at least one symbol.
            Debug.Assert(end != -1, "Should have advanced at least one symbol");

            // Add all of the symbols for the header to a token list.
            MasterList<CsToken> headerTokens = new MasterList<CsToken>();
            for (int i = 1; i <= end; ++i)
            {
                this.symbols.Advance();
                Debug.Assert(this.symbols.Current != null, "The current symbol should not be null");

                headerTokens.Add(this.ConvertSymbol(this.symbols.Current, TokenTypeFromSymbolType(this.symbols.Current.SymbolType), xmlHeaderReference));
            }

            // Get the location of the header.
            CodeLocation location = CodeLocation.Join(firstSymbol.Location, this.symbols.Current.Location);

            // Create the Xml header object.
            XmlHeader xmlHeader = new XmlHeader(headerTokens, location, elementReference, this.symbols.Generated);
            xmlHeaderReference.Target = xmlHeader;

            return xmlHeader;
        }
        /// <summary>
        /// Parses and returns a property.
        /// </summary>
        /// <param name="parent">The parent of the element.</param>
        /// <param name="elementReference">A reference to the element being created.</param>
        /// <param name="unsafeCode">Indicates whether the code is marked as unsafe.</param>
        /// <param name="generated">Indicates whether the code is marked as generated code.</param>
        /// <param name="xmlHeader">The element's documentation header.</param>
        /// <param name="attributes">The attributes on the element.</param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Property ParseProperty(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // Get the modifiers and access.
            AccessModifierType accessModifier = AccessModifierType.Private;

            // Properties within interfaces always have the access of the parent interface.
            Interface parentInterface = parent as Interface;
            if (parentInterface != null)
            {
                accessModifier = parentInterface.AccessModifier;
            }

            // Get declared modifiers.
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, PropertyModifiers);
            unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe);

            // Get the field type.
            TypeToken propertyType = this.GetTypeToken(elementReference, unsafeCode, true);
            Node<CsToken> propertyTypeNode = this.tokens.InsertLast(propertyType);

            // Get the name of the property.
            CsToken name = this.GetElementNameToken(elementReference, unsafeCode);
            Node<CsToken> propertyNameNode = this.tokens.InsertLast(name);

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Property, accessModifier, modifiers);

            Property property = new Property(this.document, parent, xmlHeader, attributes, declaration, propertyType, unsafeCode, generated);
            elementReference.Target = property;
            
            if (this.IsBodiedExpression())
            {
                this.ParseStatementContainer(property, true, unsafeCode);
            }
            else
            {
                // Parse the body of the property.
                this.ParseElementContainer(property, elementReference, null, unsafeCode);

                // Check if current property has initializer (C#6).
                Symbol nextSymbol = this.GetNextSymbol(SkipSymbols.WhiteSpace, elementReference, true);
                if (nextSymbol != null && nextSymbol.SymbolType == SymbolType.Equals)
                {
                    // Get all of the variable declarators.
                    IList<VariableDeclaratorExpression> declarators = this.ParsePropertyDeclarators(elementReference, unsafeCode, propertyType, propertyNameNode);

                    if (declarators.Count == 0)
                    {
                        throw this.CreateSyntaxException();
                    }

                    VariableDeclarationExpression declarationExpression =
                        new VariableDeclarationExpression(
                            new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), new LiteralExpression(this.tokens, propertyTypeNode), declarators);

                    // Get the trailing semicolon.
                    this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference));

                    // Create the variable declaration statement and add it to the field.
                    property.VariableDeclarationStatement = new VariableDeclarationStatement(
                        new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), false, declarationExpression);
                }
            }

            return property;
        }
        /// <summary>
        /// Parses and returns an element.
        /// </summary>
        /// <param name="elementType">
        /// The type of element to parse.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="partialElements">
        /// The collection of partial elements found while parsing the files.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private CsElement ParseElement(
            ElementType elementType,
            CsElement parent,
            Reference<ICodePart> elementReference,
            Dictionary<string, List<CsElement>> partialElements,
            bool unsafeCode,
            bool generated,
            XmlHeader xmlHeader,
            ICollection<Attribute> attributes)
        {
            Param.Ignore(elementType);
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(partialElements);
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            switch (elementType)
            {
                case ElementType.Namespace:
                    return this.ParseNamespace(parent, elementReference, partialElements, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.ExternAliasDirective:
                    return this.ParseExternAliasDirective(parent, elementReference, generated);

                case ElementType.UsingDirective:
                    return this.ParseUsingDirective(parent, elementReference, unsafeCode, generated);

                case ElementType.AssemblyOrModuleAttribute:
                    return this.ParseAssemblyOrModuleAttribute(parent, elementReference, generated);

                case ElementType.Class:
                case ElementType.Struct:
                case ElementType.Interface:
                    return this.ParseClass(elementType, parent, elementReference, partialElements, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.Enum:
                    return this.ParseEnum(parent, elementReference, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.Delegate:
                    return this.ParseDelegate(parent, elementReference, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.Field:
                    return this.ParseField(parent, elementReference, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.Method:
                    return this.ParseMethod(parent, elementReference, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.Constructor:
                    return this.ParseConstructor(parent, elementReference, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.Destructor:
                    return this.ParseDestructor(parent, elementReference, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.Property:
                    return this.ParseProperty(parent, elementReference, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.Indexer:
                    return this.ParseIndexer(parent, elementReference, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.Event:
                    return this.ParseEvent(parent, elementReference, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.Accessor:
                    return this.ParseAccessor(parent, elementReference, unsafeCode, generated, xmlHeader, attributes);

                case ElementType.EmptyElement:
                    return this.ParseEmptyElement(parent, elementReference, unsafeCode, generated);

                default:
                    Debug.Fail("Unexpected element type.");
                    throw new StyleCopException();
            }
        }
 /// <summary>
 /// Initializes a new instance of the Namespace class.
 /// </summary>
 /// <param name="document">
 /// The document that contains the element.
 /// </param>
 /// <param name="parent">
 /// The parent of the element.
 /// </param>
 /// <param name="type">
 /// The element type.
 /// </param>
 /// <param name="name">
 /// The name of this element.
 /// </param>
 /// <param name="header">
 /// The Xml header for this element.
 /// </param>
 /// <param name="attributes">
 /// The list of attributes attached to this element.
 /// </param>
 /// <param name="declaration">
 /// The declaration code for this element.
 /// </param>
 /// <param name="unsafeCode">
 /// Indicates whether the element resides within a block of unsafe code.
 /// </param>
 /// <param name="generated">
 /// Indicates whether the code element was generated or written by hand.
 /// </param>
 internal Namespace(
     CsDocument document, 
     CsElement parent, 
     ElementType type, 
     string name, 
     XmlHeader header, 
     ICollection<Attribute> attributes, 
     Declaration declaration, 
     bool unsafeCode, 
     bool generated)
     : base(document, parent, type, name, header, attributes, declaration, unsafeCode, generated)
 {
     Param.Ignore(document, parent, type, name, header, attributes, declaration, unsafeCode, generated);
 }
        /// <summary>
        /// Parses and returns an <see cref="Enum"/>.
        /// </summary>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Enum ParseEnum(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // The access defaults to public for a top-level element, or private for a nested element.
            AccessModifierType accessModifier = AccessModifierType.Public;
            if (parent.ElementType == ElementType.Class || parent.ElementType == ElementType.Struct)
            {
                accessModifier = AccessModifierType.Private;
            }

            // Get the modifiers and access.
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, EnumModifiers);

            // Get the enum keyword.
            this.tokens.Add(this.GetToken(CsTokenType.Enum, SymbolType.Enum, elementReference));

            // Add the enum name token.
            CsToken name = this.GetElementNameToken(elementReference, unsafeCode);
            this.tokens.Add(name);

            // Get the base type.
            Symbol symbol = this.GetNextSymbol(elementReference);

            if (symbol.SymbolType == SymbolType.Colon)
            {
                // Add the colon token and the base item name.
                this.tokens.Add(this.GetToken(CsTokenType.BaseColon, SymbolType.Colon, elementReference));
                this.tokens.Add(this.GetTypeToken(elementReference, unsafeCode, false));
            }

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Enum, accessModifier, modifiers);

            // Create the enum element.
            Enum @enum = new Enum(this.document, parent, xmlHeader, attributes, declaration, unsafeCode, generated);
            elementReference.Target = @enum;

            // Get the opening curly bracket.
            Bracket openingCurlyBracket = this.GetBracketToken(CsTokenType.OpenCurlyBracket, SymbolType.OpenCurlyBracket, elementReference);
            Node<CsToken> openingCurlyBracketNode = this.tokens.InsertLast(openingCurlyBracket);

            // Get each of the enum items.
            @enum.Items = this.ParseEnumItems(@enum, elementReference, unsafeCode);

            // Get the closing curly bracket.
            Bracket closingCurlyBracket = this.GetBracketToken(CsTokenType.CloseCurlyBracket, SymbolType.CloseCurlyBracket, elementReference);
            Node<CsToken> closingCurlyBracketNode = this.tokens.InsertLast(closingCurlyBracket);

            openingCurlyBracket.MatchingBracketNode = closingCurlyBracketNode;
            closingCurlyBracket.MatchingBracketNode = openingCurlyBracketNode;

            return @enum;
        }
        /// <summary>
        /// Initializes a new instance of the Event class.
        /// </summary>
        /// <param name="document">
        /// The document that contains this element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="eventHandlerType">
        /// The type of the event handler.
        /// </param>
        /// <param name="eventDeclarators">
        /// Declarators for the event.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Event(
            CsDocument document, 
            CsElement parent, 
            XmlHeader header, 
            ICollection<Attribute> attributes, 
            Declaration declaration, 
            TypeToken eventHandlerType, 
            ICollection<EventDeclaratorExpression> eventDeclarators, 
            bool unsafeCode, 
            bool generated)
            : base(document, parent, ElementType.Event, "event " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.AssertNotNull(eventHandlerType, "eventHandlerType");
            Param.AssertNotNull(eventDeclarators, "eventDeclarators");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            this.eventHandlerType = eventHandlerType;
            this.eventDeclarators = eventDeclarators;

            foreach (EventDeclaratorExpression expression in this.eventDeclarators)
            {
                this.AddExpression(expression);
                expression.ParentEvent = this;
            }
        }
        /// <summary>
        /// Parses and returns a event.
        /// </summary>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Event ParseEvent(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // Get the modifiers and access.
            AccessModifierType accessModifier = AccessModifierType.Private;

            // Events within interfaces always have the access of the parent interface.
            Interface parentInterface = parent as Interface;
            if (parentInterface != null)
            {
                accessModifier = parentInterface.AccessModifier;
            }

            // Get declared modifiers.
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, EventModifiers);

            unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe);

            // Get the event keyword.
            this.tokens.Add(this.GetToken(CsTokenType.Event, SymbolType.Event, elementReference));

            // Get the event type.
            TypeToken eventHandlerType = this.GetTypeToken(elementReference, unsafeCode, true);
            this.tokens.Add(eventHandlerType);

            List<EventDeclaratorExpression> declarators = new List<EventDeclaratorExpression>();
            string firstEventName = null;

            while (true)
            {
                Symbol symbol = this.GetNextSymbol(SymbolType.Other, elementReference);

                Reference<ICodePart> declaratorExpressionReference = new Reference<ICodePart>();

                // Get the identifier.
                LiteralExpression identifier = this.GetTypeTokenExpression(declaratorExpressionReference, unsafeCode, false);
                if (identifier == null || identifier.Tokens.First == null)
                {
                    throw new SyntaxException(this.document.SourceCode, symbol.LineNumber);
                }

                if (firstEventName == null)
                {
                    firstEventName = identifier.Token.Text;
                }

                // Get the initializer if it exists.
                Expression initializer = null;

                symbol = this.GetNextSymbol(declaratorExpressionReference);
                if (symbol.SymbolType == SymbolType.Equals)
                {
                    // Add the equals token.
                    this.tokens.Add(this.GetOperatorToken(OperatorType.Equals, declaratorExpressionReference));

                    initializer = this.GetNextExpression(ExpressionPrecedence.None, declaratorExpressionReference, unsafeCode);
                }

                // Create the token list for the declarator.
                CsTokenList partialTokens = new CsTokenList(this.tokens, identifier.Tokens.First, this.tokens.Last);

                // Create and add the declarator.
                EventDeclaratorExpression declaratorExpression = new EventDeclaratorExpression(partialTokens, identifier, initializer);

                declaratorExpressionReference.Target = declaratorExpression;
                declarators.Add(declaratorExpression);

                // Now check if the next character is a comma. If so there is another declarator.
                symbol = this.GetNextSymbol(elementReference);
                if (symbol.SymbolType != SymbolType.Comma)
                {
                    // There are no more declarators.
                    break;
                }

                // Add the comma.
                this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma, elementReference));
            }

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, firstEventName, ElementType.Event, accessModifier, modifiers);

            Event @event = new Event(this.document, parent, xmlHeader, attributes, declaration, eventHandlerType, declarators.ToArray(), unsafeCode, generated);
            elementReference.Target = @event;

            Symbol s = this.GetNextSymbol(elementReference);

            if (s.SymbolType == SymbolType.Semicolon)
            {
                this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference));
            }
            else
            {
                // Parse the body of the event.
                this.ParseElementContainer(@event, elementReference, null, unsafeCode);
            }

            return @event;
        }
        /// <summary>
        /// Initializes a new instance of the ClassBase class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="type">
        /// The element type.
        /// </param>
        /// <param name="name">
        /// The name of this element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="typeConstraints">
        /// The list of type constraints on the element.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal ClassBase(
            CsDocument document, 
            CsElement parent, 
            ElementType type, 
            string name, 
            XmlHeader header, 
            ICollection<Attribute> attributes, 
            Declaration declaration, 
            ICollection<TypeParameterConstraintClause> typeConstraints, 
            bool unsafeCode, 
            bool generated)
            : base(document, parent, type, name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.Ignore(document, parent, type, name, header, attributes, declaration, typeConstraints, unsafeCode, generated);

            this.typeConstraints = typeConstraints;

            // Set the parent of the type constraint clauses.
            if (typeConstraints != null)
            {
                Debug.Assert(typeConstraints.IsReadOnly, "The typeconstraints collection should be read-only.");

                foreach (TypeParameterConstraintClause constraint in typeConstraints)
                {
                    constraint.ParentElement = this;
                }
            }
        }
        /// <summary>
        /// Parses and returns a field.
        /// </summary>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Field ParseField(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // Get the modifiers and access.
            AccessModifierType accessModifier = AccessModifierType.Private;
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, FieldModifiers);

            unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe);

            // Get the field type.
            TypeToken fieldType = this.GetTypeToken(elementReference, unsafeCode, true);
            Node<CsToken> fieldTypeNode = this.tokens.InsertLast(fieldType);

            // Get all of the variable declarators.
            IList<VariableDeclaratorExpression> declarators = this.ParseFieldDeclarators(elementReference, unsafeCode, fieldType);

            if (declarators.Count == 0)
            {
                throw this.CreateSyntaxException();
            }

            VariableDeclarationExpression declarationExpression =
                new VariableDeclarationExpression(
                    new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), new LiteralExpression(this.tokens, fieldTypeNode), declarators);

            // Create the field.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, declarators[0].Identifier.Text, ElementType.Field, accessModifier, modifiers);

            Field field = new Field(this.document, parent, xmlHeader, attributes, declaration, fieldType, unsafeCode, generated);
            elementReference.Target = field;

            // Get the trailing semicolon.
            this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference));

            // Create the variable declaration statement and add it to the field.
            field.VariableDeclarationStatement = new VariableDeclarationStatement(
                new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), field.Const, declarationExpression);

            return field;
        }
        /// <summary>
        /// Parses the contents of the header for validity.
        /// </summary>
        /// <param name="element">
        /// The element.
        /// </param>
        /// <param name="header">
        /// The header.
        /// </param>
        /// <param name="lineNumber">
        /// The line number that the header element begins on.
        /// </param>
        /// <param name="partialElement">
        /// Indicates whether the element has the partial attribute.
        /// </param>
        private void ParseHeader(CsElement element, XmlHeader header, int lineNumber, bool partialElement)
        {
            Param.AssertNotNull(element, "element");
            Param.AssertNotNull(header, "header");
            Param.AssertGreaterThanZero(lineNumber, "lineNumber");
            Param.Ignore(partialElement);

            // Load this into an xml document.
            XmlDocument rawDocs = null;
            XmlDocument formattedDocs = null;

            this.LoadHeaderIntoDocuments(element, header, lineNumber, out rawDocs, out formattedDocs);

            if (rawDocs != null && formattedDocs != null)
            {
                // Check whether the method has an <inheritdoc> tag at the root. If so, discontinue checking the contents of the header, 
                // but verify that the class actually inherits from a base class. Otherwise this tag is not allowed.
                if (rawDocs.SelectSingleNode("root/inheritdoc") != null)
                {
                    this.CheckInheritDocRules(element);
                }
                else
                {
                    // Insert any documentation present in 'include' tags.
                    if (this.InsertIncludedDocumentation(element, formattedDocs))
                    {
                        this.CheckForBlankLinesInDocumentationHeader(element, header);
                        this.CheckHeaderSummary(element, lineNumber, partialElement, formattedDocs);
                        this.CheckHeaderElementsForEmptyText(element, formattedDocs);

                        // Check element parameters and return types.
                        if (element.ElementType == ElementType.Method)
                        {
                            Method item = element as Method;
                            this.CheckHeaderParams(element, item.Parameters, formattedDocs);
                            this.CheckHeaderReturnValue(element, item.ReturnType, formattedDocs);
                        }
                        else if (element.ElementType == ElementType.Constructor)
                        {
                            Constructor item = element as Constructor;
                            this.CheckHeaderParams(element, item.Parameters, formattedDocs);
                            this.CheckConstructorSummaryText(item, formattedDocs);
                        }
                        else if (element.ElementType == ElementType.Delegate)
                        {
                            Delegate item = element as Delegate;
                            this.CheckHeaderParams(element, item.Parameters, formattedDocs);
                            this.CheckHeaderReturnValue(element, item.ReturnType, formattedDocs);
                        }
                        else if (element.ElementType == ElementType.Indexer)
                        {
                            Indexer item = element as Indexer;
                            this.CheckHeaderParams(element, item.Parameters, formattedDocs);
                            this.CheckHeaderReturnValue(element, item.ReturnType, formattedDocs);
                        }
                        else if (element.ElementType == ElementType.Property)
                        {
                            // Check value tags on properties.
                            this.CheckPropertyValueTag(element, formattedDocs);

                            // Check that the property summary starts with the correct text.
                            this.CheckPropertySummaryFormatting(element as Property, formattedDocs);
                        }
                        else if (element.ElementType == ElementType.Destructor)
                        {
                            this.CheckDestructorSummaryText((Destructor)element, formattedDocs);
                        }

                        // Check for repeating comments on all element types which can contain params or typeparams.
                        if (element.ElementType == ElementType.Method || element.ElementType == ElementType.Constructor || element.ElementType == ElementType.Delegate
                            || element.ElementType == ElementType.Indexer || element.ElementType == ElementType.Class || element.ElementType == ElementType.Struct
                            || element.ElementType == ElementType.Interface || element.ElementType == ElementType.Property || element.ElementType == ElementType.Event
                            || element.ElementType == ElementType.Field || element.ElementType == ElementType.Destructor)
                        {
                            this.CheckForRepeatingComments(element, formattedDocs);
                        }

                        // Check generic type parameters.
                        if (element.ElementType == ElementType.Class || element.ElementType == ElementType.Method || element.ElementType == ElementType.Delegate
                            || element.ElementType == ElementType.Interface || element.ElementType == ElementType.Struct)
                        {
                            this.CheckGenericTypeParams(element, formattedDocs);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Parses and returns an indexer.
        /// </summary>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Indexer ParseIndexer(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // Get the modifiers and access.
            AccessModifierType accessModifier = AccessModifierType.Private;

            // Indexers within interfaces always have the access of the parent interface.
            Interface parentInterface = parent as Interface;
            if (parentInterface != null)
            {
                accessModifier = parentInterface.AccessModifier;
            }

            // Get declared modifiers.
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, IndexerModifiers);

            unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe);

            // Get the return type.
            TypeToken returnType = this.GetTypeToken(elementReference, unsafeCode, true);
            this.tokens.Add(returnType);

            // Get the name of the indexer.
            CsToken name = this.GetElementNameToken(elementReference, unsafeCode);
            this.tokens.Add(name);

            // Get the parameter list.
            IList<Parameter> parameters = this.ParseParameterList(elementReference, unsafeCode, SymbolType.OpenSquareBracket);

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Indexer, accessModifier, modifiers);

            Indexer indexer = new Indexer(this.document, parent, xmlHeader, attributes, declaration, returnType, parameters, unsafeCode, generated);
            elementReference.Target = indexer;

            // Parse the body of the indexer.
            this.ParseElementContainer(indexer, elementReference, null, unsafeCode);

            return indexer;
        }
Exemple #42
0
        /// <summary>
        /// Initializes a new instance of the Method class.
        /// </summary>
        /// <param name="document">
        /// The document that contains the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="header">
        /// The Xml header for this element.
        /// </param>
        /// <param name="attributes">
        /// The list of attributes attached to this element.
        /// </param>
        /// <param name="declaration">
        /// The declaration code for this element.
        /// </param>
        /// <param name="returnType">
        /// The method's return type.
        /// </param>
        /// <param name="parameters">
        /// The parameters to the method.
        /// </param>
        /// <param name="typeConstraints">
        /// The list of type constraints on the element.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the element resides within a block of unsafe code.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code element was generated or written by hand.
        /// </param>
        internal Method(
            CsDocument document,
            CsElement parent,
            XmlHeader header,
            ICollection <Attribute> attributes,
            Declaration declaration,
            TypeToken returnType,
            IList <Parameter> parameters,
            ICollection <TypeParameterConstraintClause> typeConstraints,
            bool unsafeCode,
            bool generated)
            : base(document, parent, ElementType.Method, "method " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
        {
            Param.AssertNotNull(document, "document");
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(header);
            Param.Ignore(attributes);
            Param.AssertNotNull(declaration, "declaration");
            Param.Ignore(returnType);
            Param.AssertNotNull(parameters, "parameters");
            Param.Ignore(typeConstraints);
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

            Debug.Assert(
                returnType != null || declaration.ContainsModifier(CsTokenType.Explicit, CsTokenType.Implicit),
                "A method's return type can only be null in an explicit or implicit operator overload method.");

            this.returnType      = returnType;
            this.parameters      = parameters;
            this.typeConstraints = typeConstraints;

            Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only.");

            // Determine whether this is an extension method. The method must be static.
            if (this.parameters.Count > 0 && this.Declaration.ContainsModifier(CsTokenType.Static))
            {
                // Look at this first parameter. Since the parameters collection is not an indexable list, the
                // easiest way to do this is to foreach through the parameter list and break after the first one.
                foreach (Parameter parameter in this.parameters)
                {
                    if ((parameter.Modifiers & ParameterModifiers.This) != 0)
                    {
                        this.extensionMethod = true;
                    }

                    break;
                }
            }

            // Add the qualifications.
            this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName);

            // If this is an explicit interface member implementation and our access modifier
            // is currently set to private because we don't have one, then it should be public instead.
            if (this.Declaration.Name.IndexOf(".", StringComparison.Ordinal) > -1 && !this.Declaration.Name.StartsWith("this.", StringComparison.Ordinal))
            {
                this.Declaration.AccessModifierType = AccessModifierType.Public;
            }

            // Set the parent of the type constraint clauses.
            if (typeConstraints != null)
            {
                foreach (TypeParameterConstraintClause constraint in typeConstraints)
                {
                    constraint.ParentElement = this;
                }
            }
        }
        /// <summary>
        /// Parses and returns a method.
        /// </summary>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private Method ParseMethod(
            CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // Get the modifiers and access.
            AccessModifierType accessModifier = AccessModifierType.Private;

            // Get the declared modifiers for the method.
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, MethodModifiers);

            // Methods within interfaces always have the access of the parent interface.
            Interface parentInterface = parent as Interface;
            if (parentInterface != null)
            {
                accessModifier = parentInterface.AccessModifier;
            }

            unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe);

            TypeToken returnType = null;
            if (!modifiers.ContainsKey(CsTokenType.Implicit) && !modifiers.ContainsKey(CsTokenType.Explicit))
            {
                // Get the return type.
                returnType = this.GetTypeToken(elementReference, unsafeCode, true);
                this.tokens.Add(returnType);
            }

            // Get the name of the method.
            string methodName = null;

            Symbol symbol = this.GetNextSymbol(elementReference);
            if (symbol.SymbolType == SymbolType.Operator)
            {
                this.tokens.Add(this.GetToken(CsTokenType.Operator, SymbolType.Operator, elementReference));

                // Advance up to the next symbol.
                this.AdvanceToNextCodeSymbol(elementReference);

                // The overloaded item will either be a type or a symbol.
                int endIndex = -1;
                CsToken operatorType = null;

                if (this.HasTypeSignature(1, unsafeCode, out endIndex))
                {
                    // The overloaded item is a type.
                    operatorType = this.GetTypeToken(elementReference, unsafeCode, true);
                }
                else
                {
                    // The overloaded item is a symbol.
                    operatorType = this.ConvertOperatorOverloadSymbol(elementReference);
                }

                this.tokens.Add(operatorType);
                methodName = "operator " + operatorType.Text;
            }
            else
            {
                CsToken name = this.GetElementNameToken(elementReference, unsafeCode);
                methodName = name.Text;
                this.tokens.Add(name);
            }

            // Get the parameter list.
            IList<Parameter> parameters = this.ParseParameterList(elementReference, unsafeCode, SymbolType.OpenParenthesis, modifiers.ContainsKey(CsTokenType.Static));

            // Check whether there are any type constraint clauses.
            ICollection<TypeParameterConstraintClause> typeConstraints = null;
            symbol = this.GetNextSymbol(elementReference);
            if (symbol.Text == "where")
            {
                typeConstraints = this.ParseTypeConstraintClauses(elementReference, unsafeCode);
            }

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, methodName, ElementType.Method, accessModifier, modifiers);

            Method method = new Method(this.document, parent, xmlHeader, attributes, declaration, returnType, parameters, typeConstraints, unsafeCode, generated);
            elementReference.Target = method;

            // If the element is extern, abstract, or containing within an interface, it will not have a body.
             if (modifiers.ContainsKey(CsTokenType.Abstract) || modifiers.ContainsKey(CsTokenType.Extern) || parent.ElementType == ElementType.Interface)
            {
                // Get the closing semicolon.
                this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference));
            }
            else
            {
                // Get the method body or bodied expression C# 6.
                this.ParseStatementContainer(method, true, unsafeCode);
            }

            return method;
        }
        /// <summary>
        /// Parses and returns a class, struct, or interface.
        /// </summary>
        /// <param name="elementType">
        /// The type of the element.
        /// </param>
        /// <param name="parent">
        /// The parent of the element.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="partialElements">
        /// The collection of partial elements found while parsing the files.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <param name="xmlHeader">
        /// The element's documentation header.
        /// </param>
        /// <param name="attributes">
        /// The attributes on the element.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private ClassBase ParseClass(
            ElementType elementType,
            CsElement parent,
            Reference<ICodePart> elementReference,
            Dictionary<string, List<CsElement>> partialElements,
            bool unsafeCode,
            bool generated,
            XmlHeader xmlHeader,
            ICollection<Attribute> attributes)
        {
            Param.Ignore(elementType);
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.AssertNotNull(partialElements, "partialElements");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);
            Param.Ignore(xmlHeader);
            Param.Ignore(attributes);

            Node<CsToken> previousTokenNode = this.tokens.Last;

            // Top-level classes, structs, and interfaces received Internal access by default, while classes, structs, and interfaces
            // declared within a class receive Private access by default.
            AccessModifierType accessModifier = AccessModifierType.Internal;
            if (parent.ElementType == ElementType.Class)
            {
                accessModifier = AccessModifierType.Private;
            }

            // Get the modifiers and access.
            Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, ClassModifiers);

            unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe);

            // Get the element keyword, depending on the element type.
            CsTokenType keywordType = CsTokenType.Class;
            SymbolType symbolType = SymbolType.Class;
            if (elementType == ElementType.Struct)
            {
                keywordType = CsTokenType.Struct;
                symbolType = SymbolType.Struct;
            }
            else if (elementType == ElementType.Interface)
            {
                keywordType = CsTokenType.Interface;
                symbolType = SymbolType.Interface;
            }
            else
            {
                Debug.Assert(elementType == ElementType.Class, "The method can only be called for a class, struct, or interface");
            }

            // Add the keyword token.
            this.tokens.Add(this.GetToken(keywordType, symbolType, elementReference));

            // Add the class name token.
            CsToken name = this.GetElementNameToken(elementReference, unsafeCode);
            this.tokens.Add(name);

            // Get the base classes.
            Symbol symbol = this.GetNextSymbol(elementReference);

            if (symbol.SymbolType == SymbolType.Colon)
            {
                // Add the colon token.
                this.tokens.Add(this.GetToken(CsTokenType.BaseColon, SymbolType.Colon, elementReference));

                // Get each of the base classes and interfaces.
                while (true)
                {
                    this.tokens.Add(this.GetTypeToken(elementReference, unsafeCode, false));

                    symbol = this.GetNextSymbol(elementReference);
                    if (symbol.SymbolType != SymbolType.Comma)
                    {
                        break;
                    }

                    this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma, elementReference));
                }
            }

            // Check whether there are any type constraint clauses.
            ICollection<TypeParameterConstraintClause> typeConstraints = null;
            symbol = this.GetNextSymbol(elementReference);
            if (symbol.Text == "where")
            {
                typeConstraints = this.ParseTypeConstraintClauses(elementReference, unsafeCode);
            }

            // Create the declaration.
            Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next;
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, name.Text, elementType, accessModifier, modifiers);

            // Create the element.
            ClassBase item = null;
            if (keywordType == CsTokenType.Class)
            {
                item = new Class(this.document, parent, xmlHeader, attributes, declaration, typeConstraints, unsafeCode, generated);
            }
            else if (keywordType == CsTokenType.Struct)
            {
                item = new Struct(this.document, parent, xmlHeader, attributes, declaration, typeConstraints, unsafeCode, generated);
            }
            else
            {
                Debug.Assert(keywordType == CsTokenType.Interface, "Invalid element type");
                item = new Interface(this.document, parent, xmlHeader, attributes, declaration, typeConstraints, unsafeCode, generated);
            }

            elementReference.Target = item;

            // Parse the body of the element.
            this.ParseElementContainer(item, elementReference, partialElements, unsafeCode);

            return item;
        }
Exemple #45
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Enum"/> class.
 /// </summary>
 /// <param name="document">
 /// The document that contains the element.
 /// </param>
 /// <param name="parent">
 /// The parent of the element.
 /// </param>
 /// <param name="header">
 /// The Xml header for this element.
 /// </param>
 /// <param name="attributes">
 /// The list of attributes attached to this element.
 /// </param>
 /// <param name="declaration">
 /// The declaration code for this element.
 /// </param>
 /// <param name="unsafeCode">
 /// Indicates whether the element resides within a block of unsafe code.
 /// </param>
 /// <param name="generated">
 /// Indicates whether the code element was generated or written by hand.
 /// </param>
 internal Enum(
     CsDocument document, CsElement parent, XmlHeader header, ICollection<Attribute> attributes, Declaration declaration, bool unsafeCode, bool generated)
     : base(document, parent, ElementType.Enum, "enum " + declaration.Name, header, attributes, declaration, unsafeCode, generated)
 {
     Param.Ignore(document, parent, header, attributes, declaration, unsafeCode, generated);
 }