private static SyntaxNode Normalize(SyntaxNode root, IEnumerable <SyntaxNode> members, Scope scope) { var appClass = root .DescendantNodes() .OfType <ClassDeclarationSyntax>() .Where(@class => @class.Identifier.ToString() == "testclass") .FirstOrDefault(); if (appClass == null) { appClass = CSharp.ClassDeclaration("testclass"); } return(CSharp.CompilationUnit() .WithMembers(CSharp.List(new[] { (MemberDeclarationSyntax) appClass .WithMembers(CSharp.List( members.Select( member => { var method = member as MethodDeclarationSyntax; if (method == null) { return member; } return method.WithParameterList( method .ParameterList .AddParameters(CSharp.Parameter( CSharp.ParseToken("result")) .WithType(CSharp.ParseTypeName("Dictionary<string, object>")))); }))) }))); }
public async Task <string> GenerateStubs(string testProjectPath) { MSBuildWorkspace workspace = MSBuildWorkspace.Create(); Project currentProject = await workspace.OpenProjectAsync(testProjectPath); if (currentProject == null) { throw new ArgumentException("Could not open the project located at " + testProjectPath); } CompilationUnitSyntax cu = SF.CompilationUnit(); var usings = new HashSet <string>(); usings.Add("System"); usings.Add("System.Runtime.CompilerServices"); usings.Add("Etg.SimpleStubs"); foreach (ProjectReference projectRef in currentProject.ProjectReferences) { Project project = workspace.CurrentSolution.GetProject(projectRef.ProjectId); if (_config.IgnoredProjects.Contains(project.Name)) { continue; } var res = await _projectStubber.StubProject(project, cu); cu = res.CompilationUnit; usings.UnionWith(res.Usings); } cu = cu.AddUsings(usings.Select(@using => SF.UsingDirective(SF.IdentifierName(@using))).ToArray()); return(Formatter.Format(cu, workspace).ToString()); }
public SyntaxTree CreateSyntaxTree() { // The call to CreateType must come before the call to namespaces.GetUsings. // This is because CreateType builds the list of referenced namespaces. MemberDeclarationSyntax typeDeclaration = CreateType(); if (Type.Docs != null) { DocCommentGeneratorBase <Type> generator = new TypeDocCommentGenerator(Type); SyntaxTriviaList trivia = SF.TriviaList(generator.CreateDocComment()); typeDeclaration = typeDeclaration.WithLeadingTrivia(trivia); } NamespaceDeclarationSyntax namespaceDeclaration = SF.NamespaceDeclaration( Symbols.GetNamespaceSyntax(Type), SF.List <ExternAliasDirectiveSyntax>(), SF.List <UsingDirectiveSyntax>(), SF.List(new[] { typeDeclaration }) ); return(SF.SyntaxTree( SF.CompilationUnit( SF.List <ExternAliasDirectiveSyntax>(), Namespaces.GetUsings(), SF.List <AttributeListSyntax>(), SF.List <MemberDeclarationSyntax>(new[] { namespaceDeclaration }) ).NormalizeWhitespace(elasticTrivia: true) )); }
public async Task <string> GenerateStubs(string testProjectPath) { MSBuildWorkspace workspace = MSBuildWorkspace.Create(); Project currentProject = await workspace.OpenProjectAsync(testProjectPath); if (currentProject == null) { throw new ArgumentException("Could not open the project located at " + testProjectPath); } List <Project> projectsToStub = GetListOfProjectsToStub(workspace, currentProject); if (!projectsToStub.Any()) { return(string.Empty); } CompilationUnitSyntax cu = SF.CompilationUnit(); var usings = new HashSet <UsingDirectiveSyntax>(new UsingDirectiveEqualityComparer()); usings.Add(ToUsingDirective(" System")); usings.Add(ToUsingDirective(" System.Runtime.CompilerServices")); usings.Add(ToUsingDirective(" Etg.SimpleStubs")); foreach (Project project in projectsToStub) { var res = await _projectStubber.StubProject(project, cu); cu = res.CompilationUnit; usings.UnionWith(res.Usings); } cu = cu.AddUsings(usings.ToArray()); return(Formatter.Format(cu, workspace).ToString()); }
public CompileContext(Type baseType, Type modelType, string templateNamespace = null, string templateName = null, string templatePath = null, LogHandler logHandler = null) { _templateBaseType = baseType; _location = new TemplateLocation(templatePath); _macroManager = new MacroManager(baseType); _modelTypeName = ClassContext.GetTypeName(modelType); _stateTypeName = $"TxMark.Template.IState<{_modelTypeName}>"; _nameTagManager = new NameTagManager(); _bagsByReference = new Bag <object>(); _variableTypeByName = new Dictionary <string, VariableTypes>(); if (templateNamespace == null) { templateNamespace = DEFAULT_NAMESPACE; } if (templateName == null) { templateName = "Template_" + Guid.NewGuid().ToString().Replace('-', '_'); } _logHandler = logHandler ?? DefaultLogHandler; _codeContextStack = new Stack <ICodeContext>(); _metadataReferenceManager = new MetadataReferenceManager(); AddNamespaceFor(typeof(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException)); AddNamespaceFor(typeof(DynamicObject)); AddNamespaceFor(typeof(string)); AddNamespaceFor(baseType); AddNamespaceFor(modelType); AddNamespaceFor(typeof(TemplateState <object>)); AddNamespaceFor(typeof(Dictionary <string, object>)); _namespace = SF.NamespaceDeclaration(SF.IdentifierName(templateNamespace)); _codeContext = new ClassContext(templateName, baseType, modelType, (classDeclaration) => { _namespace = _namespace.AddMembers(classDeclaration); List <UsingDirectiveSyntax> usingDirectives = new List <UsingDirectiveSyntax>(); foreach (var namespaceName in _usingNamespaces) { //usingDirectives.Add(SF.UsingDirective(SF.IdentifierName(namespaceName))); } _compilationUnit = SF.CompilationUnit(); //.AddUsings(usingDirectives.ToArray()); _compilationUnit = _compilationUnit.AddMembers(_namespace); }); }
public async Task <string> GenerateStubs(string testProjectPath, string configuration, string platform, string visualStudioVersion) { RegisterVisualStudioInstance(visualStudioVersion); using (var workspace = MSBuildWorkspace.Create(new Dictionary <string, string> { { "Configuration", configuration }, { "Platform", platform } })) { Project currentProject = await workspace.OpenProjectAsync(testProjectPath); if (workspace.Diagnostics.Any(d => d.Kind == WorkspaceDiagnosticKind.Failure)) { StringBuilder stringBuilder = new StringBuilder(); foreach (var diagnostic in workspace.Diagnostics) { stringBuilder.AppendLine(diagnostic.ToString()); } Console.WriteLine("Simplestubs encountered errors when opening the workspace; Stubs will be generated only for projects that successfully opened. Errors: " + stringBuilder.ToString()); } else { Console.WriteLine("MSBuildWorkspace loaded with no errors!"); } if (currentProject == null) { throw new ArgumentException("Could not open the project located at " + testProjectPath); } List <Project> projectsToStub = GetListOfProjectsToStub(workspace, currentProject); if (!projectsToStub.Any()) { return(string.Empty); } CompilationUnitSyntax cu = SF.CompilationUnit(); var usings = new HashSet <UsingDirectiveSyntax>(new UsingDirectiveEqualityComparer()); usings.Add(ToUsingDirective(" System")); usings.Add(ToUsingDirective(" System.Runtime.CompilerServices")); usings.Add(ToUsingDirective(" Etg.SimpleStubs")); foreach (Project project in projectsToStub) { var res = await _projectStubber.StubProject(project, cu); cu = res.CompilationUnit; usings.UnionWith(res.Usings); } cu = cu.AddUsings(usings.ToArray()); return(Formatter.Format(cu, workspace).ToString()); } }
private static CompilationUnitSyntax GenerateRootUnit(ClassDeclMeta classmeta) { return(SF.CompilationUnit() .AddUsings( SF.UsingDirective(SF.ParseName("MongoDB.Client.Bson.Reader")), SF.UsingDirective(SF.ParseName("MongoDB.Client.Bson.Writer")), SF.UsingDirective(SF.ParseName("MongoDB.Client.Bson.Serialization")), SF.UsingDirective(SF.ParseName("MongoDB.Client.Bson.Document")), SF.UsingDirective(SF.ParseName("System")), SF.UsingDirective(SF.ParseName("System.Collections.Generic")), SF.UsingDirective(SF.ParseName("System.Buffers.Binary")), SF.UsingDirective(SF.ParseName(classmeta.StringNamespace)))); // .AddMembers(SF.NamespaceDeclaration(SF.ParseName("MongoDB.Client.Bson.Serialization.Generated"))); }
protected override SyntaxNode addModules(SyntaxNode root, IEnumerable <string> modules) { var compilationUnit = root.AncestorsAndSelf() .Where(a => a is CompilationUnitSyntax) .Select(a => a as CompilationUnitSyntax) .FirstOrDefault() ?? CSharp.CompilationUnit() .WithMembers(CSharp.List(new[] { (MemberDeclarationSyntax)root })); return(compilationUnit .WithUsings(CSharp.List( compilationUnit.Usings.Union( modules .Select(module => CSharp .UsingDirective(CSharp .ParseName(module)) .WithTrailingTrivia(CSharp.EndOfLine(string.Empty)))))) ?? root); }
/// <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 static 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 = CodeGeneratorCommon.GetTypesWithImplementations( typeof(MethodInvokerAttribute), typeof(GrainReferenceAttribute), typeof(GrainStateAttribute), typeof(SerializerAttribute)); targetAssembly = null; } else { ignoredTypes = new HashSet <Type>(); targetAssembly = assemblies.FirstOrDefault(); } var members = new List <MemberDeclarationSyntax>(); // Get types from assemblies which reference Orleans and are not generated assemblies. var includedTypes = new HashSet <Type>(); foreach (var type in assemblies.SelectMany(_ => _.GetTypes())) { // The module containing the serializer. var module = runtime ? null : type.Module; // Every type which is encountered must be considered for serialization. if (!type.IsNested && !type.IsGenericParameter && type.IsSerializable) { // If a type was encountered which can be accessed, process it for serialization. var isAccessibleForSerialization = !TypeUtilities.IsTypeIsInaccessibleForSerialization(type, module, targetAssembly); if (isAccessibleForSerialization) { includedTypes.Add(type); SerializerGenerationManager.RecordTypeToGenerate(type); } } // Collect the types which require code generation. if (GrainInterfaceData.IsGrainInterface(type)) { if (Logger.IsVerbose2) { Logger.Verbose2("Will generate code for: {0}", type.GetParseableName()); } includedTypes.Add(type); } } 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.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. var isAccessibleForSerialization = !TypeUtilities.IsTypeIsInaccessibleForSerialization(encounteredType, module, targetAssembly); if (isAccessibleForSerialization) { SerializerGenerationManager.RecordTypeToGenerate(encounteredType); } }; if (Logger.IsVerbose2) { Logger.Verbose2("Generating code for: {0}", type.GetParseableName()); } if (GrainInterfaceData.IsGrainInterface(type)) { if (Logger.IsVerbose2) { Logger.Verbose2( "Generating GrainReference and MethodInvoker for {0}", type.GetParseableName()); } namespaceMembers.Add(GrainReferenceGenerator.GenerateClass(type, onEncounteredType)); namespaceMembers.Add(GrainMethodInvokerGenerator.GenerateClass(type)); } // Generate serializers. var first = true; Type toGen; while (SerializerGenerationManager.GetNextTypeToProcess(out toGen)) { // Filter types which are inaccessible by the serialzation module/assembly. var skipSerialzerGeneration = toGen.GetAllFields() .Any( field => TypeUtilities.IsTypeIsInaccessibleForSerialization( field.FieldType, module, targetAssembly)); if (skipSerialzerGeneration) { continue; } 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.Assembly.GetName()); } if (Logger.IsVerbose2) { Logger.Verbose2( "Generating & Registering Serializer for Type {0}", toGen.GetParseableName()); } namespaceMembers.AddRange(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)) .Select(_ => SF.UsingDirective(SF.ParseName(_))) .ToArray()) .AddMembers(namespaceMembers.ToArray())); } return(new GeneratedSyntax { SourceAssemblies = assemblies, Syntax = members.Count > 0 ? SF.CompilationUnit().AddMembers(members.ToArray()) : null }); }
/// <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 static 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>(); // If any KnownAssemblies have been specified, include them during code generation. var knownAssemblies = assemblies.SelectMany(_ => _.GetCustomAttributes <KnownAssemblyAttribute>()) .Select(_ => _.Assembly) .Distinct() .ToSet(); 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 <KnownTypeAttribute>()) { ConsiderType(attribute.Type, runtime, targetAssembly, includedTypes); } foreach (var type in assembly.DefinedTypes) { ConsiderType(type, runtime, targetAssembly, includedTypes); } } 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.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 (GrainInterfaceData.IsGrainInterface(type)) { if (Logger.IsVerbose2) { Logger.Verbose2( "Generating GrainReference and MethodInvoker for {0}", type.GetParseableName()); } GrainInterfaceData.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.Assembly.GetName()); } if (Logger.IsVerbose2) { Logger.Verbose2( "Generating & Registering Serializer for Type {0}", toGen.GetParseableName()); } namespaceMembers.AddRange(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)) .Select(_ => SF.UsingDirective(SF.ParseName(_))) .ToArray()) .AddMembers(namespaceMembers.ToArray())); } return(new GeneratedSyntax { SourceAssemblies = assemblies, Syntax = members.Count > 0 ? SF.CompilationUnit().AddMembers(members.ToArray()) : null }); }
/// <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(Assembly targetAssembly, bool runtime) { var grainInterfaces = new List <GrainInterfaceDescription>(); var grainClasses = new List <GrainClassDescription>(); var serializationTypes = new SerializationTypeDescriptions(); var members = new List <MemberDeclarationSyntax>(); // Expand the list of included assemblies and types. var(includedTypes, assemblies) = this.GetIncludedTypes(targetAssembly, runtime); if (Logger.IsVerbose) { Logger.Verbose( "Generating code for assemblies: {0}", string.Join(", ", assemblies.Select(_ => _.FullName))); } var serializerNamespaceMembers = new List <MemberDeclarationSyntax>(); var serializerNamespaceName = $"{SerializerNamespacePrefix}{targetAssembly?.GetName().Name.GetHashCode():X}"; // 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>(); var namespaceName = group.Key; foreach (var type in group) { // Skip generated classes. if (type.GetCustomAttribute <GeneratedCodeAttribute>() != null) { continue; } // Every type which is encountered must be considered for serialization. void OnEncounteredType(Type encounteredType) { // If a type was encountered which can be accessed, process it for serialization. this.typeCollector.RecordEncounteredType(type); this.serializerGenerationManager.RecordTypeToGenerate(encounteredType, 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); var referenceTypeName = GrainReferenceGenerator.GetGeneratedClassName(type); var invokerTypeName = GrainMethodInvokerGenerator.GetGeneratedClassName(type); namespaceMembers.Add(GrainReferenceGenerator.GenerateClass(type, referenceTypeName, OnEncounteredType)); namespaceMembers.Add(GrainMethodInvokerGenerator.GenerateClass(type, invokerTypeName)); var genericTypeSuffix = GetGenericTypeSuffix(type.GetGenericArguments().Length); grainInterfaces.Add( new GrainInterfaceDescription { Interface = type.GetTypeSyntax(includeGenericParameters: false), Reference = SF.ParseTypeName(namespaceName + '.' + referenceTypeName + genericTypeSuffix), Invoker = SF.ParseTypeName(namespaceName + '.' + invokerTypeName + genericTypeSuffix), InterfaceId = GrainInterfaceUtils.GetGrainInterfaceId(type) }); } if (TypeUtils.IsConcreteGrainClass(type)) { grainClasses.Add( new GrainClassDescription { ClassType = type.GetTypeSyntax(includeGenericParameters: false) }); } // Generate serializers. var first = true; while (this.serializerGenerationManager.GetNextTypeToProcess(out var toGen)) { if (first) { Logger.Info("ClientGenerator - Generating serializer classes for types:"); first = false; } Logger.Info( "\ttype " + toGen.FullName + " in namespace " + toGen.Namespace + " defined in Assembly " + toGen.GetTypeInfo().Assembly.GetName()); if (Logger.IsVerbose2) { Logger.Verbose2( "Generating serializer for type {0}", toGen.GetParseableName()); } var generatedSerializerName = SerializerGenerator.GetGeneratedClassName(toGen); serializerNamespaceMembers.Add(SerializerGenerator.GenerateClass(generatedSerializerName, toGen, OnEncounteredType)); var qualifiedSerializerName = serializerNamespaceName + '.' + generatedSerializerName + GetGenericTypeSuffix(toGen.GetGenericArguments().Length); serializationTypes.SerializerTypes.Add( new SerializerTypeDescription { Serializer = SF.ParseTypeName(qualifiedSerializerName), Target = toGen.GetTypeSyntax(includeGenericParameters: false) }); } } if (namespaceMembers.Count == 0) { if (Logger.IsVerbose) { Logger.Verbose2("Skipping namespace: {0}", namespaceName); } continue; } members.Add(CreateNamespace(namespaceName, namespaceMembers)); } // Add all generated serializers to their own namespace. members.Add(CreateNamespace(serializerNamespaceName, serializerNamespaceMembers)); // Add serialization metadata for the types which were encountered. this.AddSerializationTypes(serializationTypes, targetAssembly); // Generate metadata directives for all of the relevant types. var(attributeDeclarations, memberDeclarations) = FeaturePopulatorGenerator.GenerateSyntax(targetAssembly, grainInterfaces, grainClasses, serializationTypes); members.AddRange(memberDeclarations); var compilationUnit = SF.CompilationUnit().AddAttributeLists(attributeDeclarations.ToArray()).AddMembers(members.ToArray()); return(new GeneratedSyntax { SourceAssemblies = assemblies, Syntax = compilationUnit }); string GetGenericTypeSuffix(int numParams) { if (numParams == 0) { return(string.Empty); } return('<' + new string(',', numParams - 1) + '>'); } NamespaceDeclarationSyntax CreateNamespace(string namespaceName, IEnumerable <MemberDeclarationSyntax> namespaceMembers) { return (SF.NamespaceDeclaration(SF.ParseName(namespaceName)) .AddUsings( TypeUtils.GetNamespaces(typeof(GrainExtensions), typeof(IntrospectionExtensions)) .Select(_ => SF.UsingDirective(SF.ParseName(_))) .ToArray()) .AddMembers(namespaceMembers.ToArray())); } }
public CompilationUnitSyntax Build() => SF.CompilationUnit().AddUsings(_usings.ToArray()) .AddMembers(_namespaces.Select(ns => ns.Build()).ToArray());