/// <summary> /// Initializes the contents of the property. /// </summary> internal override void Initialize() { base.Initialize(); // Find the get and set accessors for this property, if they exist. foreach (CsElement child in this.ChildElements) { Accessor accessor = child as Accessor; if (accessor == null) { throw new SyntaxException(this.Document.SourceCode, accessor.LineNumber); } if (accessor.AccessorType == AccessorType.Get) { if (this.get != null) { throw new SyntaxException(this.Document.SourceCode, accessor.LineNumber); } this.get = accessor; } else if (accessor.AccessorType == AccessorType.Set) { if (this.set != null) { throw new SyntaxException(this.Document.SourceCode, accessor.LineNumber); } this.set = accessor; } else { throw new SyntaxException(this.Document.SourceCode, accessor.LineNumber); } } }
/// <summary> /// Initializes the contents of the event. /// </summary> internal override void Initialize() { base.Initialize(); // Find the add and remove accessors for this event, if they exist. foreach (CsElement child in this.ChildElements) { Accessor accessor = child as Accessor; if (accessor == null) { throw new SyntaxException(this.Document.SourceCode, accessor.LineNumber); } if (accessor.AccessorType == AccessorType.Add) { if (this.add != null) { throw new SyntaxException(this.Document.SourceCode, accessor.LineNumber); } this.add = accessor; } else if (accessor.AccessorType == AccessorType.Remove) { if (this.remove != null) { throw new SyntaxException(this.Document.SourceCode, accessor.LineNumber); } this.remove = accessor; } else { throw new SyntaxException(this.Document.SourceCode, accessor.LineNumber); } } }
/// <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> /// Determines whether to reference the set accessor within the property's summary documentation. /// </summary> /// <param name="property"> /// The property. /// </param> /// <param name="setAccessor"> /// The set accessor. /// </param> /// <returns> /// Returns true to reference the set accessor in the summary documentation, or false to omit it. /// </returns> private static bool IncludeSetAccessorInDocumentation(Property property, Accessor setAccessor) { Param.AssertNotNull(property, "property"); Param.AssertNotNull(setAccessor, "setAccessor"); // If the set accessor has the same access modifier as the property, always include it in the documentation. // Accessors get 'private' access modifiers by default if no access modifier is defined, in which case they // default to having the access of their parent property. Also include documentation for the set accessor // if it appears to be private but it does not actually define the 'private' keyword. if (setAccessor.AccessModifier == property.AccessModifier || (setAccessor.AccessModifier == AccessModifierType.Private && !setAccessor.Declaration.ContainsModifier(CsTokenType.Private))) { return true; } // If the set accessor has internal access, and the property also has internal or protected internal access, // then include the set accessor in the docs since it effectively has the same access as the overall property. if (setAccessor.AccessModifier == AccessModifierType.Internal && (property.ActualAccess == AccessModifierType.Internal || property.ActualAccess == AccessModifierType.ProtectedAndInternal)) { return true; } // If the property is effectively private (contained within a private class), and the set accessor has any access modifier other than private, then // include the set accessor in the documentation. Within a private class, other access modifiers on the set accessor are meaningless. if (property.ActualAccess == AccessModifierType.Private && !setAccessor.Declaration.ContainsModifier(CsTokenType.Private)) { return true; } // If the set accessor has protected access, then always include it in the docs since it will be visible to any // class that inherits from this class. if (setAccessor.AccessModifier == AccessModifierType.Protected || setAccessor.AccessModifier == AccessModifierType.ProtectedInternal) { return true; } // Otherwise, omit the set accessor from the documentation since its access is more restricted // than the access of the property. return false; }
/// <summary> /// 4 /// Determines whether the given accessor contains a body. /// </summary> /// <param name="accessor"> /// The accessor to check. /// </param> /// <returns> /// Returns true if the accessor contains a body. /// </returns> private static bool DoesAccessorHaveBody(Accessor accessor) { Param.AssertNotNull(accessor, "accessor"); for (Node<CsToken> node = accessor.Tokens.First; node != accessor.Tokens.Last; node = node.Next) { if (node.Value.CsTokenType == CsTokenType.OpenCurlyBracket) { return true; } } return false; }
/// <summary> /// The get function prefix. /// </summary> /// <param name="accessor"> /// The accessor. /// </param> /// <returns> /// The get function prefix. /// </returns> private string GetFunctionPrefix(Accessor accessor) { // 1 to destHeader var functionPrefix = string.Empty; switch (accessor.AccessorType) { case AccessorType.Add: functionPrefix = "add_"; break; case AccessorType.Remove: functionPrefix = "remove_"; break; case AccessorType.Get: functionPrefix = "get_"; break; case AccessorType.Set: functionPrefix = "set_"; break; default: break; } return functionPrefix; }
/// <summary> /// The save. /// </summary> /// <param name="accessor"> /// The accessor. /// </param> private void Save(Accessor accessor) { // 1 to destHeader var accessorName = accessor.Tokens.First.Value.Text; if (accessorName == "get" || accessorName == "set") { this.SaveModifiersBefore((CsElement)accessor.Parent); } else { this.SaveModifiersBefore(accessor); } TypeToken typeToken = null; typeToken = accessor.ReturnType; if (accessor.AccessorType == AccessorType.Get && typeToken != null) { // 1 to destHeader this.Save(typeToken); if (!this.IsCPPInHeader) { // 2 to Source this.Save(typeToken, this.cppWriter, SavingOptions.None); } } else { // 1 to destHeader this.headerWriter.Write("void"); if (!this.IsCPPInHeader) { // 2 to Source this.cppWriter.Write("void"); } } var functionName = accessor.Declaration.Name; this.headerWriter.Write(" "); this.headerWriter.Write(functionName); if (!this.IsCPPInHeader) { var propertyName = ((StyleCop.CSharp.CsElement)(accessor.Parent)).Declaration.Name; // 2 to Source this.cppWriter.Write(" "); this.cppWriter.Write(this.currentClassNamespace); this.cppWriter.Write("::"); this.cppWriter.Write(propertyName); this.cppWriter.Write("::"); this.cppWriter.Write(functionName); } this.SaveParameters(accessor); this.SaveModifiersAfter(accessor); if (!this.IsCPPInHeader) { this.headerWriter.WriteLine(';'); } this.Save((ICodeUnit)accessor); this.cppWriter.WriteLine(); }
/// <summary> /// Checks the order of child elements of the given element. /// </summary> /// <param name="element"> /// The element to check. /// </param> /// <param name="checkGeneratedCode"> /// Indicates whether to check the order of elements /// within generated blocks of code. /// </param> private void CheckChildElementOrdering(CsElement element, bool checkGeneratedCode) { Param.AssertNotNull(element, "element"); Param.Ignore(checkGeneratedCode); // Check the ordering of this element compared with other elements at the same level. if (element.ChildElements.Count > 0) { bool firstValid = true; CsElement[] elementsArray = new CsElement[element.ChildElements.Count]; element.ChildElements.CopyTo(elementsArray, 0); for (int i = 0; i < elementsArray.Length; ++i) { CsElement first = elementsArray[i]; if (first.AnalyzerTag == null) { for (int j = i + 1; j < elementsArray.Length; ++j) { CsElement second = elementsArray[j]; if (second.AnalyzerTag == null) { // If we're supposed to be checking the order of generated code as well, // then only perform this check if at least one of the two elements is not // generated code. Otherwise, only perform this check if both of the two // elements is not generated code. if ((checkGeneratedCode && (!first.Generated || !second.Generated)) || (!checkGeneratedCode && !first.Generated && !second.Generated)) { // Determine whether first is actually supposed to come before second if (!this.CompareItems(first, second, !firstValid)) { // Determine whether this means that first is out of order or second // is out of order. If we have not found the first item in the list that // is in the correct order, then first is marked out of order, otherwise // second is marked out of order. if (firstValid) { first.AnalyzerTag = false; } else { second.AnalyzerTag = false; } } else { // At this point we know that we've found an item that is in the correct order. if (firstValid) { firstValid = false; } } // If both of the elements are accessors, check that they appear in the correct order. if (first.ElementType == ElementType.Accessor && second.ElementType == ElementType.Accessor) { Accessor firstAccessor = (Accessor)first; Accessor secondAccessor = (Accessor)second; if (firstAccessor.AccessorType == AccessorType.Set && secondAccessor.AccessorType == AccessorType.Get) { this.AddViolation(first, Rules.PropertyAccessorsMustFollowOrder); } else if (firstAccessor.AccessorType == AccessorType.Remove && secondAccessor.AccessorType == AccessorType.Add) { this.AddViolation(first, Rules.EventAccessorsMustFollowOrder); } } } } } } this.CheckElementOrder(first, checkGeneratedCode); } } }