# Data-driven integration cases. See tests/data.rs for the field syntax.

# detect / language

name=file rust | path=sample.rs | content=fn main() {}\n | args=detect %s | type=text/plain | language=rust | supported=true
name=file stdin path | stdin=class BufferGreeter {}\n | args=detect --stdin buffer.ts | type=text/plain | file=buffer.ts | language=typescript
name=detect stdin extensionless shebang | stdin=#!/usr/bin/env bash\necho hello\n | args=detect --stdin buffer | type=text/plain | file=buffer | language=bash | supported=true
name=detect stdin extensionless with override | stdin=fn main() {}\n | args=detect --stdin buffer --language rust | type=text/plain | file=buffer | language=rust | supported=true
name=file html | path=index.html | content=<!doctype html><html><body>Hello</body></html>\n | args=detect %s | type=text/html | language=html | supported=true | mime=text/html
name=file xml | path=sample.xml | content=<?xml version="1.0"?><note><body>Hello</body></note>\n | args=detect %s | type=text/xml | language=xml | supported=true | mime=text/xml
name=file json | path=sample.json | content={"name": "sample"}\n | args=detect %s | type=text/plain | language=json | supported=true
name=file yaml | path=sample.yaml | content=name: sample\n | args=detect %s | type=text/plain | language=yaml | supported=true
name=file puppet | path=site.pp | content=class profile::sample {}\n | args=detect %s | type=text/plain | language=puppet | supported=true
name=file dockerfile | path=Dockerfile | content=FROM alpine:3.20\nRUN echo hello\n | args=detect %s | type=text/plain | language=dockerfile | supported=true
name=file nix | path=flake.nix | content={ description = "sample"; }\n | args=detect %s | type=text/plain | language=nix | supported=true
name=file lua | path=sample.lua | content=function greet()\n  return 'hello'\nend\n | args=detect %s | type=text/plain | language=lua | supported=true
name=file perl | path=sample.pl | content=sub greet { return "hello"; }\n | args=detect %s | type=text/plain | language=perl | supported=true
name=file zig | path=sample.zig | content=pub fn main() void {}\n | args=detect %s | type=text/plain | language=zig | supported=true
name=file vimscript | path=plugin.vim | content=function! Greet() abort\nendfunction\n | args=detect %s | type=text/plain | language=vimscript | supported=true
name=file meson build | path=meson.build | content=project('sample', 'c')\n | args=detect %s | type=text/plain | language=meson | supported=true
name=file language override | path=script | content=#!/usr/bin/env node\nfunction main() {}\n | args=detect %s --language typescript | type=text/x-shellscript | language=typescript | supported=true
name=file language alias | path=header | content=int add(int a, int b);\n | args=detect %s --language c-plus-plus | type=text/plain | language=cpp | supported=true
name=file special filename | path=go.mod | content=module example.com/readseek\n | args=detect %s | type=text/plain | language=go | supported=true
name=file tex | path=paper.tex | content=\\section{Intro}\nText.\n | args=detect %s | type=text/plain | language=latex | supported=true
name=file typst | path=paper.typ | content== Intro\nText.\n | args=detect %s | type=text/plain | language=typst | supported=true
name=file assembly | path=boot.S | content=_start:\n    mov %rsp, %rbp\n | args=detect %s | type=text/plain | language=assembly | supported=true
name=file riscv | path=boot.riscv | content=_start:\n    addi sp, sp, -16\n | args=detect %s | type=text/plain | language=riscv | supported=true
name=file gdscript | path=player.gd | content=func _ready():\n    pass\n | args=detect %s | type=text/plain | language=gdscript | supported=true
name=file sql | path=query.sql | content=select * from users;\n | args=detect %s | type=text/plain | language=sql | supported=true
name=file toml | path=config.toml | content=name = "demo"\n | args=detect %s | type=text/plain | language=toml | supported=true
name=file binary detected | path=blob.bin | content=\x00\x01\x02\x03 | args=detect %s | type=text/plain | binary.absent=true | language.absent=true | supported.absent=true | syntax.absent=true

