ndepend; get method's arguments - ndepend

How can I, using CQLINQ, get collection of input arguments for current method? There is any collection like "Arguments" or "Parameters" only "NbParamenter" which is not suitable for my purposes.

Indeed, CQLinq doesn't have this feature yet. However, in many cases you can compensate thanks to the fact that the properties ICodeElement.Name and IMember.FullName, for a IMethod, contain the coma separated list of names of the parameters types. For example here is the FullName of a method:
System.Windows.Forms.Control.BeginInvoke(Delegate,Object[])
and here is its Name:
BeginInvoke(Delegate,Object[])
Here is for example a CQLinq rule that harnesses parameters types names, to match event handlers methods:
// <Name>Event handler methods should be declared private</Name>
warnif count > 0
from m in Application.Methods where
!m.IsPrivate &&
// A method is considered as event handler if...
m.NbParameters == 2 && // ...it has two parameters..
m.Name.Contains("Object") && // ...of types Object...
m.Name.Contains("EventArgs") && // ...and EventArgs
// Discard special cases
!m.ParentType.IsDelegate &&
!m.IsGeneratedByCompiler
select new { m,m.Visibility }
// This rule implementation relies on the facts that:
// -> A method name contains the type of its parameters.
// -> All EventArgs derived types have the suffix "EventArgs".

Related

How to iterate over the unmapped registers of a bank in DML 1.4?

I am trying to migrate some modules to DML 1.4 and I face some problems during bank content iteration. Specifically, I originally have the snippet below:
select reg in ($signals.unmapped_registers) where (reg.signal_number == signal) {
// some statements here
} else {
log "unimplemented", 1: "Power/Board: Signal %d is unimplemented", signal;
return;
}
However, unmapped_registers is not valid in DML 1.4, thus leading to an unknown identifier compiler error.
How am I supposed to iterate over all the unmapped registers of a specific bank in DML 1.4 and select the one I want based on some specific criteria (i.e. the signal_number parameter)?
I've already tried swapping the select statement with foreach without success.
I've also tried to iterate over all bank registers that instantiate a specific template, but still without success.
You need to foreach over a template that has signal_number as type member.
When you iterate using foreach, the iteration variable is a run-time template reference, which means that not all declarations of the template can be accessed: Only parameters with a declared explicit type belong to the template type (together with all method declarations annotated with shared, and most session and saved declarations). So in your case, your problem is likely that signal_number does not have a declared type.
If you add a parameter type like this:
template register_with_signal is register {
param signal_number : int;
// default assignment must be a separate declaration
param signal_number default -1;
...
}
then you can implement your loop like this:
method handle_signal(int signal) {
foreach reg in (each register_with_signal in (this)) {
if (reg.signal_number == signal) {
// some statements here
return;
}
}
log unimpl: "signal %d is unimplemented", signal;
}

NDepend: Find fields that are either a given type or use a given type in their generic parameters

How would I go about using NDepend to not only identify JustMyCode.Fields that are exactly a given type, but also indirectly, i.e. fields like IList<MyType>, IDictionary<int, MyType>, Lazy<T> and all those "nice" generic variants/usages?
Is there any helper method similar to .UsedBy(...) available by any chance that provides such a functionality?
Here is a query to get field typed with String or Int32:
let types = Types.WithFullNameIn(
"System.String",
"System.Int32").ToArray()
from f in Application.Fields
where !f.ParentType.IsEnumeration &&
f.FieldType != null &&
types.Contains(f.FieldType)
select new { f, type =f.FieldType }
For now you cannot detect when a type is used in a generic parameter.

How to access common declared types from a function in Drools?

