The fully qualified name of a class is created by taking the name of the class and prepending the names of its namespaces and parent classes. For example, consider the following code:
{ { { { {
}
}
}
} }
For the code above, the name of class C1 is C1, but the fully qualified name is NS1.NS2.NS3.C1.
The name of class C2 is C2, but the fully qualified name is NS1.NS2.NS3.C1+C3+C2.
The key point is that class names are separated from their parent namespace(s) by a period (.), but the inner classes are separated from their outer classes by a plus sign (+).
It gets even more interesting with generics. Consider the following code:
{ { { {
}
}
} }
Generic types encode the number of generic parameters as part of their name, so for the example above the fully qualified name of C3 is NS1.NS2.NS3.C1+C3. If C3 was defined with three generic parameters, then its fully qualified name would be NS1.NS2.NS3.C1+C3, and so on and so forth.
So, if you want to exclude a generic class from coverage, you need to account for the number of generic parameters it takes. This can get interesting. Consider the following code:
{ { { {
}
}
} }
However, this inheritance is not reflected in the naming. Each parent class keeps track of the number of generic parameters it has, without worrying about the (possible) generic parameters of its parents. So the fully qualified name of C3<T, U> for the code above is NS1.NS2.NS3.C1+1+C3.
That covers how classes are named, and should help you understand how to include or exclude a specific class, whether or not it's generic.