# read

name=read requested range | path=sample.py | content=one\ntwo\nthree\n | args=read %s --start 2 --end 3 | language=python | line_count=3 | start_line=2 | end_line=3 | hashlines.len=2 | hashlines.0.line=2 | hashlines.0.text=two | hashlines.0.hash.len=3
name=read start and limit | path=start.txt | content=one\ntwo\nthree\nfour\n | args=read %s --start 2 --limit 2 | line_count=4 | start_line=2 | end_line=3 | hashlines.len=2 | hashlines.0.line=2 | hashlines.0.text=two | hashlines.1.line=3 | hashlines.1.text=three
name=read limit clamps to end | path=clamp.txt | content=one\ntwo\nthree\n | args=read %s --start 2 --limit 99 | line_count=3 | start_line=2 | end_line=3 | hashlines.len=2
name=read plain text normalizes | path=normalized.txt | content=﻿one\r\ntwo\rthree\n | args=read %s | language=unknown | line_count=3 | hashlines.0.text=one | hashlines.1.text=two | hashlines.2.text=three
name=read preserves blank lines | path=blank-lines.txt | content=one\n\nthree\n | args=read %s | line_count=3 | hashlines.len=3 | hashlines.1.line=2 | hashlines.1.text=
name=read empty file | path=empty.txt | content= | args=read %s | line_count=0 | start_line=1 | end_line=0 | hashlines.len=0
name=read target line | path=target-line.txt | content=one\ntwo\nthree\n | args=read %s:2 --limit 1 | start_line=2 | end_line=2 | hashlines.0.text=two
name=read stdin path | stdin=one\ntwo\nthree\n | args=read --stdin buffer.ts --start 2 --end 2 | file=buffer.ts | start_line=2 | end_line=2 | hashlines.0.text=two
name=read binary lossy text | path=blob-read.bin | content=\x00A\xff\n | args=read %s | language=unknown | line_count=1 | hashlines.0.text=\x00A�

# map

