False if-statement still executes - c#

I have the following method which should iterate through a tree while invoking actions on each node plus once every time it steps up or down the hierarchy. The logic itself works flawless, but I realized that my unit test fails because the if-statement which checks for already invoked elements fails to do what it is logical meant to do.
public static void IterateWithHierarchyFeedback(TBase start,
Func<TBase, IEnumerable<TBase>> childSelector,
Action<TBase> invoker,
Action stepUpInvocator,
Action stepDownInvocator,
bool invokeOnStart)
{
Stack<DynamicIterator> iterationStack = new Stack<DynamicIterator>();
iterationStack.Push(new DynamicIterator(start, childSelector(start).GetEnumerator()));
while (iterationStack.Count > 0)
{
var current = iterationStack.Pop();
// HERE it fails because current.Invoked = true but invoker() is still executed
if (!current.Invoked && invokeOnStart || current.Current != start)
invoker(current.Current);
if (current.Enumerator == null || !current.Enumerator.MoveNext())
{
if (current.Current != start)
stepUpInvocator();
continue;
}
stepDownInvocator();
current.Invoked = true;
iterationStack.Push(current);
iterationStack.Push(new DynamicIterator(current.Enumerator.Current,
childSelector(current.Enumerator.Current)?.GetEnumerator()));
continue;
}
}
This is my unit test:
[Test]
public async Task TestIterateWithFeedback()
{
StringBuilder b = new StringBuilder();
DynamicIterate<Tree>.Downwards.IterateWithHierarchyFeedback(_tree, t => t.Children,
tree => b.Append(tree.ReturnValue.ToString()),
() => b.Append('<'),
() => b.Append('>'),
true);
Assert.Warn(b.ToString());
const string expected = "1>2>3>4<>5<<>6<<>7>>";
Assert.AreEqual(expected, b.ToString());
}
And here you see that the output is not what it should be. That's because invoker() is called on elements that were already invoked, otherwise the output would be correct when it comes to order:
2) Expected string length 20 but was 23. Strings differ at index 8.
Expected: "1>2>3>4<>5<<>6<<>7>>"
But was: "1>2>3>4<3>5<3<2>6<2<>7<"
Can anyone explain to me why this happens? I found this but even without debugger it occurs. I also tried to change my state object (DynamicIterator) from struct to class (as I initially thought this might be an issue with the async variation. But that's not changing anything either.

I'm not sure that the problem is, but the iteration code looks more complicated than needed. I would propose something like this:
public static IEnumerable<(T Node, int Level)> DepthFirstWithlevel<T>(
T self,
Func<T, IEnumerable<T>> selector)
{
var stack = new Stack<(T Node, int Level)>();
stack.Push((self, 0));
while (stack.Count > 0)
{
var current = stack.Pop();
yield return current;
foreach (var child in selector(current.Node))
{
stack.Push((child, current.Level + 1));
}
}
}
This would return each node in the tree, together with the level in the tree the node has, with 0 being the root. If you specifically need methods to be called for each level change, you can make that with a separate method, something like this:
public static void IterateWithHierarchyFeedback<T>(
T self,
Func<T, IEnumerable<T>> selector,
Action<T> invoker,
Action stepUp,
Action stepDown)
{
int currentLevel = 0;
foreach (var (node, level) in DepthFirstWithLevel(self, selector))
{
while (currentLevel < level)
{
currentLevel++;
stepDown();
}
while (currentLevel > level)
{
currentLevel--;
stepUp();
}
invoker(node);
}
}
For the tree
A - B - C
| ⌞ D
⌞E - F
It will print A>E>F<B>DC, i.e. It will traverse the bottom branches first (insert a .Reverse() after selector(current.Node) to change this). And it will go from the F to B directly, without revisiting A.

Related

How to collect all MethodDeclarationSyntax transitively with Roslyn?

Given a list of MethodDeclarationSyntax I would like to collect all the methods in a solution that are calling this method transitively.
I have been using the following code:
var methods = new Stack<MethodDeclarationSyntax>();
... // fill methods with original method to start from
var visited = new HashSet<MethodDeclarationSyntax>();
while (methods.Count > 0)
{
var method = methods.Pop();
if (!visited.Add(method))
{
continue;
}
var methodSymbol = (await solution.GetDocument(method.SyntaxTree).GetSemanticModelAsync()).GetDeclaredSymbol(method);
foreach (var referencer in await SymbolFinder.FindCallersAsync(methodSymbol, solution))
{
var callingMethod = (MethodDeclarationSyntax) referencer.CallingSymbol.DeclaringSyntaxReferences[0].GetSyntax();
methods.Push(callingMethod);
}
}
The problem is that MethodDeclarationSyntax doesn't seem to be a singleton, so this loop is running forever, visiting the same methods again and again.
What is the proper way to uniquely identify a MethodDeclarationSyntax in a Dictionary/Hashset?
Edit 1)
As a workaround, I'm using the following MethodDeclarationSyntaxComparer to initialize my HashSet, but it looks very fragile:
private class MethodDeclarationSyntaxComparer: IEqualityComparer<MethodDeclarationSyntax>
{
public bool Equals(MethodDeclarationSyntax x, MethodDeclarationSyntax y)
{
var xloc = x.GetLocation();
var yloc = y.GetLocation();
return xloc.SourceTree.FilePath == yloc.SourceTree.FilePath &&
xloc.SourceSpan == yloc.SourceSpan;
}
public int GetHashCode(MethodDeclarationSyntax obj)
{
var loc = obj.GetLocation();
return (loc.SourceTree.FilePath.GetHashCode() * 307) ^ loc.SourceSpan.GetHashCode();
}
}
I'm wondering whether using SyntaxNode here is the right way to go.
Since you're already using SymbolFinder and you're using the semantic model, maybe the right way to go is to actually use ISymbols, rather than SyntaxNodes.
ISymbol already contains the SyntaxReferences you are using, so:
var methods = new Stack<IMethodSymbol>();
... // fill methods with original method to start from
... // convert methods to symbols via semanticModel.GetDeclaredSymbol (node);
var visited = new HashSet<IMethodSymbol>();
while (methods.Count > 0)
{
var method = methods.Pop();
if (!visited.Add(method))
{
continue;
}
foreach (var referencer in await SymbolFinder.FindCallersAsync(method, solution))
{
var callingMethod = (MethodDeclarationSyntax) referencer.CallingSymbol.DeclaringSyntaxReferences[0].GetSyntax();
methods.Push(callingMethod);
}
}
You could possibly make the visited hashset into a Dictionary<IMethodSymbol, IEnumerable<Location>>, and concat all the locations, and thus reconstruct the syntaxes from that result.

