/// <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> /// 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 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 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); }
/// <summary> /// Initializes a new instance of the Event class. /// </summary> /// <param name="document"> /// The document that contains this element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="eventHandlerType"> /// The type of the event handler. /// </param> /// <param name="eventDeclarators"> /// Declarators for the event. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Event( CsDocument document, CsElement parent, XmlHeader header, ICollection <Attribute> attributes, Declaration declaration, TypeToken eventHandlerType, ICollection <EventDeclaratorExpression> eventDeclarators, bool unsafeCode, bool generated) : base(document, parent, ElementType.Event, "event " + declaration.Name, header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.AssertNotNull(eventHandlerType, "eventHandlerType"); Param.AssertNotNull(eventDeclarators, "eventDeclarators"); Param.Ignore(unsafeCode); Param.Ignore(generated); this.eventHandlerType = eventHandlerType; this.eventDeclarators = eventDeclarators; foreach (EventDeclaratorExpression expression in this.eventDeclarators) { this.AddExpression(expression); expression.ParentEvent = this; } }
/// <summary> /// Initializes a new instance of the Accessor class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="accessorType"> /// The type of the accessor. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Accessor( CsDocument document, CsElement parent, AccessorType accessorType, XmlHeader header, ICollection<Attribute> attributes, Declaration declaration, bool unsafeCode, bool generated) : base(document, parent, ElementType.Accessor, declaration.Name + " accessor", header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(accessorType); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.Ignore(unsafeCode); Param.Ignore(generated); this.accessorType = accessorType; // Make sure the type and name match. Debug.Assert( (accessorType == AccessorType.Get && declaration.Name == "get") || (accessorType == AccessorType.Set && declaration.Name == "set") || (accessorType == AccessorType.Add && declaration.Name == "add") || (accessorType == AccessorType.Remove && declaration.Name == "remove"), "The accessor type does not match its name."); this.FillDetails(parent); }
/// <summary> /// Initializes a new instance of the Accessor class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="accessorType"> /// The type of the accessor. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Accessor( CsDocument document, CsElement parent, AccessorType accessorType, XmlHeader header, ICollection <Attribute> attributes, Declaration declaration, bool unsafeCode, bool generated) : base(document, parent, ElementType.Accessor, declaration.Name + " accessor", header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(accessorType); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.Ignore(unsafeCode); Param.Ignore(generated); this.accessorType = accessorType; // Make sure the type and name match. Debug.Assert( (accessorType == AccessorType.Get && declaration.Name == "get") || (accessorType == AccessorType.Set && declaration.Name == "set") || (accessorType == AccessorType.Add && declaration.Name == "add") || (accessorType == AccessorType.Remove && declaration.Name == "remove"), "The accessor type does not match its name."); this.FillDetails(parent); }
/// <summary> /// Initializes a new instance of the Class class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="typeConstraints"> /// The list of type constraints on the class, if any. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Class( CsDocument document, CsElement parent, XmlHeader header, ICollection<Attribute> attributes, Declaration declaration, ICollection<TypeParameterConstraintClause> typeConstraints, bool unsafeCode, bool generated) : base(document, parent, ElementType.Class, "class " + declaration.Name, header, attributes, declaration, typeConstraints, unsafeCode, generated) { Param.Ignore(document, parent, header, attributes, declaration, typeConstraints, unsafeCode, generated); }
/// <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 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> /// 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 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 Delegate class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="returnType"> /// The return type. /// </param> /// <param name="parameters"> /// The parameters to the delegate. /// </param> /// <param name="typeConstraints"> /// The list of type constraints on the element. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether this is generated code. /// </param> internal Delegate( CsDocument document, CsElement parent, XmlHeader header, ICollection <Attribute> attributes, Declaration declaration, TypeToken returnType, IList <Parameter> parameters, ICollection <TypeParameterConstraintClause> typeConstraints, bool unsafeCode, bool generated) : base(document, parent, ElementType.Delegate, "delegate " + declaration.Name, header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.AssertNotNull(returnType, "returnType"); Param.AssertNotNull(parameters, "parameters"); Param.Ignore(typeConstraints); Param.Ignore(unsafeCode); Param.Ignore(generated); this.returnType = returnType; this.typeConstraints = typeConstraints; this.parameters = parameters; Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only."); // Add the qualifications this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName); // Set the parent of the type constraint clauses. if (typeConstraints != null) { Debug.Assert(typeConstraints.IsReadOnly, "The collection of type constraints should be read-only."); foreach (TypeParameterConstraintClause constraint in typeConstraints) { constraint.ParentElement = this; } } }
/// <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> /// 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> /// Initializes a new instance of the Constructor class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="parameters"> /// The parameters to the constructor. /// </param> /// <param name="initializerExpression"> /// The constructor initializer, if there is one. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Constructor( CsDocument document, CsElement parent, XmlHeader header, ICollection <Attribute> attributes, Declaration declaration, IList <Parameter> parameters, MethodInvocationExpression initializerExpression, bool unsafeCode, bool generated) : base(document, parent, ElementType.Constructor, "constructor " + declaration.Name, header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.AssertNotNull(parameters, "parameters"); Param.Ignore(initializerExpression); Param.Ignore(unsafeCode); Param.Ignore(generated); // Static constructors are treated as private and handled as a special case for ordering. if (this.Declaration.ContainsModifier(CsTokenType.Static)) { this.Declaration.AccessModifierType = AccessModifierType.Private; } this.parameters = parameters; Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only."); // Add the qualifications this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName); // If there is an initializer expression, add it to the statement list for this constructor. if (initializerExpression != null) { this.initializer = initializerExpression; ConstructorInitializerStatement initializerStatement = new ConstructorInitializerStatement(initializerExpression.Tokens, initializerExpression); this.AddStatement(initializerStatement); } }
/// <summary> /// Initializes a new instance of the Constructor class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="parameters"> /// The parameters to the constructor. /// </param> /// <param name="initializerExpression"> /// The constructor initializer, if there is one. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Constructor( CsDocument document, CsElement parent, XmlHeader header, ICollection<Attribute> attributes, Declaration declaration, IList<Parameter> parameters, MethodInvocationExpression initializerExpression, bool unsafeCode, bool generated) : base(document, parent, ElementType.Constructor, "constructor " + declaration.Name, header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.AssertNotNull(parameters, "parameters"); Param.Ignore(initializerExpression); Param.Ignore(unsafeCode); Param.Ignore(generated); // Static constructors are treated as private and handled as a special case for ordering. if (this.Declaration.ContainsModifier(CsTokenType.Static)) { this.Declaration.AccessModifierType = AccessModifierType.Private; } this.parameters = parameters; Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only."); // Add the qualifications this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName); // If there is an initializer expression, add it to the statement list for this constructor. if (initializerExpression != null) { this.initializer = initializerExpression; ConstructorInitializerStatement initializerStatement = new ConstructorInitializerStatement(initializerExpression.Tokens, initializerExpression); this.AddStatement(initializerStatement); } }
/// <summary> /// Initializes a new instance of the Indexer class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="returnType"> /// The return type of the indexer. /// </param> /// <param name="parameters"> /// The parameters to the indexer. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Indexer( CsDocument document, CsElement parent, XmlHeader header, ICollection <Attribute> attributes, Declaration declaration, TypeToken returnType, IList <Parameter> parameters, bool unsafeCode, bool generated) : base(document, parent, ElementType.Indexer, "indexer " + declaration.Name, header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.Ignore(returnType); Param.AssertNotNull(parameters, "parameters"); Param.Ignore(unsafeCode); Param.Ignore(generated); this.returnType = returnType; this.parameters = parameters; Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only."); // Add the qualifications this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName); // If this is an explicit interface member implementation and our access modifier // is currently set to private because we don't have one, then it should be public instead. if (this.Declaration.Name.IndexOf(".", StringComparison.Ordinal) > -1 && !this.Declaration.Name.StartsWith("this.", StringComparison.Ordinal)) { this.Declaration.AccessModifierType = AccessModifierType.Public; } }
/// <summary> /// Parses and returns a namespace. /// </summary> /// <param name="parent"> /// The parent of the namespace. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="partialElements"> /// The collection of partial elements found while parsing the files. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Namespace ParseNamespace( CsElement parent, Reference<ICodePart> elementReference, Dictionary<string, List<CsElement>> partialElements, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.AssertNotNull(partialElements, "partialElements"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); // Add the namespace token. Node<CsToken> firstToken = this.tokens.InsertLast(this.GetToken(CsTokenType.Namespace, SymbolType.Namespace, elementReference)); // Add the namespace name token. CsToken name = this.GetElementNameToken(elementReference, unsafeCode); this.tokens.Add(name); // Create the declaration. CsTokenList declarationTokens = new CsTokenList(this.tokens, firstToken, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Namespace, AccessModifierType.Public); // Create the namespace. Namespace @namespace = new Namespace(this.document, parent, xmlHeader, attributes, declaration, unsafeCode, generated); elementReference.Target = @namespace; // Parse the body of the namespace. this.ParseElementContainer(@namespace, elementReference, partialElements, unsafeCode); return @namespace; }
/// <summary> /// Initializes a new instance of the Field class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="fieldType"> /// The type of the field. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Field( CsDocument document, CsElement parent, XmlHeader header, ICollection<Attribute> attributes, Declaration declaration, TypeToken fieldType, bool unsafeCode, bool generated) : base(document, parent, ElementType.Field, "field " + declaration.Name, header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.AssertNotNull(fieldType, "fieldType"); Param.Ignore(unsafeCode); Param.Ignore(generated); this.type = fieldType; // Determine whether the item is const /readonly / static. this.isConst = this.Declaration.ContainsModifier(CsTokenType.Const); this.isReadOnly = this.Declaration.ContainsModifier(CsTokenType.Readonly); this.isStatic = this.Declaration.ContainsModifier(CsTokenType.Static); }
/// <summary> /// Initializes a new instance of the <see cref="Enum"/> class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Enum( CsDocument document, CsElement parent, XmlHeader header, ICollection <Attribute> attributes, Declaration declaration, bool unsafeCode, bool generated) : base(document, parent, ElementType.Enum, "enum " + declaration.Name, header, attributes, declaration, unsafeCode, generated) { Param.Ignore(document, parent, header, attributes, declaration, unsafeCode, generated); }
/// <summary> /// Loads the header text for the element into a document and returns it. /// </summary> /// <param name="element"> /// The element containing the header. /// </param> /// <param name="header"> /// The header to load. /// </param> /// <param name="lineNumber"> /// The line number that the header begins on. /// </param> /// <param name="rawDocs"> /// Returns the docs with whitespace and newlines left in place. /// </param> /// <param name="formattedDocs"> /// Returns the docs with newlines filtered out. /// </param> private void LoadHeaderIntoDocuments(CsElement element, XmlHeader header, int lineNumber, out XmlDocument rawDocs, out XmlDocument formattedDocs) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(header, "header"); Param.AssertGreaterThanZero(lineNumber, "lineNumber"); rawDocs = new XmlDocument(); try { string correctxml = "<root>" + header.RawText + "</root>"; rawDocs.LoadXml(correctxml); formattedDocs = FormatXmlDocument(rawDocs); } catch (XmlException xmlex) { this.AddViolation(element, lineNumber, Rules.DocumentationMustContainValidXml, xmlex.Message); rawDocs = formattedDocs = null; } }
/// <summary> /// Initializes a new instance of the CsElement class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="type"> /// The element type. /// </param> /// <param name="name"> /// The name of this element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element is unsafe. /// </param> /// <param name="generated"> /// Indicates whether the element was generated or written by hand. /// </param> internal CsElement( CsDocument document, CsElement parent, ElementType type, string name, XmlHeader header, ICollection <Attribute> attributes, Declaration declaration, bool unsafeCode, bool generated) : base(CodePartType.Element) { Param.AssertNotNull(document, "document"); Param.Ignore(parent); Param.Ignore(type); Param.AssertNotNull(name, "name"); Param.Ignore(header); Param.Ignore(attributes); Param.Ignore(declaration); Param.Ignore(unsafeCode); Param.Ignore(generated); this.document = document; if (this.document == null) { throw new ArgumentException(Strings.DocumentMustBeCsDocument, "document"); } if (parent != null && parent.Document != document) { throw new ArgumentException(Strings.ElementMustBeInParentsDocument, "parent"); } this.type = type; this.name = CodeLexer.DecodeEscapedText(name, true); this.header = header; this.attributes = attributes; this.declaration = declaration; this.unsafeCode = unsafeCode; this.generated = generated; if (!unsafeCode && this.declaration.ContainsModifier(CsTokenType.Unsafe)) { this.unsafeCode = true; } // Fill in the element reference in the header object. if (this.header != null) { Debug.Assert(this.header.Element == null, "The header element should not be empty."); this.header.Element = this; } // Fill in the element reference in the attributes list items. if (this.attributes != null) { Debug.Assert(this.attributes.IsReadOnly, "The attributes collection should be read-only."); foreach (Attribute attribute in this.attributes) { Debug.Assert(attribute.Element == null, "The attribute element should not be empty"); attribute.Element = this; } } // Set the fully qualified base name if (parent != null) { this.fullyQualifiedBase = parent.FullyQualifiedName; this.MergeAccess(parent.ActualAccess); } else { if (this.declaration != null) { this.actualAccess = this.declaration.AccessModifierType; } else { this.actualAccess = AccessModifierType.Public; } } // Set the fully qualified name this.fullyQualifiedName = this.fullyQualifiedBase; if (this.declaration != null && this.declaration.Name != null && this.declaration.Name.Length > 0) { if (this.fullyQualifiedBase != null && this.fullyQualifiedBase.Length > 0) { this.fullyQualifiedName += "."; } int index = this.declaration.Name.LastIndexOf("\\", StringComparison.Ordinal); if (index != -1) { this.fullyQualifiedName += this.declaration.Name.Substring(index + 1, this.declaration.Name.Length - index - 1); } else { this.fullyQualifiedName += this.declaration.Name; } index = this.fullyQualifiedName.IndexOf(".cs.", StringComparison.OrdinalIgnoreCase); if (-1 == index) { this.fullNamespaceName = this.fullyQualifiedName; } else { this.fullNamespaceName = this.fullyQualifiedName.Substring(index + 4, this.fullyQualifiedName.Length - index - 4); } } // There is only one type of element which is allowed to have a token // list consisting of nothing other than whitespace, newlines, etc., // which is the document root. This happens if you have a document which // contains nothing other than whitespace. Due to this we do not want to // trim down the token list for the root element, but we do want to for // all other types of elements. if (type == ElementType.Root) { this.TrimTokens = false; } }
/// <summary> /// Checks to make sure that the slashes in in the Xml header are followed by a space. /// </summary> /// <param name="header"> /// The Xml header token. /// </param> private void CheckXmlHeaderComment(XmlHeader header) { Param.AssertNotNull(header, "header"); for (Node<CsToken> tokenNode = header.ChildTokens.First; tokenNode != null; tokenNode = tokenNode.Next) { CsToken token = tokenNode.Value; if (token.CsTokenType == CsTokenType.XmlHeaderLine) { if (token.Text.Length > 3) { if (token.Text[3] != ' ' && token.Text[3] != '\t' && token.Text[3] != '/' && token.Text[2] != '\n' && token.Text[2] != '\r') { // The header line does not start with any spaces. this.AddViolation(tokenNode.Value.FindParentElement(), token.Location, Rules.DocumentationLinesMustBeginWithSingleSpace); } else if (token.Text.Length > 4 && (token.Text[4] == ' ' || token.Text[4] == '\t')) { // The header line starts with more than one space. This is only allowed when the // header line is not the first or last line in the header. bool error = true; for (Node<CsToken> previous = tokenNode.Previous; previous != null; previous = previous.Previous) { if (previous.Value.CsTokenType == CsTokenType.XmlHeaderLine) { for (Node<CsToken> next = tokenNode.Next; next != null; next = next.Next) { if (next.Value.CsTokenType == CsTokenType.XmlHeaderLine) { error = false; break; } } break; } } if (error) { this.AddViolation(token.FindParentElement(), token.Location, Rules.DocumentationLinesMustBeginWithSingleSpace); } } } } } }
/// <summary> /// Parses and returns a delegate. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Delegate ParseDelegate( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // The access defaults to public for a top-level element, or private for a nested element. AccessModifierType accessModifier = AccessModifierType.Public; if (parent.ElementType == ElementType.Class || parent.ElementType == ElementType.Struct) { accessModifier = AccessModifierType.Private; } // Get the modifiers and access. Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, DelegateModifiers); unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); // Get the delegate keyword. this.tokens.Add(this.GetToken(CsTokenType.Delegate, SymbolType.Delegate, elementReference)); // Get the return type. TypeToken returnType = this.GetTypeToken(elementReference, unsafeCode, true); this.tokens.Add(returnType); // Get the name of the delegate. CsToken name = this.GetElementNameToken(elementReference, unsafeCode); this.tokens.Add(name); // Get the parameter list. IList<Parameter> parameters = this.ParseParameterList(elementReference, unsafeCode, SymbolType.OpenParenthesis); // Check whether there are any type constraint clauses. ICollection<TypeParameterConstraintClause> typeConstraints = null; Symbol symbol = this.GetNextSymbol(elementReference); if (symbol.Text == "where") { typeConstraints = this.ParseTypeConstraintClauses(elementReference, unsafeCode); } // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Delegate, accessModifier, modifiers); // Get the closing semicolon. this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference)); Delegate element = new Delegate(this.document, parent, xmlHeader, attributes, declaration, returnType, parameters, typeConstraints, unsafeCode, generated); elementReference.Target = element; return element; }
/// <summary> /// Parses and returns a destructor. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Destructor ParseDestructor( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, DestructorModifiers); unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); // Move past the tilde symbol. this.tokens.Add(this.GetToken(CsTokenType.DestructorTilde, SymbolType.Tilde, elementReference)); // Get the name of the destructor. CsToken nameToken = this.GetElementNameToken(elementReference, unsafeCode); this.tokens.Add(nameToken); string destructorName = "~" + nameToken.Text; // Get the opening and closing parenthesis. Bracket openingParenthesis = this.GetBracketToken(CsTokenType.OpenParenthesis, SymbolType.OpenParenthesis, elementReference); Node<CsToken> openingParenthesisNode = this.tokens.InsertLast(openingParenthesis); Bracket closingParenthesis = this.GetBracketToken(CsTokenType.CloseParenthesis, SymbolType.CloseParenthesis, elementReference); Node<CsToken> closingParenthesisNode = this.tokens.InsertLast(closingParenthesis); openingParenthesis.MatchingBracketNode = closingParenthesisNode; closingParenthesis.MatchingBracketNode = openingParenthesisNode; // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, destructorName, ElementType.Destructor, accessModifier, modifiers); Destructor destructor = new Destructor(this.document, parent, xmlHeader, attributes, declaration, unsafeCode, generated); elementReference.Target = destructor; // If the destructor is extern, it will not have a body. if (modifiers.ContainsKey(CsTokenType.Extern)) { // Get the closing semicolon. this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference)); } else { // Get the body. this.ParseStatementContainer(destructor, true, unsafeCode); } return destructor; }
/// <summary> /// Initializes a new instance of the Method class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="returnType"> /// The method's return type. /// </param> /// <param name="parameters"> /// The parameters to the method. /// </param> /// <param name="typeConstraints"> /// The list of type constraints on the element. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Method( CsDocument document, CsElement parent, XmlHeader header, ICollection<Attribute> attributes, Declaration declaration, TypeToken returnType, IList<Parameter> parameters, ICollection<TypeParameterConstraintClause> typeConstraints, bool unsafeCode, bool generated) : base(document, parent, ElementType.Method, "method " + declaration.Name, header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.Ignore(returnType); Param.AssertNotNull(parameters, "parameters"); Param.Ignore(typeConstraints); Param.Ignore(unsafeCode); Param.Ignore(generated); Debug.Assert( returnType != null || declaration.ContainsModifier(CsTokenType.Explicit, CsTokenType.Implicit), "A method's return type can only be null in an explicit or implicit operator overload method."); this.returnType = returnType; this.parameters = parameters; this.typeConstraints = typeConstraints; Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only."); // Determine whether this is an extension method. The method must be static. if (this.parameters.Count > 0 && this.Declaration.ContainsModifier(CsTokenType.Static)) { // Look at this first parameter. Since the parameters collection is not an indexable list, the // easiest way to do this is to foreach through the parameter list and break after the first one. foreach (Parameter parameter in this.parameters) { if ((parameter.Modifiers & ParameterModifiers.This) != 0) { this.extensionMethod = true; } break; } } // Add the qualifications. this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName); // If this is an explicit interface member implementation and our access modifier // is currently set to private because we don't have one, then it should be public instead. if (this.Declaration.Name.IndexOf(".", StringComparison.Ordinal) > -1 && !this.Declaration.Name.StartsWith("this.", StringComparison.Ordinal)) { this.Declaration.AccessModifierType = AccessModifierType.Public; } // Set the parent of the type constraint clauses. if (typeConstraints != null) { foreach (TypeParameterConstraintClause constraint in typeConstraints) { constraint.ParentElement = this; } } }
/// <summary> /// Parses and returns a constructor. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Constructor ParseConstructor( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, ConstructorModifiers); unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); // Get the name of the constructor. CsToken name = this.GetElementNameToken(elementReference, unsafeCode); this.tokens.Add(name); // Get the parameter list. IList<Parameter> parameters = this.ParseParameterList(elementReference, unsafeCode, SymbolType.OpenParenthesis); // Get the constructor initializer if there is one. MethodInvocationExpression constructorInitializer = null; Symbol symbol = this.GetNextSymbol(elementReference); if (symbol.SymbolType == SymbolType.Colon) { this.tokens.Add(this.GetToken(CsTokenType.BaseColon, SymbolType.Colon, elementReference)); // The next symbol must be the keyword base or this. symbol = this.GetNextSymbol(elementReference); if (symbol.SymbolType != SymbolType.This && symbol.SymbolType != SymbolType.Base) { throw this.CreateSyntaxException(); } Reference<ICodePart> initializerNameExpressionReference = new Reference<ICodePart>(); Node<CsToken> initializerNameTokenNode = this.tokens.InsertLast(this.GetToken(CsTokenType.Other, symbol.SymbolType, initializerNameExpressionReference)); // Get the name expression. LiteralExpression initializerNameExpression = new LiteralExpression(this.tokens, initializerNameTokenNode); initializerNameExpressionReference.Target = initializerNameExpression; // Get the initializer expression. constructorInitializer = this.GetMethodInvocationExpression(initializerNameExpression, ExpressionPrecedence.None, unsafeCode); } // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Constructor, accessModifier, modifiers); Constructor constructor = new Constructor( this.document, parent, xmlHeader, attributes, declaration, parameters, constructorInitializer, unsafeCode, generated); elementReference.Target = constructor; // If the constructor is extern, it will not have a body. if (modifiers.ContainsKey(CsTokenType.Extern)) { // Get the closing semicolon. this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference)); } else { // Get the body. this.ParseStatementContainer(constructor, true, unsafeCode); } return constructor; }
/// <summary> /// Parses and returns a property, indexer, or event accessor. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Accessor ParseAccessor( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, null); // Get the accessor type token. AccessorType accessorType = AccessorType.Get; CsToken accessorName = null; Symbol symbol = this.GetNextSymbol(elementReference); if (symbol.Text == "get") { accessorName = this.GetToken(CsTokenType.Get, SymbolType.Other, elementReference); if (parent.ElementType != ElementType.Property && parent.ElementType != ElementType.Indexer) { throw this.CreateSyntaxException(); } } else if (symbol.Text == "set") { accessorType = AccessorType.Set; accessorName = this.GetToken(CsTokenType.Set, SymbolType.Other, elementReference); if (parent.ElementType != ElementType.Property && parent.ElementType != ElementType.Indexer) { throw this.CreateSyntaxException(); } } else if (symbol.Text == "add") { accessorType = AccessorType.Add; accessorName = this.GetToken(CsTokenType.Add, SymbolType.Other, elementReference); if (parent.ElementType != ElementType.Event) { throw this.CreateSyntaxException(); } } else if (symbol.Text == "remove") { accessorType = AccessorType.Remove; accessorName = this.GetToken(CsTokenType.Remove, SymbolType.Other, elementReference); if (parent.ElementType != ElementType.Event) { throw this.CreateSyntaxException(); } } else { throw this.CreateSyntaxException(); } this.tokens.Add(accessorName); // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, accessorName.Text, ElementType.Accessor, accessModifier, modifiers); Accessor accessor = new Accessor(this.document, parent, accessorType, xmlHeader, attributes, declaration, unsafeCode, generated); elementReference.Target = accessor; // Get the method body. this.ParseStatementContainer(accessor, true, unsafeCode); return accessor; }
/// <summary> /// Moves past whitespace, comments, preprocessors and xml headers up to the start of the next element. /// </summary> /// <param name="element"> /// The parent element. /// </param> /// <param name="parentElementReference"> /// A reference to the parent element. /// </param> /// <param name="childElementReference"> /// A reference to the child element about to be created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is unsafe. /// </param> /// <param name="xmlHeader"> /// Returns the xml header, if any. /// </param> /// <param name="attributes"> /// Returns the list of attributes, if any. /// </param> private void MoveToElementDeclaration( CsElement element, Reference<ICodePart> parentElementReference, Reference<ICodePart> childElementReference, bool unsafeCode, out XmlHeader xmlHeader, out ICollection<Attribute> attributes) { Param.AssertNotNull(parentElementReference, "parentElementReference"); Param.AssertNotNull(childElementReference, "childElementReference"); Param.Ignore(unsafeCode); // Initialize the out parameters. xmlHeader = null; List<Attribute> tempAttributes = new List<Attribute>(); SkipSymbols skip = SkipSymbols.All; skip &= ~SkipSymbols.XmlHeader; Reference<ICodePart> currentElementReference = parentElementReference; // Loop past any comments, whitespace, preprocessor statements, xml headers, and element attributes. Keep // going until we get to the element itself. bool loop = true; Symbol symbol = this.GetNextSymbol(skip, currentElementReference, true); while (symbol != null && loop) { switch (symbol.SymbolType) { case SymbolType.XmlHeaderLine: // Get the xml header. currentElementReference = childElementReference; xmlHeader = this.GetXmlHeader(childElementReference); if (xmlHeader == null) { throw new SyntaxException(this.document.SourceCode, symbol.LineNumber); } // Add the header to the document. this.tokens.Add(xmlHeader); break; case SymbolType.OpenSquareBracket: // Need to see if its an assembly attribute. // If it is don't process it here. ElementType? nextElementType = this.GetElementType(element, unsafeCode); if (nextElementType == ElementType.AssemblyOrModuleAttribute) { loop = false; } else { // Get the attribute statement. currentElementReference = childElementReference; Attribute attribute = this.GetAttribute(childElementReference, unsafeCode); if (attribute == null) { throw new SyntaxException(this.document.SourceCode, symbol.LineNumber); } tempAttributes.Add(attribute); // Add the attribute to the document. this.tokens.Add(attribute); } break; default: // This must be the start of the element. loop = false; break; } symbol = this.GetNextSymbol(skip, currentElementReference, true); } // Set the attributes as a read-only collection. attributes = tempAttributes.ToArray(); }
/// <summary> /// Gets an xml header. /// </summary> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <returns> /// Returns the header or null if there is no header. /// </returns> private XmlHeader GetXmlHeader(Reference<ICodePart> elementReference) { Param.AssertNotNull(elementReference, "elementReference"); // Get the first symbol and make sure it is the right type. int index = 1; Symbol firstSymbol = this.symbols.Peek(index); Debug.Assert(firstSymbol != null && firstSymbol.SymbolType == SymbolType.XmlHeaderLine, "Expected an xml documentation header line"); // Marks the end of the header. int end = -1; int endOfLineCount = 0; Reference<ICodePart> xmlHeaderReference = new Reference<ICodePart>(); // Loop until the entire header is found. Symbol symbol = firstSymbol; while (symbol != null) { if (symbol.SymbolType == SymbolType.XmlHeaderLine) { // This type of token belongs in the header. end = index; endOfLineCount = 0; } else if (symbol.SymbolType == SymbolType.EndOfLine) { if (++endOfLineCount > 1) { // If there are two newlines in a row, this is the // end of the Xml header. break; } } else if (symbol.SymbolType == SymbolType.WhiteSpace || symbol.SymbolType == SymbolType.SingleLineComment) { endOfLineCount = 0; } else { // This is the end of the header. break; } // Advance the index and get the next symbol. symbol = this.symbols.Peek(++index); } // Make sure we've advanced at least one symbol. Debug.Assert(end != -1, "Should have advanced at least one symbol"); // Add all of the symbols for the header to a token list. MasterList<CsToken> headerTokens = new MasterList<CsToken>(); for (int i = 1; i <= end; ++i) { this.symbols.Advance(); Debug.Assert(this.symbols.Current != null, "The current symbol should not be null"); headerTokens.Add(this.ConvertSymbol(this.symbols.Current, TokenTypeFromSymbolType(this.symbols.Current.SymbolType), xmlHeaderReference)); } // Get the location of the header. CodeLocation location = CodeLocation.Join(firstSymbol.Location, this.symbols.Current.Location); // Create the Xml header object. XmlHeader xmlHeader = new XmlHeader(headerTokens, location, elementReference, this.symbols.Generated); xmlHeaderReference.Target = xmlHeader; return xmlHeader; }
/// <summary> /// Parses and returns a property. /// </summary> /// <param name="parent">The parent of the element.</param> /// <param name="elementReference">A reference to the element being created.</param> /// <param name="unsafeCode">Indicates whether the code is marked as unsafe.</param> /// <param name="generated">Indicates whether the code is marked as generated code.</param> /// <param name="xmlHeader">The element's documentation header.</param> /// <param name="attributes">The attributes on the element.</param> /// <returns> /// Returns the element. /// </returns> private Property ParseProperty( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; // Properties within interfaces always have the access of the parent interface. Interface parentInterface = parent as Interface; if (parentInterface != null) { accessModifier = parentInterface.AccessModifier; } // Get declared modifiers. Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, PropertyModifiers); unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); // Get the field type. TypeToken propertyType = this.GetTypeToken(elementReference, unsafeCode, true); Node<CsToken> propertyTypeNode = this.tokens.InsertLast(propertyType); // Get the name of the property. CsToken name = this.GetElementNameToken(elementReference, unsafeCode); Node<CsToken> propertyNameNode = this.tokens.InsertLast(name); // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Property, accessModifier, modifiers); Property property = new Property(this.document, parent, xmlHeader, attributes, declaration, propertyType, unsafeCode, generated); elementReference.Target = property; if (this.IsBodiedExpression()) { this.ParseStatementContainer(property, true, unsafeCode); } else { // Parse the body of the property. this.ParseElementContainer(property, elementReference, null, unsafeCode); // Check if current property has initializer (C#6). Symbol nextSymbol = this.GetNextSymbol(SkipSymbols.WhiteSpace, elementReference, true); if (nextSymbol != null && nextSymbol.SymbolType == SymbolType.Equals) { // Get all of the variable declarators. IList<VariableDeclaratorExpression> declarators = this.ParsePropertyDeclarators(elementReference, unsafeCode, propertyType, propertyNameNode); if (declarators.Count == 0) { throw this.CreateSyntaxException(); } VariableDeclarationExpression declarationExpression = new VariableDeclarationExpression( new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), new LiteralExpression(this.tokens, propertyTypeNode), declarators); // Get the trailing semicolon. this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference)); // Create the variable declaration statement and add it to the field. property.VariableDeclarationStatement = new VariableDeclarationStatement( new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), false, declarationExpression); } } return property; }
/// <summary> /// Parses and returns an element. /// </summary> /// <param name="elementType"> /// The type of element to parse. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="partialElements"> /// The collection of partial elements found while parsing the files. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private CsElement ParseElement( ElementType elementType, CsElement parent, Reference<ICodePart> elementReference, Dictionary<string, List<CsElement>> partialElements, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.Ignore(elementType); Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(partialElements); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); switch (elementType) { case ElementType.Namespace: return this.ParseNamespace(parent, elementReference, partialElements, unsafeCode, generated, xmlHeader, attributes); case ElementType.ExternAliasDirective: return this.ParseExternAliasDirective(parent, elementReference, generated); case ElementType.UsingDirective: return this.ParseUsingDirective(parent, elementReference, unsafeCode, generated); case ElementType.AssemblyOrModuleAttribute: return this.ParseAssemblyOrModuleAttribute(parent, elementReference, generated); case ElementType.Class: case ElementType.Struct: case ElementType.Interface: return this.ParseClass(elementType, parent, elementReference, partialElements, unsafeCode, generated, xmlHeader, attributes); case ElementType.Enum: return this.ParseEnum(parent, elementReference, unsafeCode, generated, xmlHeader, attributes); case ElementType.Delegate: return this.ParseDelegate(parent, elementReference, unsafeCode, generated, xmlHeader, attributes); case ElementType.Field: return this.ParseField(parent, elementReference, unsafeCode, generated, xmlHeader, attributes); case ElementType.Method: return this.ParseMethod(parent, elementReference, unsafeCode, generated, xmlHeader, attributes); case ElementType.Constructor: return this.ParseConstructor(parent, elementReference, unsafeCode, generated, xmlHeader, attributes); case ElementType.Destructor: return this.ParseDestructor(parent, elementReference, unsafeCode, generated, xmlHeader, attributes); case ElementType.Property: return this.ParseProperty(parent, elementReference, unsafeCode, generated, xmlHeader, attributes); case ElementType.Indexer: return this.ParseIndexer(parent, elementReference, unsafeCode, generated, xmlHeader, attributes); case ElementType.Event: return this.ParseEvent(parent, elementReference, unsafeCode, generated, xmlHeader, attributes); case ElementType.Accessor: return this.ParseAccessor(parent, elementReference, unsafeCode, generated, xmlHeader, attributes); case ElementType.EmptyElement: return this.ParseEmptyElement(parent, elementReference, unsafeCode, generated); default: Debug.Fail("Unexpected element type."); throw new StyleCopException(); } }
/// <summary> /// Initializes a new instance of the Namespace class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="type"> /// The element type. /// </param> /// <param name="name"> /// The name of this element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Namespace( CsDocument document, CsElement parent, ElementType type, string name, XmlHeader header, ICollection<Attribute> attributes, Declaration declaration, bool unsafeCode, bool generated) : base(document, parent, type, name, header, attributes, declaration, unsafeCode, generated) { Param.Ignore(document, parent, type, name, header, attributes, declaration, unsafeCode, generated); }
/// <summary> /// Parses and returns an <see cref="Enum"/>. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Enum ParseEnum( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // The access defaults to public for a top-level element, or private for a nested element. AccessModifierType accessModifier = AccessModifierType.Public; if (parent.ElementType == ElementType.Class || parent.ElementType == ElementType.Struct) { accessModifier = AccessModifierType.Private; } // Get the modifiers and access. Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, EnumModifiers); // Get the enum keyword. this.tokens.Add(this.GetToken(CsTokenType.Enum, SymbolType.Enum, elementReference)); // Add the enum name token. CsToken name = this.GetElementNameToken(elementReference, unsafeCode); this.tokens.Add(name); // Get the base type. Symbol symbol = this.GetNextSymbol(elementReference); if (symbol.SymbolType == SymbolType.Colon) { // Add the colon token and the base item name. this.tokens.Add(this.GetToken(CsTokenType.BaseColon, SymbolType.Colon, elementReference)); this.tokens.Add(this.GetTypeToken(elementReference, unsafeCode, false)); } // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Enum, accessModifier, modifiers); // Create the enum element. Enum @enum = new Enum(this.document, parent, xmlHeader, attributes, declaration, unsafeCode, generated); elementReference.Target = @enum; // Get the opening curly bracket. Bracket openingCurlyBracket = this.GetBracketToken(CsTokenType.OpenCurlyBracket, SymbolType.OpenCurlyBracket, elementReference); Node<CsToken> openingCurlyBracketNode = this.tokens.InsertLast(openingCurlyBracket); // Get each of the enum items. @enum.Items = this.ParseEnumItems(@enum, elementReference, unsafeCode); // Get the closing curly bracket. Bracket closingCurlyBracket = this.GetBracketToken(CsTokenType.CloseCurlyBracket, SymbolType.CloseCurlyBracket, elementReference); Node<CsToken> closingCurlyBracketNode = this.tokens.InsertLast(closingCurlyBracket); openingCurlyBracket.MatchingBracketNode = closingCurlyBracketNode; closingCurlyBracket.MatchingBracketNode = openingCurlyBracketNode; return @enum; }
/// <summary> /// Initializes a new instance of the Event class. /// </summary> /// <param name="document"> /// The document that contains this element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="eventHandlerType"> /// The type of the event handler. /// </param> /// <param name="eventDeclarators"> /// Declarators for the event. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Event( CsDocument document, CsElement parent, XmlHeader header, ICollection<Attribute> attributes, Declaration declaration, TypeToken eventHandlerType, ICollection<EventDeclaratorExpression> eventDeclarators, bool unsafeCode, bool generated) : base(document, parent, ElementType.Event, "event " + declaration.Name, header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.AssertNotNull(eventHandlerType, "eventHandlerType"); Param.AssertNotNull(eventDeclarators, "eventDeclarators"); Param.Ignore(unsafeCode); Param.Ignore(generated); this.eventHandlerType = eventHandlerType; this.eventDeclarators = eventDeclarators; foreach (EventDeclaratorExpression expression in this.eventDeclarators) { this.AddExpression(expression); expression.ParentEvent = this; } }
/// <summary> /// Parses and returns a event. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Event ParseEvent( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; // Events within interfaces always have the access of the parent interface. Interface parentInterface = parent as Interface; if (parentInterface != null) { accessModifier = parentInterface.AccessModifier; } // Get declared modifiers. Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, EventModifiers); unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); // Get the event keyword. this.tokens.Add(this.GetToken(CsTokenType.Event, SymbolType.Event, elementReference)); // Get the event type. TypeToken eventHandlerType = this.GetTypeToken(elementReference, unsafeCode, true); this.tokens.Add(eventHandlerType); List<EventDeclaratorExpression> declarators = new List<EventDeclaratorExpression>(); string firstEventName = null; while (true) { Symbol symbol = this.GetNextSymbol(SymbolType.Other, elementReference); Reference<ICodePart> declaratorExpressionReference = new Reference<ICodePart>(); // Get the identifier. LiteralExpression identifier = this.GetTypeTokenExpression(declaratorExpressionReference, unsafeCode, false); if (identifier == null || identifier.Tokens.First == null) { throw new SyntaxException(this.document.SourceCode, symbol.LineNumber); } if (firstEventName == null) { firstEventName = identifier.Token.Text; } // Get the initializer if it exists. Expression initializer = null; symbol = this.GetNextSymbol(declaratorExpressionReference); if (symbol.SymbolType == SymbolType.Equals) { // Add the equals token. this.tokens.Add(this.GetOperatorToken(OperatorType.Equals, declaratorExpressionReference)); initializer = this.GetNextExpression(ExpressionPrecedence.None, declaratorExpressionReference, unsafeCode); } // Create the token list for the declarator. CsTokenList partialTokens = new CsTokenList(this.tokens, identifier.Tokens.First, this.tokens.Last); // Create and add the declarator. EventDeclaratorExpression declaratorExpression = new EventDeclaratorExpression(partialTokens, identifier, initializer); declaratorExpressionReference.Target = declaratorExpression; declarators.Add(declaratorExpression); // Now check if the next character is a comma. If so there is another declarator. symbol = this.GetNextSymbol(elementReference); if (symbol.SymbolType != SymbolType.Comma) { // There are no more declarators. break; } // Add the comma. this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma, elementReference)); } // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, firstEventName, ElementType.Event, accessModifier, modifiers); Event @event = new Event(this.document, parent, xmlHeader, attributes, declaration, eventHandlerType, declarators.ToArray(), unsafeCode, generated); elementReference.Target = @event; Symbol s = this.GetNextSymbol(elementReference); if (s.SymbolType == SymbolType.Semicolon) { this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference)); } else { // Parse the body of the event. this.ParseElementContainer(@event, elementReference, null, unsafeCode); } return @event; }
/// <summary> /// Initializes a new instance of the ClassBase class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="type"> /// The element type. /// </param> /// <param name="name"> /// The name of this element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="typeConstraints"> /// The list of type constraints on the element. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal ClassBase( CsDocument document, CsElement parent, ElementType type, string name, XmlHeader header, ICollection<Attribute> attributes, Declaration declaration, ICollection<TypeParameterConstraintClause> typeConstraints, bool unsafeCode, bool generated) : base(document, parent, type, name, header, attributes, declaration, unsafeCode, generated) { Param.Ignore(document, parent, type, name, header, attributes, declaration, typeConstraints, unsafeCode, generated); this.typeConstraints = typeConstraints; // Set the parent of the type constraint clauses. if (typeConstraints != null) { Debug.Assert(typeConstraints.IsReadOnly, "The typeconstraints collection should be read-only."); foreach (TypeParameterConstraintClause constraint in typeConstraints) { constraint.ParentElement = this; } } }
/// <summary> /// Parses and returns a field. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Field ParseField( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, FieldModifiers); unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); // Get the field type. TypeToken fieldType = this.GetTypeToken(elementReference, unsafeCode, true); Node<CsToken> fieldTypeNode = this.tokens.InsertLast(fieldType); // Get all of the variable declarators. IList<VariableDeclaratorExpression> declarators = this.ParseFieldDeclarators(elementReference, unsafeCode, fieldType); if (declarators.Count == 0) { throw this.CreateSyntaxException(); } VariableDeclarationExpression declarationExpression = new VariableDeclarationExpression( new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), new LiteralExpression(this.tokens, fieldTypeNode), declarators); // Create the field. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, declarators[0].Identifier.Text, ElementType.Field, accessModifier, modifiers); Field field = new Field(this.document, parent, xmlHeader, attributes, declaration, fieldType, unsafeCode, generated); elementReference.Target = field; // Get the trailing semicolon. this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference)); // Create the variable declaration statement and add it to the field. field.VariableDeclarationStatement = new VariableDeclarationStatement( new CsTokenList(this.tokens, declarators[0].Tokens.First, this.tokens.Last), field.Const, declarationExpression); return field; }
/// <summary> /// Parses the contents of the header for validity. /// </summary> /// <param name="element"> /// The element. /// </param> /// <param name="header"> /// The header. /// </param> /// <param name="lineNumber"> /// The line number that the header element begins on. /// </param> /// <param name="partialElement"> /// Indicates whether the element has the partial attribute. /// </param> private void ParseHeader(CsElement element, XmlHeader header, int lineNumber, bool partialElement) { Param.AssertNotNull(element, "element"); Param.AssertNotNull(header, "header"); Param.AssertGreaterThanZero(lineNumber, "lineNumber"); Param.Ignore(partialElement); // Load this into an xml document. XmlDocument rawDocs = null; XmlDocument formattedDocs = null; this.LoadHeaderIntoDocuments(element, header, lineNumber, out rawDocs, out formattedDocs); if (rawDocs != null && formattedDocs != null) { // Check whether the method has an <inheritdoc> tag at the root. If so, discontinue checking the contents of the header, // but verify that the class actually inherits from a base class. Otherwise this tag is not allowed. if (rawDocs.SelectSingleNode("root/inheritdoc") != null) { this.CheckInheritDocRules(element); } else { // Insert any documentation present in 'include' tags. if (this.InsertIncludedDocumentation(element, formattedDocs)) { this.CheckForBlankLinesInDocumentationHeader(element, header); this.CheckHeaderSummary(element, lineNumber, partialElement, formattedDocs); this.CheckHeaderElementsForEmptyText(element, formattedDocs); // Check element parameters and return types. if (element.ElementType == ElementType.Method) { Method item = element as Method; this.CheckHeaderParams(element, item.Parameters, formattedDocs); this.CheckHeaderReturnValue(element, item.ReturnType, formattedDocs); } else if (element.ElementType == ElementType.Constructor) { Constructor item = element as Constructor; this.CheckHeaderParams(element, item.Parameters, formattedDocs); this.CheckConstructorSummaryText(item, formattedDocs); } else if (element.ElementType == ElementType.Delegate) { Delegate item = element as Delegate; this.CheckHeaderParams(element, item.Parameters, formattedDocs); this.CheckHeaderReturnValue(element, item.ReturnType, formattedDocs); } else if (element.ElementType == ElementType.Indexer) { Indexer item = element as Indexer; this.CheckHeaderParams(element, item.Parameters, formattedDocs); this.CheckHeaderReturnValue(element, item.ReturnType, formattedDocs); } else if (element.ElementType == ElementType.Property) { // Check value tags on properties. this.CheckPropertyValueTag(element, formattedDocs); // Check that the property summary starts with the correct text. this.CheckPropertySummaryFormatting(element as Property, formattedDocs); } else if (element.ElementType == ElementType.Destructor) { this.CheckDestructorSummaryText((Destructor)element, formattedDocs); } // Check for repeating comments on all element types which can contain params or typeparams. if (element.ElementType == ElementType.Method || element.ElementType == ElementType.Constructor || element.ElementType == ElementType.Delegate || element.ElementType == ElementType.Indexer || element.ElementType == ElementType.Class || element.ElementType == ElementType.Struct || element.ElementType == ElementType.Interface || element.ElementType == ElementType.Property || element.ElementType == ElementType.Event || element.ElementType == ElementType.Field || element.ElementType == ElementType.Destructor) { this.CheckForRepeatingComments(element, formattedDocs); } // Check generic type parameters. if (element.ElementType == ElementType.Class || element.ElementType == ElementType.Method || element.ElementType == ElementType.Delegate || element.ElementType == ElementType.Interface || element.ElementType == ElementType.Struct) { this.CheckGenericTypeParams(element, formattedDocs); } } } } }
/// <summary> /// Parses and returns an indexer. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Indexer ParseIndexer( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; // Indexers within interfaces always have the access of the parent interface. Interface parentInterface = parent as Interface; if (parentInterface != null) { accessModifier = parentInterface.AccessModifier; } // Get declared modifiers. Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, IndexerModifiers); unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); // Get the return type. TypeToken returnType = this.GetTypeToken(elementReference, unsafeCode, true); this.tokens.Add(returnType); // Get the name of the indexer. CsToken name = this.GetElementNameToken(elementReference, unsafeCode); this.tokens.Add(name); // Get the parameter list. IList<Parameter> parameters = this.ParseParameterList(elementReference, unsafeCode, SymbolType.OpenSquareBracket); // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, name.Text, ElementType.Indexer, accessModifier, modifiers); Indexer indexer = new Indexer(this.document, parent, xmlHeader, attributes, declaration, returnType, parameters, unsafeCode, generated); elementReference.Target = indexer; // Parse the body of the indexer. this.ParseElementContainer(indexer, elementReference, null, unsafeCode); return indexer; }
/// <summary> /// Initializes a new instance of the Method class. /// </summary> /// <param name="document"> /// The document that contains the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="header"> /// The Xml header for this element. /// </param> /// <param name="attributes"> /// The list of attributes attached to this element. /// </param> /// <param name="declaration"> /// The declaration code for this element. /// </param> /// <param name="returnType"> /// The method's return type. /// </param> /// <param name="parameters"> /// The parameters to the method. /// </param> /// <param name="typeConstraints"> /// The list of type constraints on the element. /// </param> /// <param name="unsafeCode"> /// Indicates whether the element resides within a block of unsafe code. /// </param> /// <param name="generated"> /// Indicates whether the code element was generated or written by hand. /// </param> internal Method( CsDocument document, CsElement parent, XmlHeader header, ICollection <Attribute> attributes, Declaration declaration, TypeToken returnType, IList <Parameter> parameters, ICollection <TypeParameterConstraintClause> typeConstraints, bool unsafeCode, bool generated) : base(document, parent, ElementType.Method, "method " + declaration.Name, header, attributes, declaration, unsafeCode, generated) { Param.AssertNotNull(document, "document"); Param.AssertNotNull(parent, "parent"); Param.Ignore(header); Param.Ignore(attributes); Param.AssertNotNull(declaration, "declaration"); Param.Ignore(returnType); Param.AssertNotNull(parameters, "parameters"); Param.Ignore(typeConstraints); Param.Ignore(unsafeCode); Param.Ignore(generated); Debug.Assert( returnType != null || declaration.ContainsModifier(CsTokenType.Explicit, CsTokenType.Implicit), "A method's return type can only be null in an explicit or implicit operator overload method."); this.returnType = returnType; this.parameters = parameters; this.typeConstraints = typeConstraints; Debug.Assert(parameters.IsReadOnly, "The parameters collection should be read-only."); // Determine whether this is an extension method. The method must be static. if (this.parameters.Count > 0 && this.Declaration.ContainsModifier(CsTokenType.Static)) { // Look at this first parameter. Since the parameters collection is not an indexable list, the // easiest way to do this is to foreach through the parameter list and break after the first one. foreach (Parameter parameter in this.parameters) { if ((parameter.Modifiers & ParameterModifiers.This) != 0) { this.extensionMethod = true; } break; } } // Add the qualifications. this.QualifiedName = CodeParser.AddQualifications(this.parameters, this.QualifiedName); // If this is an explicit interface member implementation and our access modifier // is currently set to private because we don't have one, then it should be public instead. if (this.Declaration.Name.IndexOf(".", StringComparison.Ordinal) > -1 && !this.Declaration.Name.StartsWith("this.", StringComparison.Ordinal)) { this.Declaration.AccessModifierType = AccessModifierType.Public; } // Set the parent of the type constraint clauses. if (typeConstraints != null) { foreach (TypeParameterConstraintClause constraint in typeConstraints) { constraint.ParentElement = this; } } }
/// <summary> /// Parses and returns a method. /// </summary> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private Method ParseMethod( CsElement parent, Reference<ICodePart> elementReference, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Get the modifiers and access. AccessModifierType accessModifier = AccessModifierType.Private; // Get the declared modifiers for the method. Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, MethodModifiers); // Methods within interfaces always have the access of the parent interface. Interface parentInterface = parent as Interface; if (parentInterface != null) { accessModifier = parentInterface.AccessModifier; } unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); TypeToken returnType = null; if (!modifiers.ContainsKey(CsTokenType.Implicit) && !modifiers.ContainsKey(CsTokenType.Explicit)) { // Get the return type. returnType = this.GetTypeToken(elementReference, unsafeCode, true); this.tokens.Add(returnType); } // Get the name of the method. string methodName = null; Symbol symbol = this.GetNextSymbol(elementReference); if (symbol.SymbolType == SymbolType.Operator) { this.tokens.Add(this.GetToken(CsTokenType.Operator, SymbolType.Operator, elementReference)); // Advance up to the next symbol. this.AdvanceToNextCodeSymbol(elementReference); // The overloaded item will either be a type or a symbol. int endIndex = -1; CsToken operatorType = null; if (this.HasTypeSignature(1, unsafeCode, out endIndex)) { // The overloaded item is a type. operatorType = this.GetTypeToken(elementReference, unsafeCode, true); } else { // The overloaded item is a symbol. operatorType = this.ConvertOperatorOverloadSymbol(elementReference); } this.tokens.Add(operatorType); methodName = "operator " + operatorType.Text; } else { CsToken name = this.GetElementNameToken(elementReference, unsafeCode); methodName = name.Text; this.tokens.Add(name); } // Get the parameter list. IList<Parameter> parameters = this.ParseParameterList(elementReference, unsafeCode, SymbolType.OpenParenthesis, modifiers.ContainsKey(CsTokenType.Static)); // Check whether there are any type constraint clauses. ICollection<TypeParameterConstraintClause> typeConstraints = null; symbol = this.GetNextSymbol(elementReference); if (symbol.Text == "where") { typeConstraints = this.ParseTypeConstraintClauses(elementReference, unsafeCode); } // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, methodName, ElementType.Method, accessModifier, modifiers); Method method = new Method(this.document, parent, xmlHeader, attributes, declaration, returnType, parameters, typeConstraints, unsafeCode, generated); elementReference.Target = method; // If the element is extern, abstract, or containing within an interface, it will not have a body. if (modifiers.ContainsKey(CsTokenType.Abstract) || modifiers.ContainsKey(CsTokenType.Extern) || parent.ElementType == ElementType.Interface) { // Get the closing semicolon. this.tokens.Add(this.GetToken(CsTokenType.Semicolon, SymbolType.Semicolon, elementReference)); } else { // Get the method body or bodied expression C# 6. this.ParseStatementContainer(method, true, unsafeCode); } return method; }
/// <summary> /// Parses and returns a class, struct, or interface. /// </summary> /// <param name="elementType"> /// The type of the element. /// </param> /// <param name="parent"> /// The parent of the element. /// </param> /// <param name="elementReference"> /// A reference to the element being created. /// </param> /// <param name="partialElements"> /// The collection of partial elements found while parsing the files. /// </param> /// <param name="unsafeCode"> /// Indicates whether the code is marked as unsafe. /// </param> /// <param name="generated"> /// Indicates whether the code is marked as generated code. /// </param> /// <param name="xmlHeader"> /// The element's documentation header. /// </param> /// <param name="attributes"> /// The attributes on the element. /// </param> /// <returns> /// Returns the element. /// </returns> private ClassBase ParseClass( ElementType elementType, CsElement parent, Reference<ICodePart> elementReference, Dictionary<string, List<CsElement>> partialElements, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Attribute> attributes) { Param.Ignore(elementType); Param.AssertNotNull(parent, "parent"); Param.AssertNotNull(elementReference, "elementReference"); Param.AssertNotNull(partialElements, "partialElements"); Param.Ignore(unsafeCode); Param.Ignore(generated); Param.Ignore(xmlHeader); Param.Ignore(attributes); Node<CsToken> previousTokenNode = this.tokens.Last; // Top-level classes, structs, and interfaces received Internal access by default, while classes, structs, and interfaces // declared within a class receive Private access by default. AccessModifierType accessModifier = AccessModifierType.Internal; if (parent.ElementType == ElementType.Class) { accessModifier = AccessModifierType.Private; } // Get the modifiers and access. Dictionary<CsTokenType, CsToken> modifiers = this.GetElementModifiers(elementReference, ref accessModifier, ClassModifiers); unsafeCode |= modifiers.ContainsKey(CsTokenType.Unsafe); // Get the element keyword, depending on the element type. CsTokenType keywordType = CsTokenType.Class; SymbolType symbolType = SymbolType.Class; if (elementType == ElementType.Struct) { keywordType = CsTokenType.Struct; symbolType = SymbolType.Struct; } else if (elementType == ElementType.Interface) { keywordType = CsTokenType.Interface; symbolType = SymbolType.Interface; } else { Debug.Assert(elementType == ElementType.Class, "The method can only be called for a class, struct, or interface"); } // Add the keyword token. this.tokens.Add(this.GetToken(keywordType, symbolType, elementReference)); // Add the class name token. CsToken name = this.GetElementNameToken(elementReference, unsafeCode); this.tokens.Add(name); // Get the base classes. Symbol symbol = this.GetNextSymbol(elementReference); if (symbol.SymbolType == SymbolType.Colon) { // Add the colon token. this.tokens.Add(this.GetToken(CsTokenType.BaseColon, SymbolType.Colon, elementReference)); // Get each of the base classes and interfaces. while (true) { this.tokens.Add(this.GetTypeToken(elementReference, unsafeCode, false)); symbol = this.GetNextSymbol(elementReference); if (symbol.SymbolType != SymbolType.Comma) { break; } this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma, elementReference)); } } // Check whether there are any type constraint clauses. ICollection<TypeParameterConstraintClause> typeConstraints = null; symbol = this.GetNextSymbol(elementReference); if (symbol.Text == "where") { typeConstraints = this.ParseTypeConstraintClauses(elementReference, unsafeCode); } // Create the declaration. Node<CsToken> firstTokenNode = previousTokenNode == null ? this.tokens.First : previousTokenNode.Next; CsTokenList declarationTokens = new CsTokenList(this.tokens, firstTokenNode, this.tokens.Last); Declaration declaration = new Declaration(declarationTokens, name.Text, elementType, accessModifier, modifiers); // Create the element. ClassBase item = null; if (keywordType == CsTokenType.Class) { item = new Class(this.document, parent, xmlHeader, attributes, declaration, typeConstraints, unsafeCode, generated); } else if (keywordType == CsTokenType.Struct) { item = new Struct(this.document, parent, xmlHeader, attributes, declaration, typeConstraints, unsafeCode, generated); } else { Debug.Assert(keywordType == CsTokenType.Interface, "Invalid element type"); item = new Interface(this.document, parent, xmlHeader, attributes, declaration, typeConstraints, unsafeCode, generated); } elementReference.Target = item; // Parse the body of the element. this.ParseElementContainer(item, elementReference, partialElements, unsafeCode); return item; }
/// <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); }