示例#1
0
        protected virtual void ResolveMultipleInheritanceMembers(CodeTypeDeclaration generatedType, HashSet <CodeTypeMember> shadows, CodeConstructor constructor)
        {
            Func <CodeTypeDeclaration, IEnumerable <CodeTypeDeclaration> > getBaseTypes =
                type => {
                var interfaceType = CodeDomHelper.GetOrCreateUserItem <CodeTypeDeclaration>(type, CodeDomHelper.InterfaceKey);
                if (interfaceType == null)
                {
                    interfaceType = type;
                }
                return(interfaceType.BaseTypes.Cast <CodeTypeReference>().Select(r => r.GetTypeForReference()).Where(c => c != null));
            };
            var layering = Layering <CodeTypeDeclaration> .CreateLayers(generatedType, getBaseTypes);

            CodeTypeDeclaration implBaseType = FindBaseClassAndCreateShadows(generatedType, shadows, layering);
            IEnumerable <CodeTypeDeclaration> inheritedBaseClasses;

            if (implBaseType != null)
            {
                inheritedBaseClasses = implBaseType.Closure(getBaseTypes);
                var implementationRef = new CodeTypeReference();
                implementationRef.BaseType = implBaseType.Name;
                var n = implBaseType.GetReferenceForType().Namespace();
                if (n != null && n.EndsWith(implBaseType.Name))
                {
                    implementationRef.BaseType = n + "." + implBaseType.Name;
                }
                else
                {
                    implementationRef.SetNamespace(n);
                }
                generatedType.BaseTypes.Insert(0, implementationRef);
            }
            else
            {
                inheritedBaseClasses = Enumerable.Empty <CodeTypeDeclaration>();
                AddImplementationBaseClass(generatedType);
            }
            for (int i = layering.Count - 1; i >= 0; i--)
            {
                foreach (var baseType in layering[i])
                {
                    if (!inheritedBaseClasses.Contains(baseType) &&
                        baseType != generatedType &&
                        ShouldContainMembers(generatedType, baseType.GetReferenceForType()))
                    {
                        var dependent = baseType.DependentMembers(false);
                        if (dependent != null)
                        {
                            foreach (var inheritedMember in dependent)
                            {
                                RecursivelyAddDependentMembers(generatedType.Members, constructor.Statements, inheritedMember, shadows);
                            }
                        }
                    }
                }
            }
        }
示例#2
0
            /// <summary>
            /// Initializes the generated type for the NMeta extension
            /// </summary>
            /// <param name="input">The NMeta extension</param>
            /// <param name="generatedType">The generated type for the extension</param>
            /// <param name="context">The transformation context</param>
            public override void Transform(IExtension input, CodeTypeDeclaration generatedType, ITransformationContext context)
            {
                SetTypeReferenceForMappedType(input, generatedType.GetReferenceForType());
                base.Transform(input, generatedType, context);
                generatedType.IsClass = true;
                generatedType.BaseTypes.Add(new CodeTypeReference(typeof(ModelElementExtension <,>).Name, CreateReference(input.AdornedClass, true, context), generatedType.GetReferenceForType()));
                generatedType.WriteDocumentation(input.Summary ?? string.Format("The {0} extension", input.Name), input.Remarks);

                CreateFromMethod(input, generatedType, context);
                CreateGetExtension(input, generatedType, context);
            }
示例#3
0
            /// <summary>
            /// Creates the constructor for the extension
            /// </summary>
            /// <param name="input">The NMeta extension</param>
            /// <param name="generatedType">The generated type declaration for the extension</param>
            /// <param name="context">The transformation context</param>
            protected virtual void CreateConstructor(IExtension input, CodeTypeDeclaration generatedType, ITransformationContext context)
            {
                var classRef    = CreateReference(input.AdornedClass, true, context);
                var constructor = CodeDomHelper.GetOrCreateDefaultConstructor(generatedType, () => new CodeConstructor());

                constructor.Attributes = MemberAttributes.Public;
                constructor.ReturnType = generatedType.GetReferenceForType();
                constructor.Parameters.Add(new CodeParameterDeclarationExpression(classRef, "parent"));
                constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("parent"));
                constructor.WriteDocumentation("Creates a new extension instance for the given parent", null, new Dictionary <string, string>()
                {
                    { "parent", "The parent model element" }
                });
                if (!generatedType.Members.Contains(constructor))
                {
                    generatedType.Members.Add(constructor);
                }
            }
