Example #1
0
        public Repository(Project project)
        {
            this.DomainByName            = new Dictionary <string, Domain>();
            this.UnitBySingularName      = new Dictionary <string, Unit>();
            this.InterfaceBySingularName = new Dictionary <string, Interface>();
            this.ClassBySingularName     = new Dictionary <string, Class>();
            this.CompositeByName         = new Dictionary <string, Composite>();
            this.TypeBySingularName      = new Dictionary <string, Type>();

            this.inflector = new Inflector(new CultureInfo("en"));

            var projectInfo = new RepositoryProject(project);

            this.CreateDomains(projectInfo);

            this.CreateUnits();
            this.CreateTypes(projectInfo);
            this.CreateHierarchy(projectInfo);
            this.CreateMembers(projectInfo);

            this.FromReflection(projectInfo);

            this.LinkImplementations();

            this.CreateInheritedProperties();
            this.CreateReverseProperties();

            var ids = new HashSet <Guid>();

            foreach (var composite in this.Composites)
            {
                this.CheckId(ids, composite.Id, $"{composite.SingularName}", "id");

                // TODO: Add id checks for properties
                foreach (var property in composite.DefinedProperties)
                {
                    this.CheckId(ids, property.Id, $"{composite.SingularName}.{property.RoleName}", "id");
                    this.CheckId(ids, property.AssociationId, $"{composite.SingularName}.{property.RoleName}", "association id");
                    this.CheckId(ids, property.RoleId, $"{composite.SingularName}.{property.RoleName}", "role id");
                }

                foreach (var method in composite.DefinedMethods)
                {
                    if (!method.AttributeByName.ContainsKey(AttributeNames.Id))
                    {
                        this.HasErrors = true;
                        Logger.Error($"{method} has no {AttributeNames.Id} attribute.");
                    }
                }
            }
        }
Example #2
0
        private void CreateDomains(RepositoryProject repositoryProject)
        {
            var parentByChild = new Dictionary <string, string>();

            foreach (var syntaxTree in repositoryProject.DocumentBySyntaxTree.Keys)
            {
                var root = syntaxTree.GetRoot();
                foreach (var structDeclaration in root.DescendantNodes().OfType <StructDeclarationSyntax>())
                {
                    var semanticModel   = repositoryProject.Compilation.GetSemanticModel(syntaxTree);
                    var structureModel  = (ITypeSymbol)semanticModel.GetDeclaredSymbol(structDeclaration);
                    var domainAttribute = structureModel.GetAttributes().FirstOrDefault(v => v.AttributeClass.Name.Equals("DomainAttribute"));

                    if (domainAttribute != null)
                    {
                        var id = Guid.Parse((string)domainAttribute.ConstructorArguments.First().Value);

                        var document      = repositoryProject.DocumentBySyntaxTree[syntaxTree];
                        var fileInfo      = new FileInfo(document.FilePath);
                        var directoryInfo = new DirectoryInfo(fileInfo.DirectoryName);

                        var domain = new Domain(id, directoryInfo);
                        this.DomainByName.Add(domain.Name, domain);

                        var extendsAttribute = structureModel.GetAttributes().FirstOrDefault(v => v.AttributeClass.Name.Equals("ExtendsAttribute"));
                        var parent           = (string)extendsAttribute.ConstructorArguments.First().Value;

                        if (!string.IsNullOrEmpty(parent))
                        {
                            parentByChild.Add(domain.Name, parent);
                        }
                    }
                }
            }

            foreach (var child in parentByChild.Keys)
            {
                var parent = parentByChild[child];
                this.DomainByName[child].Base = this.DomainByName[parent];
            }
        }
