Getting list of types that are effected by an extension method in cqlinq - ndepend

How to get the list of types that are extended by a extension method in ndepend cqlinq? Using reflection to code this seems a bit of donkey work where ndepend is already there.

NDepend code model doesn't have a straight way to resolve the method parameter type. So we can come up with a satisfying answer with code query relying on string formatting extended type name, extracted from the method name. But this query is overly complex and there are edge cases where it won't work properly (explained below).
Here is the code query, it runs fast even on large code base thanks to the use of a dictionary:
//
// First let build dicoExtensionMethods
let dicoExtensionMethods =
(from m in Application.Methods
where m.IsExtensionMethod
// extract extended type simple name (with generic parameters like "IEnumerable<String>")
let beginIndex = m.Name.IndexOf("(") + 1
let endIndex = m.Name.IndexOf(',', beginIndex) > 0 ? m.Name.IndexOf(',', beginIndex) : m.Name.IndexOf(")", beginIndex)
let extendedTypeSimpleName1 = m.Name.Substring(beginIndex, endIndex - beginIndex)
// Take care of generic type first char, like "IEnumerable<"
let extendedTypeSimpleName2 = extendedTypeSimpleName1.IndexOf('<') == -1 ? extendedTypeSimpleName1 :
extendedTypeSimpleName1.Substring(0, extendedTypeSimpleName1.IndexOf('<') + 1 )
select new { m, extendedTypeSimpleName2 })
.ToLookup(pair => pair.extendedTypeSimpleName2)
.ToDictionary(g => g.Key, g=> g.Select(p =>p.m))
//
// Second for each type get extension methods from dicoExtensionMethods
from t in Types
// Format type name like "IEnumerable<"
let typeName = !t.IsGeneric ? t.SimpleName : t.Name.Substring(0, t.Name.IndexOf('<') + 1 )
where dicoExtensionMethods.ContainsKey(typeName)
let methods = dicoExtensionMethods[typeName]
select new { t, methods }
As written it is a complex query because of type name formatting, and it works fine most of the time.
However when it comes to extending generic types, it says for example that IEnumerable<T> is extended by both methods that extend IEnumerable<String> and IEnumerable<Int32>. This is acceptable, but it is not 100% correct.
Also if you extend several types with same name but various generic arity (like Func<T1,T2> and Func<T1,T2,T3>), then this code query won't work properly.
The same if you extend several types with same name, declared in different assemblies or namespace (which is a code smell anyway).
Hope this helps!

Related

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 enumerate over columns with tokio-postgres when the field types are unknown at compile-time?

I would like a generic function that converts the result of a SQL query to JSON. I would like to build a JSON string manually (or use an external library). For that to happen, I need to be able to enumerate the columns in a row dynamically.
let rows = client
.query("select * from ExampleTable;")
.await?;
// This is how you read a string if you know the first column is a string type.
let thisValue: &str = rows[0].get(0);
Dynamic types are possible with Rust, but not with the tokio-postgres library API.
The row.get function of tokio-postgres is designed to require generic inference according to the source code
Without the right API, how can I enumerate rows and columns?
You need to enumerate the rows and columns, doing so you can get the column reference while enumerating, and from that get the postgresql-type. With the type information it's possible to have conditional logic to choose different sub-functions to both: i) get the strongly typed variable; and, ii) convert to a JSON value.
for (rowIndex, row) in rows.iter().enumerate() {
for (colIndex, column) in row.columns().iter().enumerate() {
let colType: string = col.type_().to_string();
if colType == "int4" { //i32
let value: i32 = row.get(colIndex);
return value.to_string();
}
else if colType == "text" {
let value: &str = row.get(colIndex);
return value; //TODO: escape characters
}
//TODO: more type support
else {
//TODO: raise error
}
}
}
Bonus tips for tokio-postgres code maintainers
Ideally, tokio-postgres would include a direct API that returns a dyn any type. The internals of row.rs already use the database column type information to confirm that the supplied generic type is valid. Ideally a new API uses would use the internal column information quite directly with improved FromSQL API, but a simpler middle-ground exists:-
It would be possible for an extra function layer in row.rs that uses the same column type conditional logic used in this answer to then leverage the existing get function. If a user such as myself needs to handle this kind of conditional logic, I also need to maintain this code when new types are handled by tokio-postgresql, therefore, this kind of logic should be included inside the library where such functionality can be better maintained.

