Beispiel #1
0
        /// <summary>
        /// Document line factory for the compiler processing steps : create new version of a line by copy if necessary before an update
        /// </summary>
        protected object PrepareDocumentLineForUpdate(int index, object previousLineVersion, CompilationStep compilationStep)
        {
            CodeElementsLine originalLine = (CodeElementsLine)previousLineVersion;

            // If the compilation step was not yet applied to this line, we don't need a new version of the line
            if (originalLine.CanStillBeUpdatedBy(compilationStep))
            {
                return(originalLine);
            }
            // If the compilation step was previously applied to this line, we need to create a new version of the line
            else
            {
                CodeElementsLine newLinePreparedForUpdate = new CodeElementsLine(originalLine, compilationStep);
                compilationDocumentLines[index] = newLinePreparedForUpdate;
                return(newLinePreparedForUpdate);
            }
        }
 /// <summary>
 /// Enumerator all Symbol from the CodeElementLines
 /// </summary>
 /// <returns>An Enumerator on Symbols</returns>
 public IEnumerator <TUVienna.CS_CUP.Runtime.Symbol> GetEnumerator()
 {
     if (StartToken >= 0)
     {
         TUVienna.CS_CUP.Runtime.Symbol start_symbol = new TUVienna.CS_CUP.Runtime.Symbol(StartToken, null);
         yield return(start_symbol);
     }
     if (FirstCodeElements != null)
     {
         foreach (CodeElement ce in FirstCodeElements)
         {
             if (ce != null)
             {
                 TUVienna.CS_CUP.Runtime.Symbol symbol = new TUVienna.CS_CUP.Runtime.Symbol(((int)ce.Type) + CS_CUP_START_TOKEN - 1, ce);
                 LastSymbol = symbol;
                 yield return(symbol);
             }
         }
     }
     if (CodeElementsLines != null)
     {
         int celCount = CodeElementsLines.Count;
         for (; m_CodeElementsLineIndex < celCount; m_CodeElementsLineIndex++)
         {
             CodeElementsLine cel = CodeElementsLines[m_CodeElementsLineIndex];
             if (cel.CodeElements != null)
             {
                 int ceCount = cel.CodeElements.Count;
                 for (; m_CodeElementIndex < ceCount; m_CodeElementIndex++)
                 {
                     CodeElement ce = cel.CodeElements[m_CodeElementIndex];
                     TUVienna.CS_CUP.Runtime.Symbol symbol =
                         new TUVienna.CS_CUP.Runtime.Symbol(((int)ce.Type) + CS_CUP_START_TOKEN - 1, ce);
                     LastSymbol = symbol;
                     yield return(symbol);
                 }
                 m_CodeElementIndex = 0;
             }
         }
     }
     m_CodeElementsLineIndex = 0;
     yield return(EOF);
 }
Beispiel #3
0
        /// <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;
                    bool             encounteredCodeElement;
                    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);

                        encounteredCodeElement = false;                                                       //Will allow to update allow line index without erasing all diagnostics after the first encountered line with CodeElements

                        foreach (var lineToUpdate in compilationDocumentLines.Skip(textChange.LineIndex + 1)) //Loop on every line that appears after added line
                        {
                            //Remove generated diagnostics for the line below the inserted line.
                            if (!encounteredCodeElement)
                            {
                                lineToUpdate.ResetDiagnostics();     //Reset diag when on the same zone
                            }
                            lineToUpdate.LineIndex++;
                            lineToUpdate.UpdateDiagnositcsLine();

                            if (lineToUpdate.CodeElements != null)
                            {
                                encounteredCodeElement = true;
                            }
                        }

                        appliedChange = new DocumentChange <ICobolTextLine>(DocumentChangeType.LineInserted, textChange.LineIndex, newLine);
                        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);
                        encounteredCodeElement = false;                                                   //Will allow to update allow line index without erasing all diagnostics after the first encountered line with CodeElements

                        foreach (var lineToUpdate in compilationDocumentLines.Skip(textChange.LineIndex)) //Loop on every line that appears after deleted line
                        {
                            //Remove generated diagnostics for the line below the deleted line.
                            if (!encounteredCodeElement)
                            {
                                lineToUpdate.ResetDiagnostics();
                            }

                            lineToUpdate.LineIndex--;
                            lineToUpdate.UpdateDiagnositcsLine();

                            if (lineToUpdate.CodeElements != null)
                            {
                                encounteredCodeElement = true;
                            }
                        }

                        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);
            }
        }