Beispiel #1
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);
        }
Beispiel #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;
            }
        }
 /// <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);
 }
 /// <summary>
 /// Initializes a new instance of the AssemblyOrModuleAttribute class.
 /// </summary>
 /// <param name="document">
 /// The document that contains the element.
 /// </param>
 /// <param name="parent">
 /// The parent of the element.
 /// </param>
 /// <param name="declaration">
 /// The declaration code for this element.
 /// </param>
 /// <param name="generated">
 /// Indicates whether the code element was generated or written by hand.
 /// </param>
 /// <param name="attributes">
 /// The actual attribute that this Assembly or Module level attribute contains.
 /// </param>
 internal AssemblyOrModuleAttribute(CsDocument document, CsElement parent, Declaration declaration, bool generated, ICollection<Attribute> attributes)
     : base(
         document, 
         parent, 
         ElementType.AssemblyOrModuleAttribute, 
         "assembly or module attribute " + declaration.Name, 
         null, 
         attributes, 
         declaration, 
         false, 
         generated)
 {
     Param.Ignore(document, parent, declaration, generated);
 }
Beispiel #5
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;
            }
        }
        /// <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);
            }
        }
Beispiel #7
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);
            }
        }
        /// <summary>
        /// Parses and returns a extern alias directive.
        /// </summary>
        /// <param name="parent">
        /// The parent of the namespace.
        /// </param>
        /// <param name="elementReference">
        /// A reference to the element being created.
        /// </param>
        /// <param name="generated">
        /// Indicates whether the code is marked as generated code.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private ExternAliasDirective ParseExternAliasDirective(CsElement parent, Reference<ICodePart> elementReference, bool generated)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(generated);

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

            // Add the alias token.
            this.tokens.Add(this.GetToken(CsTokenType.Alias, SymbolType.Other, elementReference));

            // Add the identifier token.
            CsToken identifier = this.GetToken(CsTokenType.Other, SymbolType.Other, elementReference);
            this.tokens.Add(identifier);

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

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

            // Create the extern alias directive.
            ExternAliasDirective element = new ExternAliasDirective(this.document, parent, declaration, generated);
            elementReference.Target = element;

            return element;
        }
        /// <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 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>
 /// 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 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 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 an assembly or module attribute.
        ///// </summary>
        ///// <param name="parent">The parent of the namespace.</param>
        ///// <param name="elementReference">A reference to the element being created.</param>
        ///// <param name="generated">Indicates whether the code is marked as generated code.</param>
        ///// <returns>Returns the element.</returns>
        private AssemblyOrModuleAttribute ParseAssemblyOrModuleAttribute(CsElement parent, Reference<ICodePart> elementReference, bool generated)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(generated);

            Attribute attribute = this.GetAttribute(elementReference, false);

            Node<CsToken> firstToken = this.tokens.InsertLast(attribute);

            // Create the declaration.
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstToken, this.tokens.Last);

            Declaration declaration = new Declaration(declarationTokens, attribute.Text, ElementType.AssemblyOrModuleAttribute, AccessModifierType.Public);

            ICollection<Attribute> attributes = new List<Attribute>(1) { attribute }.ToArray();

            AssemblyOrModuleAttribute element = new AssemblyOrModuleAttribute(this.document, parent, declaration, generated, attributes);
            elementReference.Target = element;
            return element;
        }
        /// <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;
        }
        /// <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>
        /// 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);
        }
Beispiel #19
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>
        /// 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 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 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;
        }
Beispiel #23
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;
            }
        }
        /// <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;
        }
