doci/AGENTS.md

6.4 KiB

AGENTS.md - XQuery Code Style and Build Guide

Build & Test Commands

Running Tests

basex -t /path/to/test/file.xqm    # Run all tests in a file
basex -t /path/to/test/dir         # Run all tests in directory
basex -t test/simple.xqm           # Run doci unit tests (6 tests)
basex -t test/smoke.xq             # Run smoke tests (no assertions)

Query Execution

basex query.xq                     # Execute XQuery file
basex -V query.xq                  # Verbose mode with timing info (includes compile/execute times)
basex -q "query string"            # Execute inline query
basex -Q test/file.xqm             # Execute XQuery file (explicit flag, for query files without test functions)
basex -c "commands"               # Execute BaseX commands from string
basex -C script.bxs              # Execute BaseX command script
basex  # Start interactive BaseX shell

Database Operations

(Already included in Query Execution section above)

Environment

  • XQuery Engine: BaseX 12.2
  • XQuery Version: 3.1+
  • Module System: BaseX module system with module namespace
  • Test Framework: http://basex.org/modules/unit

Code Style Guidelines

File Naming

  • Module files: lowercase.xqm (e.g., doci.xqm)
  • Test files: snake_case.xqm or snake_case.xq
  • Use hyphens for multi-word names (e.g., pdfbox.xqm)
  • Resource files: lowercase with hyphens (e.g., test-data.txt)

Namespace Declarations

module namespace module-name = 'urn:project:namespace';
  • Use reverse domain name notation for consistency
  • Match namespace URI to file path structure

Records & Types

  • Use declare record for structured data
  • Use declare type for custom types
  • Record fields use ?field syntax for access
  • Mark optional fields with ? after field name
declare record doci:doci(
  lines as xs:string+,
  separator? as xs:string
);

Function Naming

  • Module functions: prefix with module namespace (e.g., doci:build)
  • Helper functions: use camelCase internally
  • Test functions: prefix with test: namespace and test: prefix
  • Use descriptive names that clarify purpose

Import/Module Syntax

import module namespace mod = 'namespace' at "path/to/file.xqm";
  • Use relative paths for local modules
  • Keep imports at top of file, grouped logically

Module Organization

  • Group related functionality in modules
  • Export public API functions
  • Keep private functions marked with %private if needed
  • Document exported functions with (:~ doc comments

Line Separators

  • Detect automatically using doci:separator()
  • Default: file:line-separator()
  • Handle all common separators: \n, \r\n, \r

Module Function Implementation Notes

  • Use => for function chaining/piping
  • Prefer let over for for single items
  • Use if-then-else expressions
  • Leverage XQuery 3.1+ functions: tokenize(), string-join()
  • Use ! for mapping single items
  • Use * for mapping sequences: expr!func()
  • Prefer switch() case when over nested if-then-else

Error Handling

try {
  ...
} catch * {
  error(xs:QName("mod:code"), "descriptive message")
}
  • Use try/catch for external operations (files, PDFs, network)
  • Define custom error codes as xs:QName
  • Validate parameters and ranges before processing
  • Provide meaningful error messages with context
  • Use #mod:code for errorQName in error() calls

XQuery Best Practices

  • Use => for function chaining/piping
  • Prefer let over for for single items
  • Use if-then-else expressions
  • Leverage XQuery 3.1+ functions: tokenize(), string-join()
  • Use ! for mapping single items
  • Use * for mapping sequences: expr!func()
  • Prefer switch() case when over nested if-then-else

Type Checking

declare function foo($param as xs:string) as xs:integer { ... }
  • Specify parameter types using as xs:type
  • Use item(), item()* for flexible/untyped sequences
  • Return type declarations are mandatory for exported functions
  • Use doci:num for union types (e.g., integer|double)

Record Field Access

  • Use ?field syntax for record field access (e.g., $doci?lines)
  • Optional fields marked with ? after field name in record declaration

Documentation

(:~ 
 * Documentation comment
 * @param $name Description
 * @return Description
 * @see Reference URL
 :)
  • Use (:~ for module and function documentation
  • Document parameters, return values, and side effects
  • Include @see references to external docs when relevant

Test Structure

Test Module Pattern

module namespace test = 'test:module-name';
import module namespace mod = 'namespace' at "../src/file.xqm";

declare %unit:test function test:name() {
  let $result := mod:function(...)
  return unit:assert-equals(expected, $result)
};

Test Assertions

unit:assert-equals(expected, actual)
unit:assert(condition)
  • Use unit:assert-equals for value comparison
  • Use unit:assert for boolean conditions
  • Provide meaningful test names: test:functionality

Running Single Tests

basex -t test/file.xqm  # Runs all tests in the file
# To run a single test, comment out others or use test: namespaces

Test Helper Functions

declare function test:read($path as xs:string) as xs:string {
  file:resolve-path($path, file:base-dir()) => file:read-text()
};

Test Data

  • Place test resources in test/resources/
  • Use descriptive filenames (e.g., sample.txt, empty.txt)
  • Use test:read("resources/filename.txt") helper

Test Organization

  • Group tests by functionality
  • Test edge cases: empty input, null values, boundaries
  • Test error cases where applicable
  • Keep tests independent and order-independent

Commit Standards

Commit Message Format

verb: description

Examples

fix: handle empty input
add: support多元 line separators
refactor: improve error handling
test: add edge case for range updates
docs: update module documentation

Commit Guidelines

  • Add test cases for bug fixes
  • Update documentation for public API changes
  • Keep commits focused on single changes
  • Verify tests pass before committing

Notes

  • BaseX 12.2 supports XQuery 3.1 syntax
  • The fn:do-until function may not be available; use hof:until as alternative
  • Java interoperability available through Q{namespace} syntax (e.g., Q{java:java.io.File}new())
  • For PDF processing (pdfbox module), external JAR dependencies required