public PropertyTypeNode.TypeTag WhenContextAndBuiltinTypes_Resolve_Works( string contextTypePath, string typeName) { var builtinTypes = new Dictionary <string, PropertyTypeNode.TypeTag> { { "my.namespace.roottype/nested/type/roottype", PropertyTypeNode.TypeTag.Enum }, { "my.namespace.roottype/nested/type", PropertyTypeNode.TypeTag.Class }, { "my.namespace.roottype/nested", PropertyTypeNode.TypeTag.Struct }, { "my.namespace.roottype", PropertyTypeNode.TypeTag.Class }, { "my.namespace.mytype", PropertyTypeNode.TypeTag.Class }, { "topleveltype", PropertyTypeNode.TypeTag.Enum }, }; return(new TypeResolver() .WithBuiltinSymbols(builtinTypes) .Resolve( ContainerTypeTreePath.CreateFromString(contextTypePath), typeName )); }
public void Create_WithEmptyPath() { var p = ContainerTypeTreePath.CreateFromString(string.Empty); Assert.AreEqual(p.FullPath, string.Empty); }
public string Create_WithFullPathIsIdempotent(string fullPath) { return(ContainerTypeTreePath.CreateFromString(fullPath).FullPath); }
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); }