How to initialize an array of classes in kotlin?

I get an error when I put the type and size of an array of classes
I have tried:
fun main(args :Array<String>) {
class modul() {
var nommodul: String? = null
var coeff: Int? = null
var note: Int? = null
}
var releve
class notes() {
var releve: array<modul>(10){""} here the erreur
}
}
First of all, your code has several errors. This might be an MCVE and/or copy-paste issue, but I need to address these before I get started on the arrays.
var releve before the notes class isn't allowed. You don't assign it, you don't declare a type, and the compiler will complain if you copy-paste the code from your question.
Second, the array var itself: Array is upper-case, and initialization is separate. This would be more valid (note that this still does not work - the solution for that comes later in this answer):
var releve: Array<modul> = Array(10) {...}
// or
var releve = Array<modul>(10) {...}
And the last thing before I start on the array itself: please read the language conventions, especially the naming ones. Your classes should all start with an upper-case letter.
Kotlin arrays are quite different from Java arrays in many ways, but the most notable one being that direct array initialization also requires an initializer.
The brackets are expected to create a new instance, which you don't. You create a String, which isn't, in your case, a modul.
There are several ways to fix this depending on how you want to do this.
If you have instances you want to add to the array, you can use arrayOf:
arrayOf(modulInstance, modulInstance2, ...)
If you want to create them directly, you can use your approach:
var releve = Array(10) { modul() }
A note about both of these: because of the initialization, you get automatic type inference and don't need to explicitly declare <modul>
If you want Java-style arrays, you need an array of nulls.
There's two ways to do this:
var releve = arrayOfNulls<modul>(10)
// or
var releve = Array<modul?>(10) { null }
I highly recommend the first one, because it's cleaner. I'm not sure if there's a difference performance-wise though.
Note that this does infer a nullable type to the array, but it lets you work with arrays in a similar way to Java. Initialization from this point is just like Java: releve[i] = modul(). This approach is mostly useful if you have arguments you want to add to each of the classes and you need to do so manually. Using the manual initializers also provides you with an index (see the documentation) which you can use while initializing.
Note that if you're using a for loop to initialize, you can use Array(10) { YourClass() } as well, and use the supplied index if you need any index-sensitive information, such as function arguments. There's of course nothing wrong with using a for loop, but it can be cleaner.
Further reading
Array
Lambdas
here some example of kotlin array initialization:
array of Library Method
val strings = arrayOf("January", "February", "March")
Primitive Arrays
val numbers: IntArray = intArrayOf(10, 20, 30, 40, 50)
Late Initialization with Indices
val array = arrayOfNulls<Number>(5)
for (i in array.indices) {
array[i] = i * i
}
See Kotlin - Basic Types for details

Type wrapping of non-atomic types in golang

