| Crates.io | octofhir-fhirpath-analyzer |
| lib.rs | octofhir-fhirpath-analyzer |
| version | 0.4.21 |
| created_at | 2025-08-20 11:58:37.79404+00 |
| updated_at | 2025-08-29 00:50:56.243025+00 |
| description | FHIRPath static analysis and type-enriched AST engine with semantic validation |
| homepage | https://github.com/octofhir/fhirpath-rs |
| repository | https://github.com/octofhir/fhirpath-rs |
| max_upload_size | |
| id | 1803290 |
| size | 364,189 |
A high-performance, specification-compliant static analysis engine for FHIRPath expressions.
use octofhir_fhirpath_analyzer::{FhirPathAnalyzer};
use octofhir_fhirpath_model::mock_provider::MockModelProvider;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create analyzer with ModelProvider
let provider = Arc::new(MockModelProvider::new());
let analyzer = FhirPathAnalyzer::new(provider);
// Analyze FHIRPath expression
let result = analyzer.analyze("Patient.name.given").await?;
// Inspect analysis results
println!("Type annotations: {}", result.type_annotations.len());
println!("Validation errors: {}", result.validation_errors.len());
println!("Function calls: {}", result.function_calls.len());
Ok(())
}
use octofhir_fhirpath::FhirPathEngine;
use octofhir_fhirpath_model::mock_provider::MockModelProvider;
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create engine with model provider
let provider = Box::new(MockModelProvider::new());
let mut engine = FhirPathEngine::with_model_provider(provider);
let patient = json!({"resourceType": "Patient", "name": [{"given": ["John"]}]});
// Regular evaluation
let result = engine.evaluate("Patient.name.given", patient).await?;
println!("Result: {:?}", result);
Ok(())
}
The analyzer uses an external mapping approach to provide rich analysis without modifying the existing AST:
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β Expression βββββΆβ Parser (AST) βββββΆβ Analyzer β
β "Patient.name"β β ExpressionNode β β + Semantic β
βββββββββββββββββββ ββββββββββββββββββββ β Mapping β
βββββββββββββββββββ
β
βββββββββββββββββββ
β Analysis Result β
β β’ Type Info β
β β’ Validation β
β β’ Suggestions β
βββββββββββββββββββ
use octofhir_fhirpath_analyzer::FhirPathAnalyzer;
use octofhir_fhirpath_registry::create_standard_registry;
use octofhir_fhirpath_model::mock_provider::MockModelProvider;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let provider = Arc::new(MockModelProvider::new());
let registry = Arc::new(create_standard_registry().await?);
let analyzer = FhirPathAnalyzer::with_function_registry(provider, registry);
// Validates function signatures
let result = analyzer.analyze("substring('hello', 1, 3)").await?;
// Check for validation errors
for error in result.validation_errors {
println!("Error: {}", error.message);
println!("Suggestions: {:?}", error.suggestions);
}
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let provider = Arc::new(MockModelProvider::new());
let analyzer = FhirPathAnalyzer::new(provider);
// Analyzes union types from children() function
let result = analyzer.analyze("Patient.children().ofType(HumanName)").await?;
// Check for union type analysis
if !result.union_types.is_empty() {
println!("Found union types from children() analysis");
for (node_id, union_info) in result.union_types {
println!("Node {}: {} types, collection: {}",
node_id,
union_info.constituent_types.len(),
union_info.is_collection
);
}
}
// Provides suggestions for invalid type operations
for error in result.validation_errors {
println!("Error: {}", error.message);
if !error.suggestions.is_empty() {
println!("Suggestions: {}", error.suggestions.join(", "));
}
}
Ok(())
}
use octofhir_fhirpath_analyzer::{AnalyzerConfig, AnalysisSettings};
let config = AnalyzerConfig {
settings: AnalysisSettings {
enable_type_inference: true,
enable_function_validation: true,
enable_union_analysis: false, // Disable for performance
max_analysis_depth: 50,
},
cache_size: 5000,
enable_profiling: true,
};
let analyzer = FhirPathAnalyzer::with_config(provider, config);
The analyzer integrates with the FHIRPath CLI tools:
# Analyze expression
just cli-evaluate "Patient.name.given"
# Parse and validate expression
cargo run --bin octofhir-fhirpath -- parse "Patient.children().ofType(HumanName)"
# Get help
cargo run --bin octofhir-fhirpath -- --help
The analyzer provides detailed error messages with suggestions:
β Validation Error: Function 'children' expects 0 parameters, got 1
Suggestions: children() takes no arguments
β Validation Error: Type 'InvalidType' is not a valid child type for ofType operation on children()
Suggestions: HumanName, Identifier, ContactPoint, Address, CodeableConcept
The analyzer is designed for zero-impact integration:
Supports FHIRPath specification features:
See the examples/ directory for comprehensive usage examples:
basic_analysis.rs - Type inference and basic validationfunction_validation.rs - Function signature validationchildren_analysis.rs - Children function and union type analysisRun examples with:
cargo run --example basic_analysis
cargo run --example function_validation
cargo run --example children_analysis
See CONTRIBUTING.md for development setup and guidelines.
Licensed under MIT OR Apache-2.0.