Example #1
0
 private static TextChangedEvent updateLine(TextChangeType type, int line, string text, TextChangedEvent e = null)
 {
     if (e==null) e = new TextChangedEvent();
     ITextLine snapshot = new TextLineSnapshot(line, text, null);
     e.TextChanges.Add(new TextChange(type, line, snapshot));
     return e;
 }
        public void CheckPerformance()
        {
            // Sample program properties
            string folder = "Compiler" + Path.DirectorySeparatorChar + "Pipeline" + Path.DirectorySeparatorChar + "Samples";
            string textName = "BigBatch";
            DocumentFormat documentFormat = DocumentFormat.RDZReferenceFormat;

            // Create a FileCompiler for this program
            DirectoryInfo localDirectory = new DirectoryInfo(PlatformUtils.GetPathForProjectFile(folder));
            if (!localDirectory.Exists)
            {
                throw new Exception(String.Format("Directory : {0} does not exist", localDirectory.FullName));
            }
            CompilationProject project = new CompilationProject("test",
                localDirectory.FullName, new string[] { "*.cbl", "*.cpy" },
                documentFormat.Encoding, documentFormat.EndOfLineDelimiter, documentFormat.FixedLineLength, documentFormat.ColumnsLayout, new TypeCobolOptions());
            FileCompiler compiler = new FileCompiler(null, textName, project.SourceFileProvider, project, documentFormat.ColumnsLayout, new TypeCobolOptions(), null, false);

            // Execute a first (complete) compilation
            compiler.CompileOnce();

            // Append one line in the middle of the program
            ITextLine newLine = new TextLineSnapshot(9211, "094215D    DISPLAY '-ICLAUA      = ' ICLAUA.                            0000000", null);
            TextChangedEvent textChangedEvent = new TextChangedEvent();
            textChangedEvent.TextChanges.Add(new TextChange(TextChangeType.LineInserted, 9211, newLine));
            compiler.CompilationResultsForProgram.UpdateTextLines(textChangedEvent);

            // Execute a second (incremental) compilation
            compiler.CompileOnce();

            // Display a performance report
            StringBuilder report = new StringBuilder();
            report.AppendLine("Program properties :");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.CobolTextLines.Count + " lines");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.CodeElementsDocumentSnapshot.CodeElements.Count() + " code elements");
            report.AppendLine("First compilation performance");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.PerfStatsForText.FirstCompilationTime + " ms : text update");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.PerfStatsForScanner.FirstCompilationTime + " ms : scanner");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.PerfStatsForPreprocessor.FirstCompilationTime + " ms : preprocessor");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.PerfStatsForCodeElementsParser.FirstCompilationTime + " ms : code elements parser");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.PerfStatsForProgramClassParser.FirstCompilationTime + " ms : program class parser");
            report.AppendLine("Incremental compilation performance");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.PerfStatsForText.LastRefreshTime + " ms : text update");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.PerfStatsForScanner.LastRefreshTime + " ms : scanner");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.PerfStatsForPreprocessor.LastRefreshTime + " ms : preprocessor");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.PerfStatsForCodeElementsParser.LastRefreshTime + " ms : code elements parser");
            report.AppendLine("- " + compiler.CompilationResultsForProgram.PerfStatsForProgramClassParser.LastRefreshTime + " ms : program class parser");

            Console.WriteLine(report.ToString());
        }
        /// <summary>
        /// Send a change notification including all the text lines
        /// </summary>
        private void SendDocumentChangeEvent()
        {
            TextChangedEvent textLoadedEvent = new TextChangedEvent();

            foreach (var line in lines)
            {
                TextChange textChange = new TextChange(TextChangeType.LineInserted, line.LineIndex, line);
                textLoadedEvent.TextChanges.Add(textChange);
            }

            EventHandler <TextChangedEvent> textChangedEvent = TextChanged;

            if (textChangedEvent != null)
            {
                textChangedEvent(this, textLoadedEvent);
            }
        }
        /// <summary>
        /// Reloads the text document with new chars.
        /// The text source must be normalized as a sequence of Unicode chars with \r and/or \n end of line chars.
        /// </summary>
        public void LoadChars(IEnumerable <char> textSource)
        {
            // Reset document contents
            lines.Clear();

            // Build TextLines from chars enumerator
            charsCount = 0;
            int           lineIndex         = 0;
            StringBuilder currentLineText   = new StringBuilder();
            bool          previousCharWasCr = false;

            foreach (char chr in textSource)
            {
                if (chr == '\r')
                {
                    // If an end of line char is encountered, create a new line
                    ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                    lines.Add(line);
                    lineIndex++;
                    charsCount += line.Length + 1; //+1 to add the \r char

                    // Reset StringBuilder contents for next line
                    currentLineText = new StringBuilder();

                    previousCharWasCr = true;
                }
                else if (chr == '\n')
                {
                    if (!previousCharWasCr)
                    {
                        // If an end of line char is encountered, create a new line
                        ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                        lines.Add(line);
                        lineIndex++;
                        charsCount += line.Length + 1; //+1 to add the \n char

                        // Reset StringBuilder contents for next line
                        currentLineText = new StringBuilder();
                    }

                    charsCount++;
                    previousCharWasCr = false;
                }
                else
                {
                    // Append the current char to the text of the current line
                    currentLineText.Append(chr);

                    previousCharWasCr = false;
                }
            }
            // If the last line was not terminated with end of line chars
            if (currentLineText.Length > 0)
            {
                ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                lines.Add(line);
                charsCount += line.Length;
            }

            // Send a notification of the change if enabled
            if (sendNextChangeEvents)
            {
                // Send document cleared event
                TextChangedEvent documentClearedEvent = new TextChangedEvent();
                documentClearedEvent.TextChanges.Add(new TextChange(TextChangeType.DocumentCleared, 0, null));

                EventHandler <TextChangedEvent> textChangedEvent = TextChanged;
                if (textChangedEvent != null)
                {
                    textChangedEvent(this, documentClearedEvent);
                }

                // Send all new text lines
                SendDocumentChangeEvent();
            }
        }
        /// <summary>
        /// Send a change notification including all the text lines
        /// </summary>
        private void SendDocumentChangeEvent()
        {
            TextChangedEvent textLoadedEvent = new TextChangedEvent();
            foreach (var line in lines)
            {
                TextChange textChange = new TextChange(TextChangeType.LineInserted, line.LineIndex, line);
                textLoadedEvent.TextChanges.Add(textChange);
            }

            EventHandler<TextChangedEvent> textChangedEvent = TextChanged;
            if (textChangedEvent != null)
            {
                textChangedEvent(this, textLoadedEvent);
            }
        }
        /// <summary>
        /// Reloads the text document with new chars.
        /// The text source must be normalized as a sequence of Unicode chars with \r and/or \n end of line chars.
        /// </summary>
        public void LoadChars(IEnumerable<char> textSource)
        {
            // Reset document contents
            lines.Clear();

            // Build TextLines from chars enumerator
            charsCount = 0;
            int lineIndex = 0;
            StringBuilder currentLineText = new StringBuilder();
            bool previousCharWasCr = false;
            foreach (char chr in textSource)
            {
                if (chr == '\r')
                {
                    // If an end of line char is encountered, create a new line
                    ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                    lines.Add(line);
                    lineIndex++;
                    charsCount += line.Length;

                    // Reset StringBuilder contents for next line
                    currentLineText = new StringBuilder();

                    previousCharWasCr = true;
                }
                else if (chr == '\n')
                {
                    if (!previousCharWasCr)
                    {
                        // If an end of line char is encountered, create a new line
                        ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                        lines.Add(line);
                        lineIndex++;
                        charsCount += line.Length;

                        // Reset StringBuilder contents for next line
                        currentLineText = new StringBuilder();
                    }

                    previousCharWasCr = false;
                }
                else
                {
                    // Append the current char to the text of the current line
                    currentLineText.Append(chr);

                    previousCharWasCr = false;
                }
            }
            // If the last line was not terminated with end of line chars
            if (currentLineText.Length > 0)
            {
                ReadOnlyTextLine line = new ReadOnlyTextLine(lineIndex, charsCount, currentLineText.ToString(), null);
                lines.Add(line);
                charsCount += line.Length;
            }

            // Send a notification of the change if enabled
            if (sendNextChangeEvents)
            {
                // Send document cleared event
                TextChangedEvent documentClearedEvent = new TextChangedEvent();
                documentClearedEvent.TextChanges.Add(new TextChange(TextChangeType.DocumentCleared, 0, null));

                EventHandler<TextChangedEvent> textChangedEvent = TextChanged;
                if (textChangedEvent != null)
                {
                    textChangedEvent(this, documentClearedEvent);
                }

                // Send all new text lines
                SendDocumentChangeEvent();
            }
        }
        /// <summary>
        /// Update the text lines of the document after a text change event.
        /// NOT thread-safe : this method can only be called from the owner thread.
        /// </summary>
        public void UpdateTextLines(TextChangedEvent textChangedEvent)
        {
            // This method can only be called by the document owner thread
            if (documentOwnerThread == null)
            {
                documentOwnerThread = Thread.CurrentThread;
            }
            else
            {
                VerifyAccess();
            }

            // Make sure we don't update the document while taking a snapshot
            DocumentChangedEvent<ICobolTextLine> documentChangedEvent = null;
            lock (lockObjectForDocumentLines)
            {
                // Start perf measurement
                PerfStatsForText.OnStartRefresh();

                // Apply text changes to the compilation document
                IList<DocumentChange<ICobolTextLine>> documentChanges = new List<DocumentChange<ICobolTextLine>>(textChangedEvent.TextChanges.Count);
                foreach (TextChange textChange in textChangedEvent.TextChanges)
                {
                    DocumentChange<ICobolTextLine> appliedChange = null;
                    CodeElementsLine newLine = null;
                    switch (textChange.Type)
                    {
                        case TextChangeType.DocumentCleared:
                            compilationDocumentLines.Clear();
                            appliedChange = new DocumentChange<ICobolTextLine>(DocumentChangeType.DocumentCleared, 0, null);
                            // Ignore all previous document changes : they are meaningless now that the document was completely cleared
                            documentChanges.Clear();
                            break;
                        case TextChangeType.LineInserted:
                            newLine = CreateNewDocumentLine(textChange.NewLine, TextSourceInfo.ColumnsLayout);
                            compilationDocumentLines.Insert(textChange.LineIndex, newLine);
                            appliedChange = new DocumentChange<ICobolTextLine>(DocumentChangeType.LineInserted, textChange.LineIndex, newLine);
                            // Recompute the line indexes of all the changes prevously applied
                            foreach (DocumentChange<ICobolTextLine> documentChangeToAdjust in documentChanges)
                            {
                                if(documentChangeToAdjust.LineIndex >= textChange.LineIndex)
                                {
                                    documentChangeToAdjust.LineIndex = documentChangeToAdjust.LineIndex + 1;
                                }
                            }
                            break;
                        case TextChangeType.LineUpdated:
                            newLine = CreateNewDocumentLine(textChange.NewLine, TextSourceInfo.ColumnsLayout);
                            compilationDocumentLines[textChange.LineIndex] = newLine;
                            // Check to see if this change can be merged with a previous one
                            bool changeAlreadyApplied = false;
                            foreach (DocumentChange<ICobolTextLine> documentChangeToAdjust in documentChanges)
                            {
                                if (documentChangeToAdjust.LineIndex == textChange.LineIndex)
                                {
                                    changeAlreadyApplied = true;
                                    break;
                                }
                            }
                            if (!changeAlreadyApplied)
                            {
                                appliedChange = new DocumentChange<ICobolTextLine>(DocumentChangeType.LineUpdated, textChange.LineIndex, newLine);
                            }
                            // Line indexes are not impacted
                            break;
                        case TextChangeType.LineRemoved:
                            compilationDocumentLines.RemoveAt(textChange.LineIndex);
                            appliedChange = new DocumentChange<ICobolTextLine>(DocumentChangeType.LineRemoved, textChange.LineIndex, null);
                            // Recompute the line indexes of all the changes prevously applied
                            IList<DocumentChange<ICobolTextLine>> documentChangesToRemove = null;
                            foreach (DocumentChange<ICobolTextLine> documentChangeToAdjust in documentChanges)
                            {
                                if (documentChangeToAdjust.LineIndex > textChange.LineIndex)
                                {
                                    documentChangeToAdjust.LineIndex = documentChangeToAdjust.LineIndex - 1;
                                }
                                else if(documentChangeToAdjust.LineIndex == textChange.LineIndex)
                                {
                                    if(documentChangesToRemove == null)
                                    {
                                        documentChangesToRemove = new List<DocumentChange<ICobolTextLine>>(1);
                                    }
                                    documentChangesToRemove.Add(documentChangeToAdjust);
                                }
                            }
                            // Ignore all previous changes applied to a line now removed
                            if(documentChangesToRemove != null)
                            {
                                foreach (DocumentChange<ICobolTextLine> documentChangeToRemove in documentChangesToRemove)
                                {
                                    documentChanges.Remove(documentChangeToRemove);
                                }
                            }
                            break;
                    }
                    if (appliedChange != null)
                    {
                        documentChanges.Add(appliedChange);
                    }
                }

                // Create a new version of the document to track these changes
                currentTextLinesVersion.changes = documentChanges;
                currentTextLinesVersion.next = new DocumentVersion<ICobolTextLine>(currentTextLinesVersion);

                // Prepare an event to signal document change to all listeners
                documentChangedEvent = new DocumentChangedEvent<ICobolTextLine>(currentTextLinesVersion, currentTextLinesVersion.next);
                currentTextLinesVersion = currentTextLinesVersion.next;

                // Stop perf measurement
                PerfStatsForText.OnStopRefresh();
            }

            // Send events to all listeners
            EventHandler<DocumentChangedEvent<ICobolTextLine>> textLinesChanged = TextLinesChanged; // avoid race condition
            if (textLinesChanged != null)
            {
                textLinesChanged(this, documentChangedEvent);
            }
        }
