src/dotnet/ReSharperPlugin.DotNetDisassembler/JitDisasm/JitDisasmTargetUtils.cs (92 lines of code) (raw):

using System; using JetBrains.Annotations; using JetBrains.ReSharper.Psi; using JetBrains.ReSharper.Psi.CSharp.DeclaredElements; using JetBrains.ReSharper.Psi.CSharp.Tree; using JetBrains.ReSharper.Psi.DataContext; using JetBrains.ReSharper.Psi.Tree; namespace ReSharperPlugin.DotNetDisassembler.JitDisasm; public static class JitDisasmTargetUtils { [CanBeNull] public static IDeclaration FindValidDeclaration(PsiEditorView editorView) { var psiView = editorView.DefaultSourceFile.ViewDominant(); var selectedNode = psiView.GetSelectedTreeNode<ITreeNode>(); return selectedNode?.GetContainingNode<IDeclaration>(returnThis: true, predicate: IsValidDisasmTarget); } [CanBeNull] public static IDeclaration FindValidDeclaration([CanBeNull] ITreeNode treeNode) { return treeNode?.GetContainingNode<IDeclaration>(returnThis: true, predicate: IsValidDisasmTarget); } public static DisasmTarget GetTarget(IDeclaredElement declaredElement) { string target; string hostType; string methodName; bool isGenericMethod = false; string prefix = ""; ITypeElement containingType = declaredElement as ITypeElement ?? (declaredElement as ITypeMember)?.ContainingType ?? (declaredElement as ITypeOwnerDeclaration)?.GetContainingTypeElement(); if (containingType is null) throw new Exception($"Unable to determine containing type for '{declaredElement.ShortName}' (type: {declaredElement.GetType().Name}). Make sure the method is inside a .NET Core/6+ project."); // match all for nested types if (containingType.GetContainingType() is not null) prefix = "*"; else if (containingType.GetContainingNamespace() is { } containingNamespace && !string.IsNullOrWhiteSpace(containingNamespace.QualifiedName)) prefix = containingNamespace.QualifiedName + "."; prefix += containingType.ShortName; switch (declaredElement) { case ILocalFunction: // hack for mangled names target = "*" + declaredElement.ShortName + "*"; methodName = "*"; hostType = containingType.ShortName; break; case IConstructor constructor: if (constructor.IsStatic) { target = prefix + ":.cctor"; methodName = ".cctor"; } else { target = prefix + ":.ctor"; methodName = "*"; } hostType = containingType.ShortName; break; case IFunction function: target = prefix + ":" + declaredElement.ShortName; methodName = declaredElement.ShortName; hostType = containingType.ShortName; isGenericMethod = function is ITypeParametersOwner { TypeParameters.Count: > 0 }; break; case IProperty: target = prefix + ":get_" + declaredElement.ShortName + " " + prefix + ":set_" + declaredElement.ShortName; hostType = containingType.ShortName; methodName = declaredElement.ShortName; break; default: // the whole class target = prefix + ":*"; hostType = containingType.ShortName; methodName = "*"; break; } return new DisasmTarget(target, hostType, methodName, isGenericMethod); } private static bool IsValidDisasmTarget(ITreeNode node) { return node is ICSharpFunctionDeclaration or IClassDeclaration or IStructDeclaration or IRecordDeclaration or ILocalFunctionDeclaration or IConstructorDeclaration or IPropertyDeclaration or IOperatorDeclaration or IMethodDeclaration; } }