name=map javascript | path=sample.js | content=class Greeter {\n  greet() { return 'hello'; }\n}\nconst make = () => new Greeter();\n | args=map %s | language=javascript | symbol=class,Greeter,start_byte=0,name_byte=6 | symbol=method,greet | symbol=function,make
name=map jsx | path=sample.jsx | content=export function App() {\n  return <main>Hello</main>;\n}\n | args=map %s | language=jsx | symbol=function,App
name=map typescript | path=sample.ts | content=interface Named { name: string; }\nclass Greeter implements Named {\n  name = 'reader';\n  greet() { return 'hello'; }\n}\nconst make = (): Greeter => new Greeter();\n | args=map %s | language=typescript | symbol=interface,Named | symbol=class,Greeter | symbol=method,greet | symbol=function,make
name=map tsx | path=sample.tsx | content=type Props = { name: string };\nexport function App(props: Props) {\n  return <main>{props.name}</main>;\n}\n | args=map %s | language=tsx | symbol=type,Props | symbol=function,App
name=map cpp | path=sample.cpp | content=namespace demo {\nclass Thing {\npublic:\n  int value();\n};\n}\nint add(int a, int b) { return a + b; }\n | args=map %s | symbol=namespace,demo | symbol=class,Thing | symbol=function,add
name=map c variable initializer name | path=vars.c | content=int b = other;\nint c = func();\nstatic int d = a + b;\n | args=map %s | language=c | symbol=variable,b | symbol=variable,c | symbol=variable,d
name=map makefile target | path=Makefile | content=build: main.c\n\tcc -o app main.c\n | args=map %s | language=make | symbol=target,build
name=map justfile recipe | path=Justfile | content=build:\n    cargo build\n | args=map %s | language=just | symbol=recipe,build
name=map vimscript function | path=plugin.vim | content=function! s:greet(name) abort\n  echo a:name\nendfunction\n | args=map %s | language=vimscript | symbol=function,s:greet
name=map markdown headings | path=notes.md | content=# Title\n\nSome text.\n\n## Details ##\n | args=map %s | language=markdown | symbol=heading,Title,start_line=1,end_line=1,end_hash=@start_hash | symbol=heading,Details
name=map kconfig symbols | path=Kconfig | content=menu "Drivers"\n\nconfig USB_SUPPORT\n    bool "USB support"\n\nmenuconfig NET\n    bool "Networking support"\n\nendmenu\n | args=map %s | language=kconfig | symbol=menu,Drivers | symbol=config,USB_SUPPORT | symbol=menuconfig,NET
name=map swift symbols | path=sample.swift | content=actor BankAccount {\n    var balance: Double = 0\n    func deposit(_ amount: Double) {\n        balance += amount\n    }\n}\n | args=map %s | language=swift | symbol=class,actor BankAccount | symbol=function,func deposit(_ amount: Double)
name=map unknown text | path=notes.txt | content=alpha\nbeta\n | args=map %s | language=unknown | engine.absent=true | symbols.len=0
name=map stdin path | stdin=class BufferGreeter {\n  greet() { return 'hello'; }\n}\n | args=map --stdin buffer.ts | file=buffer.ts | language=typescript | symbol=class,BufferGreeter | symbol=method,greet
name=map dockerfile parser | path=Containerfile | content=FROM alpine:3.20\nRUN echo hello\n | args=map %s | language=dockerfile
name=map nix parser | path=parser.nix | content={ packages.default = null; }\n | args=map %s | language=nix
name=map lua parser | path=parser.lua | content=function greet()\n  return 'hello'\nend\n | args=map %s | language=lua
name=map perl parser | path=parser.pl | content=sub greet { return "hello"; }\n | args=map %s | language=perl
name=map zig parser | path=parser.zig | content=pub fn main() void {}\n | args=map %s | language=zig
name=map vimscript parser | path=parser.vim | content=function! Greet() abort\nendfunction\n | args=map %s | language=vimscript

# check

name=check clean source | stdin=fn main() {}\n | args=check --stdin clean.rs | error_count=0 | missing_count=0 | diagnostics.len=0
name=check parse error | stdin=fn main() {\n    let x =\n}\n | args=check --stdin broken.rs | error_count=1 | missing_count=0 | diagnostics.len=1 | diagnostics.0.kind=error | diagnostics.0.start_line=2
name=check missing token | stdin=int main() {\n  int x = 1\n  return x;\n}\n | args=check --stdin missing.c | error_count=0 | missing_count=1 | diagnostics.len=1 | diagnostics.0.kind=missing | diagnostics.0.start_line=2
name=check unsupported file | stdin=just some text\n | args=check --stdin notes.txt | language=unknown | diagnostics.len=0

# identify

name=identify cursor identifier and symbol | stdin=class BufferGreeter {\n  greet() { return 'hello'; }\n}\n | args=identify --stdin buffer.ts --line 2 --column 3 | file=buffer.ts | line=2 | line_hash=@hashlines.0.hash | identifier.text=greet | identifier.start_column=3 | identifier.end_column=8 | identifier.start_byte=24 | identifier.end_byte=29 | symbol.qualified_name=BufferGreeter.greet
name=identify unicode identifier span | stdin=fn café() {}\n | args=identify --stdin unicode.rs --line 1 --column 8 | identifier.text=café | identifier.start_column=4 | identifier.end_column=9
name=identify unknown no optional fields | stdin=  \n | args=identify --stdin note.txt --line 1 --column 1 | language=unknown | engine.absent=true | identifier.absent=true | symbol.absent=true
name=identify column out of range | stdin=fn main() {}\n | args=identify --stdin cursor.rs --line 1 --column 20 | status=1 | stderr=exceeds maximum column

# symbol

