private static void Parse(ParseResult disco, CSharpCompilation compilation, SyntaxTree tree)
        {
            var model = compilation.GetSemanticModel(tree);

            //we quite probably have errors but that is normal
            //var diags = model.GetDiagnostics();

            var classDecls = tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>();
            foreach (var classSymbol in classDecls.Select(x => model.GetDeclaredSymbol(x)))
            {
                ParseClassSymbols(disco, classSymbol);

                var baseClassSymbol = classSymbol.BaseType;
                if (baseClassSymbol != null)
                    //disco.SetContentBaseClass(SymbolDisplay.ToDisplayString(classSymbol), SymbolDisplay.ToDisplayString(baseClassSymbol));
                    disco.SetContentBaseClass(classSymbol.Name, baseClassSymbol.Name);

                var interfaceSymbols = classSymbol.Interfaces;
                disco.SetContentInterfaces(classSymbol.Name, //SymbolDisplay.ToDisplayString(classSymbol),
                    interfaceSymbols.Select(x => x.Name)); //SymbolDisplay.ToDisplayString(x)));

                var hasCtor = classSymbol.Constructors
                    .Any(x =>
                    {
                        if (x.IsStatic) return false;
                        if (x.Parameters.Length != 1) return false;
                        var type1 = x.Parameters[0].Type;
                        var type2 = typeof (global::Umbraco.Core.Models.IPublishedContent);
                        return type1.ToDisplayString() == type2.FullName;
                    });

                if (hasCtor)
                    disco.SetHasCtor(classSymbol.Name);

                foreach (var propertySymbol in classSymbol.GetMembers().Where(x => x is IPropertySymbol))
                    ParsePropertySymbols(disco, classSymbol, propertySymbol);

                foreach (var staticMethodSymbol in classSymbol.GetMembers().Where(x => x is IMethodSymbol))
                    ParseMethodSymbol(disco, classSymbol, staticMethodSymbol);
            }

            var interfaceDecls = tree.GetRoot().DescendantNodes().OfType<InterfaceDeclarationSyntax>();
            foreach (var interfaceSymbol in interfaceDecls.Select(x => model.GetDeclaredSymbol(x)))
            {
                ParseClassSymbols(disco, interfaceSymbol);

                var interfaceSymbols = interfaceSymbol.Interfaces;
                disco.SetContentInterfaces(interfaceSymbol.Name, //SymbolDisplay.ToDisplayString(interfaceSymbol),
                    interfaceSymbols.Select(x => x.Name)); // SymbolDisplay.ToDisplayString(x)));
            }

            ParseAssemblySymbols(disco, compilation.Assembly);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="Builder"/> class with a list of models to generate
        /// and the result of code parsing.
        /// </summary>
        /// <param name="typeModels">The list of models to generate.</param>
        /// <param name="parseResult">The result of code parsing.</param>
        protected Builder(IList<TypeModel> typeModels, ParseResult parseResult)
        {
            if (typeModels == null)
                throw new ArgumentNullException("typeModels");
            if (parseResult == null)
                throw new ArgumentNullException("parseResult");

            _typeModels = typeModels;
            ParseResult = parseResult;

            Prepare();
        }
        /// <summary>
        /// Parses a set of file.
        /// </summary>
        /// <param name="files">A set of (filename,content) representing content to parse.</param>
        /// <param name="referencedAssemblies">Assemblies to reference in compilations.</param>
        /// <returns>The result of the code parsing.</returns>
        /// <remarks>The set of files is a dictionary of name, content.</remarks>
        public ParseResult Parse(IDictionary<string, string> files, IEnumerable<Assembly> referencedAssemblies)
        {
            SyntaxTree[] trees;
            var compiler = new Compiler(Config.LanguageVersion);
            foreach (var asm in referencedAssemblies)
                compiler.ReferencedAssemblies.Add(asm);
            var compilation = compiler.GetCompilation("Umbraco.ModelsBuilder.Generated", files, out trees);

            var disco = new ParseResult();
            foreach (var tree in trees)
                Parse(disco, compilation, tree);

            return disco;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="Builder"/> class with a list of models to generate,
 /// the result of code parsing, and a models namespace.
 /// </summary>
 /// <param name="typeModels">The list of models to generate.</param>
 /// <param name="parseResult">The result of code parsing.</param>
 /// <param name="modelsNamespace">The models namespace.</param>
 protected Builder(IList<TypeModel> typeModels, ParseResult parseResult, string modelsNamespace)
     : this(typeModels, parseResult)
 {
     // can be null or empty, we'll manage
     ModelsNamespace = modelsNamespace;
 }
 public TestBuilder(IList<TypeModel> typeModels, ParseResult parseResult)
     : base(typeModels, parseResult)
 { }
        private static void ParseMethodSymbol(ParseResult disco, ISymbol classSymbol, ISymbol symbol)
        {
            var methodSymbol = symbol as IMethodSymbol;

            if (methodSymbol == null 
                || !methodSymbol.IsStatic
                || methodSymbol.IsGenericMethod
                || methodSymbol.ReturnsVoid
                || methodSymbol.IsExtensionMethod
                || methodSymbol.Parameters.Length != 1)
                return;

            var returnType = methodSymbol.ReturnType;
            var paramSymbol = methodSymbol.Parameters[0];
            var paramType = paramSymbol.Type;

            // cannot do this because maybe the param type is ISomething and we don't have
            // that type yet - will be generated - so cannot put any condition on it really
            //const string iPublishedContent = "Umbraco.Core.Models.IPublishedContent";
            //var implements = paramType.AllInterfaces.Any(x => x.ToDisplayString() == iPublishedContent);
            //if (!implements)
            //    return;

            disco.SetStaticMixinMethod(classSymbol.Name, methodSymbol.Name, returnType.Name, paramType.Name);
        }
        private static void ParseAssemblySymbols(ParseResult disco, ISymbol symbol)
        {
            foreach (var attrData in symbol.GetAttributes())
            {
                var attrClassSymbol = attrData.AttributeClass;

                // handle errors
                if (attrClassSymbol is IErrorTypeSymbol) continue;
                if (attrData.AttributeConstructor == null) continue;

                var attrClassName = SymbolDisplay.ToDisplayString(attrClassSymbol);
                switch (attrClassName)
                {
                    case "Umbraco.ModelsBuilder.IgnoreContentTypeAttribute":
                        var contentAliasToIgnore = (string)attrData.ConstructorArguments[0].Value;
                        // see notes in IgnoreContentTypeAttribute
                        //var ignoreContent = (bool)attrData.ConstructorArguments[1].Value;
                        //var ignoreMixin = (bool)attrData.ConstructorArguments[1].Value;
                        //var ignoreMixinProperties = (bool)attrData.ConstructorArguments[1].Value;
                        disco.SetIgnoredContent(contentAliasToIgnore /*, ignoreContent, ignoreMixin, ignoreMixinProperties*/);
                        break;

                    case "Umbraco.ModelsBuilder.RenameContentTypeAttribute":
                        var contentAliasToRename = (string) attrData.ConstructorArguments[0].Value;
                        var contentRenamed = (string)attrData.ConstructorArguments[1].Value;
                        disco.SetRenamedContent(contentAliasToRename, contentRenamed, false);
                        break;

                    case "Umbraco.ModelsBuilder.ModelsBaseClassAttribute":
                        var modelsBaseClass = (INamedTypeSymbol) attrData.ConstructorArguments[0].Value;
                        if (modelsBaseClass is IErrorTypeSymbol)
                            throw new Exception(string.Format("Invalid base class type \"{0}\".", modelsBaseClass.Name));
                        disco.SetModelsBaseClassName(SymbolDisplay.ToDisplayString(modelsBaseClass));
                        break;

                    case "Umbraco.ModelsBuilder.ModelsNamespaceAttribute":
                        var modelsNamespace= (string) attrData.ConstructorArguments[0].Value;
                        disco.SetModelsNamespace(modelsNamespace);
                        break;

                    case "Umbraco.ModelsBuilder.ModelsUsingAttribute":
                        var usingNamespace = (string)attrData.ConstructorArguments[0].Value;
                        disco.SetUsingNamespace(usingNamespace);
                        break;
                }
            }
        }
        private static void ParsePropertySymbols(ParseResult disco, ISymbol classSymbol, ISymbol symbol)
        {
            foreach (var attrData in symbol.GetAttributes())
            {
                var attrClassSymbol = attrData.AttributeClass;

                // handle errors
                if (attrClassSymbol is IErrorTypeSymbol) continue;
                if (attrData.AttributeConstructor == null) continue;

                var attrClassName = SymbolDisplay.ToDisplayString(attrClassSymbol);
                switch (attrClassName)
                {
                    case "Umbraco.ModelsBuilder.ImplementPropertyTypeAttribute":
                        var propertyAliasToIgnore = (string)attrData.ConstructorArguments[0].Value;
                        disco.SetIgnoredProperty(classSymbol.Name /*SymbolDisplay.ToDisplayString(classSymbol)*/, propertyAliasToIgnore);
                        break;
                }
            }
        }
        private static void ParseClassSymbols(ParseResult disco, ISymbol symbol)
        {
            foreach (var attrData in symbol.GetAttributes())
            {
                var attrClassSymbol = attrData.AttributeClass;

                // handle errors
                if (attrClassSymbol is IErrorTypeSymbol) continue;
                if (attrData.AttributeConstructor == null) continue;

                var attrClassName = SymbolDisplay.ToDisplayString(attrClassSymbol);
                switch (attrClassName)
                {
                    case "Umbraco.ModelsBuilder.IgnorePropertyTypeAttribute":
                        var propertyAliasToIgnore = (string)attrData.ConstructorArguments[0].Value;
                        disco.SetIgnoredProperty(symbol.Name /*SymbolDisplay.ToDisplayString(symbol)*/, propertyAliasToIgnore);
                        break;
                    case "Umbraco.ModelsBuilder.RenamePropertyTypeAttribute":
                        var propertyAliasToRename = (string)attrData.ConstructorArguments[0].Value;
                        var propertyRenamed = (string)attrData.ConstructorArguments[1].Value;
                        disco.SetRenamedProperty(symbol.Name /*SymbolDisplay.ToDisplayString(symbol)*/, propertyAliasToRename, propertyRenamed);
                        break;
                    // that one causes all sorts of issues with references to Umbraco.Core in Roslyn
                    //case "Umbraco.Core.Models.PublishedContent.PublishedContentModelAttribute":
                    //    var contentAliasToRename = (string)attrData.ConstructorArguments[0].Value;
                    //    disco.SetRenamedContent(contentAliasToRename, symbol.Name /*SymbolDisplay.ToDisplayString(symbol)*/);
                    //    break;
                    case "Umbraco.ModelsBuilder.ImplementContentTypeAttribute":
                        var contentAliasToRename = (string)attrData.ConstructorArguments[0].Value;
                        disco.SetRenamedContent(contentAliasToRename, symbol.Name, true /*SymbolDisplay.ToDisplayString(symbol)*/);
                        break;
                }
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="TextBuilder"/> class with a list of models to generate,
 /// the result of code parsing, and a models namespace.
 /// </summary>
 /// <param name="typeModels">The list of models to generate.</param>
 /// <param name="parseResult">The result of code parsing.</param>
 /// <param name="modelsNamespace">The models namespace.</param>
 public TextBuilder(IList<TypeModel> typeModels, ParseResult parseResult, string modelsNamespace)
     : base(typeModels, parseResult, modelsNamespace)
 { }