private void ApplyDescriptor(string text, int indexOfTextArgInSourceCode, SyntaxHighlightDescriptor descriptor, HighlightJobCollection jobs) { if (descriptor.Pattern == null) { var job = new HighlightJob(descriptor.ColorKey, indexOfTextArgInSourceCode, text.Length); jobs.TryInsert(job); return; } var matches = descriptor.Pattern.Matches(text); if (matches.Count == 0) { return; } foreach (Match match in matches) { CancellationToken?.ThrowIfCancellationRequested(); var job = new HighlightJob(descriptor.ColorKey, indexOfTextArgInSourceCode + match.Index, match.Length); var insertionPoint = jobs.GetInsertionPoint(job); var processChildDescriptors = (insertionPoint >= 0) && (descriptor.CapturedGroups != null); if (processChildDescriptors) { // because regex groups can't overlap, we do not require the added constraint provided by HighlightJobCollection. // A simple List<HighlightJob> is sufficient var childJobs = new List <HighlightJob>(); for (var i = 1; i < match.Groups.Count; ++i) { if (descriptor.CapturedGroups.TryGetValue(i, out var childDescriptors)) { childJobs.AddRange(ApplyDescriptors(match.Groups[i].Value, indexOfTextArgInSourceCode + match.Groups[i].Index, childDescriptors)); } } job.ChildJobs = childJobs; } // A job without a color key leaves its portion of text up for grabs by other jobs. // The portion of its text used by its child jobs (if any) are not available to other jobs if (!string.IsNullOrEmpty(job.ColorKey) && insertionPoint >= 0) { jobs.Insert(insertionPoint, job); } else if (processChildDescriptors) { jobs.AddJobs(job.ChildJobs); } } }
public bool IsAfter(HighlightJob other) { return(other.StartIndex + other.Length <= StartIndex); }
public bool IsBefore(HighlightJob other) { return(StartIndex + Length <= other.StartIndex); }