static AstInterfaceNode ParseInterface(AstAttributes interfaceAttrs, ref TokenParser parser) { var interfaceName = parser.ParseIdentifier(); string inheritsFrom = null; if (parser.TryConsume(":")) { inheritsFrom = parser.ParseIdentifier(); } EnsureOpenBracket(ref parser); var rv = new AstInterfaceNode { Name = interfaceName, Attributes = interfaceAttrs, Inherits = inheritsFrom }; while (!parser.TryConsume('}') && !parser.Eof) { var memberAttrs = ParseLocalAttributes(ref parser); var returnType = ParseType(ref parser); var name = parser.ParseIdentifier(); var member = new AstInterfaceMemberNode { Name = name, ReturnType = returnType, Attributes = memberAttrs }; rv.Add(member); parser.Consume('('); while (true) { if (parser.TryConsume(')')) { break; } var argumentAttrs = ParseLocalAttributes(ref parser); var type = ParseType(ref parser); var argName = parser.ParseIdentifier(); member.Add(new AstInterfaceMemberArgumentNode { Name = argName, Type = type, Attributes = argumentAttrs }); if (parser.TryConsume(')')) { break; } if (parser.TryConsume(',')) { continue; } throw new ParseException("Unexpected character", ref parser); } parser.Consume(';'); } return(rv); }
void GenerateInterface(ref NamespaceDeclarationSyntax ns, ref NamespaceDeclarationSyntax implNs, AstInterfaceNode iface) { var guidString = iface.GetAttribute("uuid"); var inheritsUnknown = iface.Inherits == null || iface.Inherits == "IUnknown"; var ifaceDec = InterfaceDeclaration(iface.Name) .WithBaseType(inheritsUnknown ? "Avalonia.MicroCom.IUnknown" : iface.Inherits) .AddModifiers(Token(_visibility), Token(SyntaxKind.UnsafeKeyword), Token(SyntaxKind.PartialKeyword)); var proxyClassName = "__MicroCom" + iface.Name + "Proxy"; var proxy = ClassDeclaration(proxyClassName) .AddModifiers(Token(SyntaxKind.UnsafeKeyword), Token(_visibility), Token(SyntaxKind.PartialKeyword)) .WithBaseType(inheritsUnknown ? "Avalonia.MicroCom.MicroComProxyBase" : ("__MicroCom" + iface.Inherits + "Proxy")) .AddBaseListTypes(SimpleBaseType(ParseTypeName(iface.Name))); // Generate vtable var vtbl = ClassDeclaration("__MicroCom" + iface.Name + "VTable") .AddModifiers(Token(SyntaxKind.UnsafeKeyword)); vtbl = vtbl.WithBaseType(inheritsUnknown ? "Avalonia.MicroCom.MicroComVtblBase" : "__MicroCom" + iface.Inherits + "VTable"); var vtblCtor = new List <StatementSyntax>(); for (var idx = 0; idx < iface.Count; idx++) { GenerateInterfaceMember(iface[idx], ref ifaceDec, ref proxy, ref vtbl, vtblCtor, idx); } vtbl = vtbl.AddMembers( ConstructorDeclaration(vtbl.Identifier.Text) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .WithBody(Block(vtblCtor)) ) .AddMembers(MethodDeclaration(ParseTypeName("void"), "__MicroComModuleInit") .AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword)) .WithExpressionBody(ArrowExpressionClause( ParseExpression("Avalonia.MicroCom.MicroComRuntime.RegisterVTable(typeof(" + iface.Name + "), new " + vtbl.Identifier.Text + "().CreateVTable())"))) .WithSemicolonToken(Semicolon())); // Finalize proxy code proxy = proxy.AddMembers( MethodDeclaration(ParseTypeName("void"), "__MicroComModuleInit") .AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword)) .WithBody(Block( ParseStatement("Avalonia.MicroCom.MicroComRuntime.Register(typeof(" + iface.Name + "), new Guid(\"" + guidString + "\"), (p, owns) => new " + proxyClassName + "(p, owns));") ))) .AddMembers(ParseMemberDeclaration("public " + proxyClassName + "(IntPtr nativePointer, bool ownsHandle) : base(nativePointer, ownsHandle) {}")) .AddMembers(ParseMemberDeclaration("protected override int VTableSize => base.VTableSize + " + iface.Count + ";")); ns = ns.AddMembers(RewriteMethodsToProperties(ifaceDec)); implNs = implNs.AddMembers(RewriteMethodsToProperties(proxy), RewriteMethodsToProperties(vtbl)); }