How to get arguments of method to make completion with Roslyn?

I try to make code completion with Roslyn and AvalonEdit.
For example, user have code:
public void Completion(int i,int j) { }
And he types:
Completion(
So, i want to get arguments of method (int i, int j) and make code completion.
I write simple code, wich works with '.' and may be this code will work for '(' letter?
public List<ICompletionData> GetCompletionData(String code,int offset,CompletionType completionType)
{
var syntaxTree = SyntaxFactory.ParseSyntaxTree(code);
var compilation = CSharpCompilation.Create("foo")
.AddReferences(Mscorlib)
.AddSyntaxTrees(syntaxTree);
var semanticModel = compilation.GetSemanticModel(syntaxTree);
var textSpan = GetTextSpan(offset,1);// '.' or '(' coordinates
ITypeSymbol lhsType = null;
if (completionType == CompletionType.DotCompletion)
{
var memberAccessNode = (MemberAccessExpressionSyntax)syntaxTree.GetRoot()
.DescendantNodes(textSpan).Last();
lhsType = semanticModel.GetTypeInfo(memberAccessNode.Expression).Type;
}
else if(completionType==CompletionType.ArgumentListCompletion)
{
var arr = syntaxTree.GetRoot().DescendantNodes(textSpan).Last();
var argumentListMode = (ArgumentListSyntax)syntaxTree.GetRoot().DescendantNodes(textSpan).Last();
var directive = argumentListMode.GetFirstDirective();
var arrgs=argumentListMode.Arguments;
//lhsType = semanticModel.GetTypeInfo(directive).Type;
//how to get lhsType?
}
if (lhsType == null)
return new List<ICompletionData>();
List<ICompletionData> completionDataColl = new List<ICompletionData>();
// and here i make completion data
foreach (var symbol in lhsType.GetMembers())
{
if (!symbol.CanBeReferencedByName
|| symbol.DeclaredAccessibility != Accessibility.Public
|| symbol.IsStatic)
continue;
}
}
The problem is, that i can not get ITypeSymbol lhsType. It is null.
How to get lhsType?
Or, maybe i should use another way?
I don't know the code completion (I couldn't find this class called CompletionType) itself, but here is a way based on Roslyn only: semantic model and the method invocation, which I believe you have available (make the method call string a InvocationExpressionSyntax)
To obtain the arguments of a method you can get its SymbolInfo from the semantic model. Then you get its symbol. A symbol contains the list of parameters(arguments).
You can call SemanticModel.GetSymbolInfo()
The result will provide you a symbol or candidate symbols (if it is an overloaded method).
A method symbol will provide the list of parameters, which is the arguments of that method.

