Exemple #1
0
        public List <PropertyTypeNode> Deserialize()
        {
            var definitions = new List <PropertyTypeNode>();

            if (string.IsNullOrEmpty(Code))
            {
                return(definitions);
            }

            var ast = CSharpSyntaxTree.ParseText(Code);

            var root = (CompilationUnitSyntax)ast.GetRoot();

            var references = ReferenceAssemblies.Locations.Select(
                location => (MetadataReference)MetadataReference.CreateFromFile(location)).ToArray();

            var compilation = CSharpCompilation.Create(Path.GetRandomFileName())
                              .AddReferences(references)
                              .AddSyntaxTrees(ast);

            var model = compilation.GetSemanticModel(ast);

            var collector = new SemanticInformationCollector(model);

            collector.Visit(root);

            definitions = ExtractPropertyNodesFrom(model, collector);

            return(definitions);
        }
Exemple #2
0
        private List <PropertyTypeNode> ExtractPropertyNodesFrom(
            SemanticModel model, SemanticInformationCollector collector)
        {
            if (model == null)
            {
                throw new Exception("Invalid semantic model for property node introspection (null).");
            }

            var nodes = new List <PropertyTypeNode>();

            var typePerFullTypename = new Dictionary <string, PropertyTypeNode>();

            // Expect a top -> bottom tree traversal, so it means that the
            // list contains types declared in order.

            foreach (var type in collector.ContainerTypes)
            {
                var tag = PropertyTypeNode.TypeTag.Class;
                if (type is StructDeclarationSyntax)
                {
                    tag = PropertyTypeNode.TypeTag.Struct;
                }

                var symbol = model.GetDeclaredSymbol(type);

                var typePath = new ContainerTypeTreePath
                {
                    Namespace = NamespaceForType(type)
                };

                var fullTypeNamePath = symbol.ToString().Replace(typePath.Namespace, "").Trim('.').Split('.');
                fullTypeNamePath = fullTypeNamePath.Take(fullTypeNamePath.Length - 1).ToArray();
                foreach (var pathPart in fullTypeNamePath)
                {
                    typePath.TypePath.Push(pathPart);
                }

                var node = new PropertyTypeNode
                {
                    Tag                      = tag,
                    TypePath                 = typePath,
                    TypeName                 = symbol.Name,
                    IsAbstractClass          = symbol.IsAbstract,
                    OverrideDefaultBaseClass = symbol.AllInterfaces.Any(i => i.Name == typeof(IPropertyContainer).Name)
                        ? string.Empty : symbol.BaseType.Name
                };

                var fieldCollector = new FieldCollector(model);

                fieldCollector.Visit(type);

                foreach (var field in fieldCollector.Properties)
                {
                    var genericProperty = new RoslynProperty(field.Symbol);
                    if (!genericProperty.IsValid)
                    {
                        continue;
                    }

                    // Parse

                    var property = new PropertyTypeNode()
                    {
                        PropertyName     = PropertyNameFromFieldName(field.Symbol.Name),
                        Tag              = genericProperty.TypeTag,
                        TypeName         = genericProperty.TypeID,
                        Of               = genericProperty.ListOf,
                        IsReadonly       = genericProperty.IsReadonly,
                        IsPublicProperty = field.SyntaxNode.Modifiers.Any(SyntaxKind.PublicKeyword)
                    };

                    // Extract info about backing fields

                    var initializer = field.SyntaxNode.Declaration.Variables.First().Initializer;
                    if (initializer?.Value is ExpressionSyntax)
                    {
/*
 *                      // @TODO
 *                      var initializerExpression = initializer.Value;
 *
 *                      // @TODO
 *                      var symbolNames = model.LookupSymbols(initializerExpression.SpanStart).Select(s => s.Name).ToList();
 */

                        // property.DefaultValue =
                        property.PropertyBackingAccessor = string.Empty;
                    }

                    if (!string.IsNullOrEmpty(property.PropertyName))
                    {
                        node.Properties.Add(property);
                    }
                }

                var containingSymbolFullName = symbol.ContainingSymbol.ToDisplayString();
                // symbol.ContainingSymbol.Name
                if (typePerFullTypename.ContainsKey(containingSymbolFullName))
                {
                    // This is a nested node

                    var parent = typePerFullTypename[containingSymbolFullName];

                    node.TypePath = new ContainerTypeTreePath(parent.TypePath);

                    node.TypePath.TypePath.Push(parent.TypeName);

                    parent.NestedContainers.Add(node);
                }
                else
                {
                    // This is a new node

                    typePerFullTypename[node.FullTypeName] = node;
                    nodes.Add(node);
                }
            }

            return(nodes);
        }