// 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); }
/// <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); }