-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJitDisasmTargetUtils.cs
More file actions
105 lines (95 loc) · 3.99 KB
/
JitDisasmTargetUtils.cs
File metadata and controls
105 lines (95 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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;
}
}