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); } }
public void OnTextChanged(object sender, TextChangedEvent textChangedEvent) { LastTextChangedEvent = textChangedEvent; }
/// <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(); } }
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()); } } }