예제 #1
0
        /// <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;
        }
예제 #4
0
        /// <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;
        }
예제 #5
0
        /// <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();
        }
예제 #8
0
        /// <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);
                }
            }
        }