/
StripUnusedSystemTypesPass.cs
105 lines (91 loc) · 3.57 KB
/
StripUnusedSystemTypesPass.cs
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.Collections.Generic;
using System.Linq;
using CppSharp.AST;
using CppSharp.AST.Extensions;
namespace CppSharp.Passes
{
public class StripUnusedSystemTypesPass : TranslationUnitPass
{
public StripUnusedSystemTypesPass()
{
VisitOptions.VisitClassBases = false;
VisitOptions.VisitClassMethods = false;
VisitOptions.VisitClassProperties = false;
VisitOptions.VisitEventParameters = false;
VisitOptions.VisitFunctionParameters = false;
VisitOptions.VisitFunctionReturnType = false;
VisitOptions.VisitNamespaceEnums = false;
VisitOptions.VisitNamespaceEvents = false;
VisitOptions.VisitNamespaceVariables = false;
VisitOptions.VisitTemplateArguments = false;
}
public override bool VisitASTContext(ASTContext context)
{
// we need this one for marshalling std::string
foreach (var name in new[] { "allocator", "char_traits" })
foreach (var usedStdType in context.FindClass(name, false, true).Where(
a => a.TranslationUnit.IsSystemHeader))
usedStdTypes.Add(usedStdType);
var result = base.VisitASTContext(context);
foreach (var unit in Options.SystemModule.Units)
RemoveUnusedStdTypes(unit);
return result;
}
public override bool VisitFieldDecl(Field field)
{
var desugared = field.Type.Desugar();
if (TryMarkType(desugared))
return true;
var arrayType = desugared as ArrayType;
return arrayType != null && TryMarkType(arrayType.Type.Desugar());
}
private bool TryMarkType(Type desugared)
{
var tagType = desugared as TagType;
if (tagType != null)
{
var specialization = tagType.Declaration as ClassTemplateSpecialization;
if (specialization != null)
{
MarkAsUsed(specialization.TemplatedDecl);
MarkAsUsed(specialization.TemplatedDecl.TemplatedDecl);
}
else
{
MarkAsUsed(tagType.Declaration);
}
return true;
}
var templateType = desugared as TemplateSpecializationType;
if (templateType != null)
{
MarkAsUsed(templateType.Template);
MarkAsUsed(templateType.Template.TemplatedDecl);
return true;
}
return false;
}
private void MarkAsUsed(Declaration declaration)
{
while (declaration != null && !(declaration is Namespace))
{
usedStdTypes.Add(declaration);
declaration = declaration.Namespace;
}
}
private void RemoveUnusedStdTypes(DeclarationContext context)
{
for (int i = context.Declarations.Count - 1; i >= 0; i--)
{
var declaration = context.Declarations[i];
var nestedContext = declaration as Namespace;
if (nestedContext != null)
RemoveUnusedStdTypes(nestedContext);
else if (!this.usedStdTypes.Contains(declaration) &&
!declaration.IsExplicitlyGenerated)
context.Declarations.RemoveAt(i);
}
}
private HashSet<Declaration> usedStdTypes = new HashSet<Declaration>();
}
}