name=symbol target suffix | path=symbol.ts | content=class Greeter {\n  greet() {\n    return 'hello';\n  }\n}\n | args=symbol %s --name Greeter.greet | language=typescript | symbol.kind=method | symbol.name=greet | symbol.qualified_name=Greeter.greet | hashlines.len=3 | hashlines.0.line=2
name=symbol target line | path=symbol.ts | content=class Greeter {\n  greet() {\n    return 'hello';\n  }\n}\n | args=symbol %s:3 | symbol.kind=method | symbol.name=greet | hashlines.0.line=2
name=symbol stdin target line | stdin=class BufferGreeter {\n  greet() { return 'hello'; }\n}\n | args=symbol --stdin buffer.ts --line 2 | file=buffer.ts | symbol.qualified_name=BufferGreeter.greet | hashlines.0.line=2

# search

name=search captures call | path=search.rs | content=fn greet() {}\nfn main() {\n    greet();\n}\n | args=search %s $NAME(); --language rust | results.len=1 | results.0.language=rust | results.0.matches.len=1 | results.0.matches.0.start_line=3 | results.0.matches.0.hashlines.0.text=    greet(); | results.0.matches.0.captures.len=1 | results.0.matches.0.captures.0.name=NAME
name=search no match | path=search-none.rs | content=fn greet() {}\n | args=search %s missing(); --language rust | results.len=0

# def

name=def plain function | path=def.rs | content=fn greet() {}\nfn main() {\n    greet();\n}\n | args=def %s greet --language rust --format plain | locations.len=1 | locations.0.line=1 | locations.0.kind=function | locations.0.name=greet | locations.0.qualified_name=greet | locations.0.text=fn greet() {}
name=def multi-line macro | path=macro.c | content=#define FOO(a, b) \\\n    ((a) + \\\n     (b))\nint main(void) { return FOO(1, 2); }\n | args=def %s FOO --language c | definitions.len=1 | definitions.0.symbol.kind=macro | definitions.0.symbol.name=FOO | definitions.0.symbol.start_line=1 | definitions.0.symbol.end_line=3

# refs

name=refs identifier | path=refs.rs | content=fn main() {\n    let value = 1;\n    println!("{}", value);\n}\n | args=refs %s value --language rust | references.len=2 | references.0.line=2 | references.0.column=9 | references.0.text=    let value = 1; | references.1.line=3 | references.1.column=20 | references.1.symbol.name=main
name=refs invalid identifier | path=refs-invalid.rs | content=fn main() {}\n | args=refs %s not-valid --language rust | status=1 | stderr=reference name must be an ASCII identifier
name=refs scope column out of range | path=refs-column.rs | content=fn main() {\n    let value = 1;\n}\n | args=refs %s value --scope --line 1 --column 15 --language rust | status=1 | stderr=exceeds maximum column
name=refs python scope binding | path=refs-scope.py | content=def g(items):\n    total = 0\n    for n in items:\n        total += n\n    return total\n | args=refs %s total --scope --line 2 --column 5 --language python | references.len=3 | references.0.line=2 | references.0.occurrence=definition | references.2.line=5

name=refs vimscript scope binding | path=refs-scope.vim | content=let val = 1\nfunction! Test() abort\n  let val = 2\n  echo val\nendfunction\necho val\n | args=refs %s val --scope --line 1 --column 5 --language vimscript | references.len=2 | references.0.line=1 | references.0.occurrence=definition | references.1.line=6 | references.1.occurrence=reference

# rename

