Skip to content

Commit 5eb74f2

Browse files
committed
tweak: use type aliases for uint/int
1 parent 49d4984 commit 5eb74f2

33 files changed

Lines changed: 877 additions & 270 deletions

src/NativeCodeGen.Core/Export/natives.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ enum ParamFlags {
88
PARAM_NONE = 0;
99
PARAM_OUTPUT = 1; // Pointer output parameter
1010
PARAM_THIS = 2; // @this - instance method receiver
11-
PARAM_NOTNULL = 4; // @notnull - string cannot be null
11+
PARAM_NULLABLE = 4; // @nullable - string can be null
1212
PARAM_IN = 8; // @in - input+output pointer
1313
}
1414

src/NativeCodeGen.Core/Generation/ArgumentBuilder.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public static class ArgumentBuilder
1717
/// - Output-only pointers: pass pointer placeholder
1818
/// - Input+output pointers (@in): pass initialized pointer
1919
/// </summary>
20-
public static string GetArgumentExpression(NativeParameter param, ITypeMapper typeMapper, LanguageConfig config, bool rawMode = false)
20+
public static string GetArgumentExpression(NativeParameter param, ITypeMapper typeMapper, LanguageConfig config, bool rawMode = false, string? mappedDefaultValue = null)
2121
{
2222
var f = config.FloatWrapperAlias;
2323
var h = config.HashWrapperAlias;
@@ -78,11 +78,29 @@ public static string GetArgumentExpression(NativeParameter param, ITypeMapper ty
7878
// Float type - wrap with f() to prevent bundler optimization
7979
if (param.Type.IsFloat)
8080
{
81-
return useFloat ? $"{f}({param.Name})" : param.Name;
81+
var expr = useFloat ? $"{f}({param.Name})" : param.Name;
82+
return WrapWithInlineDefault(expr, param.Name, mappedDefaultValue, config);
8283
}
8384

8485
// Regular value
85-
return param.Name;
86+
return WrapWithInlineDefault(param.Name, param.Name, mappedDefaultValue, config);
87+
}
88+
89+
/// <summary>
90+
/// Wraps an expression with inline default value check for Lua.
91+
/// Pattern: paramName == nil and defaultValue or expression
92+
/// </summary>
93+
private static string WrapWithInlineDefault(string expression, string paramName, string? mappedDefaultValue, LanguageConfig config)
94+
{
95+
if (!config.UseInlineDefaults || mappedDefaultValue == null)
96+
return expression;
97+
98+
// For simple param references, use: param == nil and default or param
99+
// For complex expressions (like f(param)), we need parentheses
100+
if (expression == paramName)
101+
return $"{paramName} == nil and {mappedDefaultValue} or {paramName}";
102+
103+
return $"({paramName} == nil and {mappedDefaultValue} or {expression})";
86104
}
87105

88106
/// <summary>

src/NativeCodeGen.Core/Generation/DocBuilder.cs

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ public abstract class DocBuilder
1111
protected readonly List<string> DescriptionLines = new();
1212
protected readonly List<DocParam> Params = new();
1313
protected readonly List<DocThrows> Throws = new();
14+
protected readonly List<string> SeeAlso = new();
15+
protected readonly List<DocExample> Examples = new();
1416
protected DocReturn? Return;
1517

1618
public DocBuilder AddDescription(string? description)
@@ -49,7 +51,53 @@ public DocBuilder AddReturn(string type, string? description = null)
4951
return this;
5052
}
5153

52-
public bool IsEmpty => DescriptionLines.Count == 0 && Params.Count == 0 && Throws.Count == 0 && Return == null;
54+
public DocBuilder AddSee(string reference)
55+
{
56+
SeeAlso.Add(reference);
57+
return this;
58+
}
59+
60+
public DocBuilder AddExample(string code, string language = "typescript")
61+
{
62+
Examples.Add(new DocExample(code, language));
63+
return this;
64+
}
65+
66+
/// <summary>
67+
/// Returns the preferred languages for examples in priority order.
68+
/// Override in language-specific builders.
69+
/// </summary>
70+
protected virtual string[] GetPreferredLanguages() => [];
71+
72+
/// <summary>
73+
/// Filters examples to prefer the target language.
74+
/// Returns examples matching the first preferred language that has any,
75+
/// or all examples if no preferred languages match.
76+
/// </summary>
77+
protected IEnumerable<DocExample> GetFilteredExamples()
78+
{
79+
if (Examples.Count == 0)
80+
return Examples;
81+
82+
var preferred = GetPreferredLanguages();
83+
if (preferred.Length == 0)
84+
return Examples;
85+
86+
// Try each preferred language in order
87+
foreach (var lang in preferred)
88+
{
89+
var matching = Examples.Where(e =>
90+
e.Language.Equals(lang, StringComparison.OrdinalIgnoreCase)).ToList();
91+
92+
if (matching.Count > 0)
93+
return matching;
94+
}
95+
96+
// No preferred match - return all examples
97+
return Examples;
98+
}
99+
100+
public bool IsEmpty => DescriptionLines.Count == 0 && Params.Count == 0 && Throws.Count == 0 && Return == null && SeeAlso.Count == 0 && Examples.Count == 0;
53101