Here am having multiple Rules in a .drl file. They are updating 6 different JSONArray. These updates are happening in the "then" section of the Drools. Rather than having the similar logic inside the rule, am trying to write a function which will update the 6 JSONArray. How would that be possible ?
declare USER1_LIST
querysetUser1 :JSONArray
end
declare USER2_LIST
querysetUser2 :JSONArray
end
......
......
......
The initialization is happening in a "Set Up" rule with highest Salience -
rule "setUp"
salience 25
when
then
USER1_LIST user1_list = new USER1_LIST();
user1_list.setQuerysetUser1(new JSONArray());
insert(user1_list);
....
In the rule am using one of the list based on the logic -
rule "RULE_XYZ"
salience 5
when
USER1_LIST($querysetUser1 :querysetUser1)
...<Some code>
then
...<Some code>
$querysetUser1.add(...);
Here I want to perform the operation "$querysetUser1.add(...);" inside a function. These JSONArray are updated by different rules. So my aim is to move the logic of selecting the JSONArray and updating it in a function, so that only this function would be called from different rules.
Declared types can be accessed in declared functions. However, from your example, it sounds like you just need to be able to do work against the JSONArray objects contained within the declared types.
The function would look something like this:
function void addToQuerySet(JSONArray querySet, JSONObject object) {// I have guessed the type of 'object'
querySet.add(object);
}
And you would invoke it from the then clause:
rule "RULE_XYZ"
when
USER1_LIST($querysetUser1 :querysetUser1)
// ...<Some code>
someObject: JSONObject() // the thing to insert
then
addToQuerySet($querysetUser1, someObject);
end
What you cannot do is write a generic method that will take any of your USER1_LIST, USER2_LIST, etc declared types because they're all unique and unrelated types, even if they all share the same structure.
Note that the fact that your declared types sharing the same structure is indicative of poor design -- it is likely they should all be instances of a single type, with somet other way of identifying which user it belongs to. For example, something like this:
declare UserList
querySet: JSONArray
userNum: int
end
Where userNum would indicate which user this is for. Then you could write a function that takes a UserList and a JSONObject (or whatever the type is of that thing is you're adding to the query set) like so:
function void addToQuerySet(UserList userList, JSONObject object) {
userList.getQuerySet().add(object);
}
And invoke it in a then clause like so:
rule "RULE XYZ version 2"
when
$user1List: UserList( userNum == 1, querySet != null)
// more code
$someObject: JSONObject() // to insert
then
addToQuerySet( $user1List, $someObject );
end
Please refer to the documentation here. I have linked to the Drools 7.11.0.Final documentation, specifically the section on functions; the section on declared types is the following section and quite extensive.

Codeeffect Rule Engine - How to define rules to check length of string

I have to define a rule like <> length is < 5 or >5 AND not equal to 'N/A'.
I am not able to get Len() function in the list of operators for the string data type.
Please suggest if any field level attributes needs to define.
In your source class define a method like this:
public int Length(string str)
{
return string.IsNullOrEmpty(str) ? 0 : str.Length;
}
Then run your project, open the rule editor and create your rule like this:
Check if YourString has any value and Length(YourString) is greater than [5]
Details on in-rule methods can be found here

How to bind parameters in replaced expression nodes in Entity Framework on the fly

I'm trying to replace a function call like (simplified) Utility.GetString(MyEntity.SomePropertyWithRelatedEntity)=="abc" with an expression visitor into something like p => p.SubRelatedEntities.FirstOrDefault(sre => sre.SomeFlag==true).SomePropertyWithRelatedEntity.
It means, the datamodel goes like:
MyEntity -> RelatedEntity -> SubRelatedEntity
I'm trying to return a string value from the SubRelatedEntity, based on some rules in the RelatedEntity, so I don't have to re-write / copy/paste the whole filtering rules in every usage; that's why I put inside a "call-signature", so my expression visitor can identify it and replace the fake-call to Utility.GetString to some complicated lambda expressions.
My expression visitor contains something like:
public override Expression Visit(Expression node)
{
if (node == null)
return null;
Expression result = null;
if (node.NodeType == ExpressionType.Call)
{
MethodCallExpression mce = node as MethodCallExpression;
if (mce.Method.DeclaringType == typeof(Utility) && mce.Method.Name == "GetString")
{
Expression<Func<RelatedEntity, string>> exp = re => re.SubRelatedEntities.FirstOrDefault(sre => sre.SomeFlag == true).SomeStringValue;
result = exp.Body;
}
else
result = base.Visit(node);
}
else
result = base.Visit(node);
return result;
}
Now, the problem is, the "sre" parameter is not bound when called the injected lambda expression. After much research, I see the lambda parameters should be replaced with another expression visitor, specifically searching for the new parameters and replacing them with the old ones. In my situation, however, I don't have an "old parameter" - I have the expression MyEntity.SomePropertyWithRelatedEntity (e.g. an property filled with the related entities) which I need to insert somehow in the generated lambda.
I hope my problem is understandable. Thank you for any insights!
After getting no answers for long time and trying hard to find a solution, I've solved it at the end :o)! It goes like this:
The newly injected lambda expression gets an ParameterExpression - well, this is a 'helper', used when directly calling the lambda, what I don't want (hence, 'parameter not bound' exception when ToEnumerable is called). So, the clue is to make a specialized ExpressionVisitor, which replaces this helper with the original expression, which is of course available in the Arguments[] for the method call, which I try to replace.
Works like a charm, like this you can reuse the same LINQ expressions, something like reusable sub-queries, instead of writing all the same LINQ stuff all time. Notice as well, that expression calling a method is not allowed in EF, in Linq2Sql it worked. Also, all the proposed web articles only replace the parameter instances, when constructing/merging more LINQ expressions together - here, I needed to replace a parameter with an faked-method-call argument, e.g. the method should not be called, it only stands for a code-marker, where I need to put my LINQ sub-query.
Hope this helps somebody, at the end it's pretty simple and logical, when one knows how the expression trees are constructed ;-).
Bye,
Andrej