Suggestion: Symbol Search Improvements
It would be nice to add the following kinds of symbol searches:
-
Find Extensions of Specific Type Only: Currently the Find Extensions feature will; find all applicable extensions, however to may be useful to limit the scope of the search to only those extension members that match the type:
- Either explicitly match concrete type.
- Or, allow for all derived types as well in case of classes or interfaces. This can be accomplished with modifier keys, similar to how other search functions are already implemented.
-
Find Type Parameter Usages: Find all concrete types for a generic type parameter in either a generic type or a method:
void Foo<T>() { }Find all concrete types of
Twithin a solution.This would be similar to how "Find parameter assignments" feature works for methods.
-
Find Direct Interface Implementations Only: Find non-inherited interface implementations, i.e. only those that are directly implemented. This is not an issue for structs, but for classes that have complex inheritance chains, the current behavior produces huge list of classes because it lists every single implementing type, even though only the base class may be implementing the interface directly.
interface IFoo { } abstract class Base : IFoo { } class Derived : Base { } class Derived2 : Base, IFoo { }So
Derivedwould not be listed under this search logic because it inheritedIFooimplementation via base. ButDerived2would still be listed, because it explicitly hasIFooin its declaration (i.e. it re-implements the interface).
Another suggestion would be find all concrete types for a generic type parameter in eitehr a generic type or a method:
void Foo<T>() { }
Find all concrete types of T within a solution.
This would be similar to how "Find parameter assignments" feature works for methods.
Interesting. I will see whether it is possible to implement that.
Oh and a 3rd feature related to this would be the ability to: find non-inherited interface implementations, i.e. only those that are directly implemented. This is not an issue for structs, but for classes that have complex inheritance chains, the current behavior produces huge list of classes because it lists every single implementing type, even though only the base class may be implementing the interface directly.
I have updated the issue to reflect all 3 use cases.
Oh, and lastly - is there any progress on finding usages of implicit conversion operators? It would really help if all such instances can be found.
is there any progress on finding usages of implicit conversion operators
No. Roslyn has not implemented it. And it is not an easy task, since there's little cue about those conversions in the code. For instance, given the following code:
There is an implicit conversion defined in the Complex struct. Try executing Find All References command in VS on the Complex symbol on the operator declaration yield no result but "symbol not referenced".
I see. Hopefully they will implement it once they get around to extension operators.
3. Find Direct Interface Implementations Only
Given an interface I and a base class B, which implements I with virtual members.
Then, a class C derives from class B, without claiming that it implements I explicitly, but it overrides all virtual members in B that implements I. That is, C has its own set of implementation for I actually.
Do you think C should be included in the direct implementation list of I?
2. Find Type Parameter Usages
How should the results look like?
Do you think C should be included in the direct implementation list of I?
I don't think so, but it might be useful for some people, so perhaps this too can be enabled with an option. But my primary use case was just finding a few base types that implement interface directly instead of getting a hue list of 100s of types, most of which are derived.
How should the results look like?
That's an interesting question! For one thing all the actual types should be listed.
Perhaps it can be a "grouped/headered" list similar to how you display members from base classes for example, or members within regions on the NaviBar. So, each concrete type would be a header for the group and link to the type's definition. Then within each such group header (type) would be all the instances where the type is used as a parameter - these could be either types themselves or members.
Not sure about listing usages of locals though - it may be excessive, i.e. all the places where Foo<int> is declared within a method body for example.
How about if an interface I2 which derives from I, and a class D claims to be implementation of I2?
When we search for the direct implementations of I, shall we include D?
When we search for the direct implementations of I, shall we include D?
I think yes, because we are looking for all non-interface types that "directly" implement an interface. Although it might be made an option as well, via a key modifier.
Do you think C should be included in the direct implementation list of I?
I don't think so,
OK. This is much easier to implement.
When we search for the direct implementations of I, shall we include D?
I think yes, because we are looking for all non-interface types that "directly" implement an interface
Done. Please download the new beta.
You can press Ctrl to limit the result to direct implementations only. If you don't press the Ctrl, the result list will also has an icon of interface on the right side of an entry if the class directly implements the specific interface.
Note that the Ctrl limitation only works for interface types, not interface members. Roslyn only returns direct implementations for interface members. Thus we can't "limit" any more.
Thank you! This works great! You are so fast :)