Beispiel #25
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 using directive.
        /// </summary>
        /// <param name="parent">
        /// The parent of the namespace.
        /// </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>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private UsingDirective ParseUsingDirective(CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

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

            int index = this.GetNextCodeSymbolIndex(2);
            if (index == -1)
            {
                throw this.CreateSyntaxException();
            }

            // Check static word introduce in C# 6
            Symbol staticSymbol = this.symbols.Peek(index);
            if (staticSymbol != null && staticSymbol.SymbolType == SymbolType.Static)
            {
                CsToken staticToken = this.GetToken(CsTokenType.Static, SymbolType.Static, elementReference);
                this.tokens.Add(staticToken);
            }

            // The next symbol will either be the namespace, or an alias. To determine this, look past this to see if there is an equals sign.
            Symbol peekAhead = this.GetNextSymbol(SymbolType.Other, elementReference);

            index = this.GetNextCodeSymbolIndex(2);
            if (index == -1)
            {
                throw this.CreateSyntaxException();
            }

            CsToken alias = null;

            peekAhead = this.symbols.Peek(index);
            if (peekAhead.SymbolType == SymbolType.Equals)
            {
                // There is an alias. First collect the alias.
                alias = this.GetToken(CsTokenType.Other, SymbolType.Other, elementReference);
                this.tokens.Add(alias);

                // Next collect the equals sign.
                this.tokens.Add(this.GetOperatorToken(OperatorType.Equals, elementReference));
            }

            // Collect and add the namespace token.
            TypeToken @namespace = this.GetTypeToken(elementReference, unsafeCode, false);
            this.tokens.Add(@namespace);

            // Create the declaration.
            CsTokenList declarationTokens = new CsTokenList(this.tokens, firstToken, this.tokens.Last);
            Declaration declaration = new Declaration(
                declarationTokens, alias == null ? @namespace.Text : alias.Text, ElementType.UsingDirective, AccessModifierType.Public);

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

            // Create the using directive.
            UsingDirective element = new UsingDirective(this.document, parent, declaration, generated, @namespace.Text, alias == null ? null : alias.Text);
            elementReference.Target = element;

            return element;
        }
        /// <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>
        /// Sets the inherited items of the class.
        /// </summary>
        /// <param name="declaration">
        /// The class declaration.
        /// </param>
        protected void SetInheritedItems(Declaration declaration)
        {
            Param.RequireNotNull(declaration, "declaration");

            // Pull out the name of the base class and any implemented interfaces 
            // from the declaration of this class.
            bool colon = false;
            bool comma = false;
            List<string> interfaces = new List<string>();

            foreach (CsToken token in declaration.Tokens)
            {
                if (colon)
                {
                    if (token.CsTokenType != CsTokenType.WhiteSpace && token.CsTokenType != CsTokenType.EndOfLine && token.CsTokenType != CsTokenType.SingleLineComment
                        && token.CsTokenType != CsTokenType.MultiLineComment && token.CsTokenType != CsTokenType.PreprocessorDirective)
                    {
                        if (token.Text.Length >= 2 && token.Text[0] == 'I' && char.IsUpper(token.Text[1]))
                        {
                            interfaces.Add(CodeParser.TrimType(token.Text));
                        }
                        else
                        {
                            this.baseClass = CodeParser.TrimType(token.Text);
                        }

                        colon = false;
                    }
                }
                else if (comma)
                {
                    if (token.CsTokenType != CsTokenType.WhiteSpace && token.CsTokenType != CsTokenType.EndOfLine && token.CsTokenType != CsTokenType.SingleLineComment
                        && token.CsTokenType != CsTokenType.MultiLineComment && token.CsTokenType != CsTokenType.PreprocessorDirective)
                    {
                        interfaces.Add(CodeParser.TrimType(token.Text));
                        comma = false;
                    }
                }
                else
                {
                    if (token.CsTokenType == CsTokenType.Where)
                    {
                        break;
                    }
                    else if (token.Text == ":")
                    {
                        if (this.baseClass.Length > 0)
                        {
                            break;
                        }
                        else
                        {
                            colon = true;
                        }
                    }
                    else if (token.CsTokenType == CsTokenType.Comma)
                    {
                        comma = true;
                    }
                }
            }

            if (interfaces.Count > 0)
            {
                this.implementedInterfaces = interfaces.ToArray();
            }
        }
        /// <summary>
        /// Parses and returns the items within an <see cref="Enum"/> element.
        /// </summary>
        /// <param name="parent">
        /// The parent <see cref="Enum"/> element.
        /// </param>
        /// <param name="parentReference">
        /// Reference to the parent of the items we're creating.
        /// </param>
        /// <param name="unsafeCode">
        /// Indicates whether the code is marked as unsafe.
        /// </param>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private ICollection<EnumItem> ParseEnumItems(Enum parent, Reference<ICodePart> parentReference, bool unsafeCode)
        {
            Param.AssertNotNull(parent, "parent");
            Param.Ignore(unsafeCode);
            Param.AssertNotNull(parentReference, "parentReference");

            List<EnumItem> enumItems = new List<EnumItem>();

            SkipSymbols skip = SkipSymbols.All;
            skip &= ~SkipSymbols.XmlHeader;
            Symbol symbol = this.GetNextSymbol(skip, parentReference);

            while (symbol.SymbolType != SymbolType.CloseCurlyBracket)
            {
                // Get the enum header.
                XmlHeader xmlHeader = null;
                ICollection<Attribute> attributes;

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

                this.MoveToElementDeclaration(parent, parentReference, enumItemReference, unsafeCode, out xmlHeader, out attributes);

                // If the next symbol is a close curly bracket, quit.
                symbol = this.GetNextSymbol(enumItemReference);
                if (symbol.SymbolType == SymbolType.CloseCurlyBracket)
                {
                    break;
                }

                // Get the enum item name.
                Node<CsToken> firstEnumItemToken = this.tokens.InsertLast(this.GetToken(CsTokenType.Other, SymbolType.Other, enumItemReference));

                Expression initializationExpression = null;

                // See if there is an equals sign.
                symbol = this.GetNextSymbol(enumItemReference);
                if (symbol.SymbolType == SymbolType.Equals)
                {
                    this.tokens.Add(this.GetOperatorToken(OperatorType.Equals, enumItemReference));

                    // Get the constant expression being assigned.
                    initializationExpression = this.GetNextExpression(ExpressionPrecedence.None, enumItemReference, unsafeCode);
                }

                CsTokenList enumItemTokens = new CsTokenList(this.tokens, firstEnumItemToken, this.tokens.Last);

                Declaration enumItemDeclaration = new Declaration(enumItemTokens, firstEnumItemToken.Value.Text, ElementType.EnumItem, AccessModifierType.Public);

                EnumItem enumItem = new EnumItem(
                    this.document, parent, xmlHeader, attributes, enumItemDeclaration, initializationExpression, unsafeCode, this.symbols.Generated);

                enumItemReference.Target = enumItem;
                enumItem.Tokens = new CsTokenList(this.tokens, firstEnumItemToken, this.tokens.Last);

                enumItems.Add(enumItem);

                // Add any suppressed rules.
                this.AddRuleSuppressionsForElement(enumItem);

                parent.AddElement(enumItem);

                symbol = this.GetNextSymbol(parentReference);

                // If the symbol is not a comma, quit.
                if (symbol.SymbolType == SymbolType.Comma)
                {
                    this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma, parentReference));
                }
                else
                {
                    break;
                }

                symbol = this.GetNextSymbol(skip, parentReference);
            }

            // Return the enum items as a read-only collection.
            return enumItems.ToArray();
        }
        /// <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;
        }
