Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

introduced a simple query extraction mechanism for single-file multi … #458

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions graphql_client_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,12 @@ pub fn generate_module_token_stream(
}
};

let query_strings = extract_queries(query_string.as_str(), query.get_query_string_positions());
// The generated modules.
let mut modules = Vec::with_capacity(operations.len());

for operation in &operations {
for (index, operation) in operations.iter().enumerate() {
let generated = generated_module::GeneratedModule {
query_string: query_string.as_str(),
query_string: query_strings[index],
schema: &schema,
resolved_query: &query,
operation: &operation.1.name,
Expand All @@ -145,6 +145,42 @@ pub fn generate_module_token_stream(
Ok(modules)
}

/// extracts single query strings from the larger query string using positions which are assumed to be present
fn extract_queries<'a>(
query_string: &'a str,
positions: &[query::QueryStringPosition],
) -> Vec<&'a str> {
positions
.iter()
.map(|position| {
let start_pos = &position.start.unwrap();
let start_idx = get_string_index(query_string, start_pos.line, start_pos.column);

let end_idx = match &position.end {
Some(end_pos) => get_string_index(query_string, end_pos.line, end_pos.column),
None => query_string.len(),
};

&query_string[start_idx..end_idx]
})
.collect()
}
/// helper function for extract_queries
fn get_string_index(s: &str, line: usize, column: usize) -> usize {
let mut current_line = 1;

for (i, c) in s.char_indices() {
if current_line == line {
return i + column - 1;
}
if c == '\n' {
current_line += 1;
}
}

s.len() // Return the end of the string if the line/column isn't found
}

#[derive(Debug)]
enum ReadFileError {
FileNotFound { path: String, io_error: io::Error },
Expand Down
33 changes: 32 additions & 1 deletion graphql_client_codegen/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ pub(crate) struct ResolvedFragmentId(u32);
#[derive(Debug, Clone, Copy)]
pub(crate) struct VariableId(u32);

#[derive(Debug, Clone, Copy)]
pub(crate) struct QueryStringPosition {
pub(crate) start: Option<graphql_parser::Pos>,
pub(crate) end: Option<graphql_parser::Pos>,
}
pub(crate) fn resolve<'doc, T>(
schema: &Schema,
query: &graphql_parser::query::Document<'doc, T>,
Expand Down Expand Up @@ -97,7 +102,7 @@ where
},
)?
}

resolved_query.post_process_query_string_positions();
Ok(resolved_query)
}

Expand Down Expand Up @@ -465,6 +470,10 @@ where
SelectionParent::Operation(id),
schema,
)?;
query.query_string_positions.push(QueryStringPosition {
start: Some(m.position),
end: None,
});
}
graphql_parser::query::OperationDefinition::Query(q) => {
let on = schema.get_object(schema.query_type());
Expand All @@ -480,6 +489,10 @@ where
SelectionParent::Operation(id),
schema,
)?;
query.query_string_positions.push(QueryStringPosition {
start: Some(q.position),
end: None,
});
}
graphql_parser::query::OperationDefinition::Subscription(s) => {
let on = schema.subscription_type().ok_or_else(|| QueryValidationError::new("Query contains a subscription operation, but the schema has no subscription type.".into()))?;
Expand All @@ -496,6 +509,10 @@ where
SelectionParent::Operation(id),
schema,
)?;
query.query_string_positions.push(QueryStringPosition {
start: Some(s.position),
end: None,
});
}
graphql_parser::query::OperationDefinition::SelectionSet(_) => {
unreachable!("unnamed queries are not supported")
Expand All @@ -512,6 +529,7 @@ pub(crate) struct Query {
selection_parent_idx: BTreeMap<SelectionId, SelectionParent>,
selections: Vec<Selection>,
variables: Vec<ResolvedVariable>,
query_string_positions: Vec<QueryStringPosition>,
}

impl Query {
Expand Down Expand Up @@ -586,6 +604,19 @@ impl Query {
.iter()
.map(move |id| (*id, self.get_selection(*id)))
}

fn post_process_query_string_positions(&mut self) {
// Only multiple operations require post processing
if self.query_string_positions.len() > 1 {
// The last query is skipped on purpose
for i in 0..self.query_string_positions.len() - 1 {
self.query_string_positions[i].end = self.query_string_positions[i + 1].start;
}
}
}
pub fn get_query_string_positions(&self) -> &Vec<QueryStringPosition> {
&self.query_string_positions
}
}

#[derive(Debug)]
Expand Down