/// <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; }
private ClassBase ParseClass(ElementType elementType, CsElement parent, Dictionary<string, List<CsElement>> partialElements, bool unsafeCode, bool generated, XmlHeader xmlHeader, ICollection<Microsoft.StyleCop.CSharp.Attribute> attributes) { Microsoft.StyleCop.Node<CsToken> last = this.tokens.Last; AccessModifierType accessModifier = AccessModifierType.Internal; if (parent.ElementType == ElementType.Class) { accessModifier = AccessModifierType.Private; } Dictionary<CsTokenType, CsToken> elementModifiers = this.GetElementModifiers(ref accessModifier, ClassModifiers); unsafeCode |= elementModifiers.ContainsKey(CsTokenType.Unsafe); CsTokenType tokenType = CsTokenType.Class; SymbolType symbolType = SymbolType.Class; if (elementType == ElementType.Struct) { tokenType = CsTokenType.Struct; symbolType = SymbolType.Struct; } else if (elementType == ElementType.Interface) { tokenType = CsTokenType.Interface; symbolType = SymbolType.Interface; } this.tokens.Add(this.GetToken(tokenType, symbolType)); CsToken elementNameToken = this.GetElementNameToken(unsafeCode); this.tokens.Add(elementNameToken); if (this.GetNextSymbol().SymbolType == SymbolType.Colon) { this.tokens.Add(this.GetToken(CsTokenType.BaseColon, SymbolType.Colon)); while (true) { this.tokens.Add(this.GetTypeToken(unsafeCode, false)); if (this.GetNextSymbol().SymbolType != SymbolType.Comma) { break; } this.tokens.Add(this.GetToken(CsTokenType.Comma, SymbolType.Comma)); } } ICollection<TypeParameterConstraintClause> typeConstraints = null; if (this.GetNextSymbol().Text == "where") { typeConstraints = this.ParseTypeConstraintClauses(unsafeCode); } Microsoft.StyleCop.Node<CsToken> firstItemNode = (last == null) ? this.tokens.First : last.Next; CsTokenList tokens = new CsTokenList(this.tokens, firstItemNode, this.tokens.Last); Declaration declaration = new Declaration(tokens, elementNameToken.Text, elementType, accessModifier, elementModifiers); ClassBase element = null; switch (tokenType) { case CsTokenType.Class: element = new Class(this.document, parent, xmlHeader, attributes, declaration, typeConstraints, unsafeCode, generated); break; case CsTokenType.Struct: element = new Struct(this.document, parent, xmlHeader, attributes, declaration, typeConstraints, unsafeCode, generated); break; default: element = new Interface(this.document, parent, xmlHeader, attributes, declaration, typeConstraints, unsafeCode, generated); break; } this.ParseElementContainer(element, partialElements, unsafeCode); return element; }