Skip to content

Commit d01d7ae

Browse files
committed
Fix static class edge cases
1 parent 919eb7f commit d01d7ae

File tree

2 files changed

+28
-19
lines changed

2 files changed

+28
-19
lines changed

src/AST/Class.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,7 @@ public Class BaseClass
149149

150150
public bool HasNonIgnoredBase =>
151151
HasBaseClass && !IsValueType
152-
&& BaseClass != null
153-
&& !BaseClass.IsValueType
154-
&& BaseClass.IsGenerated;
152+
&& BaseClass is { IsValueType: false, IsGenerated: true };
155153

156154
public bool NeedsBase => HasNonIgnoredBase && IsGenerated;
157155

src/Generator/Passes/CheckStaticClassPass.cs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ static bool IsProtectedClassMember(Declaration decl)
3232
if (decl.Access != AccessSpecifier.Protected)
3333
return false;
3434

35-
var @class = decl.Namespace as Class;
36-
return @class != null && @class.IsStatic;
35+
return decl.Namespace is Class { IsStatic: true };
3736
}
3837

3938
static void SetDeclarationAccessToPrivate(Declaration decl)
@@ -42,7 +41,7 @@ static void SetDeclarationAccessToPrivate(Declaration decl)
4241
// as an internal in the final C# wrapper.
4342
decl.Access = AccessSpecifier.Private;
4443

45-
// We need to explicity set the generation else the
44+
// We need to explicitly set the generation else the
4645
// now private declaration will get filtered out later.
4746
decl.GenerationKind = GenerationKind.Generate;
4847
}
@@ -51,20 +50,34 @@ static bool ReturnsClassInstance(Function function)
5150
{
5251
var returnType = function.ReturnType.Type.Desugar();
5352

54-
var tag = returnType as TagType;
55-
if (tag == null)
53+
if (returnType is not TagType tag)
5654
returnType.IsPointerTo(out tag);
5755

58-
if (tag == null)
56+
var decl = tag?.Declaration;
57+
if (decl is not Class)
5958
return false;
6059

6160
var @class = (Class)function.Namespace;
62-
var decl = tag.Declaration;
61+
return @class.QualifiedOriginalName == decl.QualifiedOriginalName;
62+
}
6363

64-
if (!(decl is Class))
65-
return false;
64+
static bool AcceptsClassInstance(Function function)
65+
{
66+
return function.Parameters.Any(param =>
67+
{
68+
var paramType = param.Type.Desugar();
6669

67-
return @class.QualifiedOriginalName == decl.QualifiedOriginalName;
70+
if (paramType is not TagType tag)
71+
paramType.IsPointerTo(out tag);
72+
73+
var decl = tag?.Declaration;
74+
if (decl is not Class)
75+
return false;
76+
77+
var @class = (Class)function.Namespace;
78+
return @class.QualifiedOriginalName == decl.QualifiedOriginalName;
79+
}
80+
);
6881
}
6982

7083
public override bool VisitClassDecl(Class @class)
@@ -117,12 +130,10 @@ public override bool VisitClassDecl(Class @class)
117130
return false;
118131
}
119132

120-
// Check for any static function that return a pointer to the class.
121-
// If one exists, we assume it's a factory function and the class is
122-
// not meant to be static. It's a simple heuristic, but it should be
123-
// good enough for the time being.
124-
if (@class.Functions.Any(m => !m.IsOperator && ReturnsClassInstance(m)) ||
125-
@class.Methods.Any(m => !m.IsOperator && ReturnsClassInstance(m)))
133+
// Check for any static function that accepts/returns a pointer to the class.
134+
// If one exists, we assume it's not meant to be static
135+
if (@class.Functions.Any(m => !m.IsOperator && (ReturnsClassInstance(m) || AcceptsClassInstance(m))) ||
136+
@class.Methods.Any(m => !m.IsOperator && !m.IsConstructor && (ReturnsClassInstance(m) || AcceptsClassInstance(m))))
126137
return false;
127138

128139
// TODO: We should take C++ friends into account here, they might allow

0 commit comments

Comments
 (0)