name=rename local binding | path=rename.rs | content=fn main() {\n    let value = 1;\n    println!("{}", value);\n}\n | args=rename %s --line 2 --column 9 --to renamed --language rust | old_name=value | new_name=renamed | applied=false | conflicts.len=0 | edits.len=2 | edits.0.occurrence=definition | edits.0.start_column=9 | edits.1.occurrence=reference | edits.1.line=3
name=rename invalid new name | path=rename-invalid.rs | content=fn main() {\n    let value = 1;\n}\n | args=rename %s --line 2 --column 9 --to not-valid --language rust | status=1 | stderr=new name must be a plain identifier
name=rename column out of range | path=rename-column.rs | content=fn main() {\n    let value = 1;\n}\n | args=rename %s --line 1 --column 15 --to renamed --language rust | status=1 | stderr=exceeds maximum column
name=rename python reassignment | path=reassign.py | content=def f(a, b):\n    x = a + b\n    x = x + 1\n    return x\n | args=rename %s --line 2 --column 5 --to y --language python | old_name=x | conflicts.len=0 | edits.len=4 | edits.0.occurrence=definition | edits.0.line=2 | edits.3.occurrence=reference | edits.3.line=4
name=rename python skips attribute and keyword | path=attr.py | content=def f():\n    x = 1\n    obj.x = 2\n    g(x=3)\n    return x\n | args=rename %s --line 2 --column 5 --to y --language python | old_name=x | edits.len=2 | edits.0.line=2 | edits.1.line=5
name=rename python nested shadow | path=shadow.py | content=def outer():\n    v = 1\n    def inner():\n        v = 2\n        return v\n    return v\n | args=rename %s --line 2 --column 5 --to w --language python | old_name=v | edits.len=2 | edits.0.line=2 | edits.1.line=6
name=rename python capture conflict | path=conflict.py | content=def h():\n    a = 1\n    b = 2\n    return a + b\n | args=rename %s --line 2 --column 5 --to b --language python | conflicts.len=2 | edits.len=2
name=rename python class attribute isolated | path=cls-attr.py | content=x = 1\nclass Foo:\n    x = 2\n | args=rename %s --line 1 --column 1 --to xx --language python | old_name=x | edits.len=1 | edits.0.line=1
name=rename python method name resolves to module | path=cls-method.py | content=x = 1\nclass C:\n    x = 2\n    def show(self):\n        return x\n | args=rename %s --line 1 --column 1 --to xx --language python | edits.len=2 | edits.0.line=1 | edits.1.line=5
name=rename python global statement | path=glob.py | content=x = 10\n\ndef f():\n    global x\n    x = 20\n\nprint(x)\n | args=rename %s --line 5 --column 5 --to x_new --language python | edits.len=4 | edits.0.line=1 | edits.3.line=7
name=rename python comprehension iterable scope | path=comp.py | content=items = [1, 2, 3]\nresult = [items for items in items]\n | args=rename %s --line 2 --column 12 --to ci --language python | edits.len=2 | edits.1.start_column=21
name=rename python lambda default scope | path=lam-default.py | content=def outer():\n    x = 1\n    f = lambda x=x: x\n    return f\n | args=rename %s --line 3 --column 16 --to w --language python | edits.len=2 | edits.0.start_column=16 | edits.1.start_column=21
name=rename python walrus leaks to function | path=walrus.py | content=def foo():\n    y = 0\n    result = [y := x for x in range(5)]\n    return y\n | args=rename %s --line 2 --column 5 --to yy --language python | edits.len=3 | edits.0.line=2 | edits.2.line=4
name=rename python method name isolated | path=meth.py | content=class Obj:\n    def method(self):\n        return 1\n\nmethod = Obj()\nprint(method)\n | args=rename %s --line 5 --column 1 --to obj_inst --language python | edits.len=2 | edits.0.line=5 | edits.1.line=6
name=rename python top-level function | path=func.py | content=def helper():\n    return 1\n\ndef main():\n    return helper() + helper()\n | args=rename %s --line 1 --column 5 --to helper2 --language python | edits.len=3 | edits.0.line=1 | edits.1.line=5 | edits.2.line=5
name=rename typescript parameter | path=param.ts | content=function f(value: number): number {\n  return value + 1;\n}\n | args=rename %s --line 1 --column 12 --to amount --language typescript | old_name=value | conflicts.len=0 | edits.len=2 | edits.0.occurrence=definition | edits.0.line=1 | edits.1.occurrence=reference | edits.1.line=2
name=rename typescript nested shadow | path=shadow.ts | content=function outer(v: number) {\n  function inner() {\n    const v = 2;\n    return v;\n  }\n  return v + inner();\n}\n | args=rename %s --line 1 --column 16 --to w --language typescript | old_name=v | edits.len=2 | edits.0.line=1 | edits.1.line=6
name=rename typescript skips member and key | path=member.ts | content=function f(obj: any) {\n  const value = 1;\n  obj.value = 2;\n  const o = { value: 3 };\n  return value + o.value;\n}\n | args=rename %s --line 2 --column 9 --to renamed --language typescript | old_name=value | edits.len=2 | edits.0.line=2 | edits.1.line=5
name=rename typescript destructuring shorthand | path=destr.ts | content=function f(o: any) {\n  const { count } = o;\n  const total = count + 1;\n  return { count, total };\n}\n | args=rename %s --line 2 --column 11 --to n --language typescript | old_name=count | edits.len=3 | edits.0.line=2 | edits.1.line=3 | edits.2.line=4
name=rename typescript capture conflict | path=conflict.ts | content=function h() {\n  const a = 1;\n  const b = 2;\n  return a + b;\n}\n | args=rename %s --line 2 --column 9 --to b --language typescript | conflicts.len=1 | conflicts.0.line=4 | edits.len=2
name=rename typescript top-level function | path=top.ts | content=function helper() {\n  return 1;\n}\nfunction main() {\n  return helper() + helper();\n}\n | args=rename %s --line 1 --column 10 --to helper2 --language typescript | old_name=helper | edits.len=3 | edits.0.line=1 | edits.1.line=5 | edits.2.line=5

