public IEnumerable <CodeGeneratorSettings> GenerateSettings(CodeGeneratorSettingsLoaderDefaults settings, IEnumerable <string> paths)
        {
            var root = Directory.GetCurrentDirectory();

            // we need to multi pass the source files looking for items to load
            var toProcess = new Queue <string>(paths.SelectMany(x => GlobExpander.FindFiles(root, x)));
            List <SimpleSourceFile> sourceFiles    = new List <SimpleSourceFile>();
            List <string>           processedPaths = new List <string>();

            while (toProcess.Any())
            {
                var path = toProcess.Dequeue();
                processedPaths.Add(path);
                var loaded   = Load(path, settings);
                var newPaths = loaded.Includes.Where(x => !processedPaths.Contains(x));
                foreach (var p in newPaths)
                {
                    toProcess.Enqueue(p);
                }
                sourceFiles.Add(loaded);
            }
            var schemaFiles = sourceFiles.Select(x => x.SchemaSource?.Location);
            var grouped     = sourceFiles
                              .Where(x => !schemaFiles.Contains(x.Path)) // exclude files linked in a schemas
                              .GroupBy(x => new
            {
                hash = x.SettingsHash()
            }).ToList();

            return(grouped.Select(x =>
            {
                var first = x.First();

                var nspc = "";
                var cn = first.ClassName;
                var idx = first.ClassName.LastIndexOf('.');
                if (idx > 0)
                {
                    cn = first.ClassName.Substring(idx);
                    nspc = first.ClassName.Substring(0, idx);
                }
                cn = cn.Trim('.');
                nspc = nspc.Trim('.');
                var templates = DefaultTemplates(first.OutputPath);
                templates.AddRange(x.First().Templates);
                return new CodeGeneratorSettings
                {
                    ClassName = cn,
                    Namespace = nspc,
                    OutputPath = first.OutputPath,
                    RootPath = first.RootPath,
                    TypeNameDirective = first.TypeNameDirective,
                    SourceFiles = x.Select(p => new NamedSource
                    {
                        Body = p.Body,
                        Path = p.Path
                    }).ToList(),
                    Schema = x.First().SchemaSource,
                    Templates = templates,
                    TemplateSettings = first.TemplateSettings
                };
            }).ToList());
        }
        private SimpleSourceFile Load(string path, CodeGeneratorSettingsLoaderDefaults settings)
        {
            // path must be a real full path by here

            var gql = File.ReadAllText(path);

            // lets discover / cache all settings files from this point up the stack and root them out

            var file = new SimpleSourceFile()
            {
                Path = path,
                Body = gql
            };
            var root = Path.GetDirectoryName(path);

            var matches = regex.Matches(gql);
            var pairs   = matches.OfType <Match>().Select(m => (key: m.Groups[1].Value.ToLower(), val: m.Groups[2].Value)).ToList();

            foreach (var m in pairs)
            {
                // process them in order to later directives overwrite previous ones
                switch (m.key)
                {
                case "schema":
                    file.SchemaSource          = file.SchemaSource ?? new SchemaSource();
                    file.SchemaSource.Location = GenerateFullPath(root, m.val);
                    break;

                case "schema.querytype":
                    file.SchemaSource = file.SchemaSource ?? new SchemaSource();
                    file.SchemaSource.QueryType.Add(m.val);
                    break;

                case "schema.mutationtype":
                    file.SchemaSource = file.SchemaSource ?? new SchemaSource();
                    file.SchemaSource.MutationType.Add(m.val);
                    break;

                case "output":
                    file.OutputPath = GenerateFullPath(root, m.val);
                    break;

                case "class":
                    file.ClassName = m.val;
                    break;

                case "typedirective":
                    file.TypeNameDirective = m.val;
                    break;

                case "format":
                    file.Format = m.val;
                    break;

                case "settings":
                    ExpandSettings(GenerateFullPath(root, m.val), file);
                    break;

                case "template":
                    var templateFiles = GlobExpander.FindFiles(root, m.val);
                    file.Templates.AddRange(templateFiles);
                    break;

                case "include":
                    var includeFiles = GlobExpander.FindFiles(root, m.val);
                    file.Includes.AddRange(includeFiles);
                    break;

                default:
                    break;
                }
            }

            LoadSettingsTree(file);

            if (File.Exists(settings.OverridesPath))
            {
                ExpandSettings(settings.OverridesPath, file, true);
            }

            if (string.IsNullOrWhiteSpace(file.TypeNameDirective))
            {
                file.TypeNameDirective = "__codeGenTypeName";
            }

            if (string.IsNullOrWhiteSpace(file.Format))
            {
                if (!string.IsNullOrWhiteSpace(file.OutputPath))
                {
                    file.Format = Path.GetExtension(file.OutputPath).Trim('.').ToLower();
                }

                if (string.IsNullOrWhiteSpace(file.Format))
                {
                    file.Format = settings.Format;
                }
            }

            if (string.IsNullOrWhiteSpace(file.OutputPath))
            {
                if (string.IsNullOrWhiteSpace(settings.OutputPath))
                {
                    file.OutputPath = file.Path;
                }
                else
                {
                    file.OutputPath = settings.OutputPath;
                }
            }

            if (!Path.GetExtension(file.OutputPath).Trim('.').Equals(file.Format, StringComparison.OrdinalIgnoreCase))
            {
                file.OutputPath += "." + file.Format;
            }

            if (string.IsNullOrWhiteSpace(file.ClassName))
            {
                file.ClassName = Path.GetFileNameWithoutExtension(file.Path);
            }

            settings.FixFile?.Invoke(file);
            file.OutputPath = file.OutputPath.Replace("{classname}", file.ClassName);

            return(file);
        }