@@ -301,9 +301,107 @@ var astDumpCases = []struct {
301301 {"sql_func_call" , lang .SQL , "SELECT count(*), upper(name) FROM users;\n " },
302302 {"sql_view" , lang .SQL , "CREATE VIEW active_users AS SELECT * FROM users WHERE active = true;\n " },
303303
304+ // === C# call AST diagnostics ===
305+ {"csharp_member_call" , lang .CSharp , "class A {\n \t void F() {\n \t \t _context.SaveChangesAsync(token);\n \t \t entity.AddDomainEvent(new Event());\n \t \t var x = _identityService.GetUserNameAsync(userId);\n \t }\n }\n " },
306+ {"csharp_static_call" , lang .CSharp , "class A {\n \t void F() {\n \t \t Console.WriteLine(\" hello\" );\n \t \t string.IsNullOrEmpty(s);\n \t }\n }\n " },
307+ {"csharp_simple_call" , lang .CSharp , "class A {\n \t void F() {\n \t \t DoWork();\n \t \t await SaveAsync();\n \t }\n }\n " },
308+ {"csharp_await_call" , lang .CSharp , "class A {\n \t async Task F() {\n \t \t await _context.SaveChangesAsync(token);\n \t \t var result = await next();\n \t }\n }\n " },
309+ {"csharp_new_object" , lang .CSharp , "class A {\n \t void F() {\n \t \t var e = new TodoItem();\n \t \t var list = new List<string>();\n \t }\n }\n " },
310+
311+ // === Ruby call AST diagnostics ===
312+ {"ruby_method_call" , lang .Ruby , "class A\n def f\n name.to_s\n @items.each { |i| puts i }\n response.status = 200\n end\n end\n " },
313+ {"ruby_bare_call" , lang .Ruby , "class A\n def f\n puts 'hello'\n greet('world')\n render json: data\n end\n end\n " },
314+ {"ruby_chain_call" , lang .Ruby , "class A\n def f\n users.where(active: true).order(:name).limit(10)\n end\n end\n " },
315+
304316 // === New languages: Dockerfile ===
305317 {"dockerfile_from" , lang .Dockerfile , "FROM golang:1.22-alpine AS builder\n WORKDIR /app\n COPY . .\n RUN go build -o main .\n " },
306318 {"dockerfile_env" , lang .Dockerfile , "ENV APP_PORT=8080\n ARG VERSION=latest\n EXPOSE 8080\n " },
319+
320+ // =====================================================================
321+ // v0.5 Documentation Cases — Complex patterns for extraction planning
322+ // =====================================================================
323+
324+ // === Framework Patterns: Express/Gin/Chi routes ===
325+ {"js_express_route" , lang .JavaScript , "app.get('/users/:id', async (req, res) => {\n const user = await db.findUser(req.params.id);\n res.json(user);\n });\n " },
326+ {"js_express_middleware" , lang .JavaScript , "app.use('/api', authMiddleware, rateLimit({ max: 100 }));\n " },
327+ {"ts_express_typed_route" , lang .TypeScript , "router.post('/orders', validate(OrderSchema), async (req: Request, res: Response) => {\n const order = await orderService.create(req.body);\n res.status(201).json(order);\n });\n " },
328+ {"go_chi_route" , lang .Go , "package main\n func routes(r chi.Router) {\n \t r.Get(\" /users/{id}\" , getUser)\n \t r.Post(\" /users\" , createUser)\n \t r.Route(\" /admin\" , func(r chi.Router) {\n \t \t r.Use(adminOnly)\n \t \t r.Get(\" /stats\" , getStats)\n \t })\n }\n " },
329+
330+ // === Framework Patterns: Spring/Django/Laravel annotations ===
331+ {"java_spring_controller" , lang .Java , "@RestController\n @RequestMapping(\" /api/users\" )\n class UserController {\n \t @Autowired\n \t private UserService userService;\n \t @GetMapping(\" /{id}\" )\n \t public User getUser(@PathVariable Long id) {\n \t \t return userService.findById(id);\n \t }\n }\n " },
332+ {"java_spring_service" , lang .Java , "@Service\n class UserService {\n \t @Transactional\n \t public User createUser(CreateUserRequest req) {\n \t \t User user = new User(req.getName());\n \t \t return repository.save(user);\n \t }\n }\n " },
333+ {"php_laravel_route" , lang .PHP , "<?php\n Route::middleware('auth')->group(function () {\n \t Route::get('/dashboard', [DashboardController::class, 'index']);\n \t Route::resource('posts', PostController::class);\n });\n " },
334+
335+ // === Framework Patterns: Ruby Sinatra/Rails DSL ===
336+ {"ruby_sinatra_route" , lang .Ruby , "class App < Sinatra::Base\n get '/users/:id' do\n user = User.find(params[:id])\n json user\n end\n \n post '/users' do\n user = User.create(params)\n status 201\n json user\n end\n end\n " },
337+ {"ruby_rails_model" , lang .Ruby , "class User < ApplicationRecord\n has_many :posts, dependent: :destroy\n belongs_to :organization\n validates :email, presence: true, uniqueness: true\n scope :active, -> { where(active: true) }\n end\n " },
338+
339+ // === Framework Patterns: Elixir Phoenix ===
340+ {"elixir_phoenix_router" , lang .Elixir , "defmodule MyAppWeb.Router do\n use MyAppWeb, :router\n pipeline :api do\n plug :accepts, [\" json\" ]\n end\n scope \" /api\" , MyAppWeb do\n pipe_through :api\n resources \" /users\" , UserController\n end\n end\n " },
341+
342+ // === Async Patterns ===
343+ {"ts_async_await" , lang .TypeScript , "async function fetchData(): Promise<User[]> {\n const response = await fetch('/api/users');\n if (!response.ok) throw new Error('Failed');\n return await response.json();\n }\n " },
344+ {"rust_async_await" , lang .Rust , "async fn fetch_user(id: u64) -> Result<User, Error> {\n \t let resp = client.get(format!(\" /users/{}\" , id)).send().await?;\n \t let user: User = resp.json().await?;\n \t Ok(user)\n }\n " },
345+ {"python_async_gather" , lang .Python , "async def fetch_all(ids):\n tasks = [fetch_user(id) for id in ids]\n results = await asyncio.gather(*tasks)\n return results\n " },
346+ {"kotlin_coroutine" , lang .Kotlin , "suspend fun fetchUsers(): List<User> {\n \t return withContext(Dispatchers.IO) {\n \t \t val response = api.getUsers()\n \t \t response.body() ?: emptyList()\n \t }\n }\n " },
347+ {"go_goroutine_channel" , lang .Go , "package main\n func process(ctx context.Context, items []Item) error {\n \t errCh := make(chan error, len(items))\n \t for _, item := range items {\n \t \t go func(it Item) {\n \t \t \t errCh <- handle(ctx, it)\n \t \t }(item)\n \t }\n \t for range items {\n \t \t if err := <-errCh; err != nil {\n \t \t \t return err\n \t \t }\n \t }\n \t return nil\n }\n " },
348+
349+ // === Error Handling Patterns ===
350+ {"ts_try_catch_finally" , lang .TypeScript , "async function safeFetch(url: string): Promise<Data | null> {\n try {\n const res = await fetch(url);\n return await res.json();\n } catch (err) {\n logger.error('fetch failed', { url, err });\n return null;\n } finally {\n metrics.recordFetch(url);\n }\n }\n " },
351+ {"rust_question_mark_chain" , lang .Rust , "fn process(path: &str) -> Result<Config, Error> {\n \t let data = std::fs::read_to_string(path)?;\n \t let config: Config = serde_json::from_str(&data)?;\n \t config.validate()?;\n \t Ok(config)\n }\n " },
352+ {"go_error_wrap" , lang .Go , "package main\n import \" fmt\" \n func loadConfig(path string) (*Config, error) {\n \t data, err := os.ReadFile(path)\n \t if err != nil {\n \t \t return nil, fmt.Errorf(\" read config: %w\" , err)\n \t }\n \t var cfg Config\n \t if err := json.Unmarshal(data, &cfg); err != nil {\n \t \t return nil, fmt.Errorf(\" parse config: %w\" , err)\n \t }\n \t return &cfg, nil\n }\n " },
353+ {"python_exception_chain" , lang .Python , "def process(data):\n try:\n result = validate(data)\n except ValidationError as e:\n raise ProcessingError(f'invalid: {e}') from e\n except TimeoutError:\n raise RetryableError('timeout') from None\n " },
354+ {"java_multi_catch" , lang .Java , "class A {\n \t void process() {\n \t \t try {\n \t \t \t riskyOperation();\n \t \t } catch (IOException | SQLException e) {\n \t \t \t logger.error(\" Operation failed\" , e);\n \t \t \t throw new ServiceException(e);\n \t \t } finally {\n \t \t \t cleanup();\n \t \t }\n \t }\n }\n " },
355+ {"elixir_with_error" , lang .Elixir , "defmodule A do\n def process(params) do\n with {:ok, user} <- find_user(params.id),\n {:ok, order} <- create_order(user, params),\n :ok <- send_notification(user, order) do\n {:ok, order}\n else\n {:error, :not_found} -> {:error, \" user not found\" }\n {:error, reason} -> {:error, reason}\n end\n end\n end\n " },
356+
357+ // === Generic/Template Patterns ===
358+ {"ts_generic_class" , lang .TypeScript , "class Repository<T extends Entity> {\n constructor(private readonly db: Database) {}\n async findById(id: string): Promise<T | null> {\n return this.db.collection<T>().findOne({ id });\n }\n }\n " },
359+ {"java_generic_method" , lang .Java , "class A {\n \t <T extends Comparable<T>> List<T> sort(List<T> items) {\n \t \t return items.stream().sorted().collect(Collectors.toList());\n \t }\n }\n " },
360+ {"rust_generic_impl" , lang .Rust , "impl<T: Clone + Send + 'static> From<Vec<T>> for Collection<T> {\n \t fn from(items: Vec<T>) -> Self {\n \t \t Self { items, len: items.len() }\n \t }\n }\n " },
361+ {"cpp_template_class" , lang .CPP , "template<typename T, typename Alloc = std::allocator<T>>\n class Vector {\n public:\n \t void push_back(const T& value) { data_.push_back(value); }\n \t T& operator[](size_t index) { return data_[index]; }\n private:\n \t std::vector<T, Alloc> data_;\n };\n " },
362+ {"scala_type_bounds" , lang .Scala , "object A {\n \t def process[T <: Serializable : Ordering](items: List[T]): List[T] = {\n \t \t items.sorted.distinct\n \t }\n }\n " },
363+
364+ // === Destructuring Patterns ===
365+ {"js_object_destructure" , lang .JavaScript , "const { name, age, address: { city } } = getUserInfo();\n const [first, ...rest] = getItems();\n " },
366+ {"ts_function_destructure" , lang .TypeScript , "function processUser({ id, name, roles = [] }: UserInput): Result {\n return { id, displayName: name, isAdmin: roles.includes('admin') };\n }\n " },
367+ {"python_unpack" , lang .Python , "first, *middle, last = get_items()\n (x, y), z = get_coords()\n name, age = user_info.values()\n " },
368+ {"rust_pattern_match" , lang .Rust , "fn handle(msg: Message) {\n \t match msg {\n \t \t Message::Quit => println!(\" quit\" ),\n \t \t Message::Move { x, y } => move_to(x, y),\n \t \t Message::Write(text) => println!(\" {}\" , text),\n \t \t Message::Color(r, g, b) => set_color(r, g, b),\n \t }\n }\n " },
369+ {"kotlin_destructure" , lang .Kotlin , "fun process(pair: Pair<String, Int>) {\n \t val (name, age) = pair\n \t val (first, second, third) = Triple(1, 2, 3)\n }\n " },
370+
371+ // === Metaprogramming/Dynamic Patterns ===
372+ {"python_decorator_stack" , lang .Python , "@app.route('/users', methods=['GET'])\n @login_required\n @cache(timeout=300)\n def list_users():\n return User.query.all()\n " },
373+ {"ruby_method_missing" , lang .Ruby , "class DynamicProxy\n def method_missing(name, *args, &block)\n if target.respond_to?(name)\n target.send(name, *args, &block)\n else\n super\n end\n end\n end\n " },
374+ {"python_dunder_methods" , lang .Python , "class Vector:\n def __init__(self, x, y):\n self.x = x\n self.y = y\n def __add__(self, other):\n return Vector(self.x + other.x, self.y + other.y)\n def __repr__(self):\n return f'Vector({self.x}, {self.y})'\n " },
375+ {"ts_mapped_types" , lang .TypeScript , "type Readonly<T> = { readonly [P in keyof T]: T[P] };\n type Optional<T> = { [P in keyof T]?: T[P] };\n type Pick<T, K extends keyof T> = { [P in K]: T[P] };\n " },
376+
377+ // === Pipe/Composition Patterns ===
378+ {"elixir_pipe_complex" , lang .Elixir , "defmodule A do\n def process(data) do\n data\n |> Enum.filter(&(&1.active))\n |> Enum.map(&transform/1)\n |> Enum.sort_by(& &1.priority)\n |> Enum.take(10)\n end\n end\n " },
379+ {"haskell_composition" , lang .Haskell , "processAll = map (show . succ . abs)\n " },
380+ {"ocaml_pipe_complex" , lang .OCaml , "let process items =\n items\n |> List.filter (fun x -> x > 0)\n |> List.map (fun x -> x * 2)\n |> List.sort compare\n " },
381+
382+ // === Interface/Trait Implementation Patterns ===
383+ {"rust_trait_impl" , lang .Rust , "trait Handler {\n \t fn handle(&self, req: &Request) -> Response;\n }\n struct ApiHandler { db: Database }\n impl Handler for ApiHandler {\n \t fn handle(&self, req: &Request) -> Response {\n \t \t self.db.query(req.path())\n \t }\n }\n " },
384+ {"go_interface_impl" , lang .Go , "package main\n type Handler interface {\n \t Handle(ctx context.Context, req *Request) (*Response, error)\n }\n type APIHandler struct{ db *DB }\n func (h *APIHandler) Handle(ctx context.Context, req *Request) (*Response, error) {\n \t return h.db.Query(ctx, req.Path)\n }\n " },
385+ {"csharp_interface_impl" , lang .CSharp , "interface IHandler {\n \t Task<Response> HandleAsync(Request req);\n }\n class ApiHandler : IHandler {\n \t private readonly IDb _db;\n \t public async Task<Response> HandleAsync(Request req) {\n \t \t return await _db.QueryAsync(req.Path);\n \t }\n }\n " },
386+ {"kotlin_interface_impl" , lang .Kotlin , "interface Handler {\n \t suspend fun handle(req: Request): Response\n }\n class ApiHandler(private val db: Database) : Handler {\n \t override suspend fun handle(req: Request): Response {\n \t \t return db.query(req.path)\n \t }\n }\n " },
387+
388+ // === Closure/Lambda Patterns ===
389+ {"go_closure_capture" , lang .Go , "package main\n func makeCounter() func() int {\n \t count := 0\n \t return func() int {\n \t \t count++\n \t \t return count\n \t }\n }\n " },
390+ {"rust_closure_move" , lang .Rust , "fn spawn_task(data: Vec<u8>) {\n \t tokio::spawn(async move {\n \t \t process(&data).await;\n \t \t println!(\" done\" );\n \t });\n }\n " },
391+ {"java_lambda_stream" , lang .Java , "class A {\n \t List<String> process(List<User> users) {\n \t \t return users.stream()\n \t \t \t .filter(u -> u.isActive())\n \t \t \t .map(User::getName)\n \t \t \t .sorted()\n \t \t \t .collect(Collectors.toList());\n \t }\n }\n " },
392+
393+ // === Erlang OTP Patterns ===
394+ {"erlang_gen_server" , lang .Erlang , "-module(counter).\n -behaviour(gen_server).\n -export([start_link/0, init/1, handle_call/3]).\n start_link() -> gen_server:start_link(?MODULE, 0, []).\n init(Count) -> {ok, Count}.\n handle_call(increment, _From, Count) -> {reply, Count + 1, Count + 1}.\n " },
395+ {"erlang_supervisor" , lang .Erlang , "-module(my_sup).\n -behaviour(supervisor).\n -export([start_link/0, init/1]).\n start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).\n init([]) -> {ok, {{one_for_one, 5, 10}, [{worker, {my_worker, start_link, []}, permanent, 5000, worker, [my_worker]}]}}.\n " },
396+
397+ // === Haskell Type Classes ===
398+ {"haskell_typeclass_def" , lang .Haskell , "class Container f where\n empty :: f a\n insert :: a -> f a -> f a\n member :: Eq a => a -> f a -> Bool\n " },
399+ {"haskell_instance_impl" , lang .Haskell , "instance Show Color where\n show Red = \" red\" \n show Green = \" green\" \n show Blue = \" blue\" \n " },
400+
401+ // === Complex OOP Patterns ===
402+ {"csharp_generic_constraint" , lang .CSharp , "class Repository<T> where T : class, IEntity, new() {\n \t public T FindById(int id) {\n \t \t return _context.Set<T>().Find(id);\n \t }\n }\n " },
403+ {"scala_sealed_trait" , lang .Scala , "sealed trait Shape\n case class Circle(radius: Double) extends Shape\n case class Rectangle(w: Double, h: Double) extends Shape\n object Shape {\n \t def area(s: Shape): Double = s match {\n \t \t case Circle(r) => math.Pi * r * r\n \t \t case Rectangle(w, h) => w * h\n \t }\n }\n " },
404+ {"php_trait_usage" , lang .PHP , "<?php\n trait Timestampable {\n \t public function touch(): void {\n \t \t $this->updatedAt = new DateTime();\n \t }\n }\n class Post implements JsonSerializable {\n \t use Timestampable;\n \t public function jsonSerialize(): mixed {\n \t \t return ['title' => $this->title];\n \t }\n }\n " },
307405}
308406
309407func TestDumpAST (t * testing.T ) {
0 commit comments