// match inheritances of child to known types
        /// <summary>
        /// The child is unknown, so the type/component inheritances are checked for known components and matched to the unknown child.
        /// </summary>
        /// <param name="componentMatch">The component match.</param>
        /// <param name="knownComponentTypes">The known component types.</param>
        /// <param name="reference">The reference.</param>
        /// <returns>True if the given component inherits one of the known types</returns>
        private bool MatchUnknownChildWithKnownParent(ComponentMatch componentMatch, List <SymbolInformation> knownComponentTypes, Reference reference)
        {
            var componentMatchSymbol = (INamedTypeSymbol)componentMatch.SymbolInformation.Symbol;

            var match = true;

            if (reference.Inheritance.IsReference)
            {
                var inheritanceMatch = knownComponentTypes.Any(s => this.MatchInheritance(componentMatchSymbol, (INamedTypeSymbol)s.Symbol));
                match &= reference.Inheritance.Occurrence != ComponentOccurrence.Prohibited ? inheritanceMatch : !inheritanceMatch;
            }

            if (reference.Member.IsReference)
            {
                var memberMatch = knownComponentTypes.Any(s => this.MatchMember(componentMatchSymbol, (INamedTypeSymbol)s.Symbol));
                match &= reference.Member.Occurrence != ComponentOccurrence.Prohibited ? memberMatch : !memberMatch;
            }

            if (reference.Parameter.IsReference)
            {
                var parameterMatch = knownComponentTypes.Any(s => this.MatchParameter(componentMatchSymbol, (INamedTypeSymbol)s.Symbol));
                match &= reference.Parameter.Occurrence != ComponentOccurrence.Prohibited ? parameterMatch : !parameterMatch;
            }

            return(match);
        }
        /// <summary>
        /// Update the dictionary of component matches with the found component match
        /// </summary>
        /// <param name="patternName">The name of the pattern to update</param>
        /// <param name="component">component</param>
        private void AddComponentMatch(ComponentMatch componentMatch)
        {
            if (!this.componentMatches.ContainsKey(componentMatch.Component))
            {
                // Utilize locking to enable parallel running of the scanning
                lock (componentMatchLock)
                {
                    if (!this.componentMatches.ContainsKey(componentMatch.Component))
                    {
                        this.componentMatches.Add(componentMatch.Component, new List <ComponentMatch>());
                    }
                }
            }

            this.componentMatches[componentMatch.Component].Add(componentMatch);
        }
Пример #3
0
        /// <summary>
        /// Visits the specified symbol, matches all candidates with the symbol. Returns whether a match was found, and which candidates matched.
        /// </summary>
        /// <param name="symbol">The symbol.</param>
        /// <returns>True if there was a match, and the matched componenttypes. Empty list if there are no matches</returns>
        public (bool match, IEnumerable <ComponentMatch> componentMatches) Visit(INamedTypeSymbol symbol, IEnumerable <IBaseConfigModel> candidates)
        {
            var componentMatches = new List <ComponentMatch>();
            var memberMatches    = new List <MemberMatch>();

            candidates = this.MatchSymbolNamedTypeKind(symbol, candidates);
            candidates = this.MatchAccessModifier(symbol, candidates);
            candidates = this.MatchModifier(symbol, candidates);
            candidates = this.MatchInheritance(symbol, candidates);

            // Return early when no components matched. No need to scan all members.
            if (!candidates.Any())
            {
                return(false, componentMatches);
            }

            // match childmembers, if the parent matches

            (candidates, memberMatches) = this.MatchMembers(symbol, candidates);

            var symbolPath = symbol.DeclaringSyntaxReferences[0]?.SyntaxTree?.FilePath ?? "Filepath undefined.";

            foreach (var candidate in candidates)
            {
                var match = new ComponentMatch()
                {
                    Component         = (Component)candidate,
                    SymbolInformation = new SymbolInformation()
                    {
                        Symbol = symbol, SymbolName = this.GetFullName(symbol), SymbolPath = symbolPath
                    },
                    MemberMatches = memberMatches.Where(c => c.Member.Parent == candidate)
                };

                componentMatches.Add(match);
            }

            return(candidates.Any(), componentMatches);
        }