private static void LoadSourceFiles(CanvasDocument app, DirectoryReader directory, Dictionary <string, ControlTemplate> templateDefaults, ErrorContainer errors)
        {
            foreach (var file in directory.EnumerateFiles(EditorStateDir, "*.json"))
            {
                if (!file._relativeName.EndsWith(".editorstate.json"))
                {
                    errors.FormatNotSupported($"Unexpected file present in {EditorStateDir}");
                    throw new DocumentException();
                }

                // Json peer to a .pa file.
                var controlExtraData = file.ToObject <Dictionary <string, ControlState> >();
                var topParentName    = file._relativeName.Replace(".editorstate.json", "");
                foreach (var control in controlExtraData)
                {
                    control.Value.TopParentName = topParentName;
                    if (!app._editorStateStore.TryAddControl(control.Value))
                    {
                        // Can't have duplicate control names.
                        // This might happen due to a bad merge.
                        errors.EditorStateError(file.SourceSpan, $"Control '{control.Value.Name}' is already defined.");
                    }
                }
            }

            // For now, the Themes file lives in CodeDir as a json file
            // We'd like to make this .pa.yaml as well eventually
            foreach (var file in directory.EnumerateFiles(CodeDir, "*.json", searchSubdirectories: false))
            {
                if (Path.GetFileName(file._relativeName) == "Themes.json")
                {
                    app._themes = file.ToObject <ThemesJson>();
                }
            }


            foreach (var file in directory.EnumerateFiles(CodeDir, "*.pa.yaml", searchSubdirectories: false))
            {
                AddControl(app, file._relativeName, false, file.GetContents(), errors);
            }

            foreach (var file in EnumerateComponentDirs(directory, "*.pa.yaml"))
            {
                AddControl(app, file._relativeName, true, file.GetContents(), errors);
            }

            foreach (var file in directory.EnumerateFiles(TestDir, "*.pa.yaml"))
            {
                AddControl(app, file._relativeName, false, file.GetContents(), errors);
            }

            foreach (var file in EnumerateComponentDirs(directory, "*.json"))
            {
                var componentTemplate = file.ToObject <CombinedTemplateState>();
                app._templateStore.AddTemplate(componentTemplate.ComponentManifest.Name, componentTemplate);
            }
        }
        private static void LoadSourceFiles(CanvasDocument app, DirectoryReader directory, Dictionary <string, ControlTemplate> templateDefaults, ErrorContainer errors)
        {
            foreach (var file in directory.EnumerateFiles(EditorStateDir, "*.json"))
            {
                if (!file._relativeName.EndsWith(".editorstate.json"))
                {
                    errors.FormatNotSupported($"Unexpected file present in {EditorStateDir}");
                    throw new DocumentException();
                }

                // Json peer to a .pa file.
                ControlTreeState editorState = file.ToObject <ControlTreeState>();
                if (editorState.ControlStates == null)
                {
                    ApplyV24BackCompat(editorState, file);
                }

                foreach (var control in editorState.ControlStates)
                {
                    control.Value.TopParentName = editorState.TopParentName;
                    if (!app._editorStateStore.TryAddControl(control.Value))
                    {
                        // Can't have duplicate control names.
                        // This might happen due to a bad merge.
                        errors.EditorStateError(file.SourceSpan, $"Control '{control.Value.Name}' is already defined.");
                    }
                }
            }

            // For now, the Themes file lives in CodeDir as a json file
            // We'd like to make this .fx.yaml as well eventually
            foreach (var file in directory.EnumerateFiles(CodeDir, "*.json", searchSubdirectories: false))
            {
                if (Path.GetFileName(file._relativeName) == "Themes.json")
                {
                    app._themes = file.ToObject <ThemesJson>();
                }
            }

            foreach (var file in EnumerateComponentDirs(directory, "*.fx.yaml"))
            {
                AddControl(app, file._relativeName, true, file.GetContents(), errors);
            }

            foreach (var file in EnumerateComponentDirs(directory, "*.json"))
            {
                var componentTemplate = file.ToObject <CombinedTemplateState>();
                app._templateStore.AddTemplate(componentTemplate.ComponentManifest.Name, componentTemplate);
            }

            foreach (var file in directory.EnumerateFiles(CodeDir, "*.fx.yaml", searchSubdirectories: false))
            {
                AddControl(app, file._relativeName, false, file.GetContents(), errors);
            }

            // When loading TestSuites sharded files, add them within the top parent AppTest control (i.e. Test_7F478737223C4B69)
            // Make sure to load the the Test_7F478737223C4B69.fx.yaml file first to add the top parent control.
            var shardedTestSuites = new List <DirectoryReader.Entry>();

            foreach (var file in directory.EnumerateFiles(TestDir, "*.fx.yaml"))
            {
                if (file.Kind == FileKind.AppTestParentControl)
                {
                    AddControl(app, file._relativeName, false, file.GetContents(), errors);
                }
                else
                {
                    shardedTestSuites.Add(file);
                }
            }
            shardedTestSuites.ForEach(x => AddControl(app, x._relativeName, false, x.GetContents(), errors));
        }