private static void SmallTestForPrefixOptimizedProjector(Func <Projection[], bool, ProjectItems.IProjector> createProjector) { var pi = new ProjectItems(createProjector); var gc = new GlobalContext(); WorkingGraph graph = gc.CurrentGraph; pi.Configure(gc, @"{ -pl $ (Ignore:Name) ---% SIMPLE ! :a* ---% A > :ab ---% AB ! :b* ---% B ! :c* ---% C ! :** ---% }", forceReload: false); ItemType generic2 = ItemType.Generic(2, ignoreCase: false); Item a = graph.CreateItem(generic2, "x:a"); Item ab = graph.CreateItem(generic2, "x:ab"); Item ac = graph.CreateItem(generic2, "x:ac"); Item ca = graph.CreateItem(generic2, "x:ca"); Item cb = graph.CreateItem(generic2, "x:cb"); Item s = graph.CreateItem(generic2, "m:s"); Item t = graph.CreateItem(generic2, "m:t"); var result = new List <Dependency>(); pi.Transform(gc, new ProjectItems.ConfigureOptions(), new ProjectItems.TransformOptions(), new[] { graph.CreateDependency(a, a, null, "a_a", 1), // the first surviving dependency graph.CreateDependency(a, s, null, "a_s", 1), // vanishes, because s is not mapped graph.CreateDependency(ab, s, null, "ab_s", 1), // same graph.CreateDependency(ca, s, null, "ca_s", 1), // etc. graph.CreateDependency(cb, cb, null, "cb_cb", 1), // the second surviving dependency graph.CreateDependency(cb, t, null, "cb_t", 1), // vanishes, because t is not mapped graph.CreateDependency(a, t, null, "a_t", 1), graph.CreateDependency(ac, t, null, "ac_t", 1), graph.CreateDependency(a, s, null, "a_s", 1), // Counts: // !a 5 // >ab 0 // !ac 1 // !b 0 // !ca 1 // !cb 3 // !s 4 // !t 3 }, result); Assert.AreEqual(2, result.Count); Assert.AreEqual("A", result[0].UsingItem.Values[0]); Assert.AreEqual("A", result[0].UsedItem.Values[0]); Assert.AreEqual("C", result[1].UsingItem.Values[0]); Assert.AreEqual("C", result[1].UsedItem.Values[0]); }
private static WorkingGraph CreateGraphWithLongTail() { var gc = new GlobalContext(); WorkingGraph graph = gc.CurrentGraph; ItemType g2 = ItemType.Generic(2, ignoreCase: true); Item a = graph.CreateItem(g2, "a:"); Item b = graph.CreateItem(g2, "b:0"); Item c = graph.CreateItem(g2, "c:"); Item b1 = graph.CreateItem(g2, "b:1"); Item b2 = graph.CreateItem(g2, "b:2"); Item b3 = graph.CreateItem(g2, "b:3"); Item b4 = graph.CreateItem(g2, "b:4"); Item b5 = graph.CreateItem(g2, "b:5"); graph.AddDependencies(new[] { graph.CreateDependency(a, b, null, "", 1), graph.CreateDependency(b, b, null, "", 1), graph.CreateDependency(b, c, null, "", 1), graph.CreateDependency(b, b1, null, "", 1), graph.CreateDependency(b1, b2, null, "", 1), graph.CreateDependency(b2, b3, null, "", 1), graph.CreateDependency(b3, b4, null, "", 1), graph.CreateDependency(b4, b5, null, "", 1), }); return(graph); }
public void TestBackProjectSmallCycle() { ItemType generic2 = ItemType.Generic(2, ignoreCase: false); var gc = new GlobalContext(); WorkingGraph graph = gc.CurrentGraph; Item a1 = graph.CreateItem(generic2, "a:1"); Item b1 = graph.CreateItem(generic2, "b:1"); Item a2 = graph.CreateItem(generic2, "a:2"); Item b2 = graph.CreateItem(generic2, "b:2"); Item b3 = graph.CreateItem(generic2, "b:3"); var deps = new[] { Dep(graph, a1, b1), Dep(graph, b1, a2), Dep(graph, b2, a2), Dep(graph, a1, b3) }; List <Dependency> backProjectedDeps = ProjectMarkCyclesAndBackProject(deps, gc); Assert.IsTrue(Find(backProjectedDeps, a1, b1).MarkersContain("C0")); Assert.IsTrue(Find(backProjectedDeps, a1, b3).MarkersContain("C0")); Assert.IsTrue(Find(backProjectedDeps, b1, a2).MarkersContain("C0")); Assert.IsTrue(Find(backProjectedDeps, b2, a2).MarkersContain("C0")); var pw = new FlatPathWriter(); using (var t = DisposingFile.CreateTempFileWithTail(".txt")) { pw.Render(gc, backProjectedDeps, $"{{ {FlatPathWriter.PathMarkerOption} C* }}".Replace(" ", Environment.NewLine), new WriteTarget(t.FileName, append: false, limitLinesForConsole: 100), ignoreCase: false); using (var sr = new StreamReader(t.FileName)) { var o = sr.ReadToEnd(); //Console.WriteLine(o); Assert.IsTrue(o.Contains("a:1")); Assert.IsTrue(o.Contains("<= a:2 $")); } } }
public void TestBackProjectCycle() { ItemType generic2 = ItemType.Generic(2, ignoreCase: false); var gc = new GlobalContext(); WorkingGraph graph = gc.CurrentGraph; Item a1 = graph.CreateItem(generic2, "a:1"); Item b1 = graph.CreateItem(generic2, "b:1"); Item c1 = graph.CreateItem(generic2, "c:1"); Item d1 = graph.CreateItem(generic2, "d:1"); Item e1 = graph.CreateItem(generic2, "e:1"); Item a2 = graph.CreateItem(generic2, "a:2"); Item b2 = graph.CreateItem(generic2, "b:2"); Item c2 = graph.CreateItem(generic2, "c:2"); Item d2 = graph.CreateItem(generic2, "d:2"); Item e2 = graph.CreateItem(generic2, "e:2"); Item x2 = graph.CreateItem(generic2, "x:2"); var deps = new[] { Dep(graph, a1, b1), Dep(graph, b1, c1), Dep(graph, c1, d1), Dep(graph, d1, e1), Dep(graph, d1, b1), Dep(graph, a2, x2), Dep(graph, b2, x2), Dep(graph, c2, x2), Dep(graph, d2, x2), Dep(graph, e2, x2), }; List <Dependency> backProjectedDeps = ProjectMarkCyclesAndBackProject(deps, gc); Assert.IsFalse(Find(backProjectedDeps, a1, b1).MarkersContain("C0")); Assert.IsTrue(Find(backProjectedDeps, b1, c1).MarkersContain("C0")); Assert.IsTrue(Find(backProjectedDeps, c1, d1).MarkersContain("C0")); Assert.IsFalse(Find(backProjectedDeps, d1, e1).MarkersContain("C0")); Assert.IsTrue(Find(backProjectedDeps, d1, b1).MarkersContain("C0")); Assert.IsFalse(Find(backProjectedDeps, a2, x2).MarkersContain("C0")); Assert.IsFalse(Find(backProjectedDeps, b2, x2).MarkersContain("C0")); Assert.IsFalse(Find(backProjectedDeps, c2, x2).MarkersContain("C0")); Assert.IsFalse(Find(backProjectedDeps, d2, x2).MarkersContain("C0")); Assert.IsFalse(Find(backProjectedDeps, e2, x2).MarkersContain("C0")); }
public void TestSmallSelfOptimizingPrefixTrieProjector2() { // This test found a problem in TrieNode.SetProjectors. var pi = new ProjectItems((p, i) => new ProjectItems.SelfOptimizingPrefixTrieProjector(p, i, 2, "prefixTrie")); var gc = new GlobalContext(); pi.Configure(gc, @"{ -pl $ (:Name) ---% SIMPLE ! :abc ---% ADetail ! :a* ---% A ! :t ---% T ! :** ---% }", forceReload: false); ItemType generic2 = ItemType.Generic(2, ignoreCase: false); WorkingGraph graph = gc.CurrentGraph; Item a = graph.CreateItem(generic2, "x:a"); Item ab = graph.CreateItem(generic2, "x:ab"); Item abc = graph.CreateItem(generic2, "x:abc"); Item abcd = graph.CreateItem(generic2, "x:abcd"); Item t = graph.CreateItem(generic2, "m:t"); var result = new List <Dependency>(); pi.Transform(gc, new[] { graph.CreateDependency(a, t, null, "a_t", 1), // A_T graph.CreateDependency(ab, t, null, "ab_t", 1), // A_ T graph.CreateDependency(abc, t, null, "abc_t", 1), // ADetail _T graph.CreateDependency(abcd, t, null, "abcd_t", 1), // A _ T }, "", result, s => null); Assert.AreEqual(2, result.Count); Assert.AreEqual("A", result[0].UsingItem.Values[0]); Assert.AreEqual(3, result[0].Ct); Assert.AreEqual("ADetail", result[1].UsingItem.Values[0]); Assert.AreEqual(1, result[1].Ct); }
public ItemPattern([CanBeNull] ItemType itemTypeHintOrNull, [NotNull] string itemPattern, int upperBoundOfGroupCount, bool ignoreCase, bool anyWhereMatcherOk) { const string UNCOLLECTED_GROUP = "(?:"; const string UNCOLLECTED_GROUP_MASK = "(?#@#"; IEnumerable <string> parts = itemPattern.Replace(UNCOLLECTED_GROUP, UNCOLLECTED_GROUP_MASK) .Split(':') .Select(p => p.Replace(UNCOLLECTED_GROUP_MASK, UNCOLLECTED_GROUP)) .ToArray(); bool allowNamedPattern; ItemType type = ItemType.Find(parts.First()); if (type != null) { parts = parts.Skip(1); _itemType = type; allowNamedPattern = true; } else if (itemTypeHintOrNull != null) { // Rules may optionally start with the correct type name (when they are copied from e.g. from a violation textfile). if (parts.First() == itemTypeHintOrNull.Name) { parts = parts.Skip(1); } _itemType = itemTypeHintOrNull; allowNamedPattern = true; } else { // No type found form pattern, no itemTypeHint - we guess a generic type. _itemType = ItemType.Generic(parts.Count(), ignoreCase); allowNamedPattern = false; } var result = new List <IMatcher>(); if (parts.Any(p => p.Contains("="))) { if (!allowNamedPattern) { throw new ApplicationException( $"No named patterns possible if type of pattern must be guessed; specify item type in pattern in {itemPattern}"); } // We ignore empty segments which might be included for "clarity" parts = parts.Where(p => p != ""); if (!parts.All(p => p.Contains("="))) { throw new ApplicationException( $"Pattern must either use names for all fields, or no names. Mixing positional and named parts is not allowed in {itemPattern}"); } IMatcher[] matchers = Enumerable.Repeat(_alwaysMatcher, _itemType.Keys.Length).ToArray(); foreach (var p in parts) { string[] nameAndPattern = p.Split(new[] { '=' }, 2); string[] keyAndSubkey = nameAndPattern[0].Split('.'); int i = _itemType.IndexOf(keyAndSubkey[0].Trim(), keyAndSubkey.Length > 1 ? "." + keyAndSubkey[1].Trim() : ""); if (i < 0) { throw new ApplicationException($"Key '{nameAndPattern[0]}' not defined in item type {_itemType.Name}; keys are {_itemType.KeysAndSubkeys()}"); } matchers[i] = CreateMatcher(nameAndPattern[1].Trim(), 0, ignoreCase); } _matchers = new MatcherVector(matchers); } else if (anyWhereMatcherOk && parts.Count() == 1 && !Regex.IsMatch(parts.First().Trim('*'), @"[;(\\*^$]")) { // If there is only a single pattern without any special chars in it - except leading or trailing * _matchers = new AnyWhereMatcher(CreateMatcher(parts.First(), 0, ignoreCase)); } else { int j = 0; foreach (var p in parts) { foreach (var s in p.Split(';')) { result.Add(CreateMatcher(s, upperBoundOfGroupCount, ignoreCase)); j++; } while (j > 0 && j < _itemType.Keys.Length && _itemType.Keys[j - 1] == _itemType.Keys[j]) { result.Add(_alwaysMatcher); j++; } } while (j < _itemType.Keys.Length) { result.Add(_alwaysMatcher); j++; } _matchers = new MatcherVector(result.Take(_itemType.Keys.Length).ToArray()); } }