1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
5
using System.Collections.Generic;
8
using System.Diagnostics;
10
namespace ICSharpCode.CppBinding.Project
13
/// Dependency relation between arbitrary types.
15
public class DependencyRelation<T1, T2>
17
public DependencyRelation()
18
: this(new MultiDictionary<T1, T2>())
21
public DependencyRelation(IMultiDictionary<T1, T2> innerDep)
25
revDep = new MultiDictionary<T2, T1>();
26
foreach (KeyValuePair<T1, T2> item in dep)
27
revDep.Add(item.Value, item.Key);
31
/// Adds an information that <paramref name="item"/> does depend on <paramref name="dependency"/>
33
public void Add(T1 item, T2 dependency)
35
dep.Add(item, dependency);
36
revDep.Add(dependency, item);
40
/// Removes a dependency between <paramref name="item"/> and <paramref name="dependency"/>.
42
public bool Remove(T1 item, T2 dependency)
44
if (dep.Remove(item, dependency))
46
Debug.Assert(revDep.Remove(dependency, item));
53
/// Returns a list of items given element directly depend on.
54
/// If there is no element in the dependency relation, returns an empty list.
56
public IList<T2> DependOn(T1 element)
58
if (dep.ContainsKey(element))
60
return new List<T2>();
64
/// Enumerates all items given element depend on including those that
65
/// depend indirectly. If type parameters <typeparamref name="T1"/> and <typeparamref name="T2"/>
66
/// are not equal then the result is the same as from DependOn method.
69
/// The enumeration may contain the <paramref name="element"/> if there is
70
/// a cyclic dependency. It is guaranteed that the enumaration contains an item
73
public IEnumerable<T2> DependencyTreeFrom(T1 element)
75
if (typeof(T1) != typeof(T2)) return DependOn(element);
77
//this solves the case when T1 == T2
78
return DependencyTree(dep, element).Cast<T2>();
82
/// Returns a list of elements that depend on given element.
83
/// If the is no item that depend on given element, returns an empty list.
85
/// <returns></returns>
86
public IList<T1> DependingOn(T2 element)
88
if (revDep.ContainsKey(element))
89
return revDep[element];
90
return new List<T1>();
94
/// Enumerates all items that are depending on given element including those
95
/// depending indirectly. If type parameters <typeparamref name="T1"/> and <typeparamref name="T2"/>
96
/// are not equal then the result is the same as from DependingOn method.
99
/// The enumeration may contain the <paramref name="element"/> if there is
100
/// a cyclic dependency. It is guaranteed that the enumaration contains an item
103
public IEnumerable<T1> DependencyTreeTo(T2 element)
105
if (typeof(T1) != typeof(T2)) return DependingOn(element);
107
//this solves the case when T1 == T2
108
return DependencyTree(revDep, element).Cast<T1>();
111
IEnumerable<T> DependencyTree<T, U>(IMultiDictionary<T, U> rel, T startItem)
113
HashSet<T> visited = new HashSet<T>();
114
Stack<T> pendingItems = new Stack<T>();
116
pendingItems.Push(startItem);
117
while (pendingItems.Count > 0)
119
T currentItem = pendingItems.Pop();
120
if (rel.ContainsKey(currentItem))
121
foreach (T depend in rel[currentItem].Cast<T>())
122
if (!visited.Contains(depend))
125
pendingItems.Push(depend);
131
//dependency relation
132
IMultiDictionary<T1, T2> dep;
134
//reverse dependency relation
135
IMultiDictionary<T2, T1> revDep;