Example #3
0
        private void CreateHierarchy(RepositoryProject repositoryProject)
        {
            var definedTypeBySingularName = repositoryProject.Assembly.DefinedTypes.Where(v => RepositoryNamespaceName.Equals(v.Namespace)).ToDictionary(v => v.Name);

            foreach (var composite in this.CompositeByName.Values)
            {
                var definedType      = definedTypeBySingularName[composite.SingularName];
                var allInterfaces    = definedType.GetInterfaces();
                var directInterfaces = allInterfaces.Except(allInterfaces.SelectMany(t => t.GetInterfaces()));
                foreach (var definedImplementedInterface in directInterfaces)
                {
                    if (this.InterfaceBySingularName.TryGetValue(definedImplementedInterface.Name, out var implementedInterface))
                    {
                        composite.ImplementedInterfaces.Add(implementedInterface);
                    }
                    else
                    {
                        throw new Exception("Can not find implemented interface " + definedImplementedInterface.Name + " on " + composite.SingularName);
                    }
                }
            }
        }
Example #4
0
        private void FromReflection(RepositoryProject repositoryProject)
        {
            var declaredTypeBySingularName = repositoryProject.Assembly.DefinedTypes.Where(v => RepositoryNamespaceName.Equals(v.Namespace)).ToDictionary(v => v.Name);

            foreach (var composite in this.CompositeByName.Values)
            {
                var reflectedType = declaredTypeBySingularName[composite.SingularName];

                // Type attributes
                {
                    var typeAttributesByTypeName = reflectedType.GetCustomAttributes(false).Cast <Attribute>().GroupBy(v => v.GetType());

                    foreach (var group in typeAttributesByTypeName)
                    {
                        var type     = group.Key;
                        var typeName = type.Name;
                        if (typeName.ToLowerInvariant().EndsWith("attribute"))
                        {
                            typeName = typeName.Substring(0, typeName.Length - "attribute".Length);
                        }

                        var attributeUsage = type.GetCustomAttributes <AttributeUsageAttribute>().FirstOrDefault();
                        if (attributeUsage != null && attributeUsage.AllowMultiple)
                        {
                            composite.AttributesByName[typeName] = group.ToArray();
                        }
                        else
                        {
                            composite.AttributeByName[typeName] = group.First();
                        }
                    }
                }

                // Property attributes
                foreach (var property in composite.Properties)
                {
                    var reflectedProperty = reflectedType.GetProperty(property.RoleName);
                    if (reflectedProperty == null)
                    {
                        this.HasErrors = true;
                        Logger.Error($"{reflectedType.Name}.{property.RoleName} should be public");
                        continue;
                    }

                    var propertyAttributesByTypeName = reflectedProperty.GetCustomAttributes(false).Cast <Attribute>().GroupBy(v => v.GetType());

                    var reflectedPropertyType = reflectedProperty.PropertyType;
                    var typeName = this.GetTypeName(reflectedPropertyType);
                    property.Type = this.TypeBySingularName[typeName];

                    foreach (var group in propertyAttributesByTypeName)
                    {
                        var attributeType     = group.Key;
                        var attributeTypeName = attributeType.Name;
                        if (attributeTypeName.ToLowerInvariant().EndsWith("attribute"))
                        {
                            attributeTypeName = attributeTypeName.Substring(
                                0,
                                attributeTypeName.Length - "attribute".Length);
                        }

                        var attributeUsage =
                            attributeType.GetCustomAttributes <AttributeUsageAttribute>().FirstOrDefault();
                        if (attributeUsage != null && attributeUsage.AllowMultiple)
                        {
                            property.AttributesByName.Add(attributeTypeName, group.ToArray());
                        }
                        else
                        {
                            property.AttributeByName.Add(attributeTypeName, group.First());
                        }
                    }

                    if (property.AttributeByName.Keys.Contains("Multiplicity"))
                    {
                        if (reflectedPropertyType.Name.EndsWith("[]"))
                        {
                            if (property.IsRoleOne)
                            {
                                this.HasErrors = true;
                                Logger.Error($"{reflectedType.Name}.{property.RoleName} should be many");
                            }
                        }
                        else
                        {
                            if (property.IsRoleMany)
                            {
                                this.HasErrors = true;
                                Logger.Error($"{reflectedType.Name}.{property.RoleName} should be one");
                            }
                        }
                    }
                }

                foreach (var method in composite.Methods)
                {
                    var reflectedMethod        = reflectedType.GetMethod(method.Name);
                    var methodAttributesByType = reflectedMethod.GetCustomAttributes(false).Cast <Attribute>().GroupBy(v => v.GetType());

                    foreach (var group in methodAttributesByType)
                    {
                        var attributeType     = group.Key;
                        var attributeTypeName = attributeType.Name;
                        if (attributeTypeName.ToLowerInvariant().EndsWith("attribute"))
                        {
                            attributeTypeName = attributeTypeName.Substring(0, attributeTypeName.Length - "attribute".Length);
                        }

                        var attributeUsage = attributeType.GetCustomAttributes <AttributeUsageAttribute>().FirstOrDefault();
                        if (attributeUsage != null && attributeUsage.AllowMultiple)
                        {
                            method.AttributesByName.Add(attributeTypeName, group.ToArray());
                        }
                        else
                        {
                            method.AttributeByName.Add(attributeTypeName, group.First());
                        }
                    }
                }
            }
        }
