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

fix: improved type similarity detection logic. #2231

Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
8604f2b
- added support for both input and union types.
laststylebender14 Jun 18, 2024
f5f30cc
- added snaps.
laststylebender14 Jun 18, 2024
161a15c
- added union_types method to config.
laststylebender14 Jun 18, 2024
171e317
- explore union or input fields in config only when there are such ty…
laststylebender14 Jun 18, 2024
0ca85ca
- lint changes.
laststylebender14 Jun 18, 2024
69dc948
- fix typo.
laststylebender14 Jun 18, 2024
cfec67b
- added comparable_types utility module.
laststylebender14 Jun 18, 2024
e59706d
- lint changes.
laststylebender14 Jun 18, 2024
0437659
- add config to fixtures and use it in tests.
laststylebender14 Jun 18, 2024
193d949
- fixed too many args issue.
laststylebender14 Jun 18, 2024
5a3d3d6
- refactor if condition.
laststylebender14 Jun 18, 2024
cc13e2e
- added test for union_type.
laststylebender14 Jun 18, 2024
b6e80d3
- improved configs.
laststylebender14 Jun 18, 2024
e7e7657
- consider field is same if it's output type and list matches.
laststylebender14 Jun 19, 2024
e45127a
- added comments and handled edge.
laststylebender14 Jun 19, 2024
44a8b3e
- added test case for list edge case.
laststylebender14 Jun 19, 2024
7492772
- handle required fields correctly.
laststylebender14 Jun 19, 2024
fbaccd5
- fixed typos in comments.
laststylebender14 Jun 19, 2024
7cb9d5f
- fail the merging process when we find field like. c: Int and c: [Int]
laststylebender14 Jun 20, 2024
5dcf970
- fix test cases.
laststylebender14 Jun 20, 2024
0274bb4
- adopt new api of Similarity.
laststylebender14 Jun 20, 2024
e0e492c
- updated test cases.
laststylebender14 Jun 20, 2024
f5c989a
- fix scalar comparision logic, if scalar type isn't same then fail m…
laststylebender14 Jun 20, 2024
a61eef5
- lint changes.
laststylebender14 Jun 20, 2024
cee8896
- added test to test out same field name but with different scalar ty…
laststylebender14 Jun 20, 2024
d081f73
- removed not required test cases.
laststylebender14 Jun 20, 2024
fd10170
- updated snap.
laststylebender14 Jun 20, 2024
78caa21
- removed err logging
laststylebender14 Jun 20, 2024
8c07347
chore(deps): update dependency miniflare to v3.20240610.1
renovate[bot] Jun 18, 2024
8ce8411
chore(deps): update rust crate url to v2.5.2
renovate[bot] Jun 18, 2024
ba82ce4
chore(deps): update dependency wrangler to v3.61.0
renovate[bot] Jun 19, 2024
f4786f9
chore(deps): update docker/build-push-action action to v6 (#2217)
renovate[bot] Jun 19, 2024
35a1fa2
chore(deps-dev): bump braces from 3.0.2 to 3.0.3 in /tailcall-cloudfl…
dependabot[bot] Jun 19, 2024
0f546cc
fix: query generation (#2229)
amitksingh1490 Jun 19, 2024
e1731d7
chore(deps): update dependency @cloudflare/workers-types to v4.202406…
renovate[bot] Jun 20, 2024
508075a
fix(deps): update rust crate proc-macro2 to v1.0.86
renovate[bot] Jun 21, 2024
b6ac53e
Merge branch 'bug/handle-merging-of-input-types' into bug/handle-requ…
laststylebender14 Jun 21, 2024
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
21 changes: 21 additions & 0 deletions src/core/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,14 @@ impl Config {
})
}

/// finds the all types which are present in union.
pub fn union_types(&self) -> HashSet<String> {
self.unions
.values()
.flat_map(|union| union.types.iter().cloned())
.collect()
}

/// Returns a list of all the types that are used as output types
pub fn output_types(&self) -> HashSet<String> {
let mut types = HashSet::new();
Expand Down Expand Up @@ -980,4 +988,17 @@ mod tests {
assert!(!config.is_root_operation_type("Mutation"));
assert!(!config.is_root_operation_type("Subscription"));
}

#[test]
fn test_union_types() {
let sdl = std::fs::read_to_string(tailcall_fixtures::configs::UNION_CONFIG).unwrap();
let config = Config::from_sdl(&sdl).to_result().unwrap();
let union_types = config.union_types();
let expected_union_types: HashSet<String> = ["Bar", "Baz", "Foo"]
.iter()
.cloned()
.map(String::from)
.collect();
assert_eq!(union_types, expected_union_types);
}
}
183 changes: 183 additions & 0 deletions src/core/config/transformer/type_merger/comparable_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
use std::collections::HashSet;

/// a utility module that facilitates the comparison of two types. It determines
/// whether two types are comparable and checks if they belong to certain
/// categories.
pub struct ComparableTypes {
input_types: HashSet<String>,
union_types: HashSet<String>,
}

