Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Changelog
All notable changes to this project will be documented in this file.

## 26.09.04XX
- "Go to Handler" now also works with the caret anywhere inside a `mediator.Send(...)` /
`Publish(...)` call: the first argument's type is resolved, so there is no need to navigate to the
request declaration first.
- Raise the inheritor search cap from 50 to 300 so solutions with many handlers no longer have the
matching handler truncated away before it can be selected.

## 26.08.20XX
- Fix issue #117: updated SDK to 2026.2.

Expand Down
15 changes: 7 additions & 8 deletions src/dotnet/MediatorPlugin/Actions/GoToHandlerAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using JetBrains.TextControl;
using JetBrains.Util;
using ReSharper.MediatorPlugin.Diagnostics;
using ReSharper.MediatorPlugin.ReSharper.Psi.Tree;
using ReSharper.MediatorPlugin.Services.Find;
using ReSharper.MediatorPlugin.Services.Navigation;

Expand Down Expand Up @@ -81,14 +82,12 @@ protected override Action<ITextControl> ExecutePsiTransaction(ISolution solution
private static IIdentifier? GetSelectedMediatrRequest(LanguageIndependentContextActionDataProvider dataProvider)
{
var selectedTreeNode = dataProvider.GetSelectedTreeNode<ITreeNode>();

if (selectedTreeNode is IIdentifier identifier)
{
Logger.Instance.Log(LoggingLevel.VERBOSE, $"Selected tree node is an identifier: {identifier.Name}");
return identifier;
}

Logger.Instance.Log(LoggingLevel.VERBOSE, "Selected tree node is not an identifier");
return null;
IIdentifier? identifier = MediatorCallSite.ResolveRequestIdentifier(selectedTreeNode);

if (identifier is null)
Logger.Instance.Log(LoggingLevel.VERBOSE, "Selected tree node is not a Mediator request or dispatch call");

return identifier;
}
}
11 changes: 4 additions & 7 deletions src/dotnet/MediatorPlugin/Actions/GoToHandlerNavigationAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using JetBrains.ReSharper.Feature.Services.Navigation.ContextNavigation;
using JetBrains.ReSharper.Psi.Tree;
using ReSharper.MediatorPlugin.Diagnostics;
using ReSharper.MediatorPlugin.ReSharper.Psi.Tree;
using ReSharper.MediatorPlugin.Services.Find;
using ReSharper.MediatorPlugin.Services.Navigation;

Expand All @@ -23,7 +24,9 @@ public bool Update(IDataContext context, ActionPresentation presentation, Delega
{
var selectedTreeNode = context.GetSelectedTreeNode<ITreeNode>();

if (selectedTreeNode is not IIdentifier identifier)
IIdentifier? identifier = MediatorCallSite.ResolveRequestIdentifier(selectedTreeNode);

if (identifier is null)
return nextUpdate.Invoke();

return _handlerSelector.IsMediatorRequestSupported(identifier);
Expand All @@ -36,12 +39,6 @@ public void Execute(IDataContext context, DelegateExecute nextExecute)
var solution = context.GetComponent<ISolution>();
var selectedTreeNode = context.GetSelectedTreeNode<ITreeNode>();

if (selectedTreeNode is not IIdentifier)
{
Logger.Instance.Log(LoggingLevel.VERBOSE, "Selected element is not an identifier");
return;
}

_handlerSelector.NavigateToHandler
(
solution,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,12 @@ IDataContext dataContext
var solution = dataContext.GetComponent<ISolution>();
var selectedTreeNode = dataContext.GetSelectedTreeNode<ITreeNode>();

if (selectedTreeNode is not IIdentifier)
{
Logger.Instance.Log(LoggingLevel.VERBOSE, $"Selected element is not an instance {nameof(IIdentifier)}");
return;
}

_handlerSelector.NavigateToHandler
(
solution,
selectedTreeNode,
new DataContextNavigationOptionsFactory(dataContext)
);
);
}
)
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace ReSharper.MediatorPlugin.ReSharper.Psi.Search;