Example #5
0
        private void CreateMembers(RepositoryProject repositoryProject)
        {
            foreach (var syntaxTree in repositoryProject.DocumentBySyntaxTree.Keys)
            {
                var root          = syntaxTree.GetRoot();
                var semanticModel = repositoryProject.SemanticModelBySyntaxTree[syntaxTree];
                var document      = repositoryProject.DocumentBySyntaxTree[syntaxTree];
                var fileInfo      = new FileInfo(document.FilePath);
                var domain        = this.Domains.FirstOrDefault(v => v.DirectoryInfo.Contains(fileInfo));

                if (domain != null)
                {
                    var typeDeclaration = root.DescendantNodes().SingleOrDefault(v => v is InterfaceDeclarationSyntax || v is ClassDeclarationSyntax);
                    if (typeDeclaration != null)
                    {
                        var typeSymbol = semanticModel.GetDeclaredSymbol(typeDeclaration);
                        var typeName   = typeSymbol.Name;

                        if (domain.PartialTypeBySingularName.TryGetValue(typeName, out var partialType))
                        {
                            var composite            = this.CompositeByName[typeName];
                            var propertyDeclarations = typeDeclaration.DescendantNodes().OfType <PropertyDeclarationSyntax>();
                            foreach (var propertyDeclaration in propertyDeclarations)
                            {
                                var propertySymbol   = semanticModel.GetDeclaredSymbol(propertyDeclaration);
                                var propertyRoleName = propertySymbol.Name;

                                var xmlDocString = propertySymbol.GetDocumentationCommentXml(null, true);
                                var xmlDoc       = !string.IsNullOrWhiteSpace(xmlDocString) ? new XmlDoc(xmlDocString) : null;

                                var property = new Property(this.inflector, composite, propertyRoleName)
                                {
                                    XmlDoc = xmlDoc
                                };

                                partialType.PropertyByName.Add(propertyRoleName, property);
                                composite.PropertyByRoleName.Add(propertyRoleName, property);
                            }

                            var methodDeclarations = typeDeclaration.DescendantNodes().OfType <MethodDeclarationSyntax>();
                            foreach (var methodDeclaration in methodDeclarations)
                            {
                                var methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration);
                                var methodName   = methodSymbol.Name;

                                var xmlDocString = methodSymbol.GetDocumentationCommentXml(null, true);
                                var xmlDoc       = !string.IsNullOrWhiteSpace(xmlDocString) ? new XmlDoc(xmlDocString) : null;

                                var method = new Method(composite, methodName)
                                {
                                    XmlDoc = xmlDoc
                                };

                                partialType.MethodByName.Add(methodName, method);
                                composite.MethodByName.Add(methodName, method);
                            }
                        }
                    }
                }
            }
        }