How can I ensure that an iterator method will not yield any null items?

I'm wondering whether it is possible to ensure (using code-contracts) that an iterator method will never yield a null item.
This simplified method:
public static IEnumerable<object> CreateSomeObjects()
{
Contract.Ensures(Contract.Result<IEnumerable<object>>() != null);
Contract.Ensures(Contract.ForAll(Contract.Result<IEnumerable<object>>(), _ => _ != null));
for (int i = 0; i < 10; ++i)
{
yield return new object();
}
}
Results in a compile time warning similar to this:
CodeContracts: MyClass.CreateSomeObjects()[0x9]: ensures unproven: Contract.ForAll(Contract.Result>(), _ => _ != null)
What can I do to prove it to the static checker?
Only way you can put contracts on iterators is:
public class Graph
{
public IEnumerable<Node> Nodes(Graph g)
{
Contract.Requires(g != null);
Contract.Ensures(Contract.ForAll(Contract.Result<IEnumerable<Nodei>>, node => node != null));
foreach (var x in g.MethodForGettingNodes())
yield return x;
}
}
The contracts above make sure that callers don’t pass in a null parameter, and the method itself guarantees
that all elements in the resulting collection are non-null.
Currently, the static checker does not reason about collections and thus will not be able to prove the
postcondition above.
According to documentation they still do not fix it since 2009, I had problems with cc 2 years ago, and they still did not fix it and i think they wont.

Dude, where's my object? or, Why does Linq not return my object?

