-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVisibilityExtensions.cs
More file actions
178 lines (154 loc) · 6.47 KB
/
VisibilityExtensions.cs
File metadata and controls
178 lines (154 loc) · 6.47 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
using System;
using System.Collections.Generic;
using System.Text;
using dnlib.DotNet;
namespace AssemblyExposer.MSBuild.Task;
public static class VisibilityExtensions {
private static readonly Dictionary<IMemberDef, string> cache = new();
public static void ApplyRule(this IMemberDef def, RewriteRule rule) {
switch (def) {
case FieldDef fieldDef:
fieldDef.ApplyRule(rule);
break;
case MethodDef methodDef:
methodDef.ApplyRule(rule);
break;
case TypeDef typeDef:
typeDef.ApplyRule(rule);
break;
}
}
private static void ApplyRule(this TypeDef type, RewriteRule rule) {
var visibility = rule.Visibility switch {
VisibilityOption.Public => type.IsNested
? TypeAttributes.NestedPublic
: TypeAttributes.Public,
VisibilityOption.Protected => type.IsNested
? TypeAttributes.NestedFamily
: type.Attributes & TypeAttributes.VisibilityMask,
_ => throw new Exception("Invalid visibility value")
};
type.Attributes = (type.Attributes & ~TypeAttributes.VisibilityMask) | visibility;
}
private static void ApplyRule(this MethodDef method, RewriteRule rule) {
var visibility = rule.Visibility switch {
VisibilityOption.Public => MethodAttributes.Public,
VisibilityOption.Protected => MethodAttributes.Family,
_ => throw new Exception("Invalid visibility value")
};
method.Attributes = (method.Attributes & ~MethodAttributes.MemberAccessMask) | visibility;
}
private static void ApplyRule(this FieldDef field, RewriteRule rule) {
var visibility = rule.Visibility switch {
VisibilityOption.Public => FieldAttributes.Public,
VisibilityOption.Protected => FieldAttributes.Family,
_ => throw new Exception("Invalid visibility value")
};
field.Attributes = (field.Attributes & ~FieldAttributes.FieldAccessMask) | visibility;
}
public static string ExtendedName(this IMemberDef def) => def switch {
TypeDef typeDef => typeDef.ExtendedName(),
MethodDef methodDef => methodDef.ExtendedName(),
FieldDef fieldDef => fieldDef.ExtendedName(),
_ => throw new Exception("Unsupported definition")
};
private static string ExtendedName(this TypeDef def) {
if (cache.TryGetValue(def, out var name))
return name;
StringBuilder builder = new StringBuilder();
switch (def.Visibility) {
case TypeAttributes.NotPublic:
case TypeAttributes.NestedAssembly:
builder.Append("internal ");
break;
case TypeAttributes.NestedFamily:
builder.Append("protected ");
break;
case TypeAttributes.NestedFamORAssem:
builder.Append("protected internal ");
break;
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
builder.Append("public ");
break;
case TypeAttributes.NestedPrivate:
builder.Append("private ");
break;
}
var isInterface = (def.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface;
if (isInterface) {
builder.Append("interface ");
} else {
var isSealed = def.Attributes.HasFlag(TypeAttributes.Sealed);
if (def.Attributes.HasFlag(TypeAttributes.Abstract))
builder.Append(isSealed ? "static " : "abstract ");
else if (isSealed)
builder.Append("sealed ");
builder.Append("class ");
}
builder.Append(def.FullName);
return cache[def] = builder.ToString();
}
private static string ExtendedName(this MethodDef def) {
if (cache.TryGetValue(def, out var name))
return name;
StringBuilder builder = new StringBuilder();
switch (def.Access) {
case MethodAttributes.Private:
builder.Append("private ");
break;
case MethodAttributes.Assembly:
builder.Append("internal ");
break;
case MethodAttributes.Family:
builder.Append("protected ");
break;
case MethodAttributes.Public:
builder.Append("public ");
break;
case MethodAttributes.FamORAssem:
builder.Append("protected internal ");
break;
}
var isInterface = def.DeclaringType.Attributes.HasFlag(TypeAttributes.Interface);
var isFinal = def.Attributes.HasFlag(MethodAttributes.Final);
if (def.Attributes.HasFlag(MethodAttributes.Virtual) && !isInterface && !isFinal)
builder.Append(def.Attributes.HasFlag(MethodAttributes.NewSlot) ? "virtual " : "override ");
if (def.Attributes.HasFlag(MethodAttributes.Static))
builder.Append("static ");
if (def.Attributes.HasFlag(MethodAttributes.Abstract) && !isInterface)
builder.Append("abstract ");
builder.Append(def.FullName);
return cache[def] = builder.ToString();
}
private static string ExtendedName(this FieldDef def) {
if (cache.TryGetValue(def, out var name))
return name;
StringBuilder builder = new StringBuilder();
switch (def.Access) {
case FieldAttributes.Private:
builder.Append("private ");
break;
case FieldAttributes.Assembly:
builder.Append("internal ");
break;
case FieldAttributes.Family:
builder.Append("protected ");
break;
case FieldAttributes.Public:
builder.Append("public ");
break;
case FieldAttributes.FamORAssem:
builder.Append("protected internal ");
break;
}
if (def.Attributes.HasFlag(FieldAttributes.Static))
builder.Append("static ");
if (def.Attributes.HasFlag(FieldAttributes.InitOnly))
builder.Append("readonly ");
if (def.Attributes.HasFlag(FieldAttributes.Literal))
builder.Append("const ");
builder.Append(def.FullName);
return cache[def] = builder.ToString();
}
}