Example #8
0
 public void OnTextChanged(object sender, TextChangedEvent textChangedEvent)
 {
     LastTextChangedEvent = textChangedEvent;
 }
Example #9
0
 /// <summary>
 /// Update the text contents of the file
 /// </summary>
 public void UpdateSourceFile(string fileName, TextChangedEvent textChangedEvent)
 {
     FileCompiler fileCompilerToUpdate = null;
     if (OpenedFileCompilers.TryGetValue(fileName, out fileCompilerToUpdate))
     {
         fileCompilerToUpdate.CompilationResultsForProgram.UpdateTextLines(textChangedEvent);
         fileCompilerToUpdate.CompilationResultsForProgram.UpdateTokensLines();
     }
 }
 /// <summary>
 /// Send a change notification including all the text lines
 /// </summary>
 private void SendSocumentChangeEvent()
 {
     TextChangedEvent initialEvent = new TextChangedEvent();
     int lineIndex = 0;
     foreach (ITextLine textLine in Lines)
     {
         TextChange lineAdded = new TextChange(TextChangeType.LineInserted, lineIndex, textLine);
         initialEvent.TextChanges.Add(lineAdded);
         lineIndex++;
     }
     RaiseTextChanged(initialEvent);
 }
 private void RaiseTextChanged(TextChangedEvent textEvent)
 {
     EventHandler<TextChangedEvent> textChanged = TextChanged;
     if (textChanged != null)
     {
         textChanged(this, textEvent);
     }
 }
 void ILineTracker.ChangeComplete(DocumentChangeEventArgs e)
 {
     if (sendNextChangeEvents)
     {
         RaiseTextChanged(textChangedEvent);
         textChangedEvent = new TextChangedEvent();
     }
 }