impl ComparableTypes {
pub fn new(input_types: HashSet<String>, union_types: HashSet<String>) -> Self {
Self { input_types, union_types }
}

/// checks if the given type is an object type.
fn is_object_type(&self, type_: &str) -> bool {
!self.is_input_type(type_) && !self.is_union_type(type_)
}

/// checks if the given type is an input type.
fn is_input_type(&self, type_: &str) -> bool {
self.input_types.contains(type_)
}

/// checks if the given type is a union type.
fn is_union_type(&self, type_: &str) -> bool {
self.union_types.contains(type_)
}

/// determines whether both type names represent input types.
fn are_input_type(&self, type_1: &str, type_2: &str) -> bool {
self.is_input_type(type_1) && self.is_input_type(type_2)
}

/// determines whether both type names represent union types.
fn are_union_type(&self, type_1: &str, type_2: &str) -> bool {
self.is_union_type(type_1) && self.is_union_type(type_2)
}

/// returns the threshold required to calculate the similarity between two
/// types.
///
/// If both types are input types or union types, the threshold is set to
/// 1.0, indicating that they must match completely. Otherwise, the
/// provided `threshold` value is returned.
pub fn get_threshold(&self, type_1: &str, type_2: &str, threshold: f32) -> f32 {
if self.are_input_type(type_1, type_2) || self.are_union_type(type_1, type_2) {
// if the type is input or union then they're similar only when they've exact
// same fields.
1.0
} else {
threshold
}
}

/// determines whether two type names are comparable.
///
/// types are comparable if they are both input types, both union types, or
/// neither. input types can only be compared with input types, union
/// types with union types, and object type with object type.
pub fn comparable(&self, type_1: &str, type_2: &str) -> bool {
self.are_input_type(type_1, type_2)
|| self.are_union_type(type_1, type_2)
|| self.is_object_type(type_1) && self.is_object_type(type_2)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_is_input_type() {
let input_types: HashSet<String> = ["InputType1", "InputType2"]
.iter()
.map(|s| s.to_string())
.collect();
let union_types: HashSet<String> = ["UnionType1", "UnionType2"]
.iter()
.map(|s| s.to_string())
.collect();
let comparable_types = ComparableTypes::new(input_types, union_types);

assert!(comparable_types.is_input_type("InputType1"));
assert!(!comparable_types.is_input_type("UnionType1"));
}

#[test]
fn test_is_union_type() {
let input_types: HashSet<String> = ["InputType1", "InputType2"]
.iter()
.map(|s| s.to_string())
.collect();
let union_types: HashSet<String> = ["UnionType1", "UnionType2"]
.iter()
.map(|s| s.to_string())
.collect();
let comparable_types = ComparableTypes::new(input_types, union_types);

assert!(comparable_types.is_union_type("UnionType1"));
assert!(!comparable_types.is_union_type("InputType1"));
}

#[test]
fn test_are_input_type() {
let input_types: HashSet<String> = ["InputType1", "InputType2"]
.iter()
.map(|s| s.to_string())
.collect();
let union_types: HashSet<String> = ["UnionType1", "UnionType2"]
.iter()
.map(|s| s.to_string())
.collect();
let comparable_types = ComparableTypes::new(input_types, union_types);

assert!(comparable_types.are_input_type("InputType1", "InputType2"));
assert!(!comparable_types.are_input_type("InputType1", "UnionType1"));
}

#[test]
fn test_are_union_type() {
let input_types: HashSet<String> = ["InputType1", "InputType2"]
.iter()
.map(|s| s.to_string())
.collect();
let union_types: HashSet<String> = ["UnionType1", "UnionType2"]
.iter()
.map(|s| s.to_string())
.collect();
let comparable_types = ComparableTypes::new(input_types, union_types);

assert!(comparable_types.are_union_type("UnionType1", "UnionType2"));
assert!(!comparable_types.are_union_type("UnionType1", "InputType1"));
}

#[test]
fn test_get_threshold() {
let input_types: HashSet<String> = ["InputType1", "InputType2"]
.iter()
.map(|s| s.to_string())
.collect();
let union_types: HashSet<String> = ["UnionType1", "UnionType2"]
.iter()
.map(|s| s.to_string())
.collect();
let comparable_types = ComparableTypes::new(input_types, union_types);

assert_eq!(
comparable_types.get_threshold("InputType1", "InputType2", 0.5),
1.0
);
assert_eq!(
comparable_types.get_threshold("UnionType1", "UnionType2", 0.5),
1.0
);
assert_eq!(
comparable_types.get_threshold("InputType1", "UnionType1", 0.5),
0.5
);
}

#[test]
fn test_comparable() {
let input_types: HashSet<String> = ["InputType1", "InputType2"]
.iter()
.map(|s| s.to_string())
.collect();
let union_types: HashSet<String> = ["UnionType1", "UnionType2"]
.iter()
.map(|s| s.to_string())
.collect();
let comparable_types = ComparableTypes::new(input_types, union_types);

assert!(comparable_types.comparable("InputType1", "InputType2"));
assert!(comparable_types.comparable("UnionType1", "UnionType2"));
assert!(comparable_types.comparable("ObjectType1", "ObjectType2"));

assert!(!comparable_types.comparable("InputType1", "UnionType1"));
assert!(!comparable_types.comparable("InputType1", "ObjectType1"));
assert!(!comparable_types.comparable("ObjectType1", "UnionType1"));
}
}
1 change: 1 addition & 0 deletions src/core/config/transformer/type_merger/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod comparable_type;
mod pair_map;
mod pair_set;
mod similarity;
Expand Down
Loading