void Editor_EndAtomicUndoOperation(object sender, EventArgs e) { if (beginVersion.CompareAge(Editor.Version) != 0) { RemoveWidget(); } }
public HighlightedLine HighlightLine(int lineNumber) { IDocumentLine documentLine = document.GetLineByNumber(lineNumber); if (hasCrashed) { // don't highlight anymore after we've crashed return(new HighlightedLine(document, documentLine)); } ITextSourceVersion newVersion = document.Version; CachedLine cachedLine = null; if (cachedLines != null) { for (int i = 0; i < cachedLines.Count; i++) { if (cachedLines[i].DocumentLine == documentLine) { if (newVersion == null || !newVersion.BelongsToSameDocumentAs(cachedLines[i].OldVersion)) { // cannot list changes from old to new: we can't update the cache, so we'll remove it cachedLines.RemoveAt(i); } else { cachedLine = cachedLines[i]; } break; } } if (cachedLine != null && cachedLine.IsValid && newVersion.CompareAge(cachedLine.OldVersion) == 0) { // the file hasn't changed since the cache was created, so just reuse the old highlighted line #if DEBUG cachedLine.HighlightedLine.ValidateInvariants(); #endif return(cachedLine.HighlightedLine); } } bool wasInHighlightingGroup = inHighlightingGroup; if (!inHighlightingGroup) { BeginHighlighting(); } try { return(DoHighlightLine(lineNumber, documentLine, cachedLine, newVersion)); } finally { line = null; if (!wasInHighlightingGroup) { EndHighlighting(); } } }
/// <summary> /// Compares currentVersion with version. /// -1 = currentVersion is older; 0 = same version; 1 = newVersion is older /// </summary> int CompareVersions(ITextSourceVersion newVersion) { if (currentVersion != null && newVersion != null && currentVersion.BelongsToSameDocumentAs(newVersion)) { return(currentVersion.CompareAge(newVersion)); } else { return(-1); } }
/// <summary> /// Compares currentVersion with version. /// -1 = currentVersion is older; 0 = same version; 1 = newVersion is older /// </summary> int CompareVersions(ITextSourceVersion newVersion) { Debug.Assert(rwLock.IsReadLockHeld || rwLock.IsUpgradeableReadLockHeld || rwLock.IsWriteLockHeld); if (currentVersion != null && newVersion != null && currentVersion.BelongsToSameDocumentAs(newVersion)) { return(currentVersion.CompareAge(newVersion)); } else { return(-1); } }
Task <ProjectEntry> DoParseAsync(ITextSource fileContent, IProject parentProject, bool requestFullParseInformation, CancellationToken cancellationToken) { // Create snapshot of file content, if required bool lookupOpenFileOnTargetThread; if (fileContent != null) { lookupOpenFileOnTargetThread = false; // File content was explicitly specified: // Let's make a snapshot in case the text source is mutable. fileContent = fileContent.CreateSnapshot(); } else if (SD.MainThread.InvokeRequired) { // fileContent == null && not on the main thread: // Don't fetch the file content right now; if we need to SafeThreadCall() anyways, // it's better to do so from the background task. lookupOpenFileOnTargetThread = true; } else { // fileContent == null && we are on the main thread: // Let's look up the file in the list of open files right now // so that we don't need to SafeThreadCall() later on. lookupOpenFileOnTargetThread = false; if (parser != null) { fileContent = parser.GetFileContent(fileName); } } Task <ProjectEntry> task; lock (runningAsyncParseLock) { if (fileContent != null) { // Optimization: // don't start a background task if fileContent was specified and up-to-date parse info is available rwLock.EnterReadLock(); try { int index = FindIndexForProject(parentProject); int versionComparison = CompareVersions(fileContent.Version); if (versionComparison == 0 && index >= 0) { // Ensure we have parse info for the specified project (entry.UnresolvedFile is null for newly registered projects) // If full parse info is requested, ensure we have full parse info. if (entries[index].UnresolvedFile != null && !(requestFullParseInformation && entries[index].CachedParseInformation == null)) { // We already have the requested version parsed, just return it: return(Task.FromResult(entries[index])); } } } finally { rwLock.ExitReadLock(); } // Optimization: // if an equivalent task is already running, return that one instead if (runningAsyncParseTask != null && (!requestFullParseInformation || runningAsyncParseFullInfoRequested) && runningAsyncParseProject == parentProject && runningAsyncParseFileContentVersion.BelongsToSameDocumentAs(fileContent.Version) && runningAsyncParseFileContentVersion.CompareAge(fileContent.Version) == 0) { return(runningAsyncParseTask); } } task = new Task <ProjectEntry>( delegate { try { if (lookupOpenFileOnTargetThread) { fileContent = SD.FileService.GetFileContentForOpenFile(fileName); } return(DoParse(fileContent, parentProject, requestFullParseInformation, cancellationToken)); } finally { lock (runningAsyncParseLock) { runningAsyncParseTask = null; runningAsyncParseFileContentVersion = null; runningAsyncParseProject = null; } } }, cancellationToken); if (fileContent != null && fileContent.Version != null && !cancellationToken.CanBeCanceled) { runningAsyncParseTask = task; runningAsyncParseFileContentVersion = fileContent.Version; runningAsyncParseProject = parentProject; runningAsyncParseFullInfoRequested = requestFullParseInformation; } } task.Start(); return(task); }
Task RunUpdateTask(ITextSource input, IDocumentLine startLine, int endOffset, ITextSourceVersion textSourceVersion, CancellationToken token) { return(Task.Run(delegate { var matches = new List <(UrlType, Match, IDocumentLine)> (); var line = startLine; int o = 0; while (line != null && line.Offset <= endOffset) { if (token.IsCancellationRequested) { return; } string lineText = input.GetTextAt(line.Offset, line.Length); var match = UrlRegex.Match(lineText); while (match.Success) { if (token.IsCancellationRequested) { return; } matches.Add((UrlType.Url, match, line)); o = match.Index + match.Length; var len = line.Length - o; if (len <= 0) { break; } match = UrlRegex.Match(lineText, o, len); } o = 0; match = MailRegex.Match(lineText); while (match.Success) { if (token.IsCancellationRequested) { return; } matches.Add((UrlType.Email, match, line)); o = match.Index + match.Length; var len = line.Length - o; if (len <= 0) { break; } match = MailRegex.Match(lineText, o, len); } line = line.NextLine; } Runtime.RunInMainThread(delegate { if (token.IsCancellationRequested || Editor == null) { return; } if (textSourceVersion.CompareAge(Editor.Version) != 0) { return; } line = startLine; while (line != null && line.Offset <= endOffset) { foreach (var u in Editor.GetLineMarkers(line).OfType <IUrlTextLineMarker> ()) { Editor.RemoveMarker(u); markers.Remove(u); } line = line.NextLine; } foreach (var m in matches) { var startCol = m.Item2.Index; var url = m.Item2.Value; var marker = Editor.TextMarkerFactory.CreateUrlTextMarker(Editor, url, m.Item1, "url", startCol, startCol + m.Item2.Length); markers.Add(marker); Editor.AddMarker(m.Item3, marker); } src.Remove(startLine.Offset); }); }));