public async Task <CodeGenResult> CodeGen(Workspace workspace, Project project) { var usings = new HashSet <string>(); usings.UnionWith(GetCommonUsings()); CompilationUnitSyntax cu = SF.CompilationUnit(); foreach (Document document in project.Documents) { SyntaxTree syntaxTree = await document.GetSyntaxTreeAsync(); SemanticModel semanticModel = await document.GetSemanticModelAsync(); IEnumerable <InterfaceDeclarationSyntax> interfaces = syntaxTree.GetRoot().DescendantNodes().OfType <InterfaceDeclarationSyntax>(); bool copyDocumentUsings = false; foreach (var interfaceNode in interfaces) { ClassDeclarationSyntax classDclr = GenerateApiControllerForInterface(interfaceNode, semanticModel); if (classDclr == null) { continue; } // only copy the usings in the document if at least one ApiController is generated copyDocumentUsings = true; var namespaceNode = interfaceNode.Parent as NamespaceDeclarationSyntax; // ReSharper disable once PossibleNullReferenceException usings.UnionWith(namespaceNode.Usings.Select(@using => @using.Name.ToString())); // use the same namespace in the generated class string fullNameSpace = semanticModel.GetDeclaredSymbol(namespaceNode).ToString(); NamespaceDeclarationSyntax namespaceDclr = SF.NamespaceDeclaration(SF.IdentifierName(fullNameSpace)).WithUsings(namespaceNode.Usings); namespaceDclr = namespaceDclr.AddMembers(classDclr); cu = cu.AddMembers(namespaceDclr); } if (copyDocumentUsings) { usings.UnionWith(syntaxTree.GetRoot().DescendantNodes().OfType <UsingDirectiveSyntax>().Select(@using => @using.Name.ToString())); } } return(new CodeGenResult(Formatter.Format(cu, workspace).ToString(), usings)); }
public SyntaxTree Generate(TransducerCompilation source) { var stb = source.Transducer; var sourceNamespace = source.DeclarationType.ContainingNamespace.DeclaringSyntaxReferences[0].GetSyntax() as NamespaceDeclarationSyntax; if (sourceNamespace == null) { throw new CodeGenerationException("Containing namespace declaration not found for " + source.DeclarationType); } // Follow the declaration of the original (partial) class var classDecl = source.DeclarationType.DeclaringSyntaxReferences.Select(r => r.GetSyntax()).OfType <ClassDeclarationSyntax>().FirstOrDefault() .WithLeadingTrivia().WithTrailingTrivia() // Strip any trivia .WithMembers(SF.List <MemberDeclarationSyntax>()) .WithAttributeLists(SF.List <AttributeListSyntax>()); if (classDecl == null) { throw new Exception("Class declaration for " + source.DeclarationType + " not found"); } classDecl = _concreteCG.Generate(source, stb, classDecl); var automataNamespace = SF.IdentifierName("Microsoft").Qualified(SF.IdentifierName("Automata")).Qualified(SF.IdentifierName("CSharpFrontend")); var root = SF.CompilationUnit() .WithUsings(SF.List(new[] { SF.UsingDirective(SF.IdentifierName("System")), SF.UsingDirective(SF.IdentifierName("System").Qualified(SF.IdentifierName("Text"))), SF.UsingDirective(SF.IdentifierName("System").Qualified(SF.IdentifierName("IO"))), SF.UsingDirective(SF.IdentifierName("System").Qualified(SF.IdentifierName("Collections")).Qualified(SF.IdentifierName("Generic"))), SF.UsingDirective(automataNamespace), })) .WithMembers(SF.SingletonList((MemberDeclarationSyntax)SF.NamespaceDeclaration(sourceNamespace.Name) .WithMembers(SF.SingletonList((MemberDeclarationSyntax)classDecl)))); var normalized = root.NormalizeWhitespace(); return(SF.SyntaxTree(normalized)); }
/// <summary> /// Generates a syntax tree for the provided assemblies. /// </summary> /// <param name="assemblies">The assemblies to generate code for.</param> /// <param name="runtime">Whether or not runtime code generation is being performed.</param> /// <returns>The generated syntax tree.</returns> private GeneratedSyntax GenerateForAssemblies(List <Assembly> assemblies, bool runtime) { if (Logger.IsVerbose) { Logger.Verbose( "Generating code for assemblies: {0}", string.Join(", ", assemblies.Select(_ => _.FullName))); } Assembly targetAssembly; HashSet <Type> ignoredTypes; if (runtime) { // Ignore types which have already been accounted for. ignoredTypes = GetTypesWithGeneratedSupportClasses(); targetAssembly = null; } else { ignoredTypes = new HashSet <Type>(); targetAssembly = assemblies.FirstOrDefault(); } var members = new List <MemberDeclarationSyntax>(); // Include assemblies which are marked as included. var knownAssemblyAttributes = new Dictionary <Assembly, KnownAssemblyAttribute>(); var knownAssemblies = new HashSet <Assembly>(); foreach (var attribute in assemblies.SelectMany(asm => asm.GetCustomAttributes <KnownAssemblyAttribute>())) { knownAssemblyAttributes[attribute.Assembly] = attribute; knownAssemblies.Add(attribute.Assembly); } if (knownAssemblies.Count > 0) { knownAssemblies.UnionWith(assemblies); assemblies = knownAssemblies.ToList(); } // Get types from assemblies which reference Orleans and are not generated assemblies. var includedTypes = new HashSet <Type>(); for (var i = 0; i < assemblies.Count; i++) { var assembly = assemblies[i]; foreach (var attribute in assembly.GetCustomAttributes <ConsiderForCodeGenerationAttribute>()) { ConsiderType(attribute.Type, runtime, targetAssembly, includedTypes, considerForSerialization: true); if (attribute.ThrowOnFailure && !serializerGenerationManager.IsTypeRecorded(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."); } } KnownAssemblyAttribute knownAssemblyAttribute; var considerAllTypesForSerialization = knownAssemblyAttributes.TryGetValue(assembly, out knownAssemblyAttribute) && knownAssemblyAttribute.TreatTypesAsSerializable; foreach (var type in TypeUtils.GetDefinedTypes(assembly, Logger)) { var considerForSerialization = considerAllTypesForSerialization || type.IsSerializable; ConsiderType(type.AsType(), runtime, targetAssembly, includedTypes, considerForSerialization); } } includedTypes.RemoveWhere(_ => ignoredTypes.Contains(_)); // Group the types by namespace and generate the required code in each namespace. foreach (var group in includedTypes.GroupBy(_ => CodeGeneratorCommon.GetGeneratedNamespace(_))) { var namespaceMembers = new List <MemberDeclarationSyntax>(); foreach (var type in group) { // The module containing the serializer. var module = runtime ? null : type.GetTypeInfo().Module; // Every type which is encountered must be considered for serialization. Action <Type> onEncounteredType = encounteredType => { // If a type was encountered which can be accessed, process it for serialization. serializerGenerationManager.RecordTypeToGenerate(encounteredType, module, targetAssembly); }; if (Logger.IsVerbose2) { Logger.Verbose2("Generating code for: {0}", type.GetParseableName()); } if (GrainInterfaceUtils.IsGrainInterface(type)) { if (Logger.IsVerbose2) { Logger.Verbose2( "Generating GrainReference and MethodInvoker for {0}", type.GetParseableName()); } GrainInterfaceUtils.ValidateInterfaceRules(type); namespaceMembers.Add(GrainReferenceGenerator.GenerateClass(type, onEncounteredType)); namespaceMembers.Add(GrainMethodInvokerGenerator.GenerateClass(type)); } // Generate serializers. var first = true; Type toGen; while (serializerGenerationManager.GetNextTypeToProcess(out toGen)) { if (!runtime) { if (first) { ConsoleText.WriteStatus("ClientGenerator - Generating serializer classes for types:"); first = false; } ConsoleText.WriteStatus( "\ttype " + toGen.FullName + " in namespace " + toGen.Namespace + " defined in Assembly " + toGen.GetTypeInfo().Assembly.GetName()); } if (Logger.IsVerbose2) { Logger.Verbose2( "Generating & Registering Serializer for Type {0}", toGen.GetParseableName()); } namespaceMembers.Add(SerializerGenerator.GenerateClass(toGen, onEncounteredType)); } } if (namespaceMembers.Count == 0) { if (Logger.IsVerbose) { Logger.Verbose2("Skipping namespace: {0}", group.Key); } continue; } members.Add( SF.NamespaceDeclaration(SF.ParseName(group.Key)) .AddUsings( TypeUtils.GetNamespaces(typeof(TaskUtility), typeof(GrainExtensions), typeof(IntrospectionExtensions)) .Select(_ => SF.UsingDirective(SF.ParseName(_))) .ToArray()) .AddMembers(namespaceMembers.ToArray())); } return(new GeneratedSyntax { SourceAssemblies = assemblies, Syntax = members.Count > 0 ? SF.CompilationUnit().AddMembers(members.ToArray()) : null }); }
public async Task <CodeGenResult> CodeGen(Workspace workspace, Project project) { CompilationUnitSyntax cu = SF.CompilationUnit(); var usings = new HashSet <string>(); bool copyUsings = false; foreach (Document document in project.Documents) { SyntaxTree syntaxTree = await document.GetSyntaxTreeAsync(); _semanticModel = await document.GetSemanticModelAsync(); IEnumerable <ClassDeclarationSyntax> classes = syntaxTree.GetRoot().DescendantNodes().OfType <ClassDeclarationSyntax>(); foreach (var classNode in classes) { if (!RoslynUtils.IsPublic(classNode)) { continue; } ITypeSymbol swmrInterface = FindSwmrInterface(classNode); if (swmrInterface == null) { continue; } var namespaceNode = classNode.Parent as NamespaceDeclarationSyntax; if (namespaceNode == null) { throw new Exception("A grain must be declared inside a namespace"); } usings.UnionWith(syntaxTree.GetRoot().DescendantNodes().OfType <UsingDirectiveSyntax>().Select(usingDirective => usingDirective.Name.ToString())); int replicaCount = GetReadReplicaCount(swmrInterface); NamespaceDeclarationSyntax namespaceDclr = SF.NamespaceDeclaration(SF.IdentifierName(namespaceNode.Name.ToString())).WithUsings(namespaceNode.Usings); namespaceDclr = namespaceDclr.AddMembers( GenerateWriteGrain(classNode, swmrInterface, replicaCount), GenerateReadGrain(classNode, swmrInterface, replicaCount), GenerateReadReplicaGrain(classNode, swmrInterface) ); usings.UnionWith(namespaceNode.Usings.Select(@using => @using.Name.ToString())); cu = cu.AddMembers(namespaceDclr); // only copy the usings if at least one class was generated copyUsings = true; } } if (copyUsings) { usings.UnionWith(GetCommonUsings()); } return(new CodeGenResult(Formatter.Format(cu, workspace).ToString(), usings)); }
public async Task <CodeGenResult> CodeGen(Workspace workspace, Project project) { CompilationUnitSyntax cu = SF.CompilationUnit(); var usings = new HashSet <string>(); foreach (Document document in project.Documents) { SyntaxTree syntaxTree = await document.GetSyntaxTreeAsync(); _semanticModel = await document.GetSemanticModelAsync(); IEnumerable <InterfaceDeclarationSyntax> interfaces = syntaxTree.GetRoot().DescendantNodes().OfType <InterfaceDeclarationSyntax>(); foreach (var interfaceNode in interfaces) { if (!RoslynUtils.IsPublic(interfaceNode)) { continue; } AttributeSyntax swmrAttribute = AttributeUtils.SelectAttributeOfType(interfaceNode.AttributeLists, typeof(SingleWriterMultipleReadersAttribute), _semanticModel); if (swmrAttribute == null) { continue; } var namespaceNode = interfaceNode.Parent as NamespaceDeclarationSyntax; if (namespaceNode == null) { throw new Exception("A grain interface must be declared inside a namespace"); } usings.UnionWith(syntaxTree.GetRoot().DescendantNodes().OfType <UsingDirectiveSyntax>().Select(usingDirective => usingDirective.Name.ToString())); var methods = RoslynUtils.GetMethodDeclarations(interfaceNode); var readMethods = SwmrUtils.GetReadOnlyMethods(methods, _semanticModel); var writeMethods = methods.Except(readMethods).Where(method => new MethodInspector(method).MethodName != "GetState"); readMethods = SwmrUtils.RemoveReadOnlyAttribute(readMethods, _semanticModel); string grainInterfaceName = interfaceNode.Identifier.Text; var readReplicaMethods = new List <MethodDeclarationSyntax>(readMethods) { GenerateSetStateMethod() }; InterfaceDeclarationSyntax readReplicaInterface = GenerateInterface(SwmrUtils.GetReadReplicaInterfaceName(grainInterfaceName), readReplicaMethods, interfaceNode.BaseList); readMethods = SwmrUtils.AddSessionIdParameter(readMethods); writeMethods = SwmrUtils.AddSessionIdParameter(writeMethods); string readerInterfaceName = SwmrUtils.GetReadInterfaceName(grainInterfaceName); string writerInterfaceName = SwmrUtils.GetWriteInterfaceName(grainInterfaceName); InterfaceDeclarationSyntax readerInterface = GenerateInterface(readerInterfaceName, readMethods, interfaceNode.BaseList); InterfaceDeclarationSyntax writerInterface = GenerateInterface(writerInterfaceName, writeMethods, interfaceNode.BaseList); string fullNameSpace = _semanticModel.GetDeclaredSymbol(namespaceNode).ToString(); NamespaceDeclarationSyntax namespaceDclr = SF.NamespaceDeclaration(SF.IdentifierName(fullNameSpace)).WithUsings(namespaceNode.Usings); namespaceDclr = namespaceDclr.AddMembers(readerInterface, writerInterface, readReplicaInterface); usings.UnionWith(namespaceNode.Usings.Select(@using => @using.Name.ToString())); usings.Remove("ETG.Orleans.Attributes"); cu = cu.AddMembers(namespaceDclr); } } return(new CodeGenResult(Formatter.Format(cu, workspace).ToString(), usings)); }