Thursday, September 9, 2010

My first Rx attempt

I think I overshot for a first attempt by far and I'm not sure how to validate the efficiency/concurrency of the code. However, here is Rx that so far as I've used it appears to correctly do recursive producer-consumer iteration of a call graph.



 public override ProblemCollection Check(TypeNode type)
    {
      Debug.WriteLine("Checking type:"+type.FullName);
      var initializer = type.Members.OfType<Method>( ).FirstOrDefault(x => x.FullName==type.FullName+".InitializeComponent");
 
      if (initializer==null)
        return null;
      Debug.WriteLine(initializer.FullName);
      var constructorsWithNoInitCall = type.Members.OfType<Method>( ).Where(m => m.NodeType==NodeType.InstanceInitializer).ToList( );
      var visitedMethods = new HashSet<string>( );
      var foundMethods = new ObservableHashSet<Method>( );
 
      var whenMethodsFound = Observable.FromEvent<NotifyCollectionChangedEventArgs>(foundMethods, "CollectionChanged");
 
      whenMethodsFound.Subscribe(
        e =>
        {
          switch (e.EventArgs.Action)
          {
            case NotifyCollectionChangedAction.Add:
              if (constructorsWithNoInitCall.Any( ))
                Parallel.ForEach(e.EventArgs.NewItems.Cast<Method>( ).Where(m => visitedMethods.Any(v => v==m.FullName)==false),
                  i =>
                  {
 
                    lock (visitedMethods)
                    {
                      if (visitedMethods.Contains(i.FullName))
                        return;
                      visitedMethods.Add(i.FullName);
 
                    }
                    Debug.WriteLine("Visiting:"+i.FullName);
                    var callers = (CallGraph.CallersFor(i));
                    constructorsWithNoInitCall.RemoveAll(x => callers.Any(c => x.FullName==c.FullName));
                    if (constructorsWithNoInitCall.Any( ))
                      foreach (var item in callers.Where(c => visitedMethods.Any(v => v==c.FullName)==false))
                      {
                        foundMethods.Add(item);
                      }
                  });
              break;
            default:
              break;
          }
        }
        );
      foundMethods.Add(initializer);
 
 
      ReportProblem(constructorsWithNoInitCall, type);
 
      return Problems;
    }

No comments:

Post a Comment