/// <summary>
        /// Processes a document change event and updates a given snapshot based on the doc change.
        /// </summary>
        /// <param name="result">The result.</param>
        /// <param name="currentFile">The current file.</param>
        /// <param name="lastDocChanges">The last document changes.</param>
        /// <param name="files">The files.</param>
        /// <param name="docChange">The document change.</param>
        /// <returns>The path of the current file.</returns>
        private string ProcessDocumentChange(
            EntireSnapshot result,
            string currentFile,
            Dictionary <string, DocumentChange> lastDocChanges,
            Dictionary <string, StringBuilder> files,
            Event docChange)
        {
            if (docChange is FileOpenCommand)
            {
                currentFile = ProcessFileOpenCommand(
                    (FileOpenCommand)docChange,
                    files,
                    lastDocChanges,
                    result);
            }
            else if (docChange is DocumentChange)
            {
                if (currentFile == null)
                {
                    // Ignore document change events until a FileOpenCommand appears.
                    // continue;
                }

                this.ApplyDocumentChange(
                    (DocumentChange)docChange, files, currentFile, lastDocChanges);
            }

            return(currentFile);
        }
Exemple #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="EntireSnapshot"/> class.
        /// </summary>
        /// <param name="other">The existing snapshot object to copy from.</param>
        public EntireSnapshot(EntireSnapshot other)
        {
            if (other == null)
            {
                throw new ArgumentNullException();
            }

            this.FilePaths     = new List <string>(other.FilePaths);
            this.FileSnapshots = new Dictionary <string, FileSnapshot>(other.FileSnapshots);
        }
        /// <summary>
        /// Calculates the snapshot at the given event.
        /// </summary>
        /// <param name="anEvent">The event.</param>
        /// <returns>
        /// The entire snapshot
        /// </returns>
        public EntireSnapshot CalculateSnapshotAtEvent(Event anEvent)
        {
            // Check the cache first.
            if (this.cache.ContainsKey(anEvent))
            {
                return(this.cache[anEvent]);
            }

            Event          lastEvent         = null;
            EntireSnapshot lastKnownSnapshot = null;

            var priorEvents = this.cache.Keys.Where(x => x.ID < anEvent.ID);

            if (priorEvents.Count() > 0)
            {
                lastEvent         = priorEvents.Aggregate((x, y) => x.ID > y.ID ? x : y);
                lastKnownSnapshot = this.cache[lastEvent];
            }

            return(this.CalculateSnapshotAtEvent(lastEvent, lastKnownSnapshot, anEvent));
        }
        /// <summary>
        /// Processes the file open command.
        /// </summary>
        /// <param name="foc">The file open command.</param>
        /// <param name="files">The files.</param>
        /// <param name="lastDocChanges">The last document changes.</param>
        /// <param name="result">The result.</param>
        /// <returns>The new current file path.</returns>
        private static string ProcessFileOpenCommand(
            FileOpenCommand foc,
            Dictionary <string, StringBuilder> files,
            Dictionary <string, DocumentChange> lastDocChanges,
            EntireSnapshot result)
        {
            string currentFile = foc.FilePath;

            if (!result.FilePaths.Contains(currentFile))
            {
                result.FilePaths.Insert(0, currentFile);
                lastDocChanges.Add(currentFile, null);

                if (foc.Snapshot == null)
                {
                    files.Add(currentFile, null);
                }
                else
                {
                    files.Add(currentFile, new StringBuilder(foc.Snapshot));
                }
            }
            else
            {
                // Bring the current file to the front
                result.FilePaths.Remove(currentFile);
                result.FilePaths.Insert(0, currentFile);

                // If this command has a new snapshot, replace it.
                if (foc.Snapshot != null)
                {
                    files[currentFile] = new StringBuilder(foc.Snapshot);
                }
            }

            return(currentFile);
        }
        /// <summary>
        /// Calculates the snapshot at the given event.
        /// </summary>
        /// <param name="lastEvent">The last event associated with the last known snapshot.</param>
        /// <param name="lastKnownSnapshot">The last known snapshot.</param>
        /// <param name="anEvent">The event.</param>
        /// <returns>
        /// The entire snapshot
        /// </returns>
        public EntireSnapshot CalculateSnapshotAtEvent(
            Event lastEvent,
            EntireSnapshot lastKnownSnapshot,
            Event anEvent)
        {
            if (!this.LogProvider.LoggedEvents.Contains(anEvent) ||
                (lastEvent != null && !this.LogProvider.LoggedEvents.Contains(lastEvent)))
            {
                throw new ArgumentException(
                          "The passed event is not originated from the " +
                          "LogProvider of this snapshot calculator");
            }

            if ((lastEvent != null && lastKnownSnapshot == null) ||
                (lastEvent == null && lastKnownSnapshot != null))
            {
                throw new ArgumentException(
                          "lastEvent and lastKnownSnapshot must be either both null or both non-null.");
            }

            EntireSnapshot result = lastKnownSnapshot != null
                ? new EntireSnapshot(lastKnownSnapshot)
                : new EntireSnapshot();

            var docChanges = this.LogProvider.LoggedEvents;

            if (lastEvent != null)
            {
                docChanges = docChanges.SkipUntil(x => x == lastEvent);
            }

            docChanges = docChanges
                         .TakeUntil(x => x == anEvent)
                         .Where(x => this.IsValidFileOpenCommand(x) || x is DocumentChange);

            string currentFile = result.CurrentFile;

            var lastDocChanges = new Dictionary <string, DocumentChange>();
            Dictionary <string, StringBuilder> files = new Dictionary <string, StringBuilder>();

            foreach (var fileSnapshot in result.FileSnapshots.Values)
            {
                lastDocChanges.Add(fileSnapshot.FilePath, fileSnapshot.LastChange);
                files.Add(
                    fileSnapshot.FilePath,
                    fileSnapshot.Content != null ? new StringBuilder(fileSnapshot.Content) : null);
            }

            // calculation loop.
            foreach (Event docChange in docChanges)
            {
                currentFile = this.ProcessDocumentChange(
                    result, currentFile, lastDocChanges, files, docChange);
            }

            // set the result
            foreach (string filePath in result.FilePaths)
            {
                FileSnapshot fileSnapshot = new FileSnapshot();
                fileSnapshot.FilePath   = filePath;
                fileSnapshot.Content    = files[filePath] != null ? files[filePath].ToString() : null;
                fileSnapshot.LastChange = lastDocChanges[filePath];

                result.FileSnapshots[filePath] = fileSnapshot;
            }

            // Add the current result to the cache.
            this.cache[anEvent] = result;

            return(result);
        }