Documentation
¶
Overview ¶
Package parser provides test file scanning and parsing capabilities. It supports multiple test frameworks (Jest, Vitest, Playwright, Go testing) and enables parallel processing for efficient scanning of large codebases.
Example ¶
package main
import (
"context"
"fmt"
"github.com/specvital/core/pkg/parser"
// Import strategies to register them with the default registry.
_ "github.com/specvital/core/pkg/parser/strategies/gotesting"
_ "github.com/specvital/core/pkg/parser/strategies/jest"
_ "github.com/specvital/core/pkg/parser/strategies/playwright"
_ "github.com/specvital/core/pkg/parser/strategies/vitest"
)
func main() {
ctx := context.Background()
// Scan a project directory for test files
result, err := parser.Scan(ctx, "/path/to/project")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
// Print discovered test files
for _, file := range result.Inventory.Files {
fmt.Printf("File: %s (framework: %s)\n", file.Path, file.Framework)
fmt.Printf(" Tests: %d\n", file.CountTests())
}
// Check for non-fatal errors
for _, scanErr := range result.Errors {
fmt.Printf("Warning: %v\n", scanErr)
}
}
Example (WithOptions) ¶
package main
import (
"context"
"fmt"
"time"
"github.com/specvital/core/pkg/parser"
// Import strategies to register them with the default registry.
_ "github.com/specvital/core/pkg/parser/strategies/gotesting"
_ "github.com/specvital/core/pkg/parser/strategies/jest"
_ "github.com/specvital/core/pkg/parser/strategies/playwright"
_ "github.com/specvital/core/pkg/parser/strategies/vitest"
)
func main() {
ctx := context.Background()
// Scan with custom options
result, err := parser.Scan(ctx, "/path/to/project",
parser.WithWorkers(4), // Use 4 parallel workers
parser.WithTimeout(2*time.Minute), // Set 2 minute timeout
parser.WithExclude([]string{"fixtures"}), // Skip fixtures directory
parser.WithScanPatterns([]string{"**/*.test.ts"}), // Only *.test.ts files
)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Found %d test files\n", len(result.Inventory.Files))
}
Index ¶
- Constants
- Variables
- func ClearQueryCache()
- func FindChildByType(node *sitter.Node, nodeType string) *sitter.Node
- func FindChildrenByType(node *sitter.Node, nodeType string) []*sitter.Node
- func GetLocation(node *sitter.Node, filename string) domain.Location
- func GetNodeText(node *sitter.Node, source []byte) string
- func ParseWithPool(ctx context.Context, lang domain.Language, source []byte) (*sitter.Tree, error)
- func WalkTree(node *sitter.Node, visitor func(*sitter.Node) bool)
- type DetectionResult
- type DetectorOption
- type DetectorOptions
- type QueryResult
- type ScanError
- type ScanOption
- type ScanOptions
- type ScanResult
- type TSParser
Examples ¶
Constants ¶
const ( // DefaultWorkers indicates that the scanner should use GOMAXPROCS as the worker count. DefaultWorkers = 0 // DefaultTimeout is the default scan timeout duration. DefaultTimeout = 5 * time.Minute // MaxWorkers is the maximum number of concurrent workers allowed. MaxWorkers = 1024 )
const ( // DefaultMaxFileSize is the default maximum file size for detection (10MB). DefaultMaxFileSize = 10 * 1024 * 1024 // 10MB )
const MaxTreeDepth = 1000
MaxTreeDepth is the maximum recursion depth when walking AST trees.
Variables ¶
var ( // ErrScanCancelled is returned when scanning is cancelled via context. ErrScanCancelled = errors.New("scanner: scan cancelled") // ErrScanTimeout is returned when scanning exceeds the timeout duration. ErrScanTimeout = errors.New("scanner: scan timeout") )
var DefaultSkipPatterns = []string{
"node_modules",
".git",
"vendor",
"dist",
".next",
"__pycache__",
"coverage",
".cache",
}
DefaultSkipPatterns contains directory names that are skipped by default during detection.
var ErrInvalidRootPath = errors.New("detector: root path does not exist or is not accessible")
ErrInvalidRootPath is returned when the root path does not exist or is not a directory.
Functions ¶
func ClearQueryCache ¶
func ClearQueryCache()
ClearQueryCache removes all cached queries. Only for testing.
func FindChildByType ¶
FindChildByType returns the first direct child with the given node type.
func FindChildrenByType ¶
FindChildrenByType returns all direct children with the given node type.
func GetLocation ¶
GetLocation converts a tree-sitter node position to a domain.Location. Line numbers are converted to 1-based indexing.
func GetNodeText ¶
GetNodeText returns the source text for the given AST node.
func ParseWithPool ¶
ParseWithPool parses source using a pooled parser. Caller must close the returned tree.
Types ¶
type DetectionResult ¶
type DetectionResult struct {
// Errors contains non-fatal errors encountered during directory traversal.
Errors []error
// Files contains paths to detected test files.
Files []string
}
DetectionResult contains detected test files and any errors encountered during traversal.
func DetectTestFiles ¶
func DetectTestFiles(ctx context.Context, rootPath string, opts ...DetectorOption) (*DetectionResult, error)
DetectTestFiles walks the directory tree and detects test files. It identifies test files by their naming conventions:
- JavaScript/TypeScript: *.test.ts, *.spec.ts, __tests__/*.ts
- Go: *_test.go
The function continues on errors, collecting them in [DetectionResult.Errors].
Example ¶
package main
import (
"context"
"fmt"
"github.com/specvital/core/pkg/parser"
// Import strategies to register them with the default registry.
_ "github.com/specvital/core/pkg/parser/strategies/gotesting"
_ "github.com/specvital/core/pkg/parser/strategies/jest"
_ "github.com/specvital/core/pkg/parser/strategies/playwright"
_ "github.com/specvital/core/pkg/parser/strategies/vitest"
)
func main() {
ctx := context.Background()
// Detect test files without parsing
result, err := parser.DetectTestFiles(ctx, "/path/to/project")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Found %d test files:\n", len(result.Files))
for _, path := range result.Files {
fmt.Printf(" - %s\n", path)
}
}
Example (WithPatterns) ¶
package main
import (
"context"
"fmt"
"github.com/specvital/core/pkg/parser"
// Import strategies to register them with the default registry.
_ "github.com/specvital/core/pkg/parser/strategies/gotesting"
_ "github.com/specvital/core/pkg/parser/strategies/jest"
_ "github.com/specvital/core/pkg/parser/strategies/playwright"
_ "github.com/specvital/core/pkg/parser/strategies/vitest"
)
func main() {
ctx := context.Background()
// Detect only specific test files
result, err := parser.DetectTestFiles(ctx, "/path/to/project",
parser.WithPatterns([]string{"src/**/*.spec.ts"}),
parser.WithMaxFileSize(5*1024*1024), // 5MB max
)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Found %d matching test files\n", len(result.Files))
}
type DetectorOption ¶
type DetectorOption func(*DetectorOptions)
DetectorOption is a functional option for configuring DetectTestFiles.
func WithMaxFileSize ¶
func WithMaxFileSize(size int64) DetectorOption
WithMaxFileSize returns a DetectorOption that sets the maximum file size.
func WithPatterns ¶
func WithPatterns(patterns []string) DetectorOption
WithPatterns returns a DetectorOption that filters files by glob patterns.
func WithSkipPatterns ¶
func WithSkipPatterns(patterns []string) DetectorOption
WithSkipPatterns returns a DetectorOption that replaces the skip patterns.
type DetectorOptions ¶
type DetectorOptions struct {
// SkipPatterns specifies directory names to skip during detection.
SkipPatterns []string
// Patterns specifies glob patterns to filter test files.
Patterns []string
// MaxFileSize is the maximum file size in bytes to include.
MaxFileSize int64
}
DetectorOptions configures the behavior of DetectTestFiles.
type QueryResult ¶
type QueryResult struct {
// Node is the first captured node in this match.
Node *sitter.Node
// Captures maps capture names to their corresponding nodes.
Captures map[string]*sitter.Node
}
QueryResult contains the result of a tree-sitter query match.
func Query ¶
func Query(root *sitter.Node, source []byte, lang domain.Language, queryStr string) ([]QueryResult, error)
Query executes a tree-sitter query and returns all matches. The query is compiled fresh each time; for repeated queries, use QueryWithCache.
func QueryWithCache ¶
func QueryWithCache(root *sitter.Node, source []byte, lang domain.Language, queryStr string) ([]QueryResult, error)
QueryWithCache executes a query with cached compilation.
type ScanError ¶
type ScanError struct {
// Err is the underlying error.
Err error
// Path is the file path where the error occurred (may be empty for non-file errors).
Path string
// Phase indicates which phase the error occurred in ("detection" or "parsing").
Phase string
}
ScanError represents an error that occurred during a specific phase of scanning.
type ScanOption ¶
type ScanOption func(*ScanOptions)
ScanOption is a functional option for configuring Scan.
func WithExclude ¶
func WithExclude(patterns []string) ScanOption
WithExclude returns a ScanOption that adds directory patterns to skip. These patterns are matched against directory base names.
func WithScanMaxFileSize ¶
func WithScanMaxFileSize(size int64) ScanOption
WithScanMaxFileSize returns a ScanOption that sets the maximum file size. Files larger than this size are skipped. Negative values are ignored.
func WithScanPatterns ¶
func WithScanPatterns(patterns []string) ScanOption
WithScanPatterns returns a ScanOption that filters files by glob patterns. Only files matching at least one pattern are processed. Uses doublestar syntax (e.g., "**/*.test.ts", "src/**/*.spec.js").
func WithTimeout ¶
func WithTimeout(d time.Duration) ScanOption
WithTimeout returns a ScanOption that sets the scan timeout. Negative values are ignored.
func WithWorkers ¶
func WithWorkers(n int) ScanOption
WithWorkers returns a ScanOption that sets the number of parallel workers. Zero uses GOMAXPROCS, negative values are ignored.
type ScanOptions ¶
type ScanOptions struct {
// ExcludePatterns specifies directory names to skip during scanning.
ExcludePatterns []string
// MaxFileSize is the maximum file size in bytes to process.
MaxFileSize int64
// Patterns specifies glob patterns to match test files (e.g., "**/*.test.ts").
Patterns []string
// Timeout is the maximum duration for the entire scan operation.
Timeout time.Duration
// Workers is the number of concurrent file parsers.
Workers int
}
ScanOptions configures the behavior of Scan.
type ScanResult ¶
type ScanResult struct {
// Errors contains non-fatal errors encountered during scanning.
Errors []ScanError
// Inventory contains all parsed test files.
Inventory *domain.Inventory
}
ScanResult contains the outcome of a scan operation.
func Scan ¶
func Scan(ctx context.Context, rootPath string, opts ...ScanOption) (*ScanResult, error)
Scan scans the given directory for test files and parses them. It uses parallel processing with configurable worker count and timeout. The function continues even when individual files fail to parse, collecting errors in [ScanResult.Errors].
Example (TestInventory) ¶
package main
import (
"context"
"fmt"
"github.com/specvital/core/pkg/parser"
// Import strategies to register them with the default registry.
_ "github.com/specvital/core/pkg/parser/strategies/gotesting"
_ "github.com/specvital/core/pkg/parser/strategies/jest"
_ "github.com/specvital/core/pkg/parser/strategies/playwright"
_ "github.com/specvital/core/pkg/parser/strategies/vitest"
)
func main() {
ctx := context.Background()
result, err := parser.Scan(ctx, "/path/to/project")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
inv := result.Inventory
fmt.Printf("Project: %s\n", inv.RootPath)
fmt.Printf("Total test files: %d\n", len(inv.Files))
fmt.Printf("Total tests: %d\n", inv.CountTests())
// Iterate test structure
for _, file := range inv.Files {
fmt.Printf("\n%s (%s):\n", file.Path, file.Framework)
// Top-level tests
for _, test := range file.Tests {
fmt.Printf(" - %s [%d:%d]\n", test.Name, test.Location.StartLine, test.Location.EndLine)
}
// Test suites
for _, suite := range file.Suites {
fmt.Printf(" %s:\n", suite.Name)
for _, test := range suite.Tests {
fmt.Printf(" - %s\n", test.Name)
}
}
}
}
type TSParser ¶
type TSParser struct {
// contains filtered or unexported fields
}
TSParser wraps a tree-sitter parser for a specific language.
func NewTSParser ¶
NewTSParser creates a new tree-sitter parser for the given language.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package detection provides hierarchical test framework detection.
|
Package detection provides hierarchical test framework detection. |
|
config
Package config provides scope-based configuration file resolution.
|
Package config provides scope-based configuration file resolution. |
|
matchers
Package matchers provides framework-specific detection rules.
|
Package matchers provides framework-specific detection rules. |
|
Package strategies provides the strategy pattern implementation for test file parsing.
|
Package strategies provides the strategy pattern implementation for test file parsing. |