I'm new to golang and am trying to understand a code example of type wrapping for the "non-atomic" type time.Time.
The type extension in question is from the Go client for GDAX on github, go-coinbase-exchange project.
The expected behavior would be for Time variables from the project (coinbase.Time), which are of type Time time.Time (as defined in the project's time.go file) to behave something like the following example for extending the "atomic" type int (from blog.riff.org in that they might follow a kind of "inheritance" from the base type for functions like Time.format (from golang's standard implementation of time:
package main
import "fmt"
type Int int
func (i Int) Add(j Int) Int {
return i + j
}
func main() {
i := Int(5)
j := Int(6)
fmt.Println(i.Add(j))
fmt.Println(i.Add(j) + 12)
}
But if I modify the code example from the project's List Account Ledger example found in Readme.md to include a print function which might otherwise give me a human-readable view of the CreatedAt struct variables (as follows), I get a compiler error saying that "type coinbase.Time has no field or method Format":
for _, e := range ledger {
print("Entry Creation: ")
fmt.Printf(e.CreatedAt.Format("2006-01-02 15:04:05.999999+00"))
}
The expected behavior inside the for loop would be for it to print the ledger entries in a human-readable format. I can get the contents of the structs, but I'm not really sure how to then use the resulting wall, ext and loc members.
For example, inserting fmt.Printf("%#v", e.CreatedAt) into the for loop gives me a representation of the time that looks something like this:
coinbase.Time{wall:0x3015a123, ext:63612345678, loc:(*time.Location)(nil)}
{806986000 63638738354 <nil>}
I can also see that wall is of type uint64, that ext is of type int64 and that loc is just GMT/UTC=0 by formatting the variable as a string because fmt.Printf("%s", e.CreatedAt) gives me output which is similar to the following:
{%!s(uint64=712345678) %!s(int64=63612345678) %!s(*time.Location=<nil>)}
It seems like I'm missing something. I've requested further information through issues tab on github, but maybe this is a nube question. So I'm not sure how quick the response time would be, and I'm interested in the more general case for extending non-atomic types in go.
Named types do not inherit any methods from the underlying type (indeed there is no inheritance at all in Go); you must cast to the underlying type to call any methods from that type:
(time.Time(e.CreatedAt)).Format("2006-01-02 15:04:05.999999+00")

EF1: Filtering derived types of entity class using .OfType<> by passing a string value

I have a situation where I'm trying to filter a LINQ select using a derived sub class.
ctx.BaseEntity.OfType<SubClass>() - this works fine.
However I'd like to do this using a string value instead. I've come across a performance barrier when I have lots (>20) Sub Classes and selecting an Entity without using OfType just isn't an option. I have a generic UI that renders from the base class, so I don't know what Class Type will be returned at compile time.
So what I'd like to do is this:
Perform a projected Select where I
return just the SubClassType from
the database
Perform a second select
using this value as the OfType to
only select the relevant related
entity from the database (No mass
unions generated)
int id = 1;
var classType = (from c in ctx.BaseClass.Include("ClassType")
where c.id == id
select new
{
c.ClassType.TypeName
}).First();
BaseClass caseQuery = ctx.BaseClass.OfType<classType.TypeName>()
.Include("ClassType")
.Include("ChildEntity1")
.Include("ChildEntity2")
.Where(x => x.id== id);
But obviously this won't work because OfType requires a Type and not a string.
Any ideas on how I can achieve this?
Update:
As a side note to the original question, it turns out that the moment you project a query that uses a Navigation Property - it builds the monster SQL too, so I've ended up using a stored procedure to populate my ClassType entity from the BaseClass Id.
So I've just got it to work using eSQL, which I'd never used before. I've posted the code here just in case it helps someone. Has anyone else got a more strongly typed solution they can think of?
BaseClass caseQuery = ctx.BaseClass.CreateQuery<BaseClass>("SELECT VALUE c FROM OFTYPE(Entities.[BaseClass],namespace.[" + classType.TypeName + "]) as c")
.Include("ClassType")
.Include("ChildEntity1")
.Include("ChildEntity2")
.Where(x => x.id== id).FirstOrDefault();
To answer the headline question about calling OfType with a string / runtime type, you can do the following:
// Get the type, assuming the derived type is defined in the same assembly
// as the base class and you have the type name as a string
var typeToFilter = typeof(BaseClass)
.Assembly
.GetType("Namespace." + derivedTypeName);
// The use reflection to get the OfType method and call it directly
MethodInfo ofType = typeof(Queryable).GetMethod("OfType");
MethodInfo ofTypeGeneric = method.MakeGenericMethod(new Type[] { typeToFilter });
var result = (IQueryable<Equipment>)generic.Invoke(null, new object[] { equipment });
Combine this with your stored procedure to get the class name and you (should?) avoid the massive join - I don't have table-per-type implementation to play with so I can't test.