Once I have the results of my Linq query, I am not always happy. There could be a result that I was expecting to be there but wasn't. For example, my client was expecting that a customer was in a customer list, but it wasn't. It is my client saying "Dude, where's my customer?", not me. I am the Dude, and to remain a dude, I have to give my client the reason.
Is there a simple way to take a given object instance and a Linq query and determine which expressions within the query excluded that instance?
Edit Ok, here is a better example
Output should be something along the lines:
Your Customer was excluded for 2 reasons:
Customer FirstName is Carl but it should be Daniel
Customer Age is 18 but it should be > 20
public class Customer
{
public string FirstName { get; set; }
public int Age { get; set; }
}
[Test]
public void Dude_wheres_my_object_test1()
{
var daniel = new Customer { FirstName = "Daniel", Age = 41 };
var carl = new Customer { FirstName = "Carl", Age= 18 };
var Customers = new List<Customer>() { daniel, carl };
// AsQueryable() to convert IEnumerable<T> to IQueryable<T> in
//the case of LinqtoObjects - only needed for this test, not
//production code where queies written for LinqToSql etc normally
//return IQueryable<T>
var query = from c in Customers.AsQueryable()
where c.Age > 20
where c.FirstName == "Daniel"
select c;
//query would return Daniel as you'd expect, but not executed here.
//However I want to explain why Carl was not in the results
string[] r = DudeWheresMyObject(query, carl);
Assert.AreEqual("Age is 18 but it should be > 20", r[0]);
Assert.AreEqual("FirstName is Carl but it should be Daniel", r[1]);
//Should even work for a Customer who is not
//in the original Customers collection...
var ficticiousCustomer = new Customer { FirstName = "Other", Age = 19};
string[] r2= DudeWheresMyObject(query,
ficticiousCustomer);
Assert.AreEqual("Age is 19 but it should be > 20", r2[0]);
Assert.AreEqual("FirstName is Other but it should be Daniel", r2[1]);
}
public string[] DudeWheresMyObject<T>(IQueryable<T> query, T instance)
{
//Do something here with the query.Expression and the instance
}
First of all, before I attempt to write some fancy Fluent framework, Has anyone done this already?
So far, I have considered navigating the expression tree and executing each branch against an IQueryable that only contains my object. Now I don't have a great deal of experience using raw expression trees, so I would like those who have to suggest any pitfalls or even explain whether this is a dead end and why.
I am anxious that anything that results from this should:
Be Reusable - Should be applicable to any object compared against a Linq query returning objects of the same class.
Not affect the performance of the original query (this should just be standard Linq).
Should be Linq-implementation agnostic.
If there are multiple property values set on the missing instance that excluded it from the results, then all of those reasons should be reported.
Edit
I am not suggesting that I keep executing LinqToSql against the database multiple times with different permutations of the query and comparing the results. Rather, I am looking for a way to take a single instance and compare it to the expression tree (without executing the query directly again)
Also, I would like an indication of whether others might find this useful. If so, I would consider starting an open source project to solve it.
I think you'd have to re-create the query as linq-to-objects and deal with the subtle differences between linq-to-sql/entities/whatever and linq-to-objects, accepting that some providers just won't work realistically.
You have your object you want to find in an in memory IEnumerable<T> or something.
You'd have to walk the expression tree somehow and snip out the leaves, so say you had:
where obj.foo == true && obj.bar == "yes"
you'd have to figure out that obj.foo == true and obj.bar == "yes" are leaves and start there. It'd be a sort of depth first search of the expression tree.
So, construct linq to objects queries that only had those leaves. See if the object is included in the results. If not then we've found out why it's excluded, if not then go up the tree (i.e. make the where query include more clauses, getting closer to the orignal one until the object disappears from the results).
As I see it the tough parts would be handling the differences between original linq to 'whatever' and link to objects, figuring out where to split the where claues, dealing with things like joins which can also exclude things and dealing with things like SqlMethods.Like that don't work in linq to objects.
For a one-off exploration of what's filtering out the result, it's hard to beat the Dump method in LINQPad. Here's an extract from one of their samples that shows it in action:
// Dump returns exactly what it was given, so you can sneakily inject
// a Dump (or even many Dumps) *within* an expression. This is useful
// for monitoring a query as it progresses:
new[] { 11, 5, 17, 7, 13 } .Dump ("Prime numbers")
.Where (n => n > 10) .Dump ("Prime numbers > 10")
.OrderBy (n => n) .Dump ("Prime numbers > 10 sorted")
.Select (n => n * 10) .Dump ("Prime numbers > 10 sorted, times 10!");
This gives nicely formatted tables of results:
With some fun expression hacking, you can see the results of each stage of the evaluation for each item in the set. Inspect the local result after the breakpoint has been hit to see the results of the evaluation. To actually use the results of the evaluation, just append .Where(x => x.IsIncludedInResult).Select(x => x.EvaluationTarget) to the line where the report is generated.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
namespace ConsoleApplication4
{
[DebuggerDisplay("{Condition} on {EvaluationTarget} is {EvaluationResult}")]
public class ReportItem<T>
{
public string Condition { get; private set; }
public IEnumerable<ReportItem<T>> NestedReports { get; private set; }
public object EvaluationResult { get; private set; }
public T EvaluationTarget { get; private set; }
public ReportItem(Expression condition, IEnumerable<ReportItem<T>> nestedReports, T evaluationTarget, object evaluationResult)
{
Condition = condition.ToString();
NestedReports = nestedReports;
EvaluationTarget = evaluationTarget;
EvaluationResult = evaluationResult;
}
public override string ToString()
{
return string.Format("{0} on {1} is {2}", Condition, EvaluationTarget, EvaluationResult);
}
}
[DebuggerDisplay("Included: {IsIncludedInResult} \n{Summary}")]
public class Report<T>
{
public ReportItem<T> Contents { get; private set; }
public T EvaluationTarget { get; private set; }
public Report(T source, Expression<Func<T, bool>> predicate)
{
EvaluationTarget = source;
IsIncludedInResult = predicate.Compile()(source);
Contents = Recurse(predicate.Parameters.Single(), predicate.Body, source);
}
private object Evaluate(Expression expression, ParameterExpression parameter, T source)
{
var expr = Expression.Lambda(expression, parameter);
var #delegate = expr.Compile();
var value = #delegate.DynamicInvoke(source);
return value;
}
private ReportItem<T> Recurse(ParameterExpression parameter, Expression sourceExpression, T source)
{
var constantExpression = sourceExpression as ConstantExpression;
if(constantExpression != null)
{
return new ReportItem<T>(sourceExpression, null, source, Evaluate(constantExpression, parameter, source));
}
var unaryExpression = sourceExpression as UnaryExpression;
if(unaryExpression != null)
{
var content = Recurse(parameter, unaryExpression.Operand, source);
var result = Evaluate(sourceExpression, parameter, source);
return new ReportItem<T>(sourceExpression, new[]{content}, source, result);
}
var binaryExpression = sourceExpression as BinaryExpression;
if(binaryExpression != null)
{
var left = Recurse(parameter, binaryExpression.Left, source);
var right = Recurse(parameter, binaryExpression.Right, source);
var item = new ReportItem<T>(sourceExpression, new[] {left, right}, source, Evaluate(sourceExpression, parameter, source));
return item;
}
var methodCallExpression = sourceExpression as MethodCallExpression;
if(methodCallExpression != null)
{
var args = methodCallExpression.Arguments.Select(x => Evaluate(x, parameter, source)).ToArray();
var result = methodCallExpression.Method.Invoke(Expression.Lambda(methodCallExpression.Object, parameter).Compile().DynamicInvoke(source), args);
return new ReportItem<T>(sourceExpression, null, source, result);
}
throw new Exception("Unhandled expression type " + sourceExpression.NodeType + " encountered");
}
public bool IsIncludedInResult { get; private set; }
public string Summary
{
get { return Contents.ToString(); }
}
public override string ToString()
{
return Summary;
}
}
public static class PredicateRunner
{
public static IEnumerable<Report<T>> Report<T>(this IEnumerable<T> set, Expression<Func<T, bool>> predicate)
{
return set.Select(x => new Report<T>(x, predicate));
}
}
class MyItem
{
public string Name { get; set; }
public int Value { get; set; }
public override int GetHashCode()
{
return Value % 2;
}
public override string ToString()
{
return string.Format("Name: \"{0}\" Value: {1}", Name, Value);
}
}
class Program
{
static void Main()
{
var items = new MyItem[3];
items[0] = new MyItem
{
Name = "Hello",
Value = 1
};
items[1] = new MyItem
{
Name = "Hello There",
Value = 2
};
items[2] = new MyItem
{
Name = "There",
Value = 3
};
var result = items.Report(x => !x.Name.Contains("Hello") && x.GetHashCode() == 1).ToList();
Debugger.Break();
}
}
}
It's kind of a tricky one, as in, from your example you could always code something to check for specifics and report 'I searched for term x and the object i returned was not in term x'.
I would have though as others suggested though, that this would have been along the lines for 'return me x' then in code, run a query for 'x where x.property = y' and report non matches.
Following this through, I'd imagine the issue would be that in order to generate the list of non matches, your query or object graph would become pretty massive as you'd need your original object either initially include (or to be expanded via lazy loading to include) many permutations to determine the matches or not.
This is kind of the inverse of running a query on the first place where you'd start with an object and sub select based on conditions, you'd want to select and then selectively super select, catching non conditions.
It's an interesting problem, and one that I'd normally address either client side or code wise before getting to a point where and object was returned or not. But I guess the perfect solution would be to return a single solution and perhaps examine it's associations for links.
The links wouldn't be too hard to find a generic "I've not got one of these" type reason, but to give a 'I've got this link, not that link' response would be harder.
You'd need to maybe provide a method based on some form of predicate builder which took a field and search term and returned an appropriate message if things didn't match. In my mind seems like two slightly different problems.
Slightly rambling now, but would be curious to hear any answers to this!...
I think I follow what you mean. What I think you would want to do is perform two queries, one with selection criteria, and one without, then perform a Linq Except on them to determine which items were excluded, then walk that list and determine what criteria caused them to be excluded.
I can't really think of a better way to do it.
Something like this:
var a = db.Trades.Where(z => z.user == x && z.date == y);
var b = a.Where(z => z.TradeCurrency != null && z.TradeUnderlying.Index != null);
var c = a.Except(b);
List<string> reasons;
foreach(var d in c) {
if (d.TradeCurrency == null)
// add reason
... etc..
}
This would perform a single query (which would have several sub-queries) and only return the results that were excluded (rather than trying to return all results which could be quite large). Unless of course you have a million excluded records and only a few included ones.
Not sure how efficient this is, though compared to a way I can't think of.
EDIT:
I think you are forgetting that Linq queries do not execute until you call an operation that realizes them. In this example, the database is only hit once, even though there are several linq query objects here. The expression tree is modified without executing the queries.
So in this example, when the foreach() occurs, a single database query (with several sub-queries) is executed.