示例#4
0
        /// <summary>
        /// Gets called when the given type is added to the output namespace, e.g. to prevent name conflicts
        /// </summary>
        /// <param name="type"></param>
        private void AddType(CodeNamespace ns, CodeTypeDeclaration type)
        {
            var name           = CreateNewValidName(ns, type.Name);
            var typeRef        = type.GetReferenceForType();
            var isSelfPointing = false;

            if (typeRef != null && typeRef.UserData.Contains(CodeDomHelper.NamespaceKey))
            {
                isSelfPointing = typeRef.BaseType == type.Name;
                if (CodeDomHelper.Namespace(typeRef) == null)
                {
                    CodeDomHelper.SetNamespace(typeRef, ns.Name);
                }
            }
            if (name != type.Name)
            {
                type.Name = name;
                if (isSelfPointing)
                {
                    typeRef.BaseType = name;
                }
            }
            ns.Types.Add(type);
        }
示例#5
0
        /// <summary>
        /// Initializes the generated type declaration
        /// </summary>
        /// <param name="input">The input model element</param>
        /// <param name="generatedType">The generated class declaration</param>
        /// <param name="context">The transformation context</param>
        /// <remarks>Can be overridden to refine code generation</remarks>
        public override void Transform(T input, CodeTypeDeclaration generatedType, ITransformationContext context)
        {
            HashSet <CodeTypeMember> shadows;
            var ownShadows = generatedType.Shadows(false);

            if (ownShadows != null)
            {
                shadows = new HashSet <CodeTypeMember>(ownShadows);
            }
            else
            {
                shadows = new HashSet <CodeTypeMember>();
            }
            var constructor = CodeDomHelper.GetOrCreateDefaultConstructor(generatedType, () => new CodeConstructor()
            {
                Attributes = MemberAttributes.Public
            });
            var dependends = generatedType.DependentMembers(false);

            if (dependends != null)
            {
                foreach (var member in dependends)
                {
                    RecursivelyAddDependentMembers(generatedType.Members, constructor.Statements, member, shadows);
                }
            }

            var interfaceDecl = CreateSeparatePublicInterface(input, generatedType);

            if (interfaceDecl != null)
            {
                CodeDomHelper.SetUserItem(generatedType, CodeDomHelper.InterfaceKey, interfaceDecl);
                var dependentTypes = CodeDomHelper.DependentTypes(generatedType, true);
                dependentTypes.Add(interfaceDecl);

                var typeReference = generatedType.GetReferenceForType();
                typeReference.BaseType = interfaceDecl.Name;

                CreateInterfaceMembers(generatedType, interfaceDecl);

                for (int i = generatedType.BaseTypes.Count - 1; i >= 0; i--)
                {
                    var baseTypeRef = generatedType.BaseTypes[i];
                    var baseType    = CodeDomHelper.GetOrCreateUserItem <CodeTypeDeclaration>(baseTypeRef, CodeDomHelper.ClassKey);
                    if (baseType == null)
                    {
                        continue;
                    }
                    interfaceDecl.BaseTypes.Add(baseTypeRef);
                    generatedType.BaseTypes.RemoveAt(i);
                }
                generatedType.BaseTypes.Add(typeReference);

                ResolveMultipleInheritanceMembers(generatedType, shadows, constructor);
            }

            if (constructor.Statements.Count > 0)
            {
                CodeDomHelper.SetUserItem(generatedType, CodeDomHelper.ConstructorKey, constructor);
                generatedType.Members.Add(constructor);
            }
        }