54102
/// <summary>
55103
/// Renders the documentation to the CodeBuilder.
@@ -89,6 +137,8 @@ private static string EscapeJsDoc(string text)
89137
return text.Replace("*/", "*\\/");
90138
}
91139

140+
protected override string[] GetPreferredLanguages() => ["typescript", "ts", "javascript", "js"];
141+
92142
public override void Render(CodeBuilder cb)
93143
{
94144
if (IsEmpty) return;
@@ -121,6 +171,22 @@ public override void Render(CodeBuilder cb)
121171
cb.AppendLine($" * @returns{desc}");
122172
}
123173

174+
foreach (var see in SeeAlso)
175+
{
176+
cb.AppendLine($" * @see {{{see}}}");
177+
}
178+
179+
foreach (var example in GetFilteredExamples())
180+
{
181+
cb.AppendLine(" * @example");
182+
cb.AppendLine($" * ```{example.Language}");
183+
foreach (var line in example.Code.Split('\n'))
184+
{
185+
cb.AppendLine($" * {EscapeJsDoc(line)}");
186+
}
187+
cb.AppendLine(" * ```");
188+
}
189+
124190
cb.AppendLine(" */");
125191
}
126192
}
@@ -130,6 +196,8 @@ public override void Render(CodeBuilder cb)
130196
/// </summary>
131197
public class LuaDocBuilder : DocBuilder
132198
{
199+
protected override string[] GetPreferredLanguages() => ["lua"];
200+
133201
public override void Render(CodeBuilder cb)
134202
{
135203
foreach (var line in DescriptionLines)
@@ -148,6 +216,23 @@ public override void Render(CodeBuilder cb)
148216
var desc = string.IsNullOrEmpty(Return.Description) ? "" : $" {Return.Description}";
149217
cb.AppendLine($"---@return {Return.Type}{desc}");
150218
}
219+
220+
foreach (var see in SeeAlso)
221+
{
222+
cb.AppendLine($"---@see {see}");
223+
}
224+
225+
foreach (var example in GetFilteredExamples())
226+
{
227+
cb.AppendLine("---");
228+
cb.AppendLine("---Example:");
229+
cb.AppendLine("---```" + example.Language);
230+
foreach (var line in example.Code.Split('\n'))
231+
{
232+
cb.AppendLine($"---{line}");
233+
}
234+
cb.AppendLine("---```");
235+
}
151236
}
152237
}
153238

@@ -183,3 +268,4 @@ public override void Render(CodeBuilder cb)
183268
public record DocParam(string Name, string Type, string Description);
184269
public record DocReturn(string Type, string? Description);
185270
public record DocThrows(string Type, string Description);
271+
public record DocExample(string Code, string Language);

src/NativeCodeGen.Core/Generation/ILanguageEmitter.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ public interface ILanguageEmitter
3434
/// </summary>
3535
string SelfReference { get; }
3636

37+
/// <summary>
38+
/// Maps a default value from the native signature to the language's syntax.
39+
/// </summary>
40+
string MapDefaultValue(string value, TypeInfo type);
41+
3742
// === Enum Generation ===
3843

3944
/// <summary>
@@ -214,10 +219,12 @@ public enum MethodKind
214219
/// <summary>Getter property (parameterless method returning a value)</summary>
215220
Getter,
216221
/// <summary>Setter property (single-parameter void method)</summary>
217-
Setter
222+
Setter,
223+
/// <summary>Chainable setter method that returns this/self for fluent API</summary>
224+
ChainableSetter
218225
}
219226

220227
/// <summary>
221228
/// Represents a method parameter for emission.
222229
/// </summary>
223-
public record MethodParameter(string Name, string Type, bool IsOptional = false);
230+
public record MethodParameter(string Name, string Type, string? DefaultValue = null);

src/NativeCodeGen.Core/Generation/ITypeMapper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public interface ITypeMapper
1010
/// <summary>
1111
/// Maps a C type to the target language type.
1212
/// </summary>
13-
string MapType(TypeInfo type, bool isNotNull = false, bool forReturn = false);
13+
string MapType(TypeInfo type, bool isNullable = false, bool forReturn = false);
1414

1515
/// <summary>
1616
/// Gets the expression for marking a return type in native invocation.

src/NativeCodeGen.Core/Generation/NativeClassifier.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,7 @@ public ClassifiedNatives Classify(NativeDatabase db)
110110

