// Demo fixture for the extract-method micro-tool (tools/ExtractMethod). // // This file is DATA, not project source: the test project excludes it from // compilation (see BeforeAfter.Tests.csproj) and runs Roslyn over its raw // text, so the tool sees exactly what is checked in here. It uses explicit // usings because the scratch compilation has no implicit usings. // // Bucket map (the classification yak 02 works from): // bucket where example // local, read-only (param) ScoreReads seed, score // written + read-later (return) Summarize, Heaviest total, message, best // scratch local (local) Summarize for-loop i // enclosing-method param (param) ScoreReads, Summarize bonus, limit // field access (extract-first) ScoreReads _seed (optional) // property access (extract-first) Summarize Scale (optional) // indexer access (extract-first) Heaviest widgets[i] // method invocation (extract-first, flagged) Heaviest best.Bigger(...) // multi-statement range incl. for Summarize total + for-loop // // Tests pin EXACT line numbers of the statements they select. Keep the // formatting stable; when a line must change, update DemoFixtureTests too. using System.Collections.Generic; namespace BeforeAfter.Tests.ExtractMethod.Fixtures; /// /// Small first-class citizen of the extract-method tool: every method below /// shows one or more of the classification "buckets" the tool must report. /// public class Demo { // Own-class state: reading it from a selection is "extract-first optional" // (a same-class extracted method can still see these fields). Initialized // here so the fixture compiles with zero diagnostics (CS0649 otherwise). private int _seed = 5; // Own-class property: like a field, accessible from a same-class method, // so hoisting it is optional in the report. public int Scale { get; set; } = 1; /// Small local type so the scratch compilation binds. public sealed record Widget(int Weight, int Count, string Label) { /// Instance method used to exercise the invocation bucket. public Widget Bigger(Widget other) => Weight >= other.Weight ? this : other; } /// /// Bucket: enclosing-method parameter read (bonus => param), local /// read-only (seed, score => param), own-class field access /// (_seed => extract-first, optional). Ends with a return expression. /// public int ScoreReads(int bonus) { int seed = _seed; int score = seed * 2; return score + bonus; } /// /// Bucket: written + read-later locals (total, message => return), /// scratch local (i => local), own-class property access (Scale => /// extract-first optional), multi-statement range incl. a for-loop. /// public string Summarize(int limit) { int total = 0; for (int i = 0; i < limit; i++) { total += i; } int scaled = total * Scale; string message = "sum=" + scaled; return message; } /// /// Bucket: indexer access (widgets[i] on List<T> => extract-first), /// method invocation (Bigger => extract-first, flagged because hoisting /// changes how often it is evaluated), local written + read-later /// (best => return). /// public Widget Heaviest(List widgets, int count) { Widget best = widgets[0]; for (int i = 1; i < count; i++) { best = best.Bigger(widgets[i]); } return best; } }