public void BeforeCompile(IBeforeCompileContext context) { // Firstly, I need to resolve the namespace of the ModuleProvider instance in this current compilation. string ns = GetModuleProviderNamespace(context.Compilation.SyntaxTrees); // Next, get all the available modules in assembly and compilation references. var modules = GetAvailableModules(context.Compilation).ToList(); // Map them to a collection of statements var statements = modules.Select(m => F.ParseStatement("AddModule<" + module + ">();")).ToList(); // Now, I'll create the dynamic implementation as a private class. var cu = F.CompilationUnit() .AddMembers( F.NamespaceDeclaration(F.IdentifierName(ns)) .AddMembers( F.ClassDeclaration("ModuleProvider") .WithModifiers(F.TokenList(F.Token(K.PartialKeyword))) .AddMembers( F.MethodDeclaration(F.PredefinedType(F.Token(K.VoidKeyword)), "Setup") .WithModifiers( F.TokenList( F.Token(K.ProtectedKeyword), F.Token(K.OverrideKeyword))) .WithBody(F.Block(statements)) ) ) ) .NormalizeWhitespace(indentation("\t")); var tree = T.Create(cu); context.Compilation = context.Compilation.AddSyntaxTrees(tree); }
private static string GenerateCodeBehindClass(string className, string contents, RazorCodeDocument razorCodeDocument) { var namespaceNode = (NamespaceDeclarationIntermediateNode)razorCodeDocument .GetDocumentIntermediateNode() .FindDescendantNodes <IntermediateNode>() .FirstOrDefault(n => n is NamespaceDeclarationIntermediateNode); var mock = (ClassDeclarationSyntax)CSharpSyntaxFactory.ParseMemberDeclaration($"class Class {contents}"); var @class = CSharpSyntaxFactory .ClassDeclaration(className) .AddModifiers(CSharpSyntaxFactory.Token(CSharpSyntaxKind.PublicKeyword), CSharpSyntaxFactory.Token(CSharpSyntaxKind.PartialKeyword)) .AddMembers(mock.Members.ToArray()); var @namespace = CSharpSyntaxFactory .NamespaceDeclaration(CSharpSyntaxFactory.ParseName(namespaceNode.Content)) .AddMembers(@class); var usings = FindUsings(razorCodeDocument) .Select(u => CSharpSyntaxFactory.UsingDirective(CSharpSyntaxFactory.ParseName(u))) .ToArray(); var compilationUnit = CSharpSyntaxFactory .CompilationUnit() .AddUsings(usings) .AddMembers(@namespace); return(compilationUnit.NormalizeWhitespace().ToFullString()); }
public static CompilationUnitSyntax GenUnit(NamespaceDeclarationSyntax @namespace, IEnumerable <UsingDirectiveSyntax> usings, IEnumerable <AttributeListSyntax> attributes) { return(SF.CompilationUnit( externs: SF.List <ExternAliasDirectiveSyntax>(), usings: SF.List(usings), attributeLists: SF.List(attributes), members: SF.List <MemberDeclarationSyntax>(new[] { @namespace })) .NormalizeWhitespace(" ", true)); }
private SyntaxTree CreateSyntaxTree() { var compilationUnit = SF .CompilationUnit() .AddUsings ( SF.UsingDirective (SF.ParseName("System")) ); var ns = SF .NamespaceDeclaration(SF.IdentifierName("SynTreeFred")); var cls = SF .ClassDeclaration("Henry") .AddModifiers(SF.Token(SyntaxKind.PublicKeyword)); // How to define base class and interfaces, with/without generics // //cls = cls.AddBaseListTypes( // SF.SimpleBaseType(SF.ParseTypeName("Object")), // SF.SimpleBaseType(SF.ParseTypeName("IEnumerable<string>"))); var inti = SF .VariableDeclaration(SF.ParseTypeName("int")) .AddVariables ( SF.VariableDeclarator ( SF.Identifier("i"), null, SF.EqualsValueClause ( SF.LiteralExpression ( SyntaxKind.NumericLiteralExpression, SF.Literal(12) ) ) ) ); var field = SF.FieldDeclaration(inti) .AddModifiers(SF.Token(SyntaxKind.PrivateKeyword)); var syntax = SF.ParseStatement("return ++i;"); var methodDeclaration = SF .MethodDeclaration(SF.ParseTypeName("int"), "GetNextInt") .AddModifiers(SF.Token(SyntaxKind.PublicKeyword)) .WithBody(SF.Block(syntax)); cls = cls.AddMembers(field, methodDeclaration); ns = ns.AddMembers(cls); compilationUnit = compilationUnit.AddMembers(ns); return(compilationUnit.SyntaxTree); }
private static CompilationUnitSyntax GenerateCompilationUnit(IList <ActorDescription> actors) { var usings = TypeUtil.GetNamespaces(actors, typeof(TaskUtility)).Select(SF.UsingDirective).ToList(); var ns = SF.NamespaceDeclaration(SF.ParseName("Generated" + DateTime.UtcNow.Ticks)) .AddUsings(usings.ToArray()) .AddMembers(actors.Select(GenerateClass).ToArray()); return(SF.CompilationUnit().AddMembers(ns)); }
public static CompilationUnitSyntax GenUnit(MemberDeclarationSyntax @class, string nameSpace, IEnumerable <UsingDirectiveSyntax> usings, IEnumerable <AttributeListSyntax> attributes) { var @namespace = SF.NamespaceDeclaration(SF.ParseName(nameSpace)) .AddMembers(@class); return(SF.CompilationUnit( externs: SF.List <ExternAliasDirectiveSyntax>(), usings: SF.List(usings), attributeLists: SF.List(attributes), members: SF.List <MemberDeclarationSyntax>(new[] { @namespace })) .NormalizeWhitespace(" ", true)); }
/// <summary> /// Create the <see cref="CompilationUnitSyntax"/> of the current <see cref="_classes"/>. /// </summary> /// <returns>The <see cref="CompilationUnitSyntax"/>.</returns> private CompilationUnitSyntax CreateCompilationUnit() { return(S.CompilationUnit() .AddUsings( S.UsingDirective(S.ParseName("System")), S.UsingDirective(S.ParseName(typeof(Task).Namespace)), S.UsingDirective(S.ParseName(typeof(MessageContext).Namespace)), S.UsingDirective(S.ParseName(typeof(IArgumentReader).Namespace)), S.UsingDirective(S.ParseName(typeof(ICommand).Namespace)), S.UsingDirective(S.ParseName(typeof(IDiscordUser).Namespace)), S.UsingDirective(S.ParseName(typeof(ServiceProviderServiceExtensions).Namespace)) ) .AddMembers( S.NamespaceDeclaration(S.IdentifierName(Namespace)) .AddMembers(_classes.Select(kv => kv.Value.DeclarationSyntax).Cast <MemberDeclarationSyntax>().ToArray()) )); }
internal ClassGenerator(Builder builder) { _compilationUnit = SF.CompilationUnit() .WithUsings(GenerateUsings(builder._usings)) .WithMembers(SF.SingletonList <MemberDeclarationSyntax>(SF.NamespaceDeclaration(GenerateNamespaceSyntax(builder._namespace)) .WithMembers( SF.SingletonList <MemberDeclarationSyntax>( SF.ClassDeclaration(builder._className) .WithModifiers( SF.TokenList( SF.Token(SyntaxKind.PublicKeyword))) .WithAttributeLists( SF.SingletonList( SF.AttributeList( GenerateAttributes(builder._attributes)))) .WithMembers(GenerateProperties(builder._properties)))))) .NormalizeWhitespace(); }
public CompilationUnitSyntax GetCompilationUnitForContext(WebContext context) { var cu = SF.CompilationUnit() .WithUsings( SF.List( new List <UsingDirectiveSyntax> { SF.UsingDirective(SF.ParseName(WebInfoAssemblyName)), SF.UsingDirective(SF.ParseName("System.Collections.Generic")) } ) ); var webInfoGen = GetClassForWebElement(context); cu = cu.AddMembers(webInfoGen.ClassSyntax); return(cu); }
private static SyntaxNode MoveToApplication(SyntaxNode root, IEnumerable <SyntaxNode> members, Scope scope) { var appClass = root .DescendantNodes() .OfType <ClassDeclarationSyntax>() .Where(@class => @class.Identifier.ToString() == "application") .FirstOrDefault(); if (appClass == null) { appClass = CSharp.ClassDeclaration("application"); } return(CSharp.CompilationUnit() .WithMembers(CSharp.List(new[] { (MemberDeclarationSyntax)appClass .WithMembers(CSharp.List(members)) }))); }
private static SyntaxNode MoveToMain(SyntaxNode root, IEnumerable <SyntaxNode> statements, Scope scope) { var appClass = root .DescendantNodes() .OfType <ClassDeclarationSyntax>() .Where(@class => @class.Identifier.ToString() == "application") .FirstOrDefault(); if (appClass == null) { appClass = CSharp.ClassDeclaration("application"); } return(CSharp.CompilationUnit() .WithMembers(CSharp.List(new MemberDeclarationSyntax[] { appClass.AddMembers( CSharp.MethodDeclaration(CSharp.ParseTypeName("int"), "main") .WithModifiers(CSharp.TokenList(CSharp.Token(SyntaxKind.PrivateKeyword))) .WithBody(CSharp.Block() .WithStatements(CSharp.List(statements .Union(new [] { CSharp.ParseStatement("return 0;") }))))) }))); }
public string ToFullString() { var unit = SF.CompilationUnit(); if (_options.IsJsonSerializable) { unit = unit.AddUsings(SF.UsingDirective(SF.IdentifierName("Newtonsoft.Json"))); } CSharpSyntaxNode rootNode; if (!string.IsNullOrEmpty(_options.Namespace)) { rootNode = unit.AddMembers( SF.NamespaceDeclaration(SF.IdentifierName(_options.Namespace)) .AddMembers(_rootNode)); } else { rootNode = unit.AddMembers(_rootNode); } return(Formatter.Format(rootNode, MSBuildWorkspace.Create()).ToFullString()); }
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() ); } } }
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() ); } }
public static (FixedPointType, SyntaxTree) Generate2x2Type(FixedPointType fType) { // string dimsName = shape.Select(a => a.ToString()).Aggregate((a, b) => a + "x" + b); // this would be for general tensors... string dimsName = string.Format("2x2"); string typeName = string.Format("mat{0}_{1}", dimsName, fType.name); var usingStrings = new List <string> { "System", "System.Runtime.CompilerServices", "System.Runtime.InteropServices", "UnityEngine", "Unity.Mathematics", "Ramjet.Mathematics.FixedPoint", }; var usings = new SyntaxList <UsingDirectiveSyntax>( from s in usingStrings select SF.UsingDirective(SF.ParseName(s))); var unit = SF.CompilationUnit().WithUsings(usings); var nameSpace = SF.NamespaceDeclaration(SF.ParseName("Ramjet.Mathematics.LinearAlgebra")); var type = SF.StructDeclaration(typeName) .AddModifiers(SF.Token(SK.PublicKeyword)) .WithAttributeLists(Utils.GenerateStructLayoutAttributes()); var fields = new List <MemberDeclarationSyntax>(); var rowTypeName = $@"vec2_{fType.name}"; var rowTypeSizeBytes = (fType.wordLength * 2) / 8; int fieldOffset = 0; for (int i = 0; i < 2; i++) { var row = SF.ParseMemberDeclaration($@"[FieldOffset({fieldOffset})] public {fType.name} c{i};"); fields.Add(row); fieldOffset += rowTypeSizeBytes; } type = type.AddMembers(fields.ToArray()); // var zero = SF.ParseMemberDeclaration($@"public static readonly {typeName} Zero = {typeName}.FromInt(0);"); // var constructorArgs = fields.Select((coeff, index) => $@"{fType.name} {CoefficientNames[index]}").Aggregate((a, b) => a + ", " + b); // var constructorAssignments = fields.Select((coeff, index) => $@"this.{CoefficientNames[index]} = {CoefficientNames[index]}").Aggregate((a, b) => a + ";\n" + b) + ";"; // var constructor = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public {typeName}({constructorArgs}) {{ // {constructorAssignments} // }}"); // type = type.AddMembers( // constructor); // var fromIntArgs = fields.Select((coeff, index) => $@"int {CoefficientNames[index]}").Aggregate((a, b) => a + ", " + b); // var fromIntAssignments = fields.Select((coeff, index) => $@"{fType.name}.FromInt({CoefficientNames[index]})").Aggregate((a, b) => a + ",\n" + b); // var fromInt = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static {typeName} FromInt({fromIntArgs}) {{ // return new {typeName}( // {fromIntAssignments} // ); // }}"); // var fromFloatArgs = fields.Select((coeff, index) => $@"float {CoefficientNames[index]}").Aggregate((a, b) => a + ", " + b); // var fromFloatAssignments = fields.Select((coeff, index) => $@"{fType.name}.FromFloat({CoefficientNames[index]})").Aggregate((a, b) => a + ",\n" + b); // var fromFloat = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static {typeName} FromFloat({fromFloatArgs}) {{ // return new {typeName}( // {fromFloatAssignments} // ); // }}"); // var fromDoubleArgs = fields.Select((coeff, index) => $@"double {CoefficientNames[index]}").Aggregate((a, b) => a + ", " + b); // var fromDoubleAssignments = fields.Select((coeff, index) => $@"{fType.name}.FromDouble({CoefficientNames[index]})").Aggregate((a, b) => a + ",\n" + b); // var fromDouble = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static {typeName} FromFloat({fromDoubleArgs}) {{ // return new {typeName}( // {fromDoubleAssignments} // ); // }}"); // type = type.AddMembers( // fromInt, // fromFloat, // fromDouble // ); // var opAddInstructions = fields.Select((coeff, index) => $@"lhs.{CoefficientNames[index]} + rhs.{CoefficientNames[index]}") // .Aggregate((a, b) => a + ", \n" + b); // var opAdd = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static {typeName} operator +({typeName} lhs, {typeName} rhs) {{ // return new {typeName}( // {opAddInstructions} // ); // }}"); // var opSubInstructions = fields.Select((coeff, index) => $@"lhs.{CoefficientNames[index]} - rhs.{CoefficientNames[index]}") // .Aggregate((a, b) => a + ", \n" + b); // var opSub = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static {typeName} operator -({typeName} lhs, {typeName} rhs) {{ // return new {typeName}( // {opSubInstructions} // ); // }}"); // var opMulScalarRightInstructions = fields.Select((coeff, index) => $@"lhs.{CoefficientNames[index]} * rhs") // .Aggregate((a, b) => a + ", \n" + b); // var opMulScalarRight = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static {typeName} operator *({typeName} lhs, {fType.name} rhs) {{ // return new {typeName}( // {opMulScalarRightInstructions} // ); // }}"); // var opDivScalarRightInstructions = fields.Select((coeff, index) => $@"lhs.{CoefficientNames[index]} / rhs") // .Aggregate((a, b) => a + ", \n" + b); // var opDivScalarRight = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static {typeName} operator /({typeName} lhs, {fType.name} rhs) {{ // return new {typeName}( // {opDivScalarRightInstructions} // ); // }}"); // type = type.AddMembers( // opAdd, // opSub, // opMulScalarRight, // opDivScalarRight); // /* Equality */ // var eqInstructions = fields.Select((coeff, index) => $@"this.{CoefficientNames[index]} == rhs.{CoefficientNames[index]}") // .Aggregate((a, b) => a + " &&\n" + b); // var equals = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public bool Equals({typeName} rhs) {{ // return {eqInstructions}; // }}"); // var equalsObj = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public override bool Equals(object o) {{ // if (!(o is {typeName})) {{ // return false; // }} // return Equals(({typeName})o); // }}"); // var opEq = SF.ParseMemberDeclaration($@" // public static bool operator ==({typeName} lhs, {typeName} rhs) {{ // return lhs.Equals(rhs); // }}"); // var opNEq = SF.ParseMemberDeclaration($@" // public static bool operator !=({typeName} lhs, {typeName} rhs) {{ // return !lhs.Equals(rhs); // }}"); // type = type.AddMembers( // equals, // equalsObj, // opEq, // opNEq); // // Other // /* // GetHashCode // Todo: None of these make particular sense for each type yet... // */ // var getHashCodeInstructions = fields.Select((coeff, index) => $@"this.{CoefficientNames[index]}.v") // .Aggregate((a, b) => a + " ^\n" + b); // var getHashCode = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public override int GetHashCode() {{ // return (int)({getHashCodeInstructions}); // }}"); // var toStringReplaceList = fields.Select((coeff, index) => $@"{{{index}:0.000}}") // .Aggregate((a, b) => a + ", " + b); // var toStringCoeffs = fields.Select((coeff, index) => $@"{fType.name}.ToFloat(this.{CoefficientNames[index]})") // .Aggregate((a, b) => a + ", " + b); // var toString = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public override string ToString() {{ // return string.Format(""{typeName}({toStringReplaceList})"", {toStringCoeffs}); // }}"); // var toStringFormat = SF.ParseMemberDeclaration($@" // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public string ToString(string format, IFormatProvider formatProvider) {{ // return ToString(); // }}"); // type = type.AddMembers( // getHashCode, // toString, // toStringFormat); nameSpace = nameSpace.AddMembers(type); unit = unit.AddMembers(nameSpace); return(fType, CSharpSyntaxTree.Create(unit)); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); // TODO: Replace the following code with your own analysis, generating a CodeAction for each fix to suggest var diagnostic = context.Diagnostics.First(); if (diagnostic.Id == StacksAnalyzer.CommandsEndWithCommand.Id) { var diagnosticSpan = diagnostic.Location.SourceSpan; // Find the type declaration identified by the diagnostic. var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType <TypeDeclarationSyntax>().First(); // Register a code action that will invoke the fix. context.RegisterCodeFix( CodeAction.Create( title: "Append 'Command'", createChangedSolution: c => this.AppendCommandText(context.Document, "Command", declaration, c), equivalenceKey: "Append 'Command'"), diagnostic); } else if (diagnostic.Id == StacksAnalyzer.EventsEndWithEvents.Id) { var diagnosticSpan = diagnostic.Location.SourceSpan; // Find the type declaration identified by the diagnostic. var declaration = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType <TypeDeclarationSyntax>().First(); // Register a code action that will invoke the fix. context.RegisterCodeFix( CodeAction.Create( title: "Append 'Event'", createChangedSolution: c => this.AppendCommandText(context.Document, "Event", declaration, c), equivalenceKey: "Append 'Event'"), diagnostic); } else if (diagnostic.Id == StacksAnalyzer.MessagePropertiesAreImmutable.Id) { var diagnosticSpan = diagnostic.Location.SourceSpan; var property = root.FindNode(diagnosticSpan) as PropertyDeclarationSyntax; // Register a code action that will invoke the fix. context.RegisterCodeFix( CodeAction.Create( title: "Remove setter", createChangedDocument: async c => { var previousWhiteSpacesToken = SF.Token(property.GetLeadingTrivia(), SyntaxKind.StringLiteralToken, SyntaxTriviaList.Empty); var target = property.WithModifiers(SF.TokenList(previousWhiteSpacesToken, SF.Token(SyntaxKind.PublicKeyword))) .WithAccessorList(SF.AccessorList(SF.List(new[] { SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)) }))); var updated = await context.Document.GetSyntaxRootAsync(c); return(context.Document.WithSyntaxRoot(updated.ReplaceNode(property, new[] { target }))); }, equivalenceKey: "Remove setter"), diagnostic); context.RegisterCodeFix( CodeAction.Create( title: "Make setter private", createChangedDocument: async c => { var previousWhiteSpacesToken = SF.Token(property.GetLeadingTrivia(), SyntaxKind.StringLiteralToken, SyntaxTriviaList.Empty); var target = property.WithModifiers(SF.TokenList(previousWhiteSpacesToken, SF.Token(SyntaxKind.PublicKeyword))) .WithAccessorList(SF.AccessorList(SF.List(new[] { SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)), SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) .WithModifiers(SF.TokenList(SF.Token(SyntaxKind.PrivateKeyword))) .WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)) }))); var updated = await context.Document.GetSyntaxRootAsync(c); return(context.Document.WithSyntaxRoot(updated.ReplaceNode(property, new[] { target }))); }, equivalenceKey: "Make setter private"), diagnostic); } else if (diagnostic.Id == StacksAnalyzer.UseCaseShouldHaveRules.Id) { var diagnosticSpan = diagnostic.Location.SourceSpan; var property = root.FindNode(diagnosticSpan) as ClassDeclarationSyntax; context.RegisterCodeFix( CodeAction.Create( title: "Create business rule", createChangedDocument: async c => { //property.Identifier.ValueText; var cu = SF.CompilationUnit().AddUsings( SF.UsingDirective(SF.IdentifierName("System")), SF.UsingDirective(SF.IdentifierName("Slalom.Stacks.Messaging.Validation"))); NamespaceDeclarationSyntax namespaceDeclarationSyntax = null; if (!SyntaxNodeHelper.TryGetParentSyntax(property, out namespaceDeclarationSyntax)) { } var ns = SF.NamespaceDeclaration(namespaceDeclarationSyntax.Name); var comp = await context.Document.Project.GetCompilationAsync(); string name = property.Identifier.Value + "_rule"; var command = ((IdentifierNameSyntax)((GenericNameSyntax)property.BaseList.Types[0].Type).TypeArgumentList.Arguments[0]).Identifier.ValueText; //if (comp.GetSymbolsWithName(x => x == name) != null) //{ // int i = 1; // var current = name + i; // while (comp.GetSymbolsWithName(x => x == current) != null) // { // i++; // } //} var cl = SF.ClassDeclaration(name) .WithModifiers(SF.TokenList(SF.Token(SyntaxKind.PublicKeyword))) .AddBaseListTypes(SF.SimpleBaseType(SF.ParseTypeName("BusinessRule<" + command + ">"))); ns = ns.AddMembers(cl); cu = cu.AddMembers(ns); SyntaxNode formattedNode = Formatter.Format(cu, context.Document.Project.Solution.Workspace); StringBuilder sb = new StringBuilder(); using (StringWriter writer = new StringWriter(sb)) { formattedNode.WriteTo(writer); } return(context.Document.Project.AddDocument(name + ".cs", sb.ToString(), namespaceDeclarationSyntax.Name.ToString().Split('.').Skip(1).Concat(new[] { "Rules" }))); }, equivalenceKey: "Create business rule"), diagnostic); } }
/// <summary> /// Generates a syntax tree for the provided assemblies. /// </summary> /// <param name="targetAssembly">The assemblies used for accessiblity checks, or <see langword="null"/> during runtime code generation.</param> /// <param name="assemblies">The assemblies to generate code for.</param> /// <returns>The generated syntax tree.</returns> private GeneratedSyntax GenerateCode(Assembly targetAssembly, List <Assembly> assemblies) { var features = new FeatureDescriptions(); var members = new List <MemberDeclarationSyntax>(); // Expand the list of included assemblies and types. var knownAssemblies = new Dictionary <Assembly, KnownAssemblyAttribute>( assemblies.ToDictionary(k => k, k => default(KnownAssemblyAttribute))); foreach (var attribute in assemblies.SelectMany(asm => asm.GetCustomAttributes <KnownAssemblyAttribute>())) { knownAssemblies[attribute.Assembly] = attribute; } if (logger.IsEnabled(LogLevel.Information)) { logger.Info($"Generating code for assemblies: {string.Join(", ", knownAssemblies.Keys.Select(a => a.FullName))}"); } // Get types from assemblies which reference Orleans and are not generated assemblies. var grainClasses = new HashSet <Type>(); var grainInterfaces = new HashSet <Type>(); foreach (var pair in knownAssemblies) { var assembly = pair.Key; var treatTypesAsSerializable = pair.Value?.TreatTypesAsSerializable ?? false; foreach (var type in TypeUtils.GetDefinedTypes(assembly, this.logger)) { if (treatTypesAsSerializable || type.IsSerializable || TypeHasKnownBase(type)) { string logContext = null; if (logger.IsEnabled(LogLevel.Trace)) { if (treatTypesAsSerializable) { logContext = $"known assembly {assembly.GetName().Name} where 'TreatTypesAsSerializable' = true"; } else if (type.IsSerializable) { logContext = $"known assembly {assembly.GetName().Name} where type is [Serializable]"; } else if (type.IsSerializable) { logContext = $"known assembly {assembly.GetName().Name} where type has known base type."; } } serializableTypes.RecordType(type, targetAssembly, logContext); } // Include grain interfaces and classes. var isGrainInterface = GrainInterfaceUtils.IsGrainInterface(type); var isGrainClass = TypeUtils.IsConcreteGrainClass(type); if (isGrainInterface || isGrainClass) { // If code generation is being performed at runtime, the interface must be accessible to the generated code. if (!TypeUtilities.IsAccessibleFromAssembly(type, targetAssembly)) { if (this.logger.IsEnabled(LogLevel.Debug)) { this.logger.Debug("Skipping inaccessible grain type, {0}", type.GetParseableName()); } continue; } // Attempt to generate serializers for grain state classes, i.e, T in Grain<T>. var baseType = type.BaseType; if (baseType != null && baseType.IsConstructedGenericType) { foreach (var arg in baseType.GetGenericArguments()) { string logContext = null; if (logger.IsEnabled(LogLevel.Trace)) { logContext = "generic base type of " + type.GetLogFormat(); } this.serializableTypes.RecordType(arg, targetAssembly, logContext); } } // Skip classes generated by this generator. if (IsOrleansGeneratedCode(type)) { if (this.logger.IsEnabled(LogLevel.Debug)) { this.logger.Debug("Skipping generated grain type, {0}", type.GetParseableName()); } continue; } if (this.knownGrainTypes.Contains(type)) { if (this.logger.IsEnabled(LogLevel.Debug)) { this.logger.Debug("Skipping grain type {0} since it already has generated code.", type.GetParseableName()); } continue; } if (isGrainClass) { if (this.logger.IsEnabled(LogLevel.Information)) { this.logger.Info("Found grain implementation class: {0}", type.GetParseableName()); } grainClasses.Add(type); } if (isGrainInterface) { if (this.logger.IsEnabled(LogLevel.Information)) { this.logger.Info("Found grain interface: {0}", type.GetParseableName()); } GrainInterfaceUtils.ValidateInterfaceRules(type); grainInterfaces.Add(type); } } } } // Group the types by namespace and generate the required code in each namespace. foreach (var groupedGrainInterfaces in grainInterfaces.GroupBy(_ => CodeGeneratorCommon.GetGeneratedNamespace(_))) { var namespaceName = groupedGrainInterfaces.Key; var namespaceMembers = new List <MemberDeclarationSyntax>(); foreach (var grainInterface in groupedGrainInterfaces) { var referenceTypeName = GrainReferenceGenerator.GetGeneratedClassName(grainInterface); var invokerTypeName = GrainMethodInvokerGenerator.GetGeneratedClassName(grainInterface); namespaceMembers.Add( GrainReferenceGenerator.GenerateClass( grainInterface, referenceTypeName, encounteredType => { string logContext = null; if (logger.IsEnabled(LogLevel.Trace)) { logContext = "used by grain type " + grainInterface.GetLogFormat(); } this.serializableTypes.RecordType(encounteredType, targetAssembly, logContext); })); namespaceMembers.Add(GrainMethodInvokerGenerator.GenerateClass(grainInterface, invokerTypeName)); var genericTypeSuffix = GetGenericTypeSuffix(grainInterface.GetGenericArguments().Length); features.GrainInterfaces.Add( new GrainInterfaceDescription { Interface = grainInterface.GetTypeSyntax(includeGenericParameters: false), Reference = SF.ParseTypeName(namespaceName + '.' + referenceTypeName + genericTypeSuffix), Invoker = SF.ParseTypeName(namespaceName + '.' + invokerTypeName + genericTypeSuffix), InterfaceId = GrainInterfaceUtils.GetGrainInterfaceId(grainInterface) }); } members.Add(CreateNamespace(namespaceName, namespaceMembers)); } foreach (var type in grainClasses) { features.GrainClasses.Add( new GrainClassDescription { ClassType = type.GetTypeSyntax(includeGenericParameters: false) }); } // Generate serializers into their own namespace. var serializerNamespace = this.GenerateSerializers(targetAssembly, features); members.Add(serializerNamespace); // Add serialization metadata for the types which were encountered. this.AddSerializationTypes(features.Serializers, targetAssembly, knownAssemblies.Keys.ToList()); foreach (var attribute in knownAssemblies.Keys.SelectMany(asm => asm.GetCustomAttributes <ConsiderForCodeGenerationAttribute>())) { this.serializableTypes.RecordType(attribute.Type, targetAssembly, "[ConsiderForCodeGeneration]"); if (attribute.ThrowOnFailure && !this.serializableTypes.IsTypeRecorded(attribute.Type) && !this.serializableTypes.IsTypeIgnored(attribute.Type)) { throw new CodeGenerationException( $"Found {attribute.GetType().Name} for type {attribute.Type.GetParseableName()}, but code" + " could not be generated. Ensure that the type is accessible."); } } // Generate metadata directives for all of the relevant types. var(attributeDeclarations, memberDeclarations) = FeaturePopulatorGenerator.GenerateSyntax(targetAssembly, features); members.AddRange(memberDeclarations); var compilationUnit = SF.CompilationUnit().AddAttributeLists(attributeDeclarations.ToArray()).AddMembers(members.ToArray()); return(new GeneratedSyntax { SourceAssemblies = knownAssemblies.Keys.ToList(), Syntax = compilationUnit }); }
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()));