111111
if (firstParam.IsThis && firstParam.Type.Category == TypeCategory.Handle)
112112
{
113-
var typeName = firstParam.Type.Name;
114-
return typeName == "Object" ? "Prop" : typeName;
113+
return TypeInfo.NormalizeHandleName(firstParam.Type.Name);
115114
}
116115

117116
if (firstParam.Type.Category == TypeCategory.Handle)
@@ -138,7 +137,7 @@ public ClassifiedNatives Classify(NativeDatabase db)
138137
{
139138
if (native.Namespace.Equals(expectedNs, StringComparison.OrdinalIgnoreCase))
140139
{
141-
return handleType == "Object" ? "Prop" : handleType;
140+
return TypeInfo.NormalizeHandleName(handleType);
142141
}
143142
}
144143

@@ -175,7 +174,7 @@ public ClassifiedNatives Classify(NativeDatabase db)
175174
_ => "Entity"
176175
};
177176

178-
public static string NormalizeHandleType(string typeName) => typeName == "Object" ? "Prop" : typeName;
177+
public static string NormalizeHandleType(string typeName) => TypeInfo.NormalizeHandleName(typeName);
179178
}
180179

181180
public class ClassifiedNatives

src/NativeCodeGen.Core/Generation/RawNativeBuilder.cs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,53 @@ public void EmitFunction(NativeDefinition native, BindingStyle binding, string?
138138
_cb.AppendLine();
139139
}
140140

141+
/// <summary>
142+
/// Emits a declaration-only function signature (for .d.ts files).
143+
/// Only supported for TypeScript.
144+
/// </summary>
145+
public void EmitDeclaration(NativeDefinition native, BindingStyle binding, string? nameOverride = null)
146+
{
147+
if (_lang != Language.TypeScript) return;
148+
149+
var name = nameOverride ?? GetFunctionName(native.Name);
150+
var inputParams = native.Parameters.Where(p => !p.IsPureOutput).ToList();
151+
var outputParams = native.Parameters.Where(p => p.IsPureOutput).ToList();
152+
153+
// Emit doc comment
154+
EmitDoc(native, inputParams, outputParams);
155+
156+
// Emit declaration
157+
var paramList = BuildParamList(inputParams);
158+
var returnType = BuildReturnType(native.ReturnType, outputParams);
159+
160+
switch (binding)
161+
{
162+
case BindingStyle.Export:
163+
_cb.AppendLine($"export declare function {name}({paramList}): {returnType};");
164+
break;
165+
case BindingStyle.Global:
166+
_cb.AppendLine($"declare function {name}({paramList}): {returnType};");
167+
break;
168+
case BindingStyle.Module:
169+
// Module declarations would need different handling
170+
_cb.AppendLine($"declare function {name}({paramList}): {returnType};");
171+
break;
172+
}
173+
_cb.AppendLine();
174+
}
175+
176+
/// <summary>
177+
/// Emits imports suitable for .d.ts files (type-only imports).
178+
/// </summary>
179+
public void EmitDeclarationImports(bool singleFile = false)
180+
{
181+
if (_lang != Language.TypeScript) return;
182+
183+
var prefix = singleFile ? "./" : "../";
184+
_cb.AppendLine($"import type {{ Vector3 }} from '{prefix}types/Vector3';");
185+
_cb.AppendLine();
186+
}
187+
141188
private static string GetFunctionName(string nativeName)
142189
{
143190
var normalized = NameConverter.NormalizeNativeName(nativeName);
@@ -200,8 +247,12 @@ private string BuildParamList(List<NativeParameter> inputParams)
200247
var parts = inputParams.Select(p =>
201248
{
202249
var type = MapParamType(p.Type);
203-
var opt = p.HasDefaultValue ? "?" : "";
204-
return $"{p.Name}{opt}: {type}";
250+
if (p.HasDefaultValue)
251+
{
252+
var defaultVal = MapDefaultValue(p.DefaultValue!, p.Type);
253+
return $"{p.Name}: {type} = {defaultVal}";
254+
}
255+
return $"{p.Name}: {type}";
205256
});
206257
return string.Join(", ", parts);
207258
}
@@ -211,6 +262,20 @@ private string BuildParamList(List<NativeParameter> inputParams)
211262
}
212263
}
213264

265+
private string MapDefaultValue(string value, TypeInfo type)
266+
{
267+
// Convert C-style boolean literals to TypeScript/Lua
268+
if (type.IsBool)
269+
{
270+
return value.Equals("true", StringComparison.OrdinalIgnoreCase) ||
271+
value.Equals("TRUE", StringComparison.OrdinalIgnoreCase) ||
272+
value == "1"
273+
? "true"
274+
: "false";
275+
}
276+
return value;
277+
}
278+
214279
private string BuildReturnType(TypeInfo returnType, List<NativeParameter> outputParams)
215280
{
216281
var types = new List<string>();

0 commit comments

Comments
 (0)