Пример #1
0
        public LiveProject(Fusion.IDocument fusionDocument, IFileSystem shell, IObservable <BytecodeGenerated> bytecodeGenerated, IScheduler scheduler = null)
        {
            scheduler = scheduler ?? Scheduler.Default;
            _shell    = shell;

            var mutations = new Subject <IBinaryMessage>();

            var idToElement = new BehaviorSubject <Dictionary <ObjectIdentifier, IElement> >(new Dictionary <ObjectIdentifier, IElement>());

            var metadata = bytecodeGenerated
                           .Select(bc => bc.Bytecode.Metadata.ElementTypeHierarchy.ToLookup())
                           .StartWith(Lookup.Empty <ObjectIdentifier, ObjectIdentifier>())
                           .Replay(1);

            _idToElement = idToElement;
            metadata.Connect();

            bytecodeGenerated.Subscribe(bc =>
            {
                var elements = idToElement.Value;

                foreach (var type in bc.Bytecode.Metadata.PrecompiledElements)
                {
                    IElement element;
                    if (!elements.TryGetValue(type.Id, out element))
                    {
                        elements[type.Id] = element = new LiveElement(
                            AbsoluteFilePath.Parse("N/A"),
                            metadata,
                            Observable.Return(true),
                            new Subject <Unit>(),
                            Observer.Create <IBinaryMessage>(_ => { }),
                            getElement: GetElement);
                    }

                    element.Replace(_ => Task.FromResult(SourceFragment.FromString(type.Source))).Wait();
                }

                idToElement.OnNext(elements);
            });

            var unoProj = ProjectWatcher.Create(fusionDocument, shell, scheduler);

            Name = unoProj.Name;
            PackageReferences = unoProj.PackageReferences;
            ProjectReferences = unoProj.ProjectReferences;
            var liveDocuments = unoProj.UxFiles
                                .CachePerElement(e => LiveDocument.Open(e, shell, metadata, idToElement, mutations, scheduler), val => val.Dispose())
                                .Select(ImmutableList.CreateRange)
                                .Replay(1).RefCount();

            var filePath = fusionDocument.FilePath.NotNone();


            FilePath             = filePath;
            RootDirectory        = filePath.Select(f => f.ContainingDirectory);
            BuildOutputDirectory = unoProj.BuildOutputDirectory;

            _liveDocuments = liveDocuments;
            Mutations      = mutations;

            BundleFiles = unoProj.BundleFiles;
            FuseJsFiles = unoProj.FuseJsFiles;

            Documents = liveDocuments.Select(d => ImmutableList.ToImmutableList(d.Cast <IDocument>()));

            var allElements = Documents
                              .CachePerElement(doc => doc.Elements)
                              .Select(docs => docs.ToObservableEnumerable()).Switch()
                              .Select(e => e.Join().ToArray())
                              .Replay(1).RefCount();

            var classes = allElements
                          .Where(e => e.HasProperty("ux:Class"))
                          .DistinctUntilSetChanged()
                          .Replay(1);

            var globals = allElements
                          .Where(e => e.HasProperty("ux:Global"))
                          .DistinctUntilSetChanged()
                          .Replay(1);

            Classes        = classes;
            GlobalElements = globals;

            LogMessages = _liveDocuments.Switch(docs =>
                                                docs.Select(doc => doc.Errors.NotNone().Select(o => doc.SimulatorIdPrefix + ": " + o.Message))
                                                .Merge());

            _garbage = Disposable.Combine(
                classes.Connect(),
                globals.Connect(),
                Disposable.Create(() =>
                                  liveDocuments
                                  .FirstAsync()
                                  .Subscribe(documents => documents.Each(d => d.Dispose()))));

            var app = Documents
                      .SelectPerElement(d => d.Root)
                      .WherePerElement(e => e.Name.Is("App"))
                      .Select(e => e.FirstOr(Element.Empty))
                      .Switch();

            Context = new Context(app, GetElement);
        }