protected override MemberDeclarationSyntax CreateType() { return(SF.InterfaceDeclaration ( CreateAttributes(), SF.TokenList(SF.Token(SyntaxKind.PublicKeyword)), Symbols.GetNameSyntaxToken(Type), null, CreateBaseList(), SF.List <TypeParameterConstraintClauseSyntax>(), SF.List(CreateMembers()) )); SyntaxList <AttributeListSyntax> CreateAttributes() { TypeOfExpressionSyntax typeOfExpression = SF.TypeOfExpression(Symbols.GetNameSyntax(Type)); SyntaxToken fullyQualifiedNameLiteral = SF.Literal(Type.FullyQualifiedName); return(SF.List(new[] { SF.AttributeList(SF.SeparatedList(new[] { SF.Attribute( SF.ParseName("JsiiInterface"), SF.ParseAttributeArgumentList($"({typeOfExpression}, {fullyQualifiedNameLiteral})") ) })) })); } BaseListSyntax CreateBaseList() { IEnumerable <BaseTypeSyntax> baseTypes = GetBaseTypes(); return(baseTypes?.Any() == true?SF.BaseList(SF.SeparatedList(baseTypes)) : null); IEnumerable <BaseTypeSyntax> GetBaseTypes() { foreach (TypeReference interfaceReference in Type.Interfaces ?? Enumerable.Empty <TypeReference>()) { Namespaces.Add(interfaceReference); yield return(SF.SimpleBaseType(Symbols.GetTypeSyntax(interfaceReference))); } } } IEnumerable <MemberDeclarationSyntax> CreateMembers() { return(CreateProperties().Concat(CreateMethods())); } }
/// <summary> /// Generates the class for the provided grain types. /// </summary> /// <param name="type">The grain interface type.</param> /// <param name="onEncounteredType"> /// The callback invoked when a type is encountered. /// </param> /// <returns> /// The generated class. /// </returns> internal static TypeDeclarationSyntax GenerateClass(Type type, Action <Type> onEncounteredType) { var typeInfo = type.GetTypeInfo(); var genericTypes = typeInfo.IsGenericTypeDefinition ? typeInfo.GetGenericArguments().Select(_ => SF.TypeParameter(_.ToString())).ToArray() : new TypeParameterSyntax[0]; var attributes = new List <AttributeSyntax> { CodeGeneratorCommon.GetGeneratedCodeAttributeSyntax(), #if !NETSTANDARD SF.Attribute(typeof(ExcludeFromCodeCoverageAttribute).GetNameSyntax()), #endif SF.Attribute(typeof(SerializerAttribute).GetNameSyntax()) .AddArgumentListArguments( SF.AttributeArgument(SF.TypeOfExpression(type.GetTypeSyntax(includeGenericParameters: false)))) }; var className = CodeGeneratorCommon.ClassPrefix + type.GetParseableName(GeneratedTypeNameOptions); var fields = GetFields(type); // Mark each field type for generation foreach (var field in fields) { var fieldType = field.FieldInfo.FieldType; onEncounteredType(fieldType); } var members = new List <MemberDeclarationSyntax>(GenerateStaticFields(fields)) { GenerateDeepCopierMethod(type, fields), GenerateSerializerMethod(type, fields), GenerateDeserializerMethod(type, fields), }; var classDeclaration = SF.ClassDeclaration(className) .AddModifiers(SF.Token(SyntaxKind.InternalKeyword)) .AddAttributeLists(SF.AttributeList().AddAttributes(attributes.ToArray())) .AddMembers(members.ToArray()) .AddConstraintClauses(type.GetTypeConstraintSyntax()); if (genericTypes.Length > 0) { classDeclaration = classDeclaration.AddTypeParameterListParameters(genericTypes); } return(classDeclaration); }
/// <summary> /// Generates the class for the provided grain types. /// </summary> /// <param name="grainType"> /// The grain interface type. /// </param> /// <param name="onEncounteredType"> /// The callback which is invoked when a type is encountered. /// </param> /// <returns> /// The generated class. /// </returns> internal static TypeDeclarationSyntax GenerateClass(Type grainType, Action <Type> onEncounteredType) { var grainTypeInfo = grainType.GetTypeInfo(); var genericTypes = grainTypeInfo.IsGenericTypeDefinition ? grainTypeInfo.GetGenericArguments() .Select(_ => SF.TypeParameter(_.ToString())) .ToArray() : new TypeParameterSyntax[0]; // Create the special marker attribute. var markerAttribute = SF.Attribute(typeof(GrainReferenceAttribute).GetNameSyntax()) .AddArgumentListArguments( SF.AttributeArgument( SF.TypeOfExpression(grainType.GetTypeSyntax(includeGenericParameters: false)))); var attributes = SF.AttributeList() .AddAttributes( CodeGeneratorCommon.GetGeneratedCodeAttributeSyntax(), SF.Attribute(typeof(SerializableAttribute).GetNameSyntax()), #if !NETSTANDARD_TODO //ExcludeFromCodeCoverageAttribute became an internal class in netstandard SF.Attribute(typeof(ExcludeFromCodeCoverageAttribute).GetNameSyntax()), #endif markerAttribute); var className = CodeGeneratorCommon.ClassPrefix + TypeUtils.GetSuitableClassName(grainType) + ClassSuffix; var classDeclaration = SF.ClassDeclaration(className) .AddModifiers(SF.Token(SyntaxKind.InternalKeyword)) .AddBaseListTypes( SF.SimpleBaseType(typeof(GrainReference).GetTypeSyntax()), SF.SimpleBaseType(grainType.GetTypeSyntax())) .AddConstraintClauses(grainType.GetTypeConstraintSyntax()) .AddMembers(GenerateConstructors(className)) .AddMembers( GenerateInterfaceIdProperty(grainType), GenerateInterfaceNameProperty(grainType), GenerateIsCompatibleMethod(grainType), GenerateGetMethodNameMethod(grainType)) .AddMembers(GenerateInvokeMethods(grainType, onEncounteredType)) .AddAttributeLists(attributes); if (genericTypes.Length > 0) { classDeclaration = classDeclaration.AddTypeParameterListParameters(genericTypes); } return(classDeclaration); }
public static SyntaxList <AttributeListSyntax> GenerateStructLayoutAttributes() { return(SF.SingletonList( SF.AttributeList( SF.SingletonSeparatedList( SF.Attribute(SF.IdentifierName("StructLayout")) .WithArgumentList( SF.AttributeArgumentList( SF.SingletonSeparatedList( SF.AttributeArgument( SF.MemberAccessExpression( SK.SimpleMemberAccessExpression, SF.IdentifierName("LayoutKind"), SF.IdentifierName("Explicit")))))))))); }
public static AttributeSyntax GenAttribute(string name, string args) { var attribure = SF.Attribute(SF.IdentifierName(name)); if (args != null) { attribure = attribure.WithArgumentList( SF.AttributeArgumentList( SF.SingletonSeparatedList( SF.AttributeArgument( SF.ParseExpression(args))))); } return(attribure); }
protected override MemberDeclarationSyntax CreateType() { return(SF.ClassDeclaration ( CreateAttributes(), SF.TokenList(SF.Token(SyntaxKind.InternalKeyword)), GetProxyTypeNameSyntax(), null, CreateBaseList(), SF.List <TypeParameterConstraintClauseSyntax>(), SF.List(CreateMembers()) )); SyntaxList <AttributeListSyntax> CreateAttributes() { TypeOfExpressionSyntax typeOfExpression = SF.TypeOfExpression(Symbols.GetNameSyntax(Type)); SyntaxToken fullyQualifiedNameLiteral = SF.Literal(Type.FullyQualifiedName); return(SF.List(new[] { SF.AttributeList(SF.SeparatedList(new[] { SF.Attribute( SF.ParseName("JsiiInterfaceProxy"), SF.ParseAttributeArgumentList($"({typeOfExpression}, {fullyQualifiedNameLiteral})") ) })) })); } BaseListSyntax CreateBaseList() { return(SF.BaseList(SF.SeparatedList(GetBaseTypes()))); IEnumerable <BaseTypeSyntax> GetBaseTypes() { yield return(SF.SimpleBaseType(SF.ParseTypeName("DeputyBase"))); Namespaces.Add(Type); yield return(SF.SimpleBaseType(Symbols.GetNameSyntax(Type, disambiguate: true))); } } IEnumerable <MemberDeclarationSyntax> CreateMembers() { return(CreateConstructors() .Concat(CreateProperties()) .Concat(CreateMethods())); } }
private SyntaxList <AttributeListSyntax> CreateSerializationAttribute(SymbolData symbol) { string requiredValueName; if (symbol.IsRequired) { requiredValueName = (symbol.isNullable) ? "AllowNull" : "Always"; } else { requiredValueName = "Default"; } Func <string, string, string, AttributeArgumentSyntax> createAttr = (lhs, expr, name) => { // lhs = expr.name return(SF.AttributeArgument( SF.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SF.IdentifierName(expr), SF.Token(SyntaxKind.DotToken), SF.IdentifierName(name))) .WithNameEquals( SF.NameEquals(SF.IdentifierName(lhs)))); }; var attributes = SF.SeparatedList(new[] { // Required = Required.[requiredValueName] createAttr("Required", "Required", requiredValueName), }); if (requiredValueName == "Default" && !symbol.isNullable) { // NullValueHandling = NullValueHandling.Ignore attributes = attributes.Add( createAttr("NullValueHandling", "NullValueHandling", "Ignore")); } return(SF.SingletonList( SF.AttributeList( SF.SingletonSeparatedList( SF.Attribute(SF.IdentifierName("JsonProperty")) .WithArgumentList( SF.AttributeArgumentList(attributes)))))); }
SeparatedSyntaxList <EnumMemberDeclarationSyntax> CreateValues() { return(SF.SeparatedList(Type.Members.Select(GetMemberDeclaration))); EnumMemberDeclarationSyntax GetMemberDeclaration(EnumMember member) { EnumMemberDeclarationSyntax declaration = SF.EnumMemberDeclaration ( SF.List(GetAttributeLists()), Symbols.GetNameSyntaxToken(Type, member), null ); if (member.Docs != null) { DocCommentGeneratorBase <EnumMember> generator = new EnumMemberDocCommentGenerator(member); SyntaxTriviaList trivia = SF.TriviaList(generator.CreateDocComment()); declaration = declaration.WithLeadingTrivia(trivia); } return(declaration); IEnumerable <AttributeListSyntax> GetAttributeLists() { yield return(SF.AttributeList(SF.SingletonSeparatedList( SF.Attribute( SF.ParseName("JsiiEnumMember"), SF.ParseAttributeArgumentList($"(name: \"{member.Name}\")") ) ))); if (member.Docs?.Stability == Stability.Deprecated) { var argument = member.Docs?.Deprecated != null?SF.Literal(member.Docs?.Deprecated).ToString() : ""; yield return(SF.AttributeList(SF.SingletonSeparatedList( SF.Attribute( SF.ParseName("System.Obsolete"), SF.ParseAttributeArgumentList($"({argument})") ) ))); } } } }
/// <summary> /// Yields the CompiledHandlebars Class Declaration ClassDeclaration /// public static class CompiledHandlebarsTemplate<TViewModel> {} /// </summary> internal static ClassDeclarationSyntax CompiledHandlebarsClassDeclaration(string templateName, string attribute) { return (SF.ClassDeclaration( new SyntaxList <AttributeListSyntax>().Add( SF.AttributeList(new SeparatedSyntaxList <AttributeSyntax>().Add( SF.Attribute(SF.ParseName(attribute))) )), SF.TokenList( SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword)), SF.Identifier(templateName), default(TypeParameterListSyntax), default(BaseListSyntax), default(SyntaxList <TypeParameterConstraintClauseSyntax>), default(SyntaxList <MemberDeclarationSyntax>) )); }
private static MemberDeclarationSyntax GenerateSerializerMethod(Type type, List <FieldInfoMember> fields) { Expression <Action> serializeInner = () => SerializationManager.SerializeInner(default(object), default(ISerializationContext), default(Type)); var contextParameter = SF.IdentifierName("context"); var body = new List <StatementSyntax> { SF.LocalDeclarationStatement( SF.VariableDeclaration(type.GetTypeSyntax()) .AddVariables( SF.VariableDeclarator("input") .WithInitializer( SF.EqualsValueClause( SF.CastExpression(type.GetTypeSyntax(), SF.IdentifierName("untypedInput")))))) }; var inputExpression = SF.IdentifierName("input"); // Serialize all members. foreach (var field in fields) { body.Add( SF.ExpressionStatement( serializeInner.Invoke() .AddArgumentListArguments( SF.Argument(field.GetGetter(inputExpression, forceAvoidCopy: true)), SF.Argument(contextParameter), SF.Argument(SF.TypeOfExpression(field.FieldInfo.FieldType.GetTypeSyntax()))))); } return (SF.MethodDeclaration(typeof(void).GetTypeSyntax(), "Serializer") .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword)) .AddParameterListParameters( SF.Parameter(SF.Identifier("untypedInput")).WithType(typeof(object).GetTypeSyntax()), SF.Parameter(SF.Identifier("context")).WithType(typeof(ISerializationContext).GetTypeSyntax()), SF.Parameter(SF.Identifier("expected")).WithType(typeof(Type).GetTypeSyntax())) .AddBodyStatements(body.ToArray()) .AddAttributeLists( SF.AttributeList() .AddAttributes(SF.Attribute(typeof(SerializerMethodAttribute).GetNameSyntax())))); }
private async Task <Document> AddAnnotation(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var annotationsHttp = root.FindToken(diagnostic.Location.SourceSpan.Start).Parent as AttributeListSyntax; var methodDeclaration = annotationsHttp.Parent as MethodDeclarationSyntax; var annotationValidate = SF.AttributeList() .AddAttributes(SF.Attribute(SF.IdentifierName("ValidateAntiForgeryToken"))) .WithLeadingTrivia(CodeFixUtil.KeepLastLine(annotationsHttp.GetLeadingTrivia())); var nodes = new List <SyntaxNode>(); nodes.Add(annotationValidate); var newRoot = root.InsertNodesAfter(annotationsHttp, nodes); return(document.WithSyntaxRoot(newRoot)); }
SyntaxList <AttributeListSyntax> GetAttributeLists() { return(SF.List(new[] { SF.AttributeList(SF.SeparatedList(GetAttributes())) })); IEnumerable <AttributeSyntax> GetAttributes() { SyntaxToken nameLiteral = SF.Literal(Property.Name); SyntaxToken typeJsonLiteral = SF.Literal(JsonConvert.SerializeObject(Property.Type)); SyntaxToken trueLiteral = SF.Token(SyntaxKind.TrueKeyword); string argumentList = IsOverride ? $"({nameLiteral}, {typeJsonLiteral}, {trueLiteral})" : $"({nameLiteral}, {typeJsonLiteral})"; yield return(SF.Attribute( SF.ParseName("JsiiProperty"), SF.ParseAttributeArgumentList(argumentList) )); } }
public static CompilationUnitSyntax AddGeneratedCodeAttribute(GeneratedSyntax generatedSyntax) { var codeGenTargetAttributes = SF.AttributeList() .AddAttributes( generatedSyntax.SourceAssemblies.Select( asm => SF.Attribute(typeof(OrleansCodeGenerationTargetAttribute).GetNameSyntax()) .AddArgumentListArguments( SF.AttributeArgument(asm.GetName().FullName.GetLiteralExpression()))).ToArray()) .WithTarget(SF.AttributeTargetSpecifier(SF.Token(SyntaxKind.AssemblyKeyword))); var generatedCodeAttribute = SF.AttributeList() .AddAttributes( SF.Attribute(typeof(GeneratedCodeAttribute).GetNameSyntax()) .AddArgumentListArguments( SF.AttributeArgument("Orleans-CodeGenerator".GetLiteralExpression()), SF.AttributeArgument(RuntimeVersion.FileVersion.GetLiteralExpression()))) .WithTarget(SF.AttributeTargetSpecifier(SF.Token(SyntaxKind.AssemblyKeyword))); return(generatedSyntax.Syntax.AddAttributeLists(generatedCodeAttribute, codeGenTargetAttributes)); }
SyntaxList <AttributeListSyntax> GetAttributeLists() { return(SF.List(GetAttributesLists())); IEnumerable <AttributeListSyntax> GetAttributesLists() { SyntaxToken nameLiteral = SF.Literal(Property.Name); SyntaxToken typeJsonLiteral = SF.Literal(JsonConvert.SerializeObject(Property.Type, SerializerSettings)); SyntaxToken trueLiteral = SF.Token(SyntaxKind.TrueKeyword); string argumentList = $"name: {nameLiteral}, typeJson: {typeJsonLiteral}"; if (Property.IsOptional) { argumentList += $", isOptional: {trueLiteral}"; } if (IsOverride) { argumentList += $", isOverride: {trueLiteral}"; } yield return(SF.AttributeList(SF.SingletonSeparatedList(SF.Attribute( SF.ParseName("JsiiProperty"), SF.ParseAttributeArgumentList($"({argumentList})") )))); if (Property.Docs?.Stability == Stability.Deprecated) { var argument = Property.Docs?.Deprecated != null?SF.Literal(Property.Docs?.Deprecated).ToString() : ""; yield return(SF.AttributeList(SF.SingletonSeparatedList(SF.Attribute( SF.ParseName("System.Obsolete"), SF.ParseAttributeArgumentList($"({argument})") )))); } } }
private ClassDeclarationSyntax CreateClass(SymbolData symbol) { var className = symbol.Name.ToClassName(); var node = SF.ClassDeclaration(className) .AddModifiers(SF.Token(SyntaxKind.PublicKeyword)); if (_options.IsJsonSerializable) { node = node.WithAttributeLists( SF.SingletonList( SF.AttributeList( SF.SingletonSeparatedList( SF.Attribute(SF.IdentifierName("JsonObject")))))); } if (!string.IsNullOrEmpty(symbol.Summary)) { var comment = new DocumentComment() { Summary = symbol.Summary }; node = node.WithLeadingTrivia(comment.ConstructTriviaList()); } var props = new List <MemberDeclarationSyntax>(); foreach (var member in symbol.Members) { props.Add(ConstructImpl(member) as MemberDeclarationSyntax); if (member.TypeName == "object") { var childSymbol = member.CreateInstanceSymbol(); props.Add(CreateProperty(childSymbol)); } } return(node.AddMembers(props.ToArray())); }
SyntaxList <AttributeListSyntax> GetAttributeLists() { return(SF.List(new[] { SF.AttributeList(SF.SeparatedList(GetAttributes())) })); IEnumerable <AttributeSyntax> GetAttributes() { SyntaxToken nameLiteral = SF.Literal(Method.Name); SyntaxToken returnsJsonLiteral = Method.Returns == null? SF.Token(SyntaxKind.NullKeyword) : SF.Literal(JsonConvert.SerializeObject(Method.Returns)); SyntaxToken parametersJsonLiteral = Method.GetParametersJsonSyntaxToken(); SyntaxToken trueLiteral = SF.Token(SyntaxKind.TrueKeyword); string argumentList = IsOverride ? $"({nameLiteral}, {returnsJsonLiteral}, {parametersJsonLiteral}, {trueLiteral})" : $"({nameLiteral}, {returnsJsonLiteral}, {parametersJsonLiteral})"; yield return(SF.Attribute( SF.ParseName("JsiiMethod"), SF.ParseAttributeArgumentList(argumentList) )); } }
protected override MemberDeclarationSyntax CreateType() { return(SF.InterfaceDeclaration ( CreateAttributes(), SF.TokenList(SF.Token(SyntaxKind.PublicKeyword)), Symbols.GetNameSyntaxToken(Type), null, CreateBaseList(), SF.List <TypeParameterConstraintClauseSyntax>(), SF.List(CreateMembers()) )); SyntaxList <AttributeListSyntax> CreateAttributes() { TypeOfExpressionSyntax typeOfExpression = SF.TypeOfExpression(Symbols.GetNameSyntax(Type)); SyntaxToken fullyQualifiedNameLiteral = SF.Literal(Type.FullyQualifiedName); return(SF.List(GetAttributeLists())); IEnumerable <AttributeListSyntax> GetAttributeLists() { yield return(SF.AttributeList(SF.SeparatedList(new[] { SF.Attribute( SF.ParseName("JsiiInterface"), SF.ParseAttributeArgumentList($"(nativeType: {typeOfExpression}, fullyQualifiedName: {fullyQualifiedNameLiteral})") ) }))); if (Type.Docs?.Stability == Stability.Deprecated) { var argument = Type.Docs?.Deprecated != null?SF.Literal(Type.Docs?.Deprecated).ToString() : ""; yield return(SF.AttributeList(SF.SeparatedList(new[] { SF.Attribute( SF.ParseName("System.Obsolete"), SF.ParseAttributeArgumentList($"({argument})") ) }))); } } } BaseListSyntax CreateBaseList() { IEnumerable <BaseTypeSyntax> baseTypes = GetBaseTypes(); return(baseTypes?.Any() ?? false?SF.BaseList(SF.SeparatedList(baseTypes)) : null); IEnumerable <BaseTypeSyntax> GetBaseTypes() { foreach (string interfaceReference in Type.Interfaces ?? Enumerable.Empty <string>()) { Namespaces.Add(Symbols.GetTypeFromFullyQualifiedName(interfaceReference)); yield return(SF.SimpleBaseType(Symbols.GetNameSyntax(interfaceReference, disambiguate: true))); } } } IEnumerable <MemberDeclarationSyntax> CreateMembers() { return(CreateProperties().Concat(CreateMethods())); } }
protected override MemberDeclarationSyntax CreateType() { return(SF.ClassDeclaration ( CreateAttributes(), SF.TokenList( SF.Token(SyntaxKind.InternalKeyword), SF.Token(SyntaxKind.SealedKeyword)), GetProxyTypeNameSyntax(), null, CreateBaseList(), SF.List <TypeParameterConstraintClauseSyntax>(), SF.List(CreateMembers()) )); SyntaxList <AttributeListSyntax> CreateAttributes() { var typeOfExpression = SF.TypeOfExpression(Symbols.GetNameSyntax(Type)); var fullyQualifiedNameLiteral = SF.Literal(Type.FullyQualifiedName); return(SF.List(GetAttributeLists())); IEnumerable <AttributeListSyntax> GetAttributeLists() { yield return(SF.AttributeList(SF.SingletonSeparatedList( SF.Attribute( SF.ParseName("JsiiTypeProxy"), SF.ParseAttributeArgumentList($"(nativeType: {typeOfExpression}, fullyQualifiedName: {fullyQualifiedNameLiteral})") ) ))); if (Type.Docs?.Stability == Stability.Deprecated) { var argument = Type.Docs?.Deprecated != null?SF.Literal(Type.Docs?.Deprecated).ToString() : ""; yield return(SF.AttributeList(SF.SingletonSeparatedList( SF.Attribute( SF.ParseName("System.Obsolete"), SF.ParseAttributeArgumentList($"({argument})") ) ))); } } } BaseListSyntax CreateBaseList() { return(SF.BaseList(SF.SeparatedList(GetBaseTypes()))); IEnumerable <BaseTypeSyntax> GetBaseTypes() { if (Type is InterfaceType) { yield return(SF.SimpleBaseType(SF.ParseTypeName("DeputyBase"))); } Namespaces.Add(Type); yield return(SF.SimpleBaseType(Symbols.GetNameSyntax(Type, disambiguate: true))); } } IEnumerable <MemberDeclarationSyntax> CreateMembers() { return(CreateConstructors() .Concat(CreateProperties()) .Concat(CreateMethods())); } }
/// <summary> /// Returns syntax for the deep copier method. /// </summary> /// <param name="type">The type.</param> /// <param name="fields">The fields.</param> /// <returns>Syntax for the deep copier method.</returns> private static MemberDeclarationSyntax GenerateDeepCopierMethod(Type type, List <FieldInfoMember> fields) { var originalVariable = SF.IdentifierName("original"); var inputVariable = SF.IdentifierName("input"); var resultVariable = SF.IdentifierName("result"); var body = new List <StatementSyntax>(); if (type.GetTypeInfo().GetCustomAttribute <ImmutableAttribute>() != null) { // Immutable types do not require copying. var typeName = type.GetParseableName(new TypeFormattingOptions(includeGlobal: false)); var comment = SF.Comment($"// No deep copy required since {typeName} is marked with the [Immutable] attribute."); body.Add(SF.ReturnStatement(originalVariable).WithLeadingTrivia(comment)); } else { body.Add( SF.LocalDeclarationStatement( SF.VariableDeclaration(type.GetTypeSyntax()) .AddVariables( SF.VariableDeclarator("input") .WithInitializer( SF.EqualsValueClause( SF.ParenthesizedExpression( SF.CastExpression(type.GetTypeSyntax(), originalVariable))))))); body.Add( SF.LocalDeclarationStatement( SF.VariableDeclaration(type.GetTypeSyntax()) .AddVariables( SF.VariableDeclarator("result") .WithInitializer(SF.EqualsValueClause(GetObjectCreationExpressionSyntax(type)))))); // Record this serialization. Expression <Action <ICopyContext> > recordObject = ctx => ctx.RecordCopy(default(object), default(object)); var context = SF.IdentifierName("context"); body.Add( SF.ExpressionStatement( recordObject.Invoke(context) .AddArgumentListArguments(SF.Argument(originalVariable), SF.Argument(resultVariable)))); // Copy all members from the input to the result. foreach (var field in fields) { body.Add(SF.ExpressionStatement(field.GetSetter(resultVariable, field.GetGetter(inputVariable, context)))); } body.Add(SF.ReturnStatement(resultVariable)); } return (SF.MethodDeclaration(typeof(object).GetTypeSyntax(), "DeepCopier") .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword)) .AddParameterListParameters( SF.Parameter(SF.Identifier("original")).WithType(typeof(object).GetTypeSyntax()), SF.Parameter(SF.Identifier("context")).WithType(typeof(ICopyContext).GetTypeSyntax())) .AddBodyStatements(body.ToArray()) .AddAttributeLists( SF.AttributeList().AddAttributes(SF.Attribute(typeof(CopierMethodAttribute).GetNameSyntax())))); }
private static AttributeSyntax Attribute(string attributeName) { return(SF.Attribute(SF.IdentifierName(attributeName))); }
protected override MemberDeclarationSyntax CreateType() { return(SF.ClassDeclaration ( CreateAttributes(), CreateModifiers(), Symbols.GetNameSyntaxToken(Type), null, CreateBaseList(), SF.List <TypeParameterConstraintClauseSyntax>(), SF.List(CreateMembers()) )); SyntaxList <AttributeListSyntax> CreateAttributes() { TypeOfExpressionSyntax typeOfExpression = SF.TypeOfExpression(Symbols.GetNameSyntax(Type)); SyntaxToken fullyQualifiedNameLiteral = SF.Literal(Type.FullyQualifiedName); SyntaxToken parametersJsonLiteral = Type.Initializer.GetParametersJsonSyntaxToken(); return(SF.List(new[] { SF.AttributeList(SF.SeparatedList(new[] { SF.Attribute( SF.ParseName("JsiiClass"), SF.ParseAttributeArgumentList($"({typeOfExpression}, {fullyQualifiedNameLiteral}, {parametersJsonLiteral})") ) })) })); } SyntaxTokenList CreateModifiers() { SyntaxTokenList modifierList = SF.TokenList(SF.Token(SyntaxKind.PublicKeyword)); if (Type.IsAbstract) { modifierList = modifierList.Add(SF.Token(SyntaxKind.AbstractKeyword)); } return(modifierList); } BaseListSyntax CreateBaseList() { return(SF.BaseList(SF.SeparatedList(GetBaseTypes()))); IEnumerable <BaseTypeSyntax> GetBaseTypes() { if (Type.Base == null) { yield return(SF.SimpleBaseType(SF.ParseTypeName("DeputyBase"))); } else { Namespaces.Add(Type.Base); yield return(SF.SimpleBaseType(Symbols.GetNameSyntax(Type.Base.FullyQualifiedName, disambiguate: true))); } if (Type.Interfaces == null) { yield break; } foreach (TypeReference interfaceReference in Type.Interfaces) { Namespaces.Add(interfaceReference); yield return(SF.SimpleBaseType(Symbols.GetNameSyntax(interfaceReference.FullyQualifiedName, disambiguate: true))); } } } IEnumerable <MemberDeclarationSyntax> CreateMembers() { return(CreateConstructors() .Concat(CreateProperties()) .Concat(CreateMethods())); } }
void Save(string packageOutputRoot, ISymbolMap symbols, Assembly assembly, string tarballFileName, string jsiiFileName) { if (assembly.Docs != null) { // TODO: Use Microsoft.Extensions.Logging instead of Console.Error. Console.Error.WriteLine("Warning: Ignoring documentation comment on assembly ${assembly.Name}. Assembly-level documentation comments are not supported for .NET"); } SaveProjectFile(); SaveAssemblyInfo(assembly.Name, assembly.Version, tarballFileName); foreach (Type type in assembly.Types?.Values ?? Enumerable.Empty <Type>()) { SaveType(type); } void SaveProjectFile() { XElement project = new XElement("Project", new XAttribute("Sdk", "Microsoft.NET.Sdk"), new XElement("PropertyGroup", new XElement("TargetFramework", "netstandard2.0"), new XElement("GeneratePackageOnBuild", true), new XElement("Authors", _authors), new XElement("Company", _company), new XElement("PackageVersion", assembly.Version) ), new XElement("ItemGroup", new XElement("EmbeddedResource", new XAttribute("Include", tarballFileName) ) ), new XElement("ItemGroup", new XElement("PackageReference", new XAttribute("Include", "Amazon.JSII.Runtime"), new XAttribute("Version", JsiiVersion.Version) ), GetDependencies() .Distinct() .Select(d => new { Package = symbols.GetAssemblyName(d.Key), Version = d.Value.Version }) .Select(d => new XElement("PackageReference", new XAttribute("Include", d.Package), new XAttribute("Version", d.Version) ) ) ) ); if (!_fileSystem.Directory.Exists(packageOutputRoot)) { _fileSystem.Directory.CreateDirectory(packageOutputRoot); } // Save to StringBuilder instead of directly to path, so that we can // redirect the output through the filesystem shim. Project files are // small, so this shouldn't be a memory hog. StringBuilder builder = new StringBuilder(); XmlWriterSettings settings = new XmlWriterSettings { // Visual Studio omits the XML declaration when creating project files, so we do too. OmitXmlDeclaration = true, // Visual Studio indents project files (they are often edited by hand), so we do too. Indent = true, }; using (XmlWriter writer = XmlWriter.Create(builder, settings)) { project.Save(writer); } string csProjPath = Path.Combine(packageOutputRoot, $"{assembly.GetNativeName()}.csproj"); _fileSystem.File.WriteAllText(csProjPath, builder.ToString()); IEnumerable <KeyValuePair <string, PackageVersion> > GetDependencies() { foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(assembly)) { yield return(dependency); } IEnumerable <KeyValuePair <string, PackageVersion> > GetDependenciesCore(DependencyRoot root) { if (root.Dependencies == null) { yield break; } foreach (var kvp in root.Dependencies) { yield return(kvp); foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(kvp.Value)) { yield return(dependency); } } } } } void SaveAssemblyInfo(string name, string version, string tarball) { SyntaxTree assemblyInfo = SF.SyntaxTree( SF.CompilationUnit( SF.List <ExternAliasDirectiveSyntax>(), SF.List(new[] { SF.UsingDirective(SF.ParseName("Amazon.JSII.Runtime.Deputy")) }), SF.List(new[] { SF.AttributeList( SF.AttributeTargetSpecifier( SF.Identifier("assembly"), SF.Token(SyntaxKind.ColonToken) ), SF.SeparatedList(new[] { SF.Attribute( SF.ParseName("JsiiAssembly"), SF.ParseAttributeArgumentList($"({SF.Literal(name)}, {SF.Literal(version)}, {SF.Literal(tarball)})") ) }) ) }), SF.List <MemberDeclarationSyntax>() ).NormalizeWhitespace(elasticTrivia: true) ); string assemblyInfoPath = Path.Combine(packageOutputRoot, "AssemblyInfo.cs"); _fileSystem.File.WriteAllText(assemblyInfoPath, assemblyInfo.ToString()); } void SaveType(Type type) { string packageName = Path.GetFileName(packageOutputRoot); string @namespace = symbols.GetNamespace(type); if (@namespace.StartsWith(packageName)) { @namespace = @namespace.Substring(packageName.Length).TrimStart('.'); } string directory = Path.Combine(packageOutputRoot, Path.Combine(@namespace.Split('.'))); switch (type.Kind) { case TypeKind.Class: SaveTypeFile($"{symbols.GetName(type)}.cs", new ClassGenerator(assembly.Name, (ClassType)type, symbols).CreateSyntaxTree()); return; case TypeKind.Enum: SaveTypeFile($"{symbols.GetName(type)}.cs", new EnumGenerator(assembly.Name, (EnumType)type, symbols).CreateSyntaxTree()); return; case TypeKind.Interface: InterfaceType interfaceType = (InterfaceType)type; SaveTypeFile($"{symbols.GetName(interfaceType)}.cs", new InterfaceGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree()); SaveTypeFile($"{symbols.GetInterfaceProxyName(interfaceType)}.cs", new InterfaceProxyGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree()); if (interfaceType.IsDataType == true) { SaveTypeFile($"{symbols.GetInterfaceDefaultName(interfaceType)}.cs", new InterfaceDefaultGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree()); } return; default: throw new ArgumentException($"Unkown type kind: {type.Kind}", nameof(type)); } void SaveTypeFile(string filename, SyntaxTree syntaxTree) { if (!_fileSystem.Directory.Exists(directory)) { _fileSystem.Directory.CreateDirectory(directory); } _fileSystem.File.WriteAllText( Path.Combine(directory, filename), syntaxTree.ToString() ); } } }
/// <summary> /// Returns syntax for the deep copier method. /// </summary> /// <param name="type">The type.</param> /// <param name="fields">The fields.</param> /// <returns>Syntax for the deep copier method.</returns> private static MemberDeclarationSyntax GenerateDeepCopierMethod(Type type, List <FieldInfoMember> fields) { var originalVariable = SF.IdentifierName("original"); var inputVariable = SF.IdentifierName("input"); var resultVariable = SF.IdentifierName("result"); var body = new List <StatementSyntax>(); if (type.GetCustomAttribute <ImmutableAttribute>() != null) { // Immutable types do not require copying. body.Add(SF.ReturnStatement(originalVariable)); } else { body.Add( SF.LocalDeclarationStatement( SF.VariableDeclaration(type.GetTypeSyntax()) .AddVariables( SF.VariableDeclarator("input") .WithInitializer( SF.EqualsValueClause( SF.ParenthesizedExpression( SF.CastExpression(type.GetTypeSyntax(), originalVariable))))))); body.Add( SF.LocalDeclarationStatement( SF.VariableDeclaration(type.GetTypeSyntax()) .AddVariables( SF.VariableDeclarator("result") .WithInitializer(SF.EqualsValueClause(GetObjectCreationExpressionSyntax(type)))))); // Copy all members from the input to the result. foreach (var field in fields) { body.Add(SF.ExpressionStatement(field.GetSetter(resultVariable, field.GetGetter(inputVariable)))); } // Record this serialization. Expression <Action> recordObject = () => SerializationContext.Current.RecordObject(default(object), default(object)); var currentSerializationContext = SyntaxFactory.AliasQualifiedName( SF.IdentifierName(SF.Token(SyntaxKind.GlobalKeyword)), SF.IdentifierName("Orleans")) .Qualify("Serialization") .Qualify("SerializationContext") .Qualify("Current"); body.Add( SF.ExpressionStatement( recordObject.Invoke(currentSerializationContext) .AddArgumentListArguments(SF.Argument(originalVariable), SF.Argument(resultVariable)))); body.Add(SF.ReturnStatement(resultVariable)); } return (SF.MethodDeclaration(typeof(object).GetTypeSyntax(), "DeepCopier") .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword)) .AddParameterListParameters( SF.Parameter(SF.Identifier("original")).WithType(typeof(object).GetTypeSyntax())) .AddBodyStatements(body.ToArray()) .AddAttributeLists( SF.AttributeList().AddAttributes(SF.Attribute(typeof(CopierMethodAttribute).GetNameSyntax())))); }
void Save(string packageOutputRoot, ISymbolMap symbols, Assembly assembly, string tarballFileName, string jsiiFileName) { if (assembly.Docs != null) { // TODO: Use Microsoft.Extensions.Logging instead of Console.Error. Console.Error.WriteLine($"Warning: Ignoring documentation comment on assembly {assembly.Name}. Assembly-level documentation comments are not supported for .NET"); } SaveProjectFile(); SaveAssemblyInfo(assembly.Name, assembly.Version, tarballFileName); SaveDependencyAnchorFile(); foreach (Type type in assembly.Types?.Values ?? Enumerable.Empty <Type>()) { SaveType(type); } void SaveProjectFile() { XElement project = new XElement("Project", new XAttribute("Sdk", "Microsoft.NET.Sdk"), new XElement("PropertyGroup", assembly.GetMsBuildProperties()), new XElement("ItemGroup", new XElement("EmbeddedResource", new XAttribute("Include", tarballFileName) ) ), new XElement("ItemGroup", new XElement("PackageReference", new XAttribute("Include", "Amazon.JSII.Runtime"), new XAttribute("Version", JsiiVersion.Version) ), GetDependencies() .Distinct() .Select(d => new { Package = symbols.GetAssemblyName(d.Key), Version = d.Value.GetDecoratedVersion() }) .Select(d => new XElement("PackageReference", new XAttribute("Include", d.Package), new XAttribute("Version", d.Version) ) ) ) ); if (!_fileSystem.Directory.Exists(packageOutputRoot)) { _fileSystem.Directory.CreateDirectory(packageOutputRoot); } // Save to StringBuilder instead of directly to path, so that we can // redirect the output through the filesystem shim. Project files are // small, so this shouldn't be a memory hog. StringBuilder builder = new StringBuilder(); XmlWriterSettings settings = new XmlWriterSettings { // Visual Studio omits the XML declaration when creating project files, so we do too. OmitXmlDeclaration = true, // Visual Studio indents project files (they are often edited by hand), so we do too. Indent = true, }; using (XmlWriter writer = XmlWriter.Create(builder, settings)) { project.Save(writer); } string csProjPath = Path.Combine(packageOutputRoot, $"{assembly.GetNativePackageId()}.csproj"); _fileSystem.File.WriteAllText(csProjPath, builder.ToString()); IEnumerable <KeyValuePair <string, PackageVersion> > GetDependencies() { foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(assembly)) { yield return(dependency); } IEnumerable <KeyValuePair <string, PackageVersion> > GetDependenciesCore(DependencyRoot root) { if (root.Dependencies == null) { yield break; } foreach (var kvp in root.Dependencies) { yield return(kvp); foreach (KeyValuePair <string, PackageVersion> dependency in GetDependenciesCore(kvp.Value)) { yield return(dependency); } } } } } void SaveDependencyAnchorFile() { string anchorNamespace = $"{assembly.GetNativeNamespace()}.Internal.DependencyResolution"; var syntaxTree = SF.SyntaxTree( SF.CompilationUnit( SF.List <ExternAliasDirectiveSyntax>(), SF.List <UsingDirectiveSyntax>(), SF.List <AttributeListSyntax>(), SF.List <MemberDeclarationSyntax>(new[] { SF.NamespaceDeclaration( SF.IdentifierName(anchorNamespace), SF.List <ExternAliasDirectiveSyntax>(), SF.List <UsingDirectiveSyntax>(), SF.List(new MemberDeclarationSyntax[] { GenerateDependencyAnchor() }) ) }) ).NormalizeWhitespace(elasticTrivia: true) ); string directory = GetNamespaceDirectory(packageOutputRoot, @anchorNamespace); SaveSyntaxTree(directory, "Anchor.cs", syntaxTree); ClassDeclarationSyntax GenerateDependencyAnchor() { return(SF.ClassDeclaration( SF.List <AttributeListSyntax>(), SF.TokenList(SF.Token(SyntaxKind.PublicKeyword)), SF.Identifier("Anchor"), null, null, SF.List <TypeParameterConstraintClauseSyntax>(), SF.List(new MemberDeclarationSyntax[] { SF.ConstructorDeclaration( SF.List <AttributeListSyntax>(), SF.TokenList(SF.Token(SyntaxKind.PublicKeyword)), SF.Identifier("Anchor"), SF.ParameterList(SF.SeparatedList <ParameterSyntax>()), null, SF.Block(SF.List(GenerateAnchorReferences())), null ) }) )); IEnumerable <StatementSyntax> GenerateAnchorReferences() { return(assembly.Dependencies?.Keys .Select(k => assembly.GetNativeNamespace(k)) .Select(n => $"{n}.Internal.DependencyResolution.Anchor") .Select(t => SF.ExpressionStatement(SF.ObjectCreationExpression( SF.Token(SyntaxKind.NewKeyword), SF.ParseTypeName(t), SF.ArgumentList(SF.SeparatedList <ArgumentSyntax>()), null ))) ?? Enumerable.Empty <StatementSyntax>()); } } } void SaveAssemblyInfo(string name, string version, string tarball) { SyntaxTree assemblyInfo = SF.SyntaxTree( SF.CompilationUnit( SF.List <ExternAliasDirectiveSyntax>(), SF.List(new[] { SF.UsingDirective(SF.ParseName("Amazon.JSII.Runtime.Deputy")) }), SF.List(new[] { SF.AttributeList( SF.AttributeTargetSpecifier( SF.Identifier("assembly"), SF.Token(SyntaxKind.ColonToken) ), SF.SeparatedList(new[] { SF.Attribute( SF.ParseName("JsiiAssembly"), SF.ParseAttributeArgumentList($"({SF.Literal(name)}, {SF.Literal(version)}, {SF.Literal(tarball)})") ) }) ) }), SF.List <MemberDeclarationSyntax>() ).NormalizeWhitespace(elasticTrivia: true) ); string assemblyInfoPath = Path.Combine(packageOutputRoot, "AssemblyInfo.cs"); _fileSystem.File.WriteAllText(assemblyInfoPath, assemblyInfo.ToString()); } void SaveType(Type type) { string @namespace = symbols.GetNamespace(type); string directory = GetNamespaceDirectory(packageOutputRoot, @namespace); switch (type.Kind) { case TypeKind.Class: { var classType = (ClassType)type; if (classType.IsAbstract) { SaveTypeFile($"{symbols.GetAbstractClassProxyName(classType)}.cs", new AbstractClassProxyGenerator(assembly.Name, classType, symbols).CreateSyntaxTree()); } SaveTypeFile($"{symbols.GetName(type)}.cs", new ClassGenerator(assembly.Name, classType, symbols).CreateSyntaxTree()); return; } case TypeKind.Enum: { SaveTypeFile($"{symbols.GetName(type)}.cs", new EnumGenerator(assembly.Name, (EnumType)type, symbols).CreateSyntaxTree()); return; } case TypeKind.Interface: { InterfaceType interfaceType = (InterfaceType)type; SaveTypeFile($"{symbols.GetName(interfaceType)}.cs", new InterfaceGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree()); SaveTypeFile($"{symbols.GetInterfaceProxyName(interfaceType)}.cs", new InterfaceProxyGenerator(assembly.Name, interfaceType, symbols).CreateSyntaxTree()); if (interfaceType.IsDataType) { SaveTypeFile($"{symbols.GetInterfaceDefaultName(interfaceType)}.cs", new InterfaceDefaultGenerator(assembly.Name, interfaceType, symbols) .CreateSyntaxTree()); } return; } default: { throw new ArgumentException($"Unkown type kind: {type.Kind}", nameof(type)); } } void SaveTypeFile(string filename, SyntaxTree syntaxTree) { SaveSyntaxTree(directory, filename, syntaxTree); } } void SaveSyntaxTree(string directory, string filename, SyntaxTree syntaxTree) { if (!_fileSystem.Directory.Exists(directory)) { _fileSystem.Directory.CreateDirectory(directory); } _fileSystem.File.WriteAllText( Path.Combine(directory, filename), syntaxTree.ToString() ); } }
/// <summary> /// Returns syntax for the deserializer method. /// </summary> /// <param name="type">The type.</param> /// <param name="fields">The fields.</param> /// <returns>Syntax for the deserializer method.</returns> private static MemberDeclarationSyntax GenerateDeserializerMethod(Type type, List <FieldInfoMember> fields) { Expression <Action> deserializeInner = () => SerializationManager.DeserializeInner(default(Type), default(BinaryTokenStreamReader)); var streamParameter = SF.IdentifierName("stream"); var resultDeclaration = SF.LocalDeclarationStatement( SF.VariableDeclaration(type.GetTypeSyntax()) .AddVariables( SF.VariableDeclarator("result") .WithInitializer(SF.EqualsValueClause(GetObjectCreationExpressionSyntax(type))))); var resultVariable = SF.IdentifierName("result"); var body = new List <StatementSyntax> { resultDeclaration }; // Value types cannot be referenced, only copied, so there is no need to box & record instances of value types. if (!type.IsValueType) { // Record the result for cyclic deserialization. Expression <Action> recordObject = () => DeserializationContext.Current.RecordObject(default(object)); var currentSerializationContext = SyntaxFactory.AliasQualifiedName( SF.IdentifierName(SF.Token(SyntaxKind.GlobalKeyword)), SF.IdentifierName("Orleans")) .Qualify("Serialization") .Qualify("DeserializationContext") .Qualify("Current"); body.Add( SF.ExpressionStatement( recordObject.Invoke(currentSerializationContext) .AddArgumentListArguments(SF.Argument(resultVariable)))); } // Deserialize all fields. foreach (var field in fields) { var deserialized = deserializeInner.Invoke() .AddArgumentListArguments( SF.Argument(SF.TypeOfExpression(field.Type)), SF.Argument(streamParameter)); body.Add( SF.ExpressionStatement( field.GetSetter( resultVariable, SF.CastExpression(field.Type, deserialized)))); } body.Add(SF.ReturnStatement(SF.CastExpression(type.GetTypeSyntax(), resultVariable))); return (SF.MethodDeclaration(typeof(object).GetTypeSyntax(), "Deserializer") .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword)) .AddParameterListParameters( SF.Parameter(SF.Identifier("expected")).WithType(typeof(Type).GetTypeSyntax()), SF.Parameter(SF.Identifier("stream")).WithType(typeof(BinaryTokenStreamReader).GetTypeSyntax())) .AddBodyStatements(body.ToArray()) .AddAttributeLists( SF.AttributeList() .AddAttributes(SF.Attribute(typeof(DeserializerMethodAttribute).GetNameSyntax())))); }
/// <summary> /// Returns syntax for the deserializer method. /// </summary> /// <param name="type">The type.</param> /// <param name="fields">The fields.</param> /// <returns>Syntax for the deserializer method.</returns> private static MemberDeclarationSyntax GenerateDeserializerMethod(Type type, List <FieldInfoMember> fields) { Expression <Action <IDeserializationContext> > deserializeInner = ctx => ctx.DeserializeInner(default(Type)); var contextParameter = SF.IdentifierName("context"); var resultDeclaration = SF.LocalDeclarationStatement( SF.VariableDeclaration(type.GetTypeSyntax()) .AddVariables( SF.VariableDeclarator("result") .WithInitializer(SF.EqualsValueClause(GetObjectCreationExpressionSyntax(type))))); var resultVariable = SF.IdentifierName("result"); var body = new List <StatementSyntax> { resultDeclaration }; // Value types cannot be referenced, only copied, so there is no need to box & record instances of value types. if (!type.GetTypeInfo().IsValueType) { // Record the result for cyclic deserialization. Expression <Action <IDeserializationContext> > recordObject = ctx => ctx.RecordObject(default(object)); var currentSerializationContext = contextParameter; body.Add( SF.ExpressionStatement( recordObject.Invoke(currentSerializationContext) .AddArgumentListArguments(SF.Argument(resultVariable)))); } // Deserialize all fields. foreach (var field in fields) { var deserialized = deserializeInner.Invoke(contextParameter) .AddArgumentListArguments( SF.Argument(SF.TypeOfExpression(field.Type))); body.Add( SF.ExpressionStatement( field.GetSetter( resultVariable, SF.CastExpression(field.Type, deserialized)))); } // If the type implements the internal IOnDeserialized lifecycle method, invoke it's method now. if (typeof(IOnDeserialized).IsAssignableFrom(type)) { Expression <Action <IOnDeserialized> > onDeserializedMethod = _ => _.OnDeserialized(default(ISerializerContext)); // C#: ((IOnDeserialized)result).OnDeserialized(context); var typedResult = SF.ParenthesizedExpression(SF.CastExpression(typeof(IOnDeserialized).GetTypeSyntax(), resultVariable)); var invokeOnDeserialized = onDeserializedMethod.Invoke(typedResult).AddArgumentListArguments(SF.Argument(contextParameter)); body.Add(SF.ExpressionStatement(invokeOnDeserialized)); } body.Add(SF.ReturnStatement(SF.CastExpression(type.GetTypeSyntax(), resultVariable))); return (SF.MethodDeclaration(typeof(object).GetTypeSyntax(), "Deserializer") .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.StaticKeyword)) .AddParameterListParameters( SF.Parameter(SF.Identifier("expected")).WithType(typeof(Type).GetTypeSyntax()), SF.Parameter(SF.Identifier("context")).WithType(typeof(IDeserializationContext).GetTypeSyntax())) .AddBodyStatements(body.ToArray()) .AddAttributeLists( SF.AttributeList() .AddAttributes(SF.Attribute(typeof(DeserializerMethodAttribute).GetNameSyntax())))); }
/// <summary> /// Generates the class for the provided grain types. /// </summary> /// <param name="type">The grain interface type.</param> /// <param name="onEncounteredType"> /// The callback invoked when a type is encountered. /// </param> /// <returns> /// The generated class. /// </returns> internal static IEnumerable <TypeDeclarationSyntax> GenerateClass(Type type, Action <Type> onEncounteredType) { var typeInfo = type.GetTypeInfo(); var genericTypes = typeInfo.IsGenericTypeDefinition ? typeInfo.GetGenericArguments().Select(_ => SF.TypeParameter(_.ToString())).ToArray() : new TypeParameterSyntax[0]; var attributes = new List <AttributeSyntax> { CodeGeneratorCommon.GetGeneratedCodeAttributeSyntax(), SF.Attribute(typeof(ExcludeFromCodeCoverageAttribute).GetNameSyntax()), SF.Attribute(typeof(SerializerAttribute).GetNameSyntax()) .AddArgumentListArguments( SF.AttributeArgument(SF.TypeOfExpression(type.GetTypeSyntax(includeGenericParameters: false)))) }; var className = CodeGeneratorCommon.ClassPrefix + type.GetParseableName(GeneratedTypeNameOptions); var fields = GetFields(type); // Mark each field type for generation foreach (var field in fields) { var fieldType = field.FieldInfo.FieldType; onEncounteredType(fieldType); } var members = new List <MemberDeclarationSyntax>(GenerateStaticFields(fields)) { GenerateDeepCopierMethod(type, fields), GenerateSerializerMethod(type, fields), GenerateDeserializerMethod(type, fields), }; if (typeInfo.IsConstructedGenericType || !typeInfo.IsGenericTypeDefinition) { members.Add(GenerateRegisterMethod(type)); members.Add(GenerateConstructor(className)); attributes.Add(SF.Attribute(typeof(RegisterSerializerAttribute).GetNameSyntax())); } var classDeclaration = SF.ClassDeclaration(className) .AddModifiers(SF.Token(SyntaxKind.InternalKeyword)) .AddAttributeLists(SF.AttributeList().AddAttributes(attributes.ToArray())) .AddMembers(members.ToArray()) .AddConstraintClauses(type.GetTypeConstraintSyntax()); if (genericTypes.Length > 0) { classDeclaration = classDeclaration.AddTypeParameterListParameters(genericTypes); } var classes = new List <TypeDeclarationSyntax> { classDeclaration }; if (typeInfo.IsGenericTypeDefinition) { // Create a generic representation of the serializer type. var serializerType = SF.GenericName(classDeclaration.Identifier) .WithTypeArgumentList( SF.TypeArgumentList() .AddArguments( type.GetGenericArguments() .Select(_ => SF.OmittedTypeArgument()) .Cast <TypeSyntax>() .ToArray())); var registererClassName = className + "_" + string.Join("_", type.GetTypeInfo().GenericTypeParameters.Select(_ => _.Name)) + "_" + RegistererClassSuffix; classes.Add( SF.ClassDeclaration(registererClassName) .AddModifiers(SF.Token(SyntaxKind.InternalKeyword)) .AddAttributeLists( SF.AttributeList() .AddAttributes( CodeGeneratorCommon.GetGeneratedCodeAttributeSyntax(), SF.Attribute(typeof(ExcludeFromCodeCoverageAttribute).GetNameSyntax()), SF.Attribute(typeof(RegisterSerializerAttribute).GetNameSyntax()))) .AddMembers( GenerateMasterRegisterMethod(type, serializerType), GenerateConstructor(registererClassName))); } return(classes); }
public static byte[] CreateControllerCode(IService service) { var @file = SF.CompilationUnit(); var @namespace = SF.NamespaceDeclaration(SF.ParseName("MBase.ServiceHost.Controllers")).NormalizeWhitespace(); @file = @file .AddUsings(SF.UsingDirective(SF.IdentifierName("System"))); @file = @file .AddUsings(SF.UsingDirective(SF.IdentifierName("Microsoft.AspNetCore.Mvc"))); @file = @file .AddUsings(SF.UsingDirective(SF.IdentifierName("System.Threading.Tasks"))); @file = @file.AddUsings(SF.UsingDirective(SF.IdentifierName(service.GetType().Namespace))); @file = @file.AddUsings(SF.UsingDirective(SF.IdentifierName(service.GetType().Namespace + ".Models"))); foreach (var item in service.Commands.Where(m => typeof(ICommand).IsAssignableFrom(m.GetType()))) { @file = @file.AddUsings(SF.UsingDirective(SF.IdentifierName(item.GetType().Namespace))); } var classDeclaration = SF.ClassDeclaration(service.GetType().Name.ToString() + "Controller") .AddModifiers(SF.Token(SyntaxKind.PublicKeyword)) .AddBaseListTypes(SF.SimpleBaseType(SF.ParseTypeName("ControllerBase"))) .WithAttributeLists( SF.List( new AttributeListSyntax[] { SF.AttributeList( SF.SingletonSeparatedList( SF.Attribute(SF.IdentifierName("Route")) .WithArgumentList( SF.AttributeArgumentList( SF.SingletonSeparatedList( SF.AttributeArgument( SF.LiteralExpression(SyntaxKind.StringLiteralExpression, SF.Literal($"api/[controller]")))))))), SF.AttributeList( SF.SingletonSeparatedList( SF.Attribute(SF.IdentifierName("ApiController")))) })); List <MemberDeclarationSyntax> controllerMembers = new List <MemberDeclarationSyntax>(); controllerMembers.Add( SF.FieldDeclaration( SF.VariableDeclaration( SF.ParseTypeName(service.GetType().Name)) .AddVariables(SF.VariableDeclarator("_service"))) .AddModifiers(SF.Token(SyntaxKind.PrivateKeyword))); controllerMembers.Add( SF.ConstructorDeclaration(service.GetType().Name.ToString() + "Controller") .WithParameterList( SF.ParameterList( SF.SingletonSeparatedList( SF.Parameter( SF.Identifier("service")) .WithType( SF.IdentifierName("IService"))) )) .AddModifiers(SF.Token(SyntaxKind.PublicKeyword)) .WithBody(SF.Block(SF.ParseStatement($"this._service = ({service.GetType().Name})service;")))); foreach (var item in service.Commands.Where(m => typeof(ICommand).IsAssignableFrom(m.GetType()))) { var syntax = @$ " var response = await CommandHelper.ExecuteMethod<{item.Name}>(new {item.Name}(),new Request<{item.Name}>(request, new MessageEnvelope()));