示例#6
0
        protected virtual void ResolveMultipleInheritanceMembers(CodeTypeDeclaration generatedType, HashSet <CodeTypeMember> shadows, CodeConstructor constructor)
        {
            var allClasses = generatedType.Closure(GetBaseClasses);
            var layering   = Layering <CodeTypeDeclaration> .CreateLayers(generatedType, c => Edges(c, allClasses));

            CodeTypeDeclaration implBaseType = null;
            int layerIndex;

            for (layerIndex = layering.Count - 1; layerIndex >= 0; layerIndex--)
            {
                var layer = layering[layerIndex];
                if (layer.Count == 1 && layer.First() != generatedType && !shadows.IntersectsWith(AllFeatures(layer.First())))
                {
                    implBaseType = layer.First();
                    break;
                }
                foreach (var cl in layer)
                {
                    shadows.UnionWith(Refinements(cl));
                }
            }
            IEnumerable <CodeTypeDeclaration> inheritedBaseClasses;

            if (implBaseType != null)
            {
                inheritedBaseClasses = layering.Take(layerIndex + 1).SelectMany(s => s);
                var implementationRef = new CodeTypeReference();
                implementationRef.BaseType = implBaseType.Name;
                var n = implBaseType.GetReferenceForType().Namespace();
                if (n != null && n.EndsWith(implBaseType.Name))
                {
                    implementationRef.BaseType = n + "." + implBaseType.Name;
                }
                else
                {
                    implementationRef.SetNamespace(n);
                }
                generatedType.BaseTypes.Insert(0, implementationRef);
            }
            else
            {
                inheritedBaseClasses = Enumerable.Empty <CodeTypeDeclaration>();
                AddImplementationBaseClass(generatedType);
            }
            CodeDomHelper.SetUserItem(generatedType, CodeDomHelper.BaseClassesKey, inheritedBaseClasses);
            for (int i = layerIndex + 1; i < layering.Count; i++)
            {
                foreach (var baseType in layering[i])
                {
                    if (baseType != generatedType)
                    {
                        var dependent = baseType.DependentMembers(false);
                        if (dependent != null)
                        {
                            foreach (var inheritedMember in dependent)
                            {
                                RecursivelyAddDependentMembers(generatedType.Members, constructor.Statements, inheritedMember, shadows);
                            }
                        }
                    }
                }
            }
        }
