-
Notifications
You must be signed in to change notification settings - Fork 46
Open
Labels
apollo-parserbugSomething isn't workingSomething isn't workinggood first issueGood for newcomersGood for newcomers
Description
Edit after investigation:
Example:
let input = ""; // The empty string
apollo_compiler::ast::Document::parse(input, "example.graphql").unwrap();
called `Result::unwrap()` on an `Err` value: Error: syntax error: Unexpected <EOF>.
The empty document being invalid is correct per spec, though it could be more user-friendly to return an empty document in this case. But if we do return an error, its string formatting should include a source location. For comparison:
let input = " "; // A single space
apollo_compiler::ast::Document::parse(input, "example.graphql").unwrap();
called `Result::unwrap()` on an `Err` value: Error: syntax error: Unexpected <EOF>.
╭─[ example.graphql:1:2 ]
│
1 │
│ │
│ ╰─ Unexpected <EOF>.
───╯
The underlying bug is in apollo-parser:
let input = ""; // The empty string
dbg!(apollo_parser::Parser::new(input).parse().errors().next().unwrap().index());
The error index is 1 which it out of bounds. It should be 0 instead. When apollo-compiler formats a diagnostic, Ariadne ignores locations that are out of bound.
Original report
Description
In SchemaBuilder#built_in() we have the following
let input = include_str!("../built_in_types.graphql").to_owned();
let path = "built_in.graphql";
let id = FileId::BUILT_IN;
let ast = ast::Document::parser().parse_ast_inner(input, path, id, &mut builder.errors);
// ..
builder.add_ast_document(&ast, executable_definitions_are_errors);
However, path
is incorrect.
This results in an error when we add additional documents to the schema_builder. Like for example,
ast::Document::parser().parse_into_schema_builder(&schema_content, file_path.to_string_lossy().as_ref(), &mut schema_builder);
Steps to reproduce
use apollo_compiler::schema::SchemaBuilder;
use clap::Parser as ClapParser;
use std::fs;
use std::ops::Index;
use std::path::{Path, PathBuf};
use apollo_compiler::ast;
#[derive(ClapParser)]
#[command(author, version, about, long_about = None)]
struct Cli {
/// Directory containing *.graphqls files
#[arg(short = 'd', long)]
schema_path: PathBuf,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
// get schema files from directory
let schema_files = if cli.schema_path.is_dir() {
collect_schema_files_from_directory(&cli.schema_path)?
} else {
return Err(format!("{} is not a directory", &cli.schema_path.display()).into());
};
let file_count = schema_files.len();
if file_count == 0 {
return Err("No schema files found".into());
}
// Create a schema builder to merge schemas
let mut schema_builder = SchemaBuilder::new();
// Read and merge all schema files
for file_path in &schema_files {
println!("Reading schema from: {}", file_path.display());
let schema_content = fs::read_to_string(file_path)?;
// Add to schema builder
ast::Document::parser().parse_into_schema_builder(&schema_content, file_path.to_string_lossy().as_ref(), &mut schema_builder);
}
// Build the final merged schema
let merged_schema = schema_builder.build();
// Check for validation errors
match merged_schema {
Ok(_) => {
println!("Successfully validated and merged {} schema files",
file_count);
// Convert the merged schema to SDL (String)
let merged_schema_sdl = merged_schema.unwrap().to_string();
println!("Merged schema:");
println!("{}", merged_schema_sdl);
},
Err(errors) => {
println!("Schema validation errors:");
for (index, error) in errors.errors.iter().enumerate() {
println!("{}: {}", error.sources.index(index).path().display(), error);
}
return Err("Schema validation failed".into());
}
}
Ok(())
}
/// Collect all *.graphqls files from a directory
fn collect_schema_files_from_directory(dir: &Path) -> Result<Vec<PathBuf>, Box<dyn std::error::Error>> {
// Check if composite-schema.graphqls exists
let composite_path = dir.join("composite-schema.graphqls");
if composite_path.exists() {
println!("Found composite schema file, using only this file");
return Ok(vec![composite_path]);
}
// Otherwise collect all *.graphqls files
let mut schema_files = Vec::new();
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_file() {
if let Some(extension) = path.extension() {
if extension == "graphqls" {
schema_files.push(path);
}
}
}
}
if schema_files.is_empty() {
println!("No *.graphqls files found in directory: {}", dir.display());
} else {
println!("Found {} schema files in directory", schema_files.len());
}
Ok(schema_files)
}
Expected result
A schema definition string in output
Actual result
Schema validation errors:
built_in.graphql: Error: syntax error: Unexpected <EOF>.
Environment
- Operating system and version: Mac OSX Sequoia 15.3.1
- Shell (bash/zsh/powershell): zsh
apollo-rs
crate: apollo_compiler- Crate version: 1.27.0
Metadata
Metadata
Assignees
Labels
apollo-parserbugSomething isn't workingSomething isn't workinggood first issueGood for newcomersGood for newcomers