internal sealed class InheritorsConsumer : IFindResultConsumer<ITypeElement>
{
private const int MaxInheritors = 50;
private const int MaxInheritors = 300;

private readonly HashSet<ITypeElement> _elements = new();

Expand Down
81 changes: 81 additions & 0 deletions src/dotnet/MediatorPlugin/ReSharper/Psi/Tree/MediatorCallSite.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System.Linq;
using JetBrains.Diagnostics;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp;
using JetBrains.ReSharper.Psi.CSharp.Tree;
using JetBrains.ReSharper.Psi.Tree;
using JetBrains.ReSharper.Psi.Util;
using ReSharper.MediatorPlugin.Diagnostics;

namespace ReSharper.MediatorPlugin.ReSharper.Psi.Tree;

internal static class MediatorCallSite
{
public static IIdentifier? ResolveRequestIdentifier(ITreeNode? node)
{
if (node is null)
return null;

return ResolveFromEnclosingCall(node) ?? node as IIdentifier;
}

private static IIdentifier? ResolveFromEnclosingCall(ITreeNode node)
{
IInvocationExpression? invocation = node.GetContainingNode<IInvocationExpression>(returnThis: true);

if (invocation is null)
{
Logger.Instance.Log(LoggingLevel.VERBOSE, "> Caret is not inside an invocation expression");
return null;
}

foreach (ICSharpArgument argument in invocation.Arguments)
{
IIdentifier? identifier = ArgumentTypeDeclarationIdentifier(argument.Value);

if (identifier is not null)
return identifier;
}

Logger.Instance.Log(LoggingLevel.VERBOSE, $"> No invocation argument resolved to a navigable type declaration (method '{InvokedMethodName(invocation)}')");
return null;
}

private static IIdentifier? ArgumentTypeDeclarationIdentifier(ICSharpExpression? argumentValue)
{
ITypeElement? typeElement = ResolveTypeElement(argumentValue);

if (typeElement is null)
return null;

if (typeElement.GetDeclarations().FirstOrDefault() is not IClassLikeDeclaration declaration)
{
Logger.Instance.Log(LoggingLevel.VERBOSE, $"> Argument type '{typeElement.GetClrName().FullName}' has no source declaration to navigate from");
return null;
}

Logger.Instance.Log(LoggingLevel.VERBOSE, $"> Resolved invocation argument to type '{declaration.DeclaredName}'");
return declaration.NameIdentifier;
}

private static ITypeElement? ResolveTypeElement(ICSharpExpression? expression)
{
switch (expression)
{
case null:
return null;

case IObjectCreationExpression objectCreation
when objectCreation.TypeReference?.Resolve().DeclaredElement is ITypeElement created:
return created;

default:
return (expression.GetExpressionType().ToIType() as IDeclaredType)?.GetTypeElement();
}
}

private static string InvokedMethodName(IInvocationExpression invocation)
{
return (invocation.InvokedExpression as IReferenceExpression)?.Reference.GetName() ?? "<unknown>";
}
}
9 changes: 6 additions & 3 deletions src/dotnet/MediatorPlugin/Services/Find/HandlerSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using JetBrains.ReSharper.Psi.Tree;
using JetBrains.TextControl;
using ReSharper.MediatorPlugin.Diagnostics;
using ReSharper.MediatorPlugin.ReSharper.Psi.Tree;
using ReSharper.MediatorPlugin.Services.Libraries;
using ReSharper.MediatorPlugin.Services.Navigation;
using System.Collections.Generic;
Expand Down Expand Up @@ -34,13 +35,15 @@ IIdentifier identifier
public void NavigateToHandler
(
ISolution solution,
ITreeNode selectedTreeNode,
ITreeNode? selectedTreeNode,
INavigationOptionsFactory navigationOptionsFactory
)
{
if (selectedTreeNode is not IIdentifier selectedIdentifier)
IIdentifier? selectedIdentifier = MediatorCallSite.ResolveRequestIdentifier(selectedTreeNode);

if (selectedIdentifier is null)
{
Logger.Instance.Log(LoggingLevel.VERBOSE, $"Selected element is not an instance {nameof(IIdentifier)}");
Logger.Instance.Log(LoggingLevel.VERBOSE, "Selected element is not a Mediator request or dispatch call");
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ IIdentifier identifier
void NavigateToHandler
(
ISolution solution,
ITreeNode selectedTreeNode,
ITreeNode? selectedTreeNode,
INavigationOptionsFactory navigationOptionsFactory
);
}
Loading