Exemple #1
0
 private void CallReceiveMissingCopies(NotificationType notificationType, object parameters)
 {
     try
     {
         OnDidReceiveMissingCopies((MissingCopiesParams)parameters);
     }
     catch (Exception e)
     {
         RemoteConsole.Error(String.Format("Error while handling notification {0} : {1}", notificationType.Method, e.Message));
     }
 }
        public override void OnDidChangeTextDocument(DidChangeTextDocumentParams parameters)
        {
            var fileCompiler = GetFileCompilerFromStringUri(parameters.uri, false); //Text Change do not have to trigger node phase, it's only a another event that will do it

            if (fileCompiler == null)
            {
                return;
            }

            Uri objUri = new Uri(parameters.uri);

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

            TextChangedEvent textChangedEvent = new TextChangedEvent();
            foreach (var contentChange in parameters.contentChanges)
            {
                // Split the text updated into distinct lines
                List <string> lineUpdates = null;
                bool          replacementTextStartsWithNewLine = false;

                if (!string.IsNullOrEmpty(contentChange.text))
                {
                    replacementTextStartsWithNewLine = contentChange.text[0] == '\r' ||
                                                       contentChange.text[0] == '\n';
                    //Allow to know if a new line was added
                    //Split on \r \n to know the number of lines added
                    lineUpdates = contentChange.text.Replace("\r", "").Split('\n').ToList();
                    if (string.IsNullOrEmpty(lineUpdates.FirstOrDefault()) && replacementTextStartsWithNewLine)
                    {
                        lineUpdates.RemoveAt(0);
                    }
                }

                // Document cleared
                if (contentChange.range == null)
                {
                    //JCM: I have noticed that if the entire text has changed, is better to reload the entire file
                    //To avoid crashes.
                    try
                    {
                        typeCobolWorkspace.OpenSourceFile(objUri, contentChange.text, this.Workspace.LsrTestOptions);
                        return;
                    }
                    catch (Exception e)
                    {
                        //Don't rethow an exception on save.
                        RemoteConsole.Error(string.Format("Error while handling notification {0} : {1}",
                                                          "textDocument/didChange", e.Message));
                        return;
                    }
                }
                // Document updated
                else
                {
                    // Get original lines text before change
                    string originalFirstLineText =
                        fileCompiler.CompilationResultsForProgram.CobolTextLines[contentChange.range.start.line]
                        .Text;
                    string originalLastLineText = originalFirstLineText;


                    // Check if the first line was inserted
                    int firstLineIndex = contentChange.range.start.line;
                    int firstLineChar  = contentChange.range.start.character;
                    if (replacementTextStartsWithNewLine &&
                        !(contentChange.range.start.character < originalLastLineText.Length))
                    {
                        firstLineIndex++;
                        firstLineChar = 0;
                    }
                    else if (replacementTextStartsWithNewLine)
                    //Detected that the add line appeared inside an existing line
                    {
                        lineUpdates.Add(lineUpdates.First());
                        //Add the default 7 spaces + add lineUpdates in order to update the current line and add the new one.
                    }

                    // Check if the last line was deleted
                    int lastLineIndex = contentChange.range.end.line;
                    if (contentChange.range.end.line > contentChange.range.start.line &&
                        contentChange.range.end.character == 0)
                    {
                        //Allows to detect if the next line was suppressed
                    }
                    if (contentChange.text?.Length == 0)
                    {
                        lineUpdates = new List <string>();
                    }

                    if (lastLineIndex > firstLineIndex)
                    {
                        originalLastLineText =
                            fileCompiler.CompilationResultsForProgram.CobolTextLines[
                                Math.Min(lastLineIndex,
                                         fileCompiler.CompilationResultsForProgram.CobolTextLines.Count - 1)].Text;
                    }

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

                    // Text not modified at the end of the last replaced line
                    string endOfLastLine = null;
                    if (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);
                        //Mark the index line to be removed. The index will remains the same for each line delete, because text change are apply one after another
                    }

                    // Insert the updated lines
                    if (!(startOfFirstLine == null && lineUpdates == null && endOfLastLine == null))
                    {
                        int lineUpdatesCount = (lineUpdates != null && lineUpdates.Count > 0)
                            ? lineUpdates.Count
                            : 1;
                        for (int i = 0; i < lineUpdatesCount; i++)
                        {
                            string newLine = (lineUpdates != null && lineUpdates.Count > 0)
                                ? lineUpdates[i]
                                : string.Empty;
                            if (i == 0)
                            {
                                newLine = startOfFirstLine + newLine;
                            }
                            if (i == lineUpdatesCount - 1)
                            {
                                newLine = newLine + endOfLastLine;
                            }
                            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(objUri, textChangedEvent);

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