示例#7
0
            private void GenerateTypeConverter(CodeTypeDeclaration generatedType, Dictionary <ILiteral, string> fieldNames)
            {
                var dependents = generatedType.DependentTypes(true);

                if (dependents.Any(c => c.Name == generatedType.Name + "Converter") ||
                    fieldNames.All(field => field.Value == field.Key.Name))
                {
                    return;
                }

                var typeConverter = new CodeTypeDeclaration(generatedType.Name + "Converter");

                typeConverter.BaseTypes.Add(typeof(TypeConverter).ToTypeReference());
                var stringTypeRef = new CodeTypeOfExpression(typeof(string));

                var canConvertFromMethod = new CodeMemberMethod
                {
                    Name       = "CanConvertFrom",
                    Attributes = MemberAttributes.Public | MemberAttributes.Override,
                    ReturnType = new CodeTypeReference(typeof(bool))
                };

                canConvertFromMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ITypeDescriptorContext).ToTypeReference(), "context"));
                canConvertFromMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(System.Type).ToTypeReference(), "sourceType"));
                var sourceTypeRef = new CodeArgumentReferenceExpression("sourceType");

                canConvertFromMethod.Statements.Add(new CodeMethodReturnStatement(new CodeBinaryOperatorExpression(sourceTypeRef, CodeBinaryOperatorType.IdentityEquality, stringTypeRef)));
                typeConverter.Members.Add(canConvertFromMethod);

                var canConvertTo = new CodeMemberMethod
                {
                    Name       = "CanConvertTo",
                    Attributes = MemberAttributes.Public | MemberAttributes.Override,
                    ReturnType = new CodeTypeReference(typeof(bool))
                };

                canConvertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ITypeDescriptorContext).ToTypeReference(), "context"));
                canConvertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(System.Type), "destinationType"));
                var destinationTypeRef = new CodeArgumentReferenceExpression("destinationType");

                canConvertTo.Statements.Add(new CodeMethodReturnStatement(new CodeBinaryOperatorExpression(destinationTypeRef, CodeBinaryOperatorType.IdentityEquality, stringTypeRef)));
                typeConverter.Members.Add(canConvertTo);

                var typeRef        = generatedType.GetReferenceForType();
                var typeExpression = new CodeTypeReferenceExpression(typeRef);
                var convertFrom    = new CodeMemberMethod
                {
                    Name       = "ConvertFrom",
                    Attributes = MemberAttributes.Public | MemberAttributes.Override,
                    ReturnType = new CodeTypeReference(typeof(object))
                };

                convertFrom.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ITypeDescriptorContext).ToTypeReference(), "context"));
                convertFrom.Parameters.Add(new CodeParameterDeclarationExpression(typeof(CultureInfo).ToTypeReference(), "culture"));
                convertFrom.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "value"));
                var valueRef = new CodeArgumentReferenceExpression("value");
                var nullRef  = new CodePrimitiveExpression();

                convertFrom.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(valueRef, CodeBinaryOperatorType.IdentityEquality, nullRef),
                                                                      new CodeMethodReturnStatement(new CodeDefaultValueExpression(typeRef))));
                var valueString = new CodeVariableDeclarationStatement(typeof(string), "valueString", new CodeMethodInvokeExpression(valueRef, "ToString"));

                convertFrom.Statements.Add(valueString);
                var valueStringRef = new CodeVariableReferenceExpression(valueString.Name);

                foreach (var field in fieldNames)
                {
                    convertFrom.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(valueStringRef, CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(field.Key.Name)),
                                                                          new CodeMethodReturnStatement(new CodeFieldReferenceExpression(typeExpression, field.Value))));
                }
                convertFrom.Statements.Add(new CodeMethodReturnStatement(new CodeDefaultValueExpression(typeRef)));
                typeConverter.Members.Add(convertFrom);

                var convertTo = new CodeMemberMethod
                {
                    Name       = "ConvertTo",
                    Attributes = MemberAttributes.Public | MemberAttributes.Override,
                    ReturnType = new CodeTypeReference(typeof(object))
                };

                convertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ITypeDescriptorContext).ToTypeReference(), "context"));
                convertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(CultureInfo).ToTypeReference(), "culture"));
                convertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "value"));
                convertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(System.Type).ToTypeReference(), "destinationType"));
                convertTo.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(valueRef, CodeBinaryOperatorType.IdentityEquality, nullRef),
                                                                    new CodeMethodReturnStatement(nullRef)));
                var valueCasted = new CodeVariableDeclarationStatement(typeRef, "valueCasted", new CodeCastExpression(typeRef, valueRef));

                convertTo.Statements.Add(valueCasted);
                var valueCastedRef = new CodeVariableReferenceExpression(valueCasted.Name);

                foreach (var field in fieldNames)
                {
                    convertTo.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(valueCastedRef, CodeBinaryOperatorType.ValueEquality, new CodeFieldReferenceExpression(typeExpression, field.Value)),
                                                                        new CodeMethodReturnStatement(new CodePrimitiveExpression(field.Key.Name))));
                }
                convertTo.ThrowException <ArgumentOutOfRangeException>("value");
                typeConverter.Members.Add(convertTo);

                generatedType.AddAttribute(typeof(TypeConverterAttribute), new CodeTypeOfExpression(typeConverter.Name));
                dependents.Add(typeConverter);
            }