From cc705dd09a88ffa18c4503d424c731bfc45437ff Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 26 May 2026 08:03:49 +0000 Subject: [PATCH] perf: optimize GetViolationsFromExperimental with dictionary lookups for O(n) complexity Implements optimized GetViolationsFromExperimental() in both ProjectPathViolationDetector and ProjectTagViolationDetector. For ProjectTag, uses a Dictionary for O(1) lookup per reference. For ProjectPath, pre-filters matching rules to reduce inner iterations. Fixes mfogliatto/ReferenceCop#54 --- .../Detectors/ProjectPathViolationDetector.cs | 29 ++++++++++++++-- .../Detectors/ProjectTagViolationDetector.cs | 34 +++++++++++++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/ReferenceCop/Detectors/ProjectPathViolationDetector.cs b/src/ReferenceCop/Detectors/ProjectPathViolationDetector.cs index bd522e5..2eb2e61 100644 --- a/src/ReferenceCop/Detectors/ProjectPathViolationDetector.cs +++ b/src/ReferenceCop/Detectors/ProjectPathViolationDetector.cs @@ -1,4 +1,4 @@ -namespace ReferenceCop +namespace ReferenceCop { using System.Collections.Generic; using System.Linq; @@ -46,7 +46,32 @@ public IEnumerable GetViolationsFrom(IEnumerable GetViolationsFromExperimental(IEnumerable> references) { - return this.GetViolationsFrom(references); + var fromProjectPath = this.projectPathProvider.GetRelativePath(this.projectFilePath); + + var matchingRules = this.rules.Where(r => fromProjectPath.StartsWith(r.FromPath)).ToList(); + if (matchingRules.Count == 0) + { + yield break; + } + + foreach (var referenceContext in references) + { + if (referenceContext.IsWarningSuppressed) + { + continue; + } + + var toProjectPath = this.projectPathProvider.GetRelativePath(referenceContext.Reference); + + foreach (var rule in matchingRules) + { + if (toProjectPath.StartsWith(rule.ToPath)) + { + yield return new Violation(rule, referenceContext.Reference); + break; + } + } + } } private void LoadRulesFrom(ReferenceCopConfig config) diff --git a/src/ReferenceCop/Detectors/ProjectTagViolationDetector.cs b/src/ReferenceCop/Detectors/ProjectTagViolationDetector.cs index a2e4062..e63ec3c 100644 --- a/src/ReferenceCop/Detectors/ProjectTagViolationDetector.cs +++ b/src/ReferenceCop/Detectors/ProjectTagViolationDetector.cs @@ -1,4 +1,4 @@ -namespace ReferenceCop +namespace ReferenceCop { using System.Collections.Generic; using System.Linq; @@ -46,7 +46,37 @@ public IEnumerable GetViolationsFrom(IEnumerable GetViolationsFromExperimental(IEnumerable> references) { - return this.GetViolationsFrom(references); + var fromProjectTag = this.projectTagProvider.GetProjectTag(this.projectFilePath); + + var matchingRules = this.rules.Where(r => r.FromProjectTag == fromProjectTag).ToList(); + if (matchingRules.Count == 0) + { + yield break; + } + + var blockedTagToRule = new Dictionary(); + foreach (var rule in matchingRules) + { + if (!blockedTagToRule.ContainsKey(rule.ToProjectTag)) + { + blockedTagToRule[rule.ToProjectTag] = rule; + } + } + + foreach (var referenceContext in references) + { + if (referenceContext.IsWarningSuppressed) + { + continue; + } + + var toTag = this.projectTagProvider.GetProjectTag(referenceContext.Reference); + + if (blockedTagToRule.TryGetValue(toTag, out var matchedRule)) + { + yield return new Violation(matchedRule, referenceContext.Reference); + } + } } private void LoadRulesFrom(ReferenceCopConfig config)