public static void Main(string[] args) { PrintVersionInfo(typeof(Program).GetTypeInfo().Assembly); CommandLine commandLine = CommandLine.Parse(args); if (commandLine.DesignTime) { throw new NotSupportedException("DesignTime mode is not supported yet."); } string assemblyPath = commandLine.AssemblyFile; Assembly testAssembly = AssemblyHelper.LoadTestAssemblyOrDependency(assemblyPath); Assembly mspecAssembly = AssemblyHelper.LoadTestAssemblyOrDependency( Path.Combine(Path.GetDirectoryName(assemblyPath), "Machine.Specifications.dll") ); PrintVersionInfo(mspecAssembly); ConsoleOutputRunListener runListener = new ConsoleOutputRunListener(); ISpecificationRunListener allListeneres = new AggregateRunListener(new ISpecificationRunListener[] { runListener, new AssemblyLocationAwareRunListener(new[] { testAssembly }) }); var testController = new TestController(mspecAssembly, allListeneres); if (commandLine.List) { Console.WriteLine(testController.DiscoverTestsRaw(testAssembly)); } else { var runBuilder = new RunBuilder(testController); var runManager = new RunManager(testController, runBuilder); var assembliesToRun = new[] { testAssembly }; runManager.Run(commandLine, assembliesToRun); if (runListener.FailureOccurred) { Environment.Exit(-1); } } }
void AppendCaptures(ICancellable cnc, GroupInfo groupInfo, Paragraph para, int leftWidthForMatch, string text, IMatch match, IGroup group, StyleInfo highlightStyle, RunBuilder runBuilder, RunBuilder siblingRunBuilder) { int capture_number = -1; foreach (ICapture capture in group.Captures) { if (cnc.IsCancellationRequested) { break; } ++capture_number; var span = new Span( ); string capture_name_text = $" ◦ Cᴀᴘᴛᴜʀᴇ {capture_number}"; int left_width_for_capture = leftWidthForMatch - Math.Max(0, Math.Max(match.TextIndex - group.TextIndex, match.TextIndex - capture.TextIndex)); var start_run = new Run(capture_name_text.PadRight(left_width_for_capture, ' '), span.ContentEnd); start_run.Style(GroupNameStyleInfo); Inline value_inline; Inline inline; if (capture.Length == 0) { value_inline = new Run("(empty)", span.ContentEnd); value_inline.Style(MatchNormalStyleInfo, LocationStyleInfo); } else { string left = Utilities.SubstringFromTo(text, Math.Min(match.TextIndex, group.TextIndex), capture.TextIndex); string middle = capture.Value; string right = Utilities.SubstringFromTo(text, capture.TextIndex + capture.TextLength, Math.Max(match.TextIndex + match.TextLength, group.TextIndex + group.TextLength)); inline = siblingRunBuilder.Build(left, span.ContentEnd); inline.Style(GroupSiblingValueStyleInfo); value_inline = runBuilder.Build(middle, span.ContentEnd); value_inline.Style(GroupValueStyleInfo, highlightStyle); inline = siblingRunBuilder.Build(right, span.ContentEnd); inline.Style(GroupSiblingValueStyleInfo); } inline = new Run($"\x200E ({capture.Index}, {capture.Length})", span.ContentEnd); inline.Style(MatchNormalStyleInfo, LocationStyleInfo); para.Inlines.Add(span); _ = new LineBreak(span.ElementEnd); // (after span) var capture_info = new CaptureInfo { Parent = groupInfo, CaptureSegment = new Segment(capture.TextIndex, capture.TextLength), Span = span, ValueInline = value_inline }; span.Tag = capture_info; groupInfo.CaptureInfos.Add(capture_info); } }
void ShowMatchesThreadProc(ICancellable cnc) { lock ( MatchInfos ) { MatchInfos.Clear( ); ExternalUnderliningLoop.SendWaitAndExecute( ); } string text; RegexMatches matches; bool show_captures; bool show_succeeded_groups_only; bool show_first_only; lock (this) { text = LastText; matches = LastMatches; show_captures = LastShowCaptures; show_succeeded_groups_only = LastShowSucceededGroupsOnly; show_first_only = LastShowFirstOnly; } if (matches.Count == 0) { Dispatcher.BeginInvoke(new Action(() => { CancelInfo( ); ShowOne(rtbNoMatches); })); return; } ChangeEventHelper.Invoke(CancellationToken.None, () => { pbProgress.Maximum = matches.Count; pbProgress.Value = 0; if (secMatches.Blocks.Count > matches.Count) { // remove unneeded paragraphs var r = new TextRange(secMatches.Blocks.ElementAt(matches.Count).ElementStart, secMatches.ContentEnd); r.Text = ""; } CancelInfo( ); ShowOne(rtbMatches); }); if (cnc.IsCancellationRequested) { return; } int show_pb_time = unchecked (Environment.TickCount + 333); // (ignore overflow) Paragraph previous_para = null; int match_number = -1; bool document_has_changed = false; int left_width = EvaluateLeftWidth(matches, show_succeeded_groups_only); foreach (IMatch match in matches.Matches) { Debug.Assert(match.Success); ++match_number; if (cnc.IsCancellationRequested) { break; } var ordered_groups = match.Groups .Skip(1) // skip match .Where(g => g.Success || !show_succeeded_groups_only) //OrderBy( g => g.Success ? g.Index : match.Index ) .ToList( ); if (cnc.IsCancellationRequested) { break; } int min_index = ordered_groups.Select(g => g.Success ? g.TextIndex : match.TextIndex).Concat(new[] { match.TextIndex }).Min( ); if (show_captures) { min_index = ordered_groups.SelectMany(g => g.Captures).Select(c => c.TextIndex).Concat(new[] { min_index }).Min( ); } if (cnc.IsCancellationRequested) { break; } int left_width_for_match = left_width + (match.TextIndex - min_index); Paragraph para = null; Run run = null; MatchInfo match_info = null; RunBuilder match_run_builder = new RunBuilder(MatchValueSpecialStyleInfo); var highlight_style = HighlightStyleInfos[match_number % HighlightStyleInfos.Length]; var highlight_light_style = HighlightLightStyleInfos[match_number % HighlightStyleInfos.Length]; // show match string match_name_text = show_first_only ? "Fɪʀꜱᴛ Mᴀᴛᴄʜ" : $"Mᴀᴛᴄʜ {match_number + 1}"; ChangeEventHelper.Invoke(CancellationToken.None, () => { pbProgress.Value = match_number; if (Environment.TickCount >= show_pb_time) { pbProgress.Visibility = Visibility.Visible; } var span = new Span( ); para = new Paragraph(span); var start_run = new Run(match_name_text.PadRight(left_width_for_match, ' '), span.ContentEnd); start_run.Style(MatchNormalStyleInfo); Inline value_inline; if (match.Length == 0) { value_inline = new Run("(empty)", span.ContentEnd); // value_inline.Style(MatchNormalStyleInfo, LocationStyleInfo); } else { value_inline = match_run_builder.Build(match.Value, span.ContentEnd); value_inline.Style(MatchValueStyleInfo, highlight_style); } run = new Run($"\x200E ({match.Index}, {match.Length})", span.ContentEnd); run.Style(MatchNormalStyleInfo, LocationStyleInfo); _ = new LineBreak(span.ElementEnd); // (after span) match_info = new MatchInfo { MatchSegment = new Segment(match.TextIndex, match.TextLength), Span = span, ValueInline = value_inline, }; span.Tag = match_info; lock ( MatchInfos ) { MatchInfos.Add(match_info); //...ExternalUnderliningEvents.SendRestart( ); } // captures for match //if( showCaptures) AppendCaptures( ct, para, LEFT_WIDTH, match, match ); }); if (cnc.IsCancellationRequested) { break; } // show groups RunBuilder sibling_run_builder = new RunBuilder(null); foreach (var group in ordered_groups) { if (cnc.IsCancellationRequested) { break; } string group_name_text = $" • Gʀᴏᴜᴘ ‹{group.Name}›"; int left_width_for_group = left_width_for_match - Math.Max(0, match.TextIndex - (group.Success ? group.TextIndex : match.TextIndex)); ChangeEventHelper.Invoke(CancellationToken.None, () => { var span = new Span( ); var start_run = new Run(group_name_text.PadRight(left_width_for_group, ' '), span.ContentEnd); start_run.Style(GroupNameStyleInfo); // (NOTE. Overlaps are possible in this example: (?=(..)) Inline value_inline; Inline inl; if (!group.Success) { value_inline = new Run("(fail)", span.ContentEnd); value_inline.Style(GroupFailedStyleInfo); } else if (group.Length == 0) { value_inline = new Run("(empty)", span.ContentEnd); value_inline.Style(LocationStyleInfo); } else { string left = Utilities.SubstringFromTo(text, match.TextIndex, group.TextIndex); string middle = group.Value; string right = Utilities.SubstringFromTo(text, group.TextIndex + group.TextLength, Math.Max(match.TextIndex + match.TextLength, group.TextIndex + group.TextLength)); inl = sibling_run_builder.Build(left, span.ContentEnd); inl.Style(GroupSiblingValueStyleInfo); value_inline = match_run_builder.Build(middle, span.ContentEnd); value_inline.Style(GroupValueStyleInfo, highlight_light_style); inl = sibling_run_builder.Build(right, span.ContentEnd); inl.Style(GroupSiblingValueStyleInfo); } if (cnc.IsCancellationRequested) { return; } run = new Run($"\x200E ({group.Index}, {group.Length})", span.ContentEnd); run.Style(MatchNormalStyleInfo, LocationStyleInfo); para.Inlines.Add(span); _ = new LineBreak(span.ElementEnd); // (after span) var group_info = new GroupInfo { Parent = match_info, IsSuccess = group.Success, GroupSegment = new Segment(group.TextIndex, group.TextLength), Span = span, ValueInline = value_inline, }; span.Tag = group_info; match_info.GroupInfos.Add(group_info); // captures for group if (show_captures) { AppendCaptures(cnc, group_info, para, left_width_for_match, text, match, group, highlight_light_style, match_run_builder, sibling_run_builder); } }); } if (cnc.IsCancellationRequested) { break; } ChangeEventHelper.Invoke(CancellationToken.None, () => { if (previous_para == null) { var first_block = secMatches.Blocks.FirstBlock; if (first_block == null) { secMatches.Blocks.Add(para); } else { secMatches.Blocks.InsertBefore(first_block, para); secMatches.Blocks.Remove(first_block); } } else { if (!previous_para.ContentStart.IsInSameDocument(rtbMatches.Document.ContentStart)) { document_has_changed = true; } else { var next = previous_para.NextBlock; if (next != null) { secMatches.Blocks.Remove(next); } secMatches.Blocks.InsertAfter(previous_para, para); } } }); if (document_has_changed) { break; } previous_para = para; } if (document_has_changed) { return; } if (cnc.IsCancellationRequested) { return; } ChangeEventHelper.Invoke(CancellationToken.None, () => { pbProgress.Visibility = Visibility.Hidden; }); ExternalUnderliningLoop.SendWaitAndExecute( ); }