Example #6
0
        private void CreateTypes(RepositoryProject repositoryProject)
        {
            foreach (var syntaxTree in repositoryProject.DocumentBySyntaxTree.Keys)
            {
                var root          = syntaxTree.GetRoot();
                var semanticModel = repositoryProject.SemanticModelBySyntaxTree[syntaxTree];
                var document      = repositoryProject.DocumentBySyntaxTree[syntaxTree];
                var fileInfo      = new FileInfo(document.FilePath);

                var interfaceDeclaration = root.DescendantNodes().OfType <InterfaceDeclarationSyntax>().SingleOrDefault();
                if (interfaceDeclaration != null)
                {
                    var typeModel   = (ITypeSymbol)semanticModel.GetDeclaredSymbol(interfaceDeclaration);
                    var idAttribute = typeModel.GetAttributes().FirstOrDefault(v => v.AttributeClass.Name.Equals("IdAttribute"));

                    if (idAttribute != null)
                    {
                        var id     = Guid.Parse((string)idAttribute.ConstructorArguments.First().Value);
                        var domain = this.Domains.First(v => v.DirectoryInfo.Contains(fileInfo));

                        var symbol = semanticModel.GetDeclaredSymbol(interfaceDeclaration);
                        if (RepositoryNamespaceName.Equals(symbol.ContainingNamespace.ToDisplayString()))
                        {
                            var interfaceSingularName = symbol.Name;

                            var partialInterface = new PartialInterface(interfaceSingularName);
                            domain.PartialInterfaceByName.Add(interfaceSingularName, partialInterface);
                            domain.PartialTypeBySingularName.Add(interfaceSingularName, partialInterface);

                            if (!this.InterfaceBySingularName.TryGetValue(interfaceSingularName, out var @interface))
                            {
                                @interface = new Interface(this.inflector, id, interfaceSingularName);
                                this.InterfaceBySingularName.Add(interfaceSingularName, @interface);
                                this.CompositeByName.Add(interfaceSingularName, @interface);
                                this.TypeBySingularName.Add(interfaceSingularName, @interface);
                            }

                            @interface.PartialByDomainName.Add(domain.Name, partialInterface);
                            var xmlDoc = symbol.GetDocumentationCommentXml(null, true);
                            @interface.XmlDoc = !string.IsNullOrWhiteSpace(xmlDoc) ? new XmlDoc(xmlDoc) : null;
                        }
                    }
                }

                var classDeclaration = root.DescendantNodes().OfType <ClassDeclarationSyntax>().SingleOrDefault();
                if (classDeclaration != null)
                {
                    var typeModel   = (ITypeSymbol)semanticModel.GetDeclaredSymbol(classDeclaration);
                    var idAttribute = typeModel.GetAttributes().FirstOrDefault(v => v.AttributeClass.Name.Equals("IdAttribute"));

                    if (idAttribute != null)
                    {
                        var id     = Guid.Parse((string)idAttribute.ConstructorArguments.First().Value);
                        var domain = this.Domains.First(v => v.DirectoryInfo.Contains(fileInfo));

                        var symbol = semanticModel.GetDeclaredSymbol(classDeclaration);
                        if (RepositoryNamespaceName.Equals(symbol.ContainingNamespace.ToDisplayString()))
                        {
                            var classSingularName = symbol.Name;

                            var partialClass = new PartialClass(classSingularName);
                            domain.PartialClassBySingularName.Add(classSingularName, partialClass);
                            domain.PartialTypeBySingularName.Add(classSingularName, partialClass);

                            if (!this.ClassBySingularName.TryGetValue(classSingularName, out Class @class))
                            {
                                @class = new Class(this.inflector, id, classSingularName);
                                this.ClassBySingularName.Add(classSingularName, @class);
                                this.CompositeByName.Add(classSingularName, @class);
                                this.TypeBySingularName.Add(classSingularName, @class);
                            }

                            @class.PartialByDomainName.Add(domain.Name, partialClass);

                            var xmlDoc = symbol.GetDocumentationCommentXml(null, true);
                            @class.XmlDoc = !string.IsNullOrWhiteSpace(xmlDoc) ? new XmlDoc(xmlDoc) : null;
                        }
                    }
                }
            }
        }