name=rename vimscript function | path=plugin.vim | content=function! Greet() abort\n  echo "hello"\nendfunction\ncall Greet()\n | args=rename %s --line 1 --column 11 --to Hello --language vimscript | old_name=Greet | new_name=Hello | edits.len=2

name=rename vimscript let variable | path=var.vim | content=let l:count = 0\nlet l:total = count + 1\ncall Feed(count)\n | args=rename %s --line 1 --column 7 --to n --language vimscript | old_name=count | edits.len=3

name=rename vimscript nested shadow | path=shadow.vim | content=let val = 1\nfunction! Test() abort\n  let val = 2\n  echo val\nendfunction\necho val\n | args=rename %s --line 1 --column 5 --to x --language vimscript | old_name=val | edits.len=2 | edits.0.occurrence=definition | edits.0.line=1 | edits.0.start_column=5 | edits.1.occurrence=reference | edits.1.line=6 | edits.1.start_column=6

# image

name=detect png image | path=detpix.png | content=\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x0d\x49\x44\x41\x54\x78\x9c\x63\xf8\xcf\xc0\xf0\x1f\x00\x05\x00\x01\xff\x89\x99\x3d\x1d\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82 | args=detect %s | type=image/png | mime=image/png | format=png | width=1 | height=1 | animated=false | binary.absent=true | language.absent=true | engine.absent=true | supported.absent=true | syntax.absent=true | image.absent=true
name=detect gif image | path=detpix.gif | content=\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\xff\xff\xff\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3b | args=detect %s | type=image/gif | mime=image/gif | format=gif | width=1 | height=1 | animated=false | binary.absent=true | language.absent=true | syntax.absent=true
name=detect apng animated | path=detanim.png | content=\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\x08\x61\x63\x54\x4c\x00\x00\x00\x01\x00\x00\x00\x00\xb4\x2d\xe9\xa0\x00\x00\x00\x1a\x66\x63\x54\x4c\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6a\x88\x9c\xb6\x00\x00\x00\x0d\x49\x44\x41\x54\x78\x9c\x63\xf8\xcf\xc0\xf0\x1f\x00\x05\x00\x01\xff\x89\x99\x3d\x1d\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82 | args=detect %s | type=image/png | format=png | width=1 | height=1 | animated=true | language.absent=true | syntax.absent=true
name=detect transcribe ignored on non-image | path=note.txt | content=hi\n | args=detect %s --transcribe | type=text/plain | binary.absent=true | language.absent=true | syntax.absent=true