Does LINQ to objects stop processing Any() when condition is true?

Consider the following:
bool invalidChildren = this.Children.Any(c => !c.IsValid());
This class has a collection of child objects that have an IsValid() method. Suppose that the IsValid() method is a processor intensive task. After encountering the first child object where IsValid() is false, theoretically processing can stop because the result can never become true. Does LINQ to objects actually stop evaluating after the first IsValid() = false (like a logical AND) or does it continue evaluating all child objects?
Obviously I could just put this in a foreach loop and break on the first invalid result, but I was just wondering if LINQ to objects is smart enough to do this as well.
EDIT:
Thanks for the answers, for some reason I didn't think to look it up on MSDN myself.
Yes it does. As soon as it finds a match, the criteria is satified. All is similar in that it checks all items but if one doesn't match it ends immeditately as well.
Exists works in the same manner too.
Any
The enumeration of source is stopped as soon as the result can be determined.
Exists
The elements of the current List are individually passed to the Predicate delegate, and processing is stopped when a match is found.
All
The enumeration of source is stopped as soon as the result can be determined.
etc...
Yes, it stops as soon as the results can be evaluated. Here's a quick proof:
class Program
{
static void Main(string[] args)
{
bool allvalid = TestClasses().Any(t => !t.IsValid());
Console.ReadLine();
}
public static IEnumerable<TestClass> TestClasses()
{
yield return new TestClass() { IsValid = () => { Console.Write(string.Format("TRUE{0}",Environment.NewLine)); return true; } };
yield return new TestClass() { IsValid = () => { Console.Write(string.Format("FALSE{0}", Environment.NewLine)); return false; } };
yield return new TestClass() { IsValid = () => { Console.Write(string.Format("TRUE{0}", Environment.NewLine)); return true; } };
yield return new TestClass() { IsValid = () => { Console.Write(string.Format("TRUE{0}", Environment.NewLine)); return true; } };
}
}
public class TestClass
{
public Func<bool> IsValid {get;set;}
}
Yes it will stop after it encounters the first item for which the condition matches, in your case the first item for which c.IsValid() returns false.
From MSDN:
The enumeration of source is stopped
as soon as the result can be
determined.
Here's a quick and dirty empirical test to see for yourself:
class Kebab
{
public static int NumberOfCallsToIsValid = 0;
public bool IsValid()
{
NumberOfCallsToIsValid++;
return false;
}
}
...
var kebabs = new Kebab[] { new Kebab(), new Kebab() };
kebabs.Any(kebab => !kebab.IsValid());
Debug.Assert(Kebab.NumberOfCallsToIsValid == 1);
The result is that yes, the Any LINQ operator stops as soon as a collection item matches the predicate.
as per MSDN,
The enumeration of source is stopped as soon as the result can be determined.

Categories

Resources