Example #13
0
        public override void OnDidChangeTextDocument(DidChangeTextDocumentParams parameters)
        {
            Uri objUri = new Uri(parameters.uri);
            if (objUri.IsFile)
            {
                string fileName = Path.GetFileName(objUri.LocalPath);
                var fileCompiler = typeCobolWorkspace.OpenedFileCompilers[fileName];

                #region Convert text changes format from multiline range replacement to single line updates

                // THIS CONVERSION STILL NEEDS MORE WORK : much more complicated than you would think

                TextChangedEvent textChangedEvent = new TextChangedEvent();
                foreach (var contentChange in parameters.contentChanges)
                {
                    // Split the text updated into distinct lines
                    string[] lineUpdates = null;
                    bool replacementTextStartsWithNewLine = false;
                    if(contentChange.text != null && contentChange.text.Length > 0)
                    {
                        replacementTextStartsWithNewLine = contentChange.text[0] == '\r' || contentChange.text[0] == '\n';
                        lineUpdates = contentChange.text.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                    }

                    // Document cleared
                    if (contentChange.range == null)
                    {
                        var textChange = new TextChange(TextChangeType.DocumentCleared, 0, null);
                        textChangedEvent.TextChanges.Add(textChange);
                        if (lineUpdates != null)
                        {
                            for (int i = 0; i < lineUpdates.Length; i++)
                            {
                                textChange = new TextChange(TextChangeType.LineInserted, i, new TextLineSnapshot(i, lineUpdates[i], null));
                                textChangedEvent.TextChanges.Add(textChange);
                            }
                        }
                    }
                    // Document updated
                    else
                    {
                        // Check if the first line was inserted
                        int firstLineIndex = contentChange.range.start.line;
                        int firstLineChar = contentChange.range.start.character;
                        if (replacementTextStartsWithNewLine)
                        {
                            firstLineIndex++;
                            firstLineChar = 0;
                        }

                        // Check if the last line was deleted
                        int lastLineIndex = contentChange.range.end.line;
                        bool lastLineDeleted = false;
                        if (contentChange.range.end.line > contentChange.range.start.line && contentChange.range.end.character == 0)
                        {
                            lastLineIndex--;
                            lastLineDeleted = true;
                        }
                        if(!lastLineDeleted && contentChange.text.Length == 0)
                        {
                            lineUpdates = new string[0];
                        }

                        // Get original lines text before change
                        string originalFirstLineText = fileCompiler.CompilationResultsForProgram.CobolTextLines[contentChange.range.start.line].Text;
                        string originalLastLineText = originalFirstLineText;
                        if(lastLineIndex > firstLineIndex)
                        {
                            originalLastLineText = fileCompiler.CompilationResultsForProgram.CobolTextLines[lastLineIndex].Text;
                        }

                        // Text not modified at the beginning of the first replaced line
                        string startOfFirstLine = null;
                        if (firstLineChar > 0)
                        {
                            startOfFirstLine = originalFirstLineText.Substring(0, contentChange.range.start.character);
                        }

                        // Text not modified at the end of the last replaced line
                        string endOfLastLine = null;
                        if (!lastLineDeleted && contentChange.range.end.character < originalLastLineText.Length)
                        {
                            endOfLastLine = originalLastLineText.Substring(contentChange.range.end.character);
                        }

                        // Remove all the old lines
                        for (int i = firstLineIndex; i <= lastLineIndex; i++)
                        {
                            var textChange = new TextChange(TextChangeType.LineRemoved, firstLineIndex, null);
                            textChangedEvent.TextChanges.Add(textChange);
                        }

                        // Insert the updated lines
                        if (!(startOfFirstLine == null && lineUpdates == null && endOfLastLine == null))
                        {
                            int lineUpdatesCount = (lineUpdates != null && lineUpdates.Length > 0) ? lineUpdates.Length : 1;
                            for (int i = 0; i < lineUpdatesCount; i++)
                            {
                                string newLine = (lineUpdates != null && lineUpdates.Length > 0) ? lineUpdates[i] : String.Empty;
                                if (i == 0)
                                {
                                    newLine = startOfFirstLine + newLine;
                                }
                                if(i == lineUpdatesCount - 1)
                                {
                                    newLine = newLine + endOfLastLine;
                                    if (lastLineDeleted) break;
                                }
                                var textChange = new TextChange(TextChangeType.LineInserted, firstLineIndex + i, new TextLineSnapshot(firstLineIndex + i, newLine, null));
                                textChangedEvent.TextChanges.Add(textChange);
                            }
                        }
                    }
                }
                #endregion

                // Update the source file with the computed text changes
                typeCobolWorkspace.UpdateSourceFile(fileName, textChangedEvent);

                // DEBUG information
                RemoteConsole.Log("Udpated source file : " + fileName);
                foreach(var textChange in textChangedEvent.TextChanges)
                {
                    RemoteConsole.Log(" - " + textChange.ToString());
                }
            }
        }