private void LoadSettingsTree(SimpleSourceFile file)
        {
            Stack <SimpleSettings> settingsList = new Stack <SimpleSettings>();
            var directory = Path.GetDirectoryName(file.Path);

            while (directory != null)
            {
                var settingsFile = Path.Combine(directory, "gqlsettings.json");
                if (File.Exists(settingsFile))
                {
                    if (ExpandSettings(settingsFile, file))
                    {
                        return;
                    }
                }

                directory = Path.GetDirectoryName(directory);
            }
        }
        private bool ExpandSettings(string path, SimpleSourceFile file, bool overwrite = false)
        {
            var root         = Path.GetDirectoryName(path);
            var settingsJson = File.ReadAllText(path);

            var settings = Newtonsoft.Json.JsonConvert.DeserializeObject <SimpleSettings>(settingsJson);

            if (!string.IsNullOrWhiteSpace(settings.Class) && (string.IsNullOrWhiteSpace(file.ClassName) || overwrite))
            {
                file.ClassName = settings.Class;
            }
            if (!string.IsNullOrWhiteSpace(settings.TypeNameDirective) && (string.IsNullOrWhiteSpace(file.TypeNameDirective) || overwrite))
            {
                file.TypeNameDirective = settings.TypeNameDirective;
            }
            if (!string.IsNullOrWhiteSpace(settings.Output) && (string.IsNullOrWhiteSpace(file.OutputPath) || overwrite))
            {
                file.OutputPath = GenerateFullPath(root, settings.Output);
            }
            if (!string.IsNullOrWhiteSpace(settings.Format) && (string.IsNullOrWhiteSpace(file.Format) || overwrite))
            {
                file.Format = settings.Format;
            }
            if (settings.Template != null)
            {
                foreach (var t in settings.Template)
                {
                    var templateFiles = GlobExpander.FindFiles(root, t);
                    file.Templates.AddRange(templateFiles);
                }
            }

            if (settings.TemplateSettings != null)
            {
                foreach (var t in settings.TemplateSettings)
                {
                    if (!file.TemplateSettings.TryGetValue(t.Key, out _))
                    {
                        // set if doesn't exist
                        file.TemplateSettings[t.Key] = t.Value;
                    }
                }
            }

            if (settings.Include != null)
            {
                foreach (var t in settings.Include)
                {
                    var files = GlobExpander.FindFiles(root, t);
                    file.Includes.AddRange(files);
                }
            }

            if (string.IsNullOrWhiteSpace(file.SchemaSource?.Location) || overwrite)
            {
                if (settings.Schema != null && !string.IsNullOrWhiteSpace(settings.Schema.Location))
                {
                    file.SchemaSource = settings.Schema;
                    if (file.SchemaSource.SchemaType() != SchemaSource.SchemaTypes.Http)
                    {
                        // we are not and url based location then it must be a path
                        file.SchemaSource.Location = GlobExpander.FindFile(root, file.SchemaSource.Location);
                    }
                }
            }

            if (settings.Root)
            {
                file.RootPath = root;
            }

            return(settings.Root);
        }
        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);
        }