1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use crate::ast::ext::{
    ImplementingInterfaceExtension, PossibleTypesExtension, TypeDefinitionExtension,
};
use crate::static_graphql::schema::{self, TypeDefinition};

use super::TypeInfoRegistry;

pub struct DefaultVisitorContext;

pub fn find_schema_definition(schema: &schema::Document) -> Option<&schema::SchemaDefinition> {
    schema
        .definitions
        .iter()
        .find_map(|definition| match definition {
            schema::Definition::SchemaDefinition(schema_definition) => Some(schema_definition),
            _ => None,
        })
}

/**
 * Extracts nested NamedType from a potentially recursive wrapped definition.
 *
 * Example: Returns String from [String] or String!
 */
pub fn get_named_type(t: &schema::Type) -> String {
    match t {
        schema::Type::NamedType(name) => name.clone(),
        schema::Type::ListType(inner_type) => get_named_type(inner_type),
        schema::Type::NonNullType(inner_type) => get_named_type(inner_type),
    }
}

/**
 * Provided two composite types, determine if they "overlap". Two composite
 * types overlap when the Sets of possible concrete types for each intersect.
 *
 * This is often used to determine if a fragment of a given type could possibly
 * be visited in a context of another type.
 *
 * This function is commutative.
 */
pub fn do_types_overlap(
    type_info_registry: &TypeInfoRegistry,
    t1: &schema::TypeDefinition,
    t2: &schema::TypeDefinition,
) -> bool {
    if t1.name().eq(&t2.name()) {
        return true;
    }

    if t1.is_abstract_type() {
        if t2.is_abstract_type() {
            let possible_types = t1.possible_types(type_info_registry);

            return possible_types
                .into_iter()
                .filter(|possible_type| {
                    t2.has_sub_type(&TypeDefinition::Object(possible_type.clone()))
                })
                .count()
                > 0;
        }

        return t1.has_sub_type(t2);
    }

    if t2.is_abstract_type() {
        return t2.has_sub_type(t1);
    }

    false
}