/// <summary>
        /// Searches the given source code file for a source element matching the given <see cref="SourceElement"/>.
        /// If the source element can be found, a <see cref="SourceElementPosition"/> containing the start and end line numbers is returned.
        /// Otherwise <c>null</c> is returned.
        /// </summary>
        /// <param name="filename">The filename.</param>
        /// <param name="sourceElement">The source element.</param>
        /// <returns>A <see cref="SourceElementPosition"/> or <c>null</c> if source element can not be found.</returns>
        internal static SourceElementPosition FindSourceElement(string filename, SourceElement sourceElement)
        {
            if (filename == null)
            {
                throw new ArgumentNullException(nameof(filename));
            }

            if (sourceElement == null)
            {
                throw new ArgumentNullException(nameof(sourceElement));
            }

            AstNode parentNode = GetParentNode(filename);

            if (parentNode == null)
            {
                return null;
            }
            else
            {
                var matchingClasses = FindClasses(new AstNode[] { parentNode }).Where(c => GetFullClassName(c) == sourceElement.Classname);

                return FindSourceElement(matchingClasses, sourceElement);
            }
        }
        /// <summary>
        /// Searches the given source code file for a source element matching the given <see cref="SourceElement"/>.
        /// If the source element can be found, a <see cref="SourceElementPosition"/> containing the start and end line numbers is returned.
        /// Otherwise <c>null</c> is returned.
        /// </summary>
        /// <param name="filename">The filename.</param>
        /// <param name="sourceElement">The source element.</param>
        /// <returns>A <see cref="SourceElementPosition"/> or <c>null</c> if source element can not be found.</returns>
        internal static SourceElementPosition FindSourceElement(string filename, SourceElement sourceElement)
        {
            if (filename == null)
            {
                throw new ArgumentNullException(nameof(filename));
            }

            if (sourceElement == null)
            {
                throw new ArgumentNullException(nameof(sourceElement));
            }

            AstNode parentNode = GetParentNode(filename);

            if (parentNode == null)
            {
                return(null);
            }
            else
            {
                var matchingClasses = FindClasses(new AstNode[] { parentNode }).Where(c => GetFullClassName(c) == sourceElement.Classname);

                return(FindSourceElement(matchingClasses, sourceElement));
            }
        }
        /// <summary>
        /// Searches the given source element (e.g. property) and updates the report if element can be found in source code files.
        /// </summary>
        /// <param name="sourceElement">The source element.</param>
        /// <param name="filenameByFileIdDictionary">Dictionary containing all files used in the report by their corresponding id.</param>
        /// <param name="fileIdsOfClass">The file ids of class.</param>
        /// <param name="reportElement">The report element.</param>
        /// <param name="updateReportElement">Action that updates the report element.</param>
        /// <param name="filesContainer">The files container.</param>
        /// <returns><c>true</c> if source element has been found.</returns>
        protected bool SearchElement(
            SourceElement sourceElement,
            Dictionary<string, string> filenameByFileIdDictionary,
            IEnumerable<string> fileIdsOfClass,
            XContainer reportElement,
            Action<XContainer, SourceElementPosition, string> updateReportElement,
            XContainer filesContainer)
        {
            Func<bool> searchSourceElement = () =>
            {
                foreach (var fileId in fileIdsOfClass)
                {
                    var elementPosition = SourceCodeAnalyzer.FindSourceElement(filenameByFileIdDictionary[fileId], sourceElement);

                    if (elementPosition != null)
                    {
                        updateReportElement(reportElement, elementPosition, fileId);
                        return true;
                    }
                }

                return false;
            };

            // Search files from module first
            if (!searchSourceElement())
            {
                // Property has not been found in classes of module, now search the common directory
                if (this.ClassSearcher == null)
                {
                    this.ClassSearcher = this.classSearcherFactory.CreateClassSearcher(CommonDirectorySearcher.GetCommonDirectory(filenameByFileIdDictionary.Values));
                }

                fileIdsOfClass = this.TryToFindFileIdsOfClass(
                   this.ClassSearcher,
                   sourceElement.Classname,
                   filenameByFileIdDictionary,
                   filesContainer);

                // Property has not been found in common directory, now search the global directory
                if (!searchSourceElement())
                {
                    fileIdsOfClass = this.TryToFindFileIdsOfClass(
                        this.globalClassSearcher,
                        sourceElement.Classname,
                        filenameByFileIdDictionary,
                        filesContainer);
                    return searchSourceElement();
                }
            }

            return true;
        }
        /// <summary>
        /// Searches the given <see cref="ICSharpCode.NRefactory.PatternMatching.INode">INodes</see> recursively for the given <see cref="SourceElement"/>.
        /// </summary>
        /// <param name="nodes">The nodes.</param>
        /// <param name="sourceElement">The source element.</param>
        /// <returns>A <see cref="SourceElementPosition"/> or <c>null</c> if source element can not be found.</returns>
        private static SourceElementPosition FindSourceElement(IEnumerable<AstNode> nodes, SourceElement sourceElement)
        {
            foreach (var node in nodes)
            {
                var sourceElementPosition = sourceElement.GetSourceElementPosition(node);
                if (sourceElementPosition != null)
                {
                    return sourceElementPosition;
                }
            }

            foreach (var node in nodes)
            {
                var sourceElementPosition = FindSourceElement(node.Children, sourceElement);
                if (sourceElementPosition != null)
                {
                    return sourceElementPosition;
                }
            }

            return null;
        }
        /// <summary>
        /// Searches the given <see cref="ICSharpCode.NRefactory.PatternMatching.INode">INodes</see> recursively for the given <see cref="SourceElement"/>.
        /// </summary>
        /// <param name="nodes">The nodes.</param>
        /// <param name="sourceElement">The source element.</param>
        /// <returns>A <see cref="SourceElementPosition"/> or <c>null</c> if source element can not be found.</returns>
        private static SourceElementPosition FindSourceElement(IEnumerable <AstNode> nodes, SourceElement sourceElement)
        {
            foreach (var node in nodes)
            {
                var sourceElementPosition = sourceElement.GetSourceElementPosition(node);
                if (sourceElementPosition != null)
                {
                    return(sourceElementPosition);
                }
            }

            foreach (var node in nodes)
            {
                var sourceElementPosition = FindSourceElement(node.Children, sourceElement);
                if (sourceElementPosition != null)
                {
                    return(sourceElementPosition);
                }
            }

            return(null);
        }