mirror of https://github.com/mono/CppSharp.git
12 changed files with 853 additions and 3 deletions
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic; |
||||
using CppSharp.AST; |
||||
using CppSharp.Generators.C; |
||||
using CppSharp.Passes; |
||||
|
||||
namespace CppSharp.Generators.TS |
||||
{ |
||||
/// <summary>
|
||||
/// C++ generator responsible for driving the generation of source and
|
||||
/// header files.
|
||||
/// </summary>
|
||||
public class TSGenerator : CGenerator |
||||
{ |
||||
private readonly TSTypePrinter typePrinter; |
||||
|
||||
public TSGenerator(BindingContext context) : base(context) |
||||
{ |
||||
typePrinter = new TSTypePrinter(Context); |
||||
} |
||||
|
||||
public override List<CodeGenerator> Generate(IEnumerable<TranslationUnit> units) |
||||
{ |
||||
var outputs = new List<CodeGenerator>(); |
||||
|
||||
var header = new TSSources(Context, units); |
||||
outputs.Add(header); |
||||
|
||||
return outputs; |
||||
} |
||||
|
||||
public override bool SetupPasses() |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
protected override string TypePrinterDelegate(Type type) |
||||
{ |
||||
return type.Visit(typePrinter).ToString(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,505 @@
@@ -0,0 +1,505 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using CppSharp.AST; |
||||
using CppSharp.AST.Extensions; |
||||
using CppSharp.Generators.C; |
||||
using CppSharp.Generators.CLI; |
||||
|
||||
namespace CppSharp.Generators.TS |
||||
{ |
||||
/// <summary>
|
||||
/// Generates TypeScript interface files.
|
||||
/// </summary>
|
||||
public class TSSources : CCodeGenerator |
||||
{ |
||||
public TSSources(BindingContext context, IEnumerable<TranslationUnit> units) |
||||
: base(context, units) |
||||
{ |
||||
typePrinter = new TSTypePrinter(Context); |
||||
} |
||||
|
||||
public override string FileExtension => "d.ts"; |
||||
|
||||
public override bool GenerateSemicolonAsDeclarationTerminator => false; |
||||
|
||||
public virtual bool GenerateNamespaces => true; |
||||
|
||||
public virtual bool GenerateSelectiveImports => false; |
||||
|
||||
public override void Process() |
||||
{ |
||||
GenerateFilePreamble(CommentKind.BCPL); |
||||
|
||||
if (GenerateSelectiveImports) |
||||
GenerateImports(); |
||||
else |
||||
GenerateWildcardImports(); |
||||
|
||||
GenerateMain(); |
||||
} |
||||
|
||||
public virtual void GenerateMain() |
||||
{ |
||||
VisitTranslationUnit(TranslationUnit); |
||||
} |
||||
|
||||
public virtual Dictionary<TranslationUnit, List<Declaration>> ComputeExternalReferences() |
||||
{ |
||||
var typeReferenceCollector = new CLITypeReferenceCollector(Context.TypeMaps, |
||||
Context.Options); |
||||
typeReferenceCollector.Process(TranslationUnit); |
||||
|
||||
var typeReferences = typeReferenceCollector.TypeReferences; |
||||
var imports = new Dictionary<TranslationUnit, List<Declaration>>(); |
||||
|
||||
foreach (var typeRef in typeReferences) |
||||
{ |
||||
if (typeRef.Include.TranslationUnit == TranslationUnit) |
||||
continue; |
||||
|
||||
if (typeRef.Include.File == TranslationUnit.FileName) |
||||
continue; |
||||
|
||||
var include = typeRef.Include; |
||||
var typeRefUnit = include.TranslationUnit; |
||||
|
||||
if (typeRefUnit != null && !typeRefUnit.IsDeclared) |
||||
continue; |
||||
|
||||
if (!imports.ContainsKey(typeRefUnit)) |
||||
imports[typeRefUnit] = new List<Declaration>(); |
||||
|
||||
imports[typeRefUnit].Add(typeRef.Declaration); |
||||
} |
||||
|
||||
return imports; |
||||
} |
||||
|
||||
public virtual bool NeedsExternalImports() |
||||
{ |
||||
var imports = ComputeExternalReferences(); |
||||
return imports.Keys.Count > 0; |
||||
} |
||||
|
||||
public virtual void GenerateWildcardImports() |
||||
{ |
||||
if (!NeedsExternalImports()) |
||||
return; |
||||
|
||||
foreach (var module in Options.Modules) |
||||
{ |
||||
if (module == Options.SystemModule) |
||||
continue; |
||||
|
||||
WriteLine($"import * as {module.LibraryName} from \"{module.LibraryName}\";"); |
||||
} |
||||
} |
||||
|
||||
public virtual void GenerateImports() |
||||
{ |
||||
PushBlock(BlockKind.ForwardReferences); |
||||
|
||||
var imports = ComputeExternalReferences(); |
||||
|
||||
foreach (var unit in imports) |
||||
{ |
||||
string unitName = unit.Key.FileNameWithoutExtension; |
||||
if (Options.GenerateName != null) |
||||
unitName = Options.GenerateName(unit.Key); |
||||
|
||||
var names = string.Join(", ", unit.Value.Select(d => d.Name)); |
||||
WriteLine($"import {{{names}}} from \"{unitName}\";"); |
||||
} |
||||
|
||||
PopBlock(NewLineKind.BeforeNextBlock); |
||||
} |
||||
|
||||
public override bool VisitNamespace(Namespace @namespace) |
||||
{ |
||||
var isTopLevel = @namespace is TranslationUnit; |
||||
var generateNamespace = GenerateNamespaces; |
||||
|
||||
if (generateNamespace) |
||||
{ |
||||
PushBlock(BlockKind.Namespace, @namespace); |
||||
WriteLine(isTopLevel |
||||
? $"declare module \"{@namespace.TranslationUnit.Module.LibraryName}\"" |
||||
: $"namespace {@namespace.Name}"); |
||||
WriteOpenBraceAndIndent(); |
||||
} |
||||
|
||||
VisitDeclContext(@namespace); |
||||
|
||||
if (generateNamespace) |
||||
{ |
||||
UnindentAndWriteCloseBrace(); |
||||
PopBlock(NewLineKind.BeforeNextBlock); |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public override bool VisitClassDecl(Class @class) |
||||
{ |
||||
if (!@class.IsGenerated || @class.IsIncomplete) |
||||
return false; |
||||
|
||||
//if (@class.IsOpaque)
|
||||
// return false;
|
||||
|
||||
PushBlock(BlockKind.Class, @class); |
||||
|
||||
GenerateDeclarationCommon(@class); |
||||
|
||||
GenerateClassSpecifier(@class); |
||||
|
||||
if (@class.IsOpaque) |
||||
{ |
||||
WriteLine(";"); |
||||
return false; |
||||
} |
||||
|
||||
NewLine(); |
||||
WriteLine("{"); |
||||
NewLine(); |
||||
|
||||
// Process the nested types.
|
||||
Indent(); |
||||
VisitDeclContext(@class); |
||||
Unindent(); |
||||
|
||||
GenerateClassConstructors(@class); |
||||
GenerateClassProperties(@class); |
||||
GenerateClassEvents(@class); |
||||
GenerateClassMethods(@class.Methods); |
||||
|
||||
GenerateClassVariables(@class); |
||||
|
||||
PushBlock(BlockKind.Fields); |
||||
GenerateClassFields(@class); |
||||
PopBlock(); |
||||
|
||||
WriteLine("}"); |
||||
|
||||
PopBlock(NewLineKind.BeforeNextBlock); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public void GenerateClassConstructors(Class @class) |
||||
{ |
||||
if (@class.IsStatic) |
||||
return; |
||||
|
||||
Indent(); |
||||
|
||||
var classNativeName = @class.Visit(CTypePrinter); |
||||
|
||||
foreach (var ctor in @class.Constructors) |
||||
{ |
||||
if (ASTUtils.CheckIgnoreMethod(ctor) || FunctionIgnored(ctor)) |
||||
continue; |
||||
|
||||
ctor.Visit(this); |
||||
} |
||||
|
||||
Unindent(); |
||||
} |
||||
|
||||
public void GenerateClassFields(Class @class) |
||||
{ |
||||
// Handle the case of struct (value-type) inheritance by adding the base
|
||||
// properties to the managed value subtypes.
|
||||
if (@class.IsValueType) |
||||
{ |
||||
foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class.IsDeclared)) |
||||
{ |
||||
GenerateClassFields(@base.Class); |
||||
} |
||||
} |
||||
|
||||
Indent(); |
||||
// check for value types because some of the ignored fields may back properties;
|
||||
// not the case for ref types because the NativePtr pattern is used there
|
||||
foreach (var field in @class.Fields.Where(f => !ASTUtils.CheckIgnoreField(f))) |
||||
{ |
||||
var property = @class.Properties.FirstOrDefault(p => p.Field == field); |
||||
if (property != null && !property.IsInRefTypeAndBackedByValueClassField()) |
||||
{ |
||||
field.Visit(this); |
||||
} |
||||
} |
||||
Unindent(); |
||||
} |
||||
|
||||
public void GenerateClassMethods(List<Method> methods) |
||||
{ |
||||
if (methods.Count == 0) |
||||
return; |
||||
|
||||
Indent(); |
||||
|
||||
var @class = (Class) methods[0].Namespace; |
||||
|
||||
if (@class.IsValueType) |
||||
foreach (var @base in @class.Bases.Where(b => b.IsClass && !b.Class.Ignore)) |
||||
GenerateClassMethods(@base.Class.Methods.Where(m => !m.IsOperator).ToList()); |
||||
|
||||
var staticMethods = new List<Method>(); |
||||
foreach (var method in methods) |
||||
{ |
||||
if (ASTUtils.CheckIgnoreMethod(method) || FunctionIgnored(method)) |
||||
continue; |
||||
|
||||
if (method.IsConstructor) |
||||
continue; |
||||
|
||||
if (method.IsOperator) |
||||
continue; |
||||
|
||||
if (method.IsStatic) |
||||
{ |
||||
staticMethods.Add(method); |
||||
continue; |
||||
} |
||||
|
||||
method.Visit(this); |
||||
} |
||||
|
||||
foreach(var method in staticMethods) |
||||
method.Visit(this); |
||||
|
||||
Unindent(); |
||||
} |
||||
|
||||
public void GenerateClassVariables(Class @class) |
||||
{ |
||||
foreach (var variable in @class.Variables) |
||||
{ |
||||
if (!variable.IsGenerated) continue; |
||||
variable.Visit(this); |
||||
} |
||||
} |
||||
|
||||
public static string GetClassTemplateParameters(Class @class) |
||||
{ |
||||
var @params = @class.TemplateParameters.OfType<TypeTemplateParameter>().Select( |
||||
p => !string.IsNullOrEmpty(p.Constraint) ? $"{p.Name} extends {p.Constraint}" : p.Name); |
||||
|
||||
return $"<{string.Join(", ", @params)}>"; |
||||
} |
||||
|
||||
public string GetBaseClassTemplateParameters(BaseClassSpecifier baseClassSpec) |
||||
{ |
||||
if (!(baseClassSpec.Type is TemplateSpecializationType templateSpecType)) |
||||
throw new NotSupportedException(); |
||||
|
||||
var args = templateSpecType.Arguments.Select(arg => |
||||
{ |
||||
arg.Type.Type.TryGetClass(out var @class); |
||||
return @class; |
||||
}); |
||||
|
||||
return $"<{string.Join(", ", args.Select(c => c.Name))}>"; |
||||
} |
||||
|
||||
public override void GenerateClassSpecifier(Class @class) |
||||
{ |
||||
if (@class.IsAbstract) |
||||
Write("abstract "); |
||||
|
||||
Write(@class.IsInterface ? "interface" : "class"); |
||||
Write($" {@class.Name}"); |
||||
if (@class.IsDependent) |
||||
Write(GetClassTemplateParameters(@class)); |
||||
|
||||
if (!@class.IsStatic && @class.HasNonIgnoredBase) |
||||
{ |
||||
var baseClassSpec = @class.Bases.First(bs => bs.Class == @class.BaseClass); |
||||
var baseClass = baseClassSpec.Class; |
||||
var needsQualifiedName = baseClass.TranslationUnit != @class.TranslationUnit; |
||||
var baseClassName = needsQualifiedName ? QualifiedIdentifier(baseClass) : baseClass.Name; |
||||
|
||||
Write($" extends {baseClassName}"); |
||||
if (baseClass.IsDependent) |
||||
Write($"{GetBaseClassTemplateParameters(baseClassSpec)}"); |
||||
} |
||||
} |
||||
|
||||
public void GenerateClassProperties(Class @class) |
||||
{ |
||||
// Handle the case of struct (value-type) inheritance by adding the base
|
||||
// properties to the managed value subtypes.
|
||||
if (@class.IsValueType) |
||||
{ |
||||
foreach (var @base in @class.Bases.Where(b => b.IsClass && b.Class.IsDeclared)) |
||||
{ |
||||
GenerateClassProperties(@base.Class); |
||||
} |
||||
} |
||||
|
||||
Indent(); |
||||
foreach (var prop in @class.Properties.Where( |
||||
prop => !ASTUtils.CheckIgnoreProperty(prop) && !TypeIgnored(prop.Type))) |
||||
{ |
||||
if (prop.IsInRefTypeAndBackedByValueClassField()) |
||||
{ |
||||
prop.Field.Visit(this); |
||||
continue; |
||||
} |
||||
|
||||
prop.Visit(this); |
||||
} |
||||
Unindent(); |
||||
} |
||||
|
||||
public virtual void GenerateIndexer(Property property) |
||||
{ |
||||
throw new System.NotImplementedException(); |
||||
} |
||||
|
||||
public override string GenerateEnumSpecifier(Enumeration @enum) |
||||
{ |
||||
Write($"enum {@enum.Name}"); |
||||
return @enum.Name; |
||||
} |
||||
|
||||
public override bool VisitFieldDecl(Field field) |
||||
{ |
||||
PushBlock(BlockKind.Field, field); |
||||
|
||||
GenerateDeclarationCommon(field); |
||||
|
||||
var fieldType = field.Type.Visit(CTypePrinter); |
||||
WriteLine($"{fieldType} {field.Name};"); |
||||
|
||||
PopBlock(); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public override bool VisitEvent(Event @event) |
||||
{ |
||||
PushBlock(BlockKind.Event, @event); |
||||
|
||||
GenerateDeclarationCommon(@event); |
||||
|
||||
//WriteLine($"{@event.Name}: CppSharp.Signal;");
|
||||
|
||||
PopBlock(NewLineKind.BeforeNextBlock); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public override bool VisitProperty(Property property) |
||||
{ |
||||
GenerateDeclarationCommon(property); |
||||
|
||||
return base.VisitProperty(property); |
||||
} |
||||
|
||||
public override bool VisitMethodDecl(Method method) |
||||
{ |
||||
if (ASTUtils.CheckIgnoreMethod(method) || FunctionIgnored(method)) |
||||
return false; |
||||
|
||||
PushBlock(BlockKind.Method, method); |
||||
GenerateDeclarationCommon(method); |
||||
|
||||
GenerateMethodSpecifier(method); |
||||
WriteLine(";"); |
||||
|
||||
PopBlock(NewLineKind.BeforeNextBlock); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public override void GenerateMethodSpecifier(Method method, MethodSpecifierKind? kind = null) |
||||
{ |
||||
if (method.IsConstructor || method.IsDestructor || |
||||
method.OperatorKind == CXXOperatorKind.Conversion || |
||||
method.OperatorKind == CXXOperatorKind.ExplicitConversion) |
||||
{ |
||||
Write($"{GetMethodIdentifier(method)}("); |
||||
GenerateMethodParameters(method); |
||||
Write($")"); |
||||
return; |
||||
} |
||||
|
||||
Write($"{GetMethodIdentifier(method)}("); |
||||
GenerateMethodParameters(method); |
||||
|
||||
var returnType = method.ReturnType.Visit(CTypePrinter); |
||||
Write($"): {returnType}"); |
||||
} |
||||
|
||||
public override string GetMethodIdentifier(Function function, |
||||
TypePrinterContextKind context = TypePrinterContextKind.Managed) |
||||
{ |
||||
if (function is Method method) |
||||
{ |
||||
if (method.IsConstructor) |
||||
return "constructor"; |
||||
} |
||||
|
||||
return base.GetMethodIdentifier(function, context); |
||||
} |
||||
|
||||
public override bool VisitTypedefNameDecl(TypedefNameDecl typedef) |
||||
{ |
||||
if (!typedef.IsGenerated) |
||||
return false; |
||||
|
||||
var functionType = typedef.Type as FunctionType; |
||||
if (functionType != null || typedef.Type.IsPointerTo(out functionType)) |
||||
{ |
||||
PushBlock(BlockKind.Typedef, typedef); |
||||
GenerateDeclarationCommon(typedef); |
||||
|
||||
var @delegate = string.Format(CTypePrinter.VisitDelegate(functionType), typedef.Name); |
||||
WriteLine($"{@delegate};"); |
||||
|
||||
PopBlock(NewLineKind.BeforeNextBlock); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public override bool VisitFunctionDecl(Function function) |
||||
{ |
||||
if (!function.IsGenerated || FunctionIgnored(function)) |
||||
return false; |
||||
|
||||
PushBlock(BlockKind.Function, function); |
||||
|
||||
GenerateDeclarationCommon(function); |
||||
|
||||
var retType = function.ReturnType.Visit(CTypePrinter); |
||||
Write($"export function {function.Name}("); |
||||
|
||||
GenerateMethodParameters(function); |
||||
WriteLine($"): {retType};"); |
||||
|
||||
PopBlock(); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
public static bool FunctionIgnored(Function function) |
||||
{ |
||||
return TypeIgnored(function.ReturnType.Type) || |
||||
function.Parameters.Any(param => TypeIgnored(param.Type)); |
||||
} |
||||
|
||||
public static bool TypeIgnored(CppSharp.AST.Type type) |
||||
{ |
||||
var desugared = type.Desugar(); |
||||
var finalType = (desugared.GetFinalPointee() ?? desugared).Desugar(); |
||||
Class @class; |
||||
return finalType.TryGetClass(out @class) && (@class.CompleteDeclaration == null && @class.IsIncomplete); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,166 @@
@@ -0,0 +1,166 @@
|
||||
using System; |
||||
using System.Linq; |
||||
using CppSharp.AST; |
||||
using CppSharp.AST.Extensions; |
||||
using CppSharp.Generators.C; |
||||
|
||||
namespace CppSharp.Generators.TS |
||||
{ |
||||
public class TSTypePrinter : CppTypePrinter |
||||
{ |
||||
public override string NamespaceSeparator => "."; |
||||
|
||||
public override bool HasGlobalNamespacePrefix => false; |
||||
|
||||
public override bool PrefixSpecialFunctions => true; |
||||
|
||||
public TSTypePrinter(BindingContext context) : base(context) |
||||
{ |
||||
PrintTypeModifiers = false; |
||||
} |
||||
|
||||
public override string GlobalNamespace(Declaration declaration) |
||||
{ |
||||
return declaration.TranslationUnit?.Module?.LibraryName; |
||||
} |
||||
|
||||
public override TypePrinterResult GetDeclName(Declaration declaration, TypePrintScopeKind scope) |
||||
{ |
||||
var result = base.GetDeclName(declaration, scope); |
||||
result.Type = result.Type.Replace("::", NamespaceSeparator); |
||||
return result; |
||||
} |
||||
|
||||
public override TypePrinterResult VisitArrayType(ArrayType array, TypeQualifiers quals) |
||||
{ |
||||
return $"{array.Type.Visit(this)}[]"; |
||||
} |
||||
|
||||
public override TypePrinterResult VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) |
||||
{ |
||||
return VisitPrimitiveType(builtin.Type); |
||||
} |
||||
|
||||
public override TypePrinterResult VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers quals) |
||||
{ |
||||
return VisitPrimitiveType(primitive); |
||||
} |
||||
|
||||
public override TypePrinterResult VisitTypedefType(TypedefType typedef, TypeQualifiers quals) |
||||
{ |
||||
if (typedef.Declaration.QualifiedOriginalName == "std::nullptr_t") |
||||
return VisitPrimitiveType(PrimitiveType.Null); |
||||
|
||||
if (typedef.Declaration.Type.IsPrimitiveType()) |
||||
return typedef.Declaration.Type.Visit(this); |
||||
|
||||
return base.VisitTypedefType(typedef, quals); |
||||
} |
||||
|
||||
public override TypePrinterResult VisitPrimitiveType(PrimitiveType primitive) |
||||
{ |
||||
switch (primitive) |
||||
{ |
||||
case PrimitiveType.Bool: |
||||
return "boolean"; |
||||
case PrimitiveType.Void: |
||||
return "void"; |
||||
case PrimitiveType.Char16: |
||||
case PrimitiveType.Char32: |
||||
case PrimitiveType.WideChar: |
||||
case PrimitiveType.Char: |
||||
case PrimitiveType.SChar: |
||||
case PrimitiveType.UChar: |
||||
case PrimitiveType.Short: |
||||
case PrimitiveType.UShort: |
||||
case PrimitiveType.Int: |
||||
case PrimitiveType.UInt: |
||||
case PrimitiveType.Long: |
||||
case PrimitiveType.ULong: |
||||
case PrimitiveType.LongLong: |
||||
return "number"; |
||||
case PrimitiveType.ULongLong: |
||||
return "bigint"; |
||||
case PrimitiveType.Half: |
||||
case PrimitiveType.Float: |
||||
case PrimitiveType.Double: |
||||
return "number"; |
||||
case PrimitiveType.LongDouble: |
||||
case PrimitiveType.Float128: |
||||
case PrimitiveType.Int128: |
||||
case PrimitiveType.UInt128: |
||||
case PrimitiveType.IntPtr: |
||||
case PrimitiveType.UIntPtr: |
||||
case PrimitiveType.Null: |
||||
return "null"; |
||||
case PrimitiveType.String: |
||||
return "string"; |
||||
case PrimitiveType.Decimal: |
||||
return "number"; |
||||
} |
||||
|
||||
throw new NotSupportedException(); |
||||
} |
||||
|
||||
public override TypePrinterResult VisitPointerType(PointerType pointer, TypeQualifiers quals) |
||||
{ |
||||
if (pointer.IsConstCharString()) |
||||
return VisitPrimitiveType(PrimitiveType.String); |
||||
|
||||
return base.VisitPointerType(pointer, quals); |
||||
} |
||||
|
||||
public override TypePrinterResult VisitTagType(TagType tag, TypeQualifiers quals) |
||||
{ |
||||
if (FindTypeMap(tag, out var result)) |
||||
return result; |
||||
|
||||
return tag.Declaration.Visit(this); |
||||
} |
||||
|
||||
public override TypePrinterResult VisitTemplateSpecializationType(TemplateSpecializationType template, |
||||
TypeQualifiers quals) |
||||
{ |
||||
if (!template.Desugared.Type.TryGetClass(out var @class)) |
||||
return string.Empty; |
||||
|
||||
var args = template.Arguments.Select(a => a.Type.Visit(this)); |
||||
return $"{@class.Visit(this)}<{string.Join(", ", args)}>"; |
||||
} |
||||
|
||||
public override TypePrinterResult VisitParameter(Parameter param, bool hasName = true) |
||||
{ |
||||
var oldParam = Parameter; |
||||
Parameter = param; |
||||
var result = param.QualifiedType.Visit(this); |
||||
result.Kind = GeneratorKind.TypeScript; |
||||
Parameter = oldParam; |
||||
|
||||
var printName = hasName && !string.IsNullOrEmpty(param.Name); |
||||
if (!printName) |
||||
return result; |
||||
|
||||
result.Name = param.Name; |
||||
|
||||
/* |
||||
if (param.DefaultArgument != null && Options.GenerateDefaultValuesForArguments) |
||||
{ |
||||
try |
||||
{ |
||||
var expressionPrinter = new CSharpExpressionPrinter(this); |
||||
var defaultValue = expressionPrinter.VisitParameter(param); |
||||
return $"{result} = {defaultValue}"; |
||||
} |
||||
catch (Exception) |
||||
{ |
||||
var function = param.Namespace as Function; |
||||
Diagnostics.Warning($"Error printing default argument expression: " + |
||||
$"{function.QualifiedOriginalName}({param.OriginalName})"); |
||||
} |
||||
} |
||||
*/ |
||||
|
||||
return $"{result}"; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash |
||||
set -e |
||||
dir=$(cd "$(dirname "$0")"; pwd) |
||||
rootdir="$dir/../.." |
||||
dotnet_configuration=Release |
||||
configuration=debug |
||||
platform=x64 |
||||
jsinterp="$rootdir/deps/quickjs/qjs-debug" |
||||
|
||||
red=`tput setaf 1` |
||||
green=`tput setaf 2` |
||||
reset=`tput sgr0` |
||||
|
||||
generate=true |
||||
|
||||
if [ $generate = true ]; then |
||||
echo "${green}Generating bindings${reset}" |
||||
dotnet $rootdir/bin/${dotnet_configuration}_${platform}/CppSharp.CLI.dll \ |
||||
--gen=ts -I$dir/.. -I$rootdir/include -o $dir/gen -m tests $dir/../*.h |
||||
fi |
||||
|
||||
echo "${green}Building generated binding files${reset}" |
||||
#make -C $dir/gen |
||||
echo |
||||
|
||||
echo "${green}Typechecking generated binding files with tsc${reset}" |
||||
#tsc --noEmit --strict --noImplicitAny --strictNullChecks --strictFunctionTypes --noImplicitThis gen/*.d.ts |
||||
|
||||
# echo "${green}Executing JS tests with QuickJS${reset}" |
||||
# cp $dir/gen/bin/$configuration/libtest.so $dir |
||||
# #cp $dir/gen/bin/$configuration/libtest.dylib $dir |
||||
# $jsinterp --std $dir/test.js |
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
import * as test from "tests"; |
||||
|
||||
|
||||
function builtins() |
||||
{ |
||||
eq(test.ReturnsVoid(), undefined) |
||||
|
||||
eq(test.ReturnsBool(), true) |
||||
eq(test.PassAndReturnsBool(false), false) |
||||
|
||||
eq(test.ReturnsNullptr(), null) |
||||
//eq(test.PassAndReturnsNullptr(null), null)
|
||||
eq(test.ReturnsNullptr(), null) |
||||
|
||||
eq(test.ReturnsChar (), ascii('a')); |
||||
eq(test.ReturnsSChar(), ascii('a')); |
||||
eq(test.ReturnsUChar(), ascii('a')); |
||||
|
||||
eq(test.PassAndReturnsChar (ascii('a')), ascii('a')); |
||||
eq(test.PassAndReturnsSChar(ascii('b')), ascii('b')); |
||||
eq(test.PassAndReturnsUChar(ascii('c')), ascii('c')); |
||||
|
||||
// TODO: add wchar_t tests
|
||||
|
||||
eq(test.ReturnsFloat (), 5.0); |
||||
eq(test.ReturnsDouble(), -5.0); |
||||
//eq(test.ReturnsLongDouble(), -5.0);
|
||||
|
||||
//floateq(test.PassAndReturnsFloat (1.32), 1.32);
|
||||
floateq(test.PassAndReturnsDouble(1.32), 1.32); |
||||
//float(test.PassAndReturnsLongDouble(1.32), 1.32);
|
||||
|
||||
eq(test.ReturnsInt8 (), -5); |
||||
eq(test.ReturnsUInt8 (), 5); |
||||
eq(test.ReturnsInt16 (), -5); |
||||
eq(test.ReturnsUInt16(), 5); |
||||
eq(test.ReturnsInt32 (), -5); |
||||
eq(test.ReturnsUInt32(), 5); |
||||
eq(test.ReturnsInt64 (), -5n); |
||||
eq(test.ReturnsUInt64(), 5n); |
||||
|
||||
const int8 = { min: -(2**7), max: (2**7) - 1 }; |
||||
eq(test.PassAndReturnsInt8(int8.min), int8.min); |
||||
eq(test.PassAndReturnsInt8(int8.max), int8.max); |
||||
|
||||
const uint8 = { min: 0, max: (2**8) - 1 }; |
||||
eq(test.PassAndReturnsUInt8(uint8.min), uint8.min); |
||||
eq(test.PassAndReturnsUInt8(uint8.max), uint8.max); |
||||
|
||||
const int16 = { min: -(2**15), max: (2**15) - 1 }; |
||||
eq(test.PassAndReturnsInt16(int16.min), int16.min); |
||||
eq(test.PassAndReturnsInt16(int16.max), int16.max); |
||||
|
||||
const uint16 = { min: 0, max: (2**16) - 1 }; |
||||
eq(test.PassAndReturnsUInt16(uint16.min), uint16.min); |
||||
eq(test.PassAndReturnsUInt16(uint16.max), uint16.max); |
||||
|
||||
const int32 = { min: -(2**31), max: (2**31) - 1 }; |
||||
eq(test.PassAndReturnsInt32(int32.min), int32.min); |
||||
eq(test.PassAndReturnsInt32(int32.max), int32.max); |
||||
|
||||
const uint32 = { min: 0, max: (2**32) - 1 }; |
||||
eq(test.PassAndReturnsUInt32(uint32.min), uint32.min); |
||||
eq(test.PassAndReturnsUInt32(uint32.max), uint32.max); |
||||
|
||||
const int64 = { min: BigInt(2**63) * -1n, max: BigInt(2**63) - 1n }; |
||||
eq(test.PassAndReturnsInt64(int64.min), int64.min); |
||||
eq(test.PassAndReturnsInt64(int64.max), int64.max); |
||||
|
||||
const uint64 = { min: BigInt(0), max: BigInt(2**64) - 1n }; |
||||
eq(test.PassAndReturnsUInt64(uint64.min), uint64.min); |
||||
eq(test.PassAndReturnsUInt64(uint64.max), uint64.max); |
||||
} |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
{ |
||||
"include": ["*.ts", "./gen/*.ts"], |
||||
"compilerOptions": { |
||||
"alwaysStrict": true, // Parse in strict mode and emit "use strict" for each source file. |
||||
"noImplicitAny": true, |
||||
"strictNullChecks": true, |
||||
"sourceMap": true, |
||||
"typeRoots": ["./gen"] |
||||
}, |
||||
"typeAcquisition": { |
||||
"include": ["gen"] |
||||
} |
||||
} |
Loading…
Reference in new issue