Skip to content

Commit

Permalink
Fixed a few bugs in the generator (#787)
Browse files Browse the repository at this point in the history
Fixes #785 
Fixes #786
  • Loading branch information
obmarg authored Oct 1, 2023
1 parent 63b105d commit ec288e4
Show file tree
Hide file tree
Showing 15 changed files with 35,081 additions and 13,067 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html

- Using `#[cynic(spread)]` more than once no longer results in rust compile
errors.
- The generator won't output an incorrect comma in between attributes in
certain circumstances.
- The generator now uses the same re-casing as codegen - leading to less bugs.
- The generator will now rename more QueryFragment fields that require it.

## v3.2.2 - 2023-06-26

Expand Down
2 changes: 2 additions & 0 deletions cynic-codegen/src/idents/old_ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub fn to_pascal_case(s: &str) -> String {
prev_is_upper = true;
} else if c == '_' {
prev_is_underscore = true;
prev_is_upper = false;
} else {
if prev_is_upper {
buf.extend(c.to_lowercase())
Expand Down Expand Up @@ -177,6 +178,7 @@ mod tests {
assert_eq!(to_pascal_case("_another_one"), "_anotherOne");
assert_eq!(to_pascal_case("RepeatedUPPERCASE"), "RepeatedUppercase");
assert_eq!(to_pascal_case("UUID"), "Uuid");
assert_eq!(to_pascal_case("CREATED_AT"), "CreatedAt");
assert_eq!(to_pascal_case("__typename"), "__typename");
}

Expand Down
68 changes: 64 additions & 4 deletions cynic-querygen/src/casings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,73 @@ impl CasingExt for &str {
}

fn to_camel_case(&self) -> String {
// Might be nice to not use inflector for this but cba writing it just now
inflector::cases::camelcase::to_camel_case(self)
let s = self.to_pascal_case();

let mut buf = String::with_capacity(s.len());
let mut chars = s.chars();

if let Some(first_char) = chars.next() {
buf.extend(first_char.to_lowercase());
}

buf.extend(chars);

buf
}

fn to_pascal_case(&self) -> std::string::String {
// Might be nice to not use inflector for this but cba writing it just now
inflector::cases::pascalcase::to_pascal_case(self)
let mut buf = String::with_capacity(self.len());
let mut first_char = true;
let mut prev_is_upper = false;
let mut prev_is_underscore = false;
let mut chars = self.chars().peekable();
loop {
let c = chars.next();
if c.is_none() {
break;
}
let c = c.unwrap();
if first_char {
if c == '_' {
// keep leading underscores
buf.push('_');
while let Some('_') = chars.peek() {
buf.push(chars.next().unwrap());
}
} else if c.is_uppercase() {
prev_is_upper = true;
buf.push(c);
} else {
buf.extend(c.to_uppercase());
}
first_char = false;
continue;
}

if c.is_uppercase() {
if prev_is_upper {
buf.extend(c.to_lowercase());
} else {
buf.push(c);
}
prev_is_upper = true;
} else if c == '_' {
prev_is_underscore = true;
prev_is_upper = false;
} else {
if prev_is_upper {
buf.extend(c.to_lowercase())
} else if prev_is_underscore {
buf.extend(c.to_uppercase());
} else {
buf.push(c);
}
prev_is_upper = false;
prev_is_underscore = false;
}
}

buf
}
}

Expand Down
3 changes: 0 additions & 3 deletions cynic-querygen/src/output/inline_fragments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ impl std::fmt::Display for InlineFragments {
}

if let Some(name) = &self.variable_struct_name {
if self.target_type != self.name {
write!(f, ", ")?;
}
attributes.push(format!("variables = \"{name}\""));
}

Expand Down
6 changes: 5 additions & 1 deletion cynic-querygen/src/query_parsing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub use normalisation::Variable;
pub use value::{LiteralContext, TypedValue};

use crate::{
casings::CasingExt,
naming::Namer,
output::{self, Output},
Error, TypeIndex,
Expand Down Expand Up @@ -109,7 +110,10 @@ fn make_query_fragment<'text>(

OutputField {
name: field.alias.unwrap_or(schema_field.name),
rename: field.alias.map(|_| schema_field.name),
rename: field.alias.map(|_| schema_field.name).or_else(|| {
(schema_field.name.to_snake_case().to_camel_case() != schema_field.name)
.then_some(schema_field.name)
}),
field_type: RustOutputFieldType::from_schema_type(
&schema_field.value_type,
type_name_override,
Expand Down
6 changes: 6 additions & 0 deletions cynic-querygen/tests/github-tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,11 @@ test_query!(
inline_fragment_with_arguments,
"inline-fragment-with-arguments.graphql"
);
test_query!(
inline_fragment_with_renames,
"inline-fragment-with-renames.graphql"
);
test_query!(field_on_interface, "field-on-interface.graphql");
test_query!(queries_with_typename, "queries-with-typename.graphql");

test_query!(issue_786, "issue-786.graphql");
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
query RepoIssues($first: Int!) {
repository(owner: "obmarg", name: "cynic") {
one: issueOrPullRequest(number: 100) {
... on Issue {
body
assignees(first: $first) {
totalCount
}
}
... on PullRequest {
body
assignees(first: $first) {
totalCount
}
}
}
two: issueOrPullRequest(number: 200) {
... on Issue {
closed
assignees(first: $first) {
totalCount
}
}
... on PullRequest {
changedFiles
assignees(first: $first) {
totalCount
}
}
}
}
}
45 changes: 45 additions & 0 deletions cynic-querygen/tests/queries/github/issue-786.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
query ProjectMetadataQuery($id: ID!, $after: String) {
node(id: $id) {
... on ProjectV2 {
id
title
number
public
readme
shortDescription
url
fields(first: 100) {
totalCount
pageInfo {
hasNextPage
endCursor
hasPreviousPage
startCursor
}
nodes {
... on ProjectV2SingleSelectField {
name
dataType
options {
id
name
nameHTML
}
}
... on ProjectV2Field {
name
dataType
}
... on ProjectV2IterationField {
name
dataType
configuration {
duration
startDay
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
source: cynic-querygen/tests/github-tests.rs
expression: "document_to_fragment_structs(query, schema,\n &QueryGenOptions::default()).expect(\"QueryGen Failed\")"
---
#[derive(cynic::QueryVariables, Debug)]
pub struct RepoIssuesVariables {
pub first: i32,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Query", variables = "RepoIssuesVariables")]
pub struct RepoIssues {
#[arguments(owner: "obmarg", name: "cynic")]
pub repository: Option<Repository>,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(variables = "RepoIssuesVariables")]
pub struct Repository {
#[arguments(number: 100)]
#[cynic(rename = "issueOrPullRequest")]
pub one: Option<IssueOrPullRequest>,
#[arguments(number: 200)]
#[cynic(rename = "issueOrPullRequest")]
pub two: Option<IssueOrPullRequest2>,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(variables = "RepoIssuesVariables")]
pub struct PullRequest {
pub changed_files: i32,
#[arguments(first: $first)]
pub assignees: UserConnection,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "PullRequest", variables = "RepoIssuesVariables")]
pub struct PullRequest2 {
pub body: String,
#[arguments(first: $first)]
pub assignees: UserConnection,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(variables = "RepoIssuesVariables")]
pub struct Issue {
pub closed: bool,
#[arguments(first: $first)]
pub assignees: UserConnection,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Issue", variables = "RepoIssuesVariables")]
pub struct Issue2 {
pub body: String,
#[arguments(first: $first)]
pub assignees: UserConnection,
}

#[derive(cynic::QueryFragment, Debug)]
pub struct UserConnection {
pub total_count: i32,
}

#[derive(cynic::InlineFragments, Debug)]
#[cynic(variables = "RepoIssuesVariables")]
pub enum IssueOrPullRequest {
Issue2(Issue2),
PullRequest2(PullRequest2),
#[cynic(fallback)]
Unknown
}

#[derive(cynic::InlineFragments, Debug)]
#[cynic(graphql_type = "IssueOrPullRequest", variables = "RepoIssuesVariables")]
pub enum IssueOrPullRequest2 {
Issue(Issue),
PullRequest(PullRequest),
#[cynic(fallback)]
Unknown
}


Loading

0 comments on commit ec288e4

Please sign in to comment.