Beispiel #31
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;
            }
        }
Beispiel #32
0
        /// <summary>
        /// Parses the contents of the document.
        /// </summary>
        internal void ParseDocument()
        {
            Debug.Assert(this.document == null, "A CodeParser instance may only be used once.");

            // Find the list of symbols in the document.
            List<Symbol> symbolList = this.lexer.GetSymbols(this.lexer.SourceCode, this.lexer.SourceCode.Project.Configuration);

            // Create the symbol manager class.
            this.symbols = new SymbolManager(symbolList);

            // Create the document object.
            this.document = new CsDocument(this.lexer.SourceCode, this.parser, this.tokens);

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

            // Get the file header if it exists.
            FileHeader fileHeader = this.GetFileHeader(documentRootReference);

            // Let the symbol manager know if this document contains generated code.
            if (fileHeader.Generated)
            {
                this.symbols.IncrementGeneratedCodeBlocks();
            }

            this.document.FileHeader = fileHeader;

            // Create a declaration for the root element.
            Declaration declaration = new Declaration(
                new CsTokenList(this.document.Tokens), Strings.Root, ElementType.Root, AccessModifierType.Public, new Dictionary<CsTokenType, CsToken>());

            // Create the root element for the document.
            DocumentRoot root = new DocumentRoot(this.document, declaration, fileHeader.Generated);
            documentRootReference.Target = root;

            // Parse the contents of the document.
            this.ParseElementContainerBody(root, documentRootReference, this.parser.PartialElements, false);

            // Check if there are any tokens in the document.
            if (this.document.Tokens.Count > 0)
            {
                // Fill in the token list for the root element.
                root.Tokens = new CsTokenList(this.document.Tokens, this.document.Tokens.First, this.document.Tokens.Last);

                // Fill in the location for the element.
                root.Location = CsToken.JoinLocations(this.document.Tokens.First, this.document.Tokens.Last);
            }

            // Add the root element to the document.
            this.document.RootElement = root;

            // When in debug mode, ensure that all tokens are correctly mapped to a parent element.
            this.DebugValidateParentReferences();
        }
        /// <summary>
        /// Parses and returns an empty element.
        /// </summary>
        /// <param name="parent">
        /// The parent of the namespace.
        /// </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>
        /// <returns>
        /// Returns the element.
        /// </returns>
        private EmptyElement ParseEmptyElement(CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated)
        {
            Param.AssertNotNull(parent, "parent");
            Param.AssertNotNull(elementReference, "elementReference");
            Param.Ignore(unsafeCode);
            Param.Ignore(generated);

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

            // Create the declaration.
            CsTokenList declarationTokens = new CsTokenList(this.tokens, this.tokens.Last, this.tokens.Last);
            Declaration declaration = new Declaration(declarationTokens, string.Empty, ElementType.EmptyElement, AccessModifierType.Public);

            // Create the element.
            EmptyElement element = new EmptyElement(this.document, parent, declaration, unsafeCode, generated);
            elementReference.Target = element;

            return element;
        }