public CompilationAnalyzer(IGeneratorExecutionContext context, WellKnownTypes wellKnownTypes, Compilation compilation) { this.context = context; this.wellKnownTypes = wellKnownTypes; this.serializableAttribute = wellKnownTypes.SerializableAttribute; this.knownBaseTypeAttribute = wellKnownTypes.KnownBaseTypeAttribute; this.knownAssemblyAttribute = wellKnownTypes.KnownAssemblyAttribute; this.considerForCodeGenerationAttribute = wellKnownTypes.ConsiderForCodeGenerationAttribute; this.compilation = compilation; }
public CodeGenerator(IGeneratorExecutionContext context, CodeGeneratorOptions options) { this.context = context; this.compilation = context.Compilation; this.options = options; this.wellKnownTypes = new WellKnownTypes(compilation); this.compilationAnalyzer = new CompilationAnalyzer(context, this.wellKnownTypes, compilation); var firstSyntaxTree = compilation.SyntaxTrees.FirstOrDefault() ?? throw new InvalidOperationException("Compilation has no syntax trees."); this.semanticModelForAccessibility = compilation.GetSemanticModel(firstSyntaxTree); this.serializerTypeAnalyzer = SerializerTypeAnalyzer.Create(this.wellKnownTypes); this.serializerGenerator = new SerializerGenerator(this.options, this.wellKnownTypes); this.grainMethodInvokerGenerator = new GrainMethodInvokerGenerator(this.options, this.wellKnownTypes); this.grainReferenceGenerator = new GrainReferenceGenerator(this.options, this.wellKnownTypes); }
/// <summary> /// Generates the non serializer class for the provided grain types. /// </summary> internal (TypeDeclarationSyntax, TypeSyntax) GenerateClass(IGeneratorExecutionContext context, SemanticModel model, SerializerTypeDescription description) { var className = GetGeneratedClassName(description.Target); var type = description.Target; var genericTypes = type.GetHierarchyTypeParameters().Select(_ => TypeParameter(_.ToString())).ToArray(); var attributes = new List <AttributeSyntax> { GeneratedCodeAttributeGenerator.GetGeneratedCodeAttributeSyntax(wellKnownTypes), Attribute(wellKnownTypes.ExcludeFromCodeCoverageAttribute.ToNameSyntax()), Attribute(wellKnownTypes.SerializerAttribute.ToNameSyntax()) .AddArgumentListArguments( AttributeArgument(TypeOfExpression(type.WithoutTypeParameters().ToTypeSyntax()))) }; var fields = GetFields(context, model, type); var members = new List <MemberDeclarationSyntax>(GenerateFields(fields)) { GenerateConstructor(className, fields), GenerateDeepCopierMethod(type, fields, model), GenerateSerializerMethod(type, fields, model), GenerateDeserializerMethod(type, fields, model), }; var classDeclaration = ClassDeclaration(className) .AddModifiers(Token(SyntaxKind.InternalKeyword)) .AddModifiers(Token(SyntaxKind.SealedKeyword)) .AddAttributeLists(AttributeList().AddAttributes(attributes.ToArray())) .AddMembers(members.ToArray()) .AddConstraintClauses(type.GetTypeConstraintSyntax()); if (genericTypes.Length > 0) { classDeclaration = classDeclaration.AddTypeParameterListParameters(genericTypes); } if (this.options.DebuggerStepThrough) { var debuggerStepThroughAttribute = Attribute(this.wellKnownTypes.DebuggerStepThroughAttribute.ToNameSyntax()); classDeclaration = classDeclaration.AddAttributeLists(AttributeList().AddAttributes(debuggerStepThroughAttribute)); } return(classDeclaration, ParseTypeName(type.GetParsableReplacementName(className))); }
/// <summary> /// Returns a sorted list of the fields of the provided type. /// </summary> private List <FieldInfoMember> GetFields(IGeneratorExecutionContext context, SemanticModel model, INamedTypeSymbol type) { var result = new List <FieldInfoMember>(); foreach (var field in type.GetDeclaredInstanceMembers <IFieldSymbol>()) { if (ShouldSerializeField(field)) { result.Add(new FieldInfoMember(this, model, type, field, result.Count)); } } if (type.TypeKind == TypeKind.Class) { // Some reference assemblies are compiled without private fields. // Warn the user if they are inheriting from a type in one of these assemblies using a heuristic: // If the type inherits from a type in a reference assembly and there are no fields declared on those // base types, emit a warning. var hasUnsupportedRefAsmBase = false; var referenceAssemblyHasFields = false; var baseType = type.BaseType; while (baseType != null && !SymbolEqualityComparer.Default.Equals(baseType, wellKnownTypes.Object) && !SymbolEqualityComparer.Default.Equals(baseType, wellKnownTypes.Attribute)) { if (!hasUnsupportedRefAsmBase && baseType.ContainingAssembly.HasAttribute("ReferenceAssemblyAttribute") && !IsSupportedRefAsmType(baseType)) { hasUnsupportedRefAsmBase = true; } foreach (var field in baseType.GetDeclaredInstanceMembers <IFieldSymbol>()) { if (hasUnsupportedRefAsmBase) { referenceAssemblyHasFields = true; } if (ShouldSerializeField(field)) { result.Add(new FieldInfoMember(this, model, type, field, result.Count)); } } baseType = baseType.BaseType; } if (hasUnsupportedRefAsmBase && !referenceAssemblyHasFields) { var declaration = type.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax() as TypeDeclarationSyntax; context.ReportDiagnostic(RefAssemblyBaseTypeDiagnosticAnalyzer.CreateDiagnostic(declaration)); } bool IsSupportedRefAsmType(INamedTypeSymbol t) { INamedTypeSymbol baseDefinition; if (t.IsGenericType && !t.IsUnboundGenericType) { baseDefinition = t.ConstructUnboundGenericType().OriginalDefinition; } else { baseDefinition = t.OriginalDefinition; } foreach (var refAsmType in wellKnownTypes.SupportedRefAsmBaseTypes) { if (SymbolEqualityComparer.Default.Equals(baseDefinition, refAsmType)) { return(true); } } return(false); } } result.Sort(FieldInfoMember.Comparer.Instance); return(result); }