From 15c2715fc203317018390f7ecafe52ce0cbc79cb Mon Sep 17 00:00:00 2001 From: Andrey Lunyov Date: Tue, 29 Aug 2023 10:03:01 -0700 Subject: [PATCH] Fix compiler issue with stale artifacts for Resolvers in watch mode (#4415) Summary: The Issue: When running the compiler in watch mode, the compiler may produce artifacts for relay resolvers. For example: ``` /** RelayResolver MyType */ ``` This code would create fragments for the model resolver, including an identifier, a model instance fragment, etc. However, a problem arises in watch mode when we rename the type to: ``` /** RelayResolver MyNewType */ ``` In this case, the old artifacts are not automatically deleted. The issue lies in the compiler's inability to establish a connection between the resolver definition code and the artifacts it produces. To resolve this, we need to establish that connection. The solution: The relationship between the source documents (fragments, queries, and now resolvers) and the generated artifacts is represented in the artifact_map. In this map, the key corresponds to the document's name (fragment or query), and the value is a list of the generated artifacts. For resolvers, we will use the resolver's hash (MD5 of the source) as the key in the map, and the associated value will be the list of generated artifacts. The solution involves passing this hash to the artifact generation *place* and ensuring the proper handling of the removal of outdated artifacts. Pull Request resolved: https://github.com/facebook/relay/pull/4415 Test Plan: **Watch mode** - Add new resolver /** RelayResolver MyType **/ - New files are created for the resolver (id, model_instance) - Change the name to /** RelayResolver MyNewType **/ - New files are created, files for MyType are deleted. --- **Non-watch Compilation (no saved state)** Run 1: - Add new resolver /** RelayResolver MyType **/ - New files are created for the resolver (id, model_instance) Rename - Change the name to /** RelayResolver MyNewType **/ Run 2: - New files are created, files for MyType are deleted. --- **Non-watch Compilation (with saved-state)** Pre-run: - Add new resolver /** RelayResolver MyType **/ - New files are created for the resolver (id, model_instance) - Commit changes. Run compiler and create saved state: ``` ./scripts/compiler.sh xplat build --export-state=/tmp/compiler-state ``` Run compiler with saved state ``` ./scripts/compiler.sh xplat build --import-state=/tmp/compiler-state ``` - No changes, quick compilation. - Update file: Change the name to /** RelayResolver MyNewType **/ Run compiler with the saved state: Old files deleted, new files created: {F1076577864} --- **Build with saved-state + dirty resolvers artifact** See the same steps for for preparation of the saved-state. Also run: - Update/Remove generated artifact for the Resolver - Run compiler with saved-state - Artifacts are restored to the correct version. Reviewed By: captbaritone Differential Revision: D48588439 Pulled By: alunyov fbshipit-source-id: 72fbebbf79eed0d512d24575601b203c3aee85a1 --- compiler/Cargo.lock | 5 ++ compiler/crates/docblock-shared/Cargo.toml | 3 + compiler/crates/docblock-shared/src/lib.rs | 7 +++ .../src/resolver_source_hash.rs | 37 ++++++++++++ compiler/crates/docblock-syntax/Cargo.toml | 1 + compiler/crates/docblock-syntax/src/ast.rs | 2 + compiler/crates/docblock-syntax/src/lib.rs | 4 ++ .../fixtures/docblock-ends-mid-line.expected | 3 + .../tests/parse/fixtures/empty-block.expected | 3 + .../field-followed-by-free-text.expected | 3 + .../free-text-starting-with-star.expected | 3 + .../parse/fixtures/multiple-fields.expected | 3 + .../parse/fixtures/simple_docblock.expected | 3 + compiler/crates/graphql-ir/src/program.rs | 6 +- compiler/crates/relay-compiler/Cargo.toml | 1 + .../crates/relay-compiler/src/artifact_map.rs | 18 +++++- .../src/build_project/generate_artifacts.rs | 60 ++++++++++++++----- .../relay-compiler/src/build_project/mod.rs | 10 ++-- .../crates/relay-compiler/src/compiler.rs | 57 +++++++++++++++++- .../relay-compiler/src/compiler_state.rs | 10 ++-- .../crates/relay-compiler/src/graphql_asts.rs | 38 +++++++++--- compiler/crates/relay-compiler/src/lib.rs | 1 + .../crates/relay-docblock/src/docblock_ir.rs | 14 +++++ compiler/crates/relay-docblock/src/ir.rs | 45 +++++++++++++- .../src/untyped_representation.rs | 8 ++- ...esolver-deprecated-no-description.expected | 3 + .../relay-resolver-deprecated.expected | 3 + .../fixtures/relay-resolver-live.expected | 3 + .../relay-resolver-named-export.expected | 3 + ...ver-strong-object-with-implements.expected | 3 + .../relay-resolver-strong-object.expected | 3 + .../relay-resolver-with-args.expected | 3 + ...lver-with-field-and-fragment-args.expected | 3 + .../relay-resolver-with-field-args.expected | 3 + .../relay-resolver-with-fragment.expected | 3 + .../relay-resolver-with-output-type.expected | 3 + .../parse/fixtures/relay-resolver.expected | 3 + ...y-resolver-non-nullable-list-item.expected | 3 + .../fixtures/terse-relay-resolver.expected | 3 + .../client-edge-relay-resolver.expected | 2 +- ...olver-with-root-fragment-on-model.expected | 4 +- ...esolver-deprecated-no-description.expected | 2 +- .../relay-resolver-deprecated.expected | 2 +- .../relay-resolver-named-export.expected | 2 +- .../relay-resolver-on-interface.expected | 12 ++-- ...ver-strong-object-with-implements.expected | 2 +- ...g-object-with-multiple-implements.expected | 2 +- .../relay-resolver-strong-object.expected | 2 +- .../relay-resolver-with-args.expected | 2 +- ...lver-with-field-and-fragment-args.expected | 2 +- .../relay-resolver-with-field-args.expected | 2 +- .../relay-resolver-with-output-type.expected | 2 +- .../fixtures/relay-resolver.expected | 2 +- .../terse-relay-resolver-interface.expected | 14 ++--- ...e-relay-resolver-with-output-type.expected | 2 +- ...olver-with-root-fragment-on-model.expected | 4 +- .../fixtures/terse-relay-resolver.expected | 2 +- .../to_schema/fixtures/weak-type.expected | 2 +- .../src/server/lsp_state_resources.rs | 20 +++++-- ...enerate_relay_resolvers_model_fragments.rs | 36 ++++++++++- ...resolvers_operations_for_nested_objects.rs | 15 ++--- compiler/crates/relay-transforms/src/lib.rs | 1 + .../fixtures/output-type-client-type.expected | 8 +-- ...output-type-with-client-interface.expected | 8 +-- ...e-recursion-but-lying-client-type.expected | 8 +-- ...t-type-with-relay-resolver-fields.expected | 8 +-- .../src/__generated__/AppQuery.graphql.js | 27 +++++++-- .../__generated__/Component_node.graphql.js | 27 +++++++-- 68 files changed, 477 insertions(+), 132 deletions(-) create mode 100644 compiler/crates/docblock-shared/src/resolver_source_hash.rs diff --git a/compiler/Cargo.lock b/compiler/Cargo.lock index 1775195a9d403..95dd829edb20c 100644 --- a/compiler/Cargo.lock +++ b/compiler/Cargo.lock @@ -451,8 +451,11 @@ name = "docblock-shared" version = "0.0.0" dependencies = [ "common", + "hex", "intern", "lazy_static", + "md-5", + "serde", ] [[package]] @@ -460,6 +463,7 @@ name = "docblock-syntax" version = "0.0.0" dependencies = [ "common", + "docblock-shared", "fixture-tests", "graphql-test-helpers", "intern", @@ -1645,6 +1649,7 @@ dependencies = [ "common-path", "dashmap", "dependency-analyzer", + "docblock-shared", "docblock-syntax", "dunce", "errors", diff --git a/compiler/crates/docblock-shared/Cargo.toml b/compiler/crates/docblock-shared/Cargo.toml index a61574c2a36a5..6f15d27fb7102 100644 --- a/compiler/crates/docblock-shared/Cargo.toml +++ b/compiler/crates/docblock-shared/Cargo.toml @@ -8,5 +8,8 @@ license = "MIT" [dependencies] common = { path = "../common" } +hex = "0.4.3" intern = { path = "../intern" } lazy_static = "1.4" +md-5 = "0.10" +serde = { version = "1.0.185", features = ["derive", "rc"] } diff --git a/compiler/crates/docblock-shared/src/lib.rs b/compiler/crates/docblock-shared/src/lib.rs index 3adfda188434e..6a7a6e5112fb6 100644 --- a/compiler/crates/docblock-shared/src/lib.rs +++ b/compiler/crates/docblock-shared/src/lib.rs @@ -5,12 +5,15 @@ * LICENSE file in the root directory of this source tree. */ +mod resolver_source_hash; + use common::ArgumentName; use common::DirectiveName; use common::ScalarName; use intern::string_key::Intern; use intern::string_key::StringKey; use lazy_static::lazy_static; +pub use resolver_source_hash::ResolverSourceHash; lazy_static! { pub static ref RELAY_RESOLVER_DIRECTIVE_NAME: DirectiveName = @@ -51,4 +54,8 @@ lazy_static! { // Note: this should **only** be used for resolvers! The id field for server // types is configurable in the config, and thus cannot be hard-coded. pub static ref KEY_RESOLVER_ID_FIELD: StringKey = "id".intern(); + + pub static ref RELAY_RESOLVER_SOURCE_HASH: DirectiveName = DirectiveName("resolver_source_hash".intern()); + pub static ref RELAY_RESOLVER_SOURCE_HASH_VALUE: ArgumentName = ArgumentName("value".intern()); + } diff --git a/compiler/crates/docblock-shared/src/resolver_source_hash.rs b/compiler/crates/docblock-shared/src/resolver_source_hash.rs new file mode 100644 index 0000000000000..af8ea812cd3c1 --- /dev/null +++ b/compiler/crates/docblock-shared/src/resolver_source_hash.rs @@ -0,0 +1,37 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +use intern::string_key::Intern; +use intern::string_key::StringKey; +use md5::Digest; +use md5::Md5; +use serde::Deserialize; +use serde::Serialize; + +#[derive(Serialize, Deserialize, Debug, Clone, Copy, Eq, PartialEq, Hash)] + +pub struct ResolverSourceHash(StringKey); + +impl ResolverSourceHash { + pub fn new(source: &str) -> Self { + Self(md5(source).intern()) + } + + pub fn from_raw(source: StringKey) -> Self { + Self(source) + } + + pub fn value(&self) -> StringKey { + self.0 + } +} + +fn md5(data: &str) -> String { + let mut md5 = Md5::new(); + md5.update(data); + hex::encode(md5.finalize()) +} diff --git a/compiler/crates/docblock-syntax/Cargo.toml b/compiler/crates/docblock-syntax/Cargo.toml index 04f373ecdedc7..496f6fd12274a 100644 --- a/compiler/crates/docblock-syntax/Cargo.toml +++ b/compiler/crates/docblock-syntax/Cargo.toml @@ -12,6 +12,7 @@ path = "tests/parse_test.rs" [dependencies] common = { path = "../common" } +docblock-shared = { path = "../docblock-shared" } intern = { path = "../intern" } serde = { version = "1.0.185", features = ["derive", "rc"] } thiserror = "1.0.43" diff --git a/compiler/crates/docblock-syntax/src/ast.rs b/compiler/crates/docblock-syntax/src/ast.rs index a58437c6fee14..f54066c10f9eb 100644 --- a/compiler/crates/docblock-syntax/src/ast.rs +++ b/compiler/crates/docblock-syntax/src/ast.rs @@ -8,6 +8,7 @@ use common::Location; use common::Named; use common::WithLocation; +use docblock_shared::ResolverSourceHash; use intern::string_key::StringKey; #[derive(Debug, PartialEq)] pub struct DocblockField { @@ -32,6 +33,7 @@ pub enum DocblockSection { pub struct DocblockAST { pub location: Location, pub sections: Vec, + pub source_hash: ResolverSourceHash, } impl DocblockAST { diff --git a/compiler/crates/docblock-syntax/src/lib.rs b/compiler/crates/docblock-syntax/src/lib.rs index bdb96313a9988..5f2014c70e084 100644 --- a/compiler/crates/docblock-syntax/src/lib.rs +++ b/compiler/crates/docblock-syntax/src/lib.rs @@ -21,6 +21,7 @@ use common::SourceLocationKey; use common::Span; use common::TextSource; use common::WithLocation; +use docblock_shared::ResolverSourceHash; use errors::SyntaxError; use intern::string_key::Intern; use intern::string_key::StringKey; @@ -94,6 +95,7 @@ struct DocblockParser<'a> { errors: Vec, in_progress_text: Option, sections: Vec, + source_hash: ResolverSourceHash, } impl<'a> DocblockParser<'a> { @@ -106,6 +108,7 @@ impl<'a> DocblockParser<'a> { chars, in_progress_text: None, sections: Vec::new(), + source_hash: ResolverSourceHash::new(source), } } @@ -146,6 +149,7 @@ impl<'a> DocblockParser<'a> { */ Span::new(start, end - 1), ), + source_hash: self.source_hash, }) } else { Err(self.errors) diff --git a/compiler/crates/docblock-syntax/tests/parse/fixtures/docblock-ends-mid-line.expected b/compiler/crates/docblock-syntax/tests/parse/fixtures/docblock-ends-mid-line.expected index e73216a3e7002..50bb99db38661 100644 --- a/compiler/crates/docblock-syntax/tests/parse/fixtures/docblock-ends-mid-line.expected +++ b/compiler/crates/docblock-syntax/tests/parse/fixtures/docblock-ends-mid-line.expected @@ -12,4 +12,7 @@ DocblockAST { }, ), ], + source_hash: ResolverSourceHash( + "4595a2a06568991a6d7594afbbe370ab", + ), } diff --git a/compiler/crates/docblock-syntax/tests/parse/fixtures/empty-block.expected b/compiler/crates/docblock-syntax/tests/parse/fixtures/empty-block.expected index 219e0bd3ef845..3c58b519fd26c 100644 --- a/compiler/crates/docblock-syntax/tests/parse/fixtures/empty-block.expected +++ b/compiler/crates/docblock-syntax/tests/parse/fixtures/empty-block.expected @@ -5,4 +5,7 @@ DocblockAST { location: empty-block.ecmascript:0:2, sections: [], + source_hash: ResolverSourceHash( + "75966d011d530b35f16483422368e364", + ), } diff --git a/compiler/crates/docblock-syntax/tests/parse/fixtures/field-followed-by-free-text.expected b/compiler/crates/docblock-syntax/tests/parse/fixtures/field-followed-by-free-text.expected index 9299c97617b26..b398ee16afbb1 100644 --- a/compiler/crates/docblock-syntax/tests/parse/fixtures/field-followed-by-free-text.expected +++ b/compiler/crates/docblock-syntax/tests/parse/fixtures/field-followed-by-free-text.expected @@ -23,4 +23,7 @@ DocblockAST { }, ), ], + source_hash: ResolverSourceHash( + "b408df07614b47f8b522bf4e528448d3", + ), } diff --git a/compiler/crates/docblock-syntax/tests/parse/fixtures/free-text-starting-with-star.expected b/compiler/crates/docblock-syntax/tests/parse/fixtures/free-text-starting-with-star.expected index 8a8f02fa565ab..3e0f5e6a1000a 100644 --- a/compiler/crates/docblock-syntax/tests/parse/fixtures/free-text-starting-with-star.expected +++ b/compiler/crates/docblock-syntax/tests/parse/fixtures/free-text-starting-with-star.expected @@ -15,4 +15,7 @@ DocblockAST { }, ), ], + source_hash: ResolverSourceHash( + "a49d092bbb5fbad6582962e62fac5d2c", + ), } diff --git a/compiler/crates/docblock-syntax/tests/parse/fixtures/multiple-fields.expected b/compiler/crates/docblock-syntax/tests/parse/fixtures/multiple-fields.expected index 540aaeb18453d..594d5520be89f 100644 --- a/compiler/crates/docblock-syntax/tests/parse/fixtures/multiple-fields.expected +++ b/compiler/crates/docblock-syntax/tests/parse/fixtures/multiple-fields.expected @@ -36,4 +36,7 @@ DocblockAST { }, ), ], + source_hash: ResolverSourceHash( + "c8f9872da22c679b3a9385d453c2d7d8", + ), } diff --git a/compiler/crates/docblock-syntax/tests/parse/fixtures/simple_docblock.expected b/compiler/crates/docblock-syntax/tests/parse/fixtures/simple_docblock.expected index 4e2abcb1b6aae..c4355642b3b24 100644 --- a/compiler/crates/docblock-syntax/tests/parse/fixtures/simple_docblock.expected +++ b/compiler/crates/docblock-syntax/tests/parse/fixtures/simple_docblock.expected @@ -13,4 +13,7 @@ DocblockAST { }, ), ], + source_hash: ResolverSourceHash( + "39bf0ba989cb8ca55688669aa89f1f43", + ), } diff --git a/compiler/crates/graphql-ir/src/program.rs b/compiler/crates/graphql-ir/src/program.rs index cf266f0971598..eabef2d15185c 100644 --- a/compiler/crates/graphql-ir/src/program.rs +++ b/compiler/crates/graphql-ir/src/program.rs @@ -125,7 +125,7 @@ impl Program { pub fn merge_program( &mut self, other_program: &Self, - removed_definition_names: Option<&[ExecutableDefinitionName]>, + removed_definition_names: Option>, ) { let mut operations: HashMap< OperationDefinitionName, @@ -147,10 +147,10 @@ impl Program { for removed in removed_definition_names { match removed { ExecutableDefinitionName::OperationDefinitionName(name) => { - operations.remove(name); + operations.remove(&name); } ExecutableDefinitionName::FragmentDefinitionName(name) => { - self.fragments.remove(name); + self.fragments.remove(&name); } }; } diff --git a/compiler/crates/relay-compiler/Cargo.toml b/compiler/crates/relay-compiler/Cargo.toml index a64f59a691597..178d603d12b2c 100644 --- a/compiler/crates/relay-compiler/Cargo.toml +++ b/compiler/crates/relay-compiler/Cargo.toml @@ -21,6 +21,7 @@ common = { path = "../common" } common-path = "1.0.0" dashmap = { version = "5.4", features = ["rayon", "serde"] } dependency-analyzer = { path = "../dependency-analyzer" } +docblock-shared = { path = "../docblock-shared" } docblock-syntax = { path = "../docblock-syntax" } dunce = "1.0.2" errors = { path = "../errors" } diff --git a/compiler/crates/relay-compiler/src/artifact_map.rs b/compiler/crates/relay-compiler/src/artifact_map.rs index dfc5732c4348d..e4fca54e31e87 100644 --- a/compiler/crates/relay-compiler/src/artifact_map.rs +++ b/compiler/crates/relay-compiler/src/artifact_map.rs @@ -9,8 +9,10 @@ use std::path::PathBuf; use dashmap::mapref::entry::Entry; use dashmap::DashMap; +use docblock_shared::ResolverSourceHash; use graphql_ir::ExecutableDefinitionName; use relay_codegen::QueryID; +use relay_transforms::ArtifactSourceKeyData; use serde::Deserialize; use serde::Serialize; @@ -25,7 +27,19 @@ pub struct ArtifactRecord { } /// A map from DefinitionName to output artifacts records #[derive(Default, Serialize, Deserialize, Debug, Clone)] -pub struct ArtifactMap(pub DashMap>); +pub struct ArtifactMap(pub DashMap>); + +#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq, Hash)] +pub enum ArtifactSourceKey { + ExecutableDefinition(ExecutableDefinitionName), + ResolverHash(ResolverSourceHash), +} + +impl From for ArtifactSourceKey { + fn from(directive: ArtifactSourceKeyData) -> Self { + ArtifactSourceKey::ResolverHash(directive.0) + } +} impl ArtifactMap { pub fn insert(&self, artifact: Artifact) { @@ -42,7 +56,7 @@ impl ArtifactMap { }, }; - for source_definition_name in artifact.source_definition_names { + for source_definition_name in artifact.artifact_source_keys { match self.0.entry(source_definition_name) { Entry::Occupied(mut entry) => { entry.get_mut().push(artifact_tuple.clone()); diff --git a/compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs b/compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs index 22d202797712d..f14b4a66d7c2a 100644 --- a/compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs +++ b/compiler/crates/relay-compiler/src/build_project/generate_artifacts.rs @@ -11,13 +11,13 @@ use std::sync::Arc; use common::NamedItem; use common::SourceLocationKey; use fnv::FnvHashMap; -use graphql_ir::ExecutableDefinitionName; use graphql_ir::FragmentDefinition; use graphql_ir::OperationDefinition; use graphql_text_printer::OperationPrinter; use graphql_text_printer::PrinterOptions; use intern::string_key::StringKey; use intern::Lookup; +use relay_transforms::ArtifactSourceKeyData; use relay_transforms::ClientEdgeGeneratedQueryMetadataDirective; use relay_transforms::Programs; use relay_transforms::RawResponseGenerationMode; @@ -27,12 +27,15 @@ use relay_transforms::UPDATABLE_DIRECTIVE; pub use super::artifact_content::ArtifactContent; use super::build_ir::SourceHashes; +use crate::artifact_map::ArtifactSourceKey; use crate::config::Config; use crate::config::ProjectConfig; /// Represents a generated output artifact. pub struct Artifact { - pub source_definition_names: Vec, + /// List of source definitions that this artifact is generated from. + /// It may be the name of the query/fragment or relay resolver hash. + pub artifact_source_keys: Vec, pub path: PathBuf, pub content: ArtifactContent, /// The source file responsible for generating this file. @@ -68,8 +71,17 @@ pub fn generate_artifacts( None }; + let artifact_source_keys = if let Some(artifact_source) = ArtifactSourceKeyData::find(&normalization.directives) { + vec![ + ArtifactSourceKey::ResolverHash(artifact_source.0) + ] + } else { + // TODO: refactor `parent_documents` to include ArtifactSource and not ExecutableDefinition + metadata.parent_documents.iter().copied().map(ArtifactSourceKey::ExecutableDefinition).collect() + }; + return Artifact { - source_definition_names: metadata.parent_documents.iter().copied().collect(), + artifact_source_keys, path: project_config .path_for_artifact(source_file, normalization.name.item.0), content: ArtifactContent::SplitOperation { @@ -92,7 +104,7 @@ pub fn generate_artifacts( return generate_normalization_artifact( &mut operation_printer, - source_name.into(), + ArtifactSourceKey::ExecutableDefinition(source_name.into()), project_config, &operations, source_hash, @@ -109,7 +121,7 @@ pub fn generate_artifacts( let source_hash = source_hashes.get(&source_name).cloned().unwrap(); return generate_normalization_artifact( &mut operation_printer, - source_name, + ArtifactSourceKey::ExecutableDefinition(source_name), project_config, &operations, source_hash, @@ -122,7 +134,7 @@ pub fn generate_artifacts( .unwrap(); return generate_normalization_artifact( &mut operation_printer, - normalization.name.item.into(), + ArtifactSourceKey::ExecutableDefinition(normalization.name.item.into()), project_config, &operations, source_hash, @@ -142,7 +154,7 @@ pub fn generate_artifacts( .cloned() .unwrap(); return generate_updatable_query_artifact( - reader.name.item.into(), + ArtifactSourceKey::ExecutableDefinition(reader.name.item.into()), project_config, &operations, source_hash, @@ -160,15 +172,31 @@ pub fn generate_artifacts( } else { reader_fragment.name.item.into() }; - + // If the fragment is generated for the RelayResolver model (id, or model instance) + // we need to update the source definition to include the original text of the resolver. let source_hash = source_hashes.get(&source_name).cloned(); - let source_definition_names = vec![source_name]; + + // We need this `if/else` here because of the way the compiler is handling the aritfacts + // deletion (see commit_project in compiler.rs). + // To remove the artifact, the artifact map should not contain any document/source that may + // generate the artifact. If we merge these sources (fragment name and resolver hash) + // then the removal of the source hash won't trigger the removal of the artifact, because + // there will be anothe key (fragment name) in the artifacts map that will point to the + // same generate artifact. + let artifact_source_keys = if let Some(artifact_source) = ArtifactSourceKeyData::find(&reader_fragment.directives) { + vec![ + ArtifactSourceKey::ResolverHash(artifact_source.0) + ] + } else { + vec![ArtifactSourceKey::ExecutableDefinition(source_name)] + }; + generate_reader_artifact( project_config, programs, reader_fragment, source_hash, - source_definition_names, + artifact_source_keys, ) })) .collect(); @@ -176,7 +204,7 @@ pub fn generate_artifacts( fn generate_normalization_artifact( operation_printer: &mut OperationPrinter<'_>, - source_definition_name: ExecutableDefinitionName, + artifact_source: ArtifactSourceKey, project_config: &ProjectConfig, operations: &OperationGroup<'_>, source_hash: String, @@ -191,7 +219,7 @@ fn generate_normalization_artifact( .expect("Operations must have a normalization entry."); Artifact { - source_definition_names: vec![source_definition_name], + artifact_source_keys: vec![artifact_source], path: project_config.path_for_artifact(source_file, normalization.name.item.0), content: ArtifactContent::Operation { normalization_operation: Arc::clone(normalization), @@ -206,7 +234,7 @@ fn generate_normalization_artifact( } fn generate_updatable_query_artifact( - source_definition_name: ExecutableDefinitionName, + artifact_source: ArtifactSourceKey, project_config: &ProjectConfig, operations: &OperationGroup<'_>, source_hash: String, @@ -217,7 +245,7 @@ fn generate_updatable_query_artifact( .expect("Updatable operations must have a reader entry."); Artifact { - source_definition_names: vec![source_definition_name], + artifact_source_keys: vec![artifact_source], path: project_config.path_for_artifact(source_file, reader.name.item.0), content: ArtifactContent::UpdatableQuery { reader_operation: operations.expect_reader(), @@ -233,7 +261,7 @@ fn generate_reader_artifact( programs: &Programs, reader_fragment: &Arc, source_hash: Option, - source_definition_names: Vec, + artifact_source_keys: Vec, ) -> Artifact { let name = reader_fragment.name.item; let typegen_fragment = programs @@ -241,7 +269,7 @@ fn generate_reader_artifact( .fragment(name) .expect("a type fragment should be generated for this fragment"); Artifact { - source_definition_names, + artifact_source_keys, path: project_config .path_for_artifact(reader_fragment.name.location.source_location(), name.0), content: ArtifactContent::Fragment { diff --git a/compiler/crates/relay-compiler/src/build_project/mod.rs b/compiler/crates/relay-compiler/src/build_project/mod.rs index 01d2354304f5b..4d63e0dcb3469 100644 --- a/compiler/crates/relay-compiler/src/build_project/mod.rs +++ b/compiler/crates/relay-compiler/src/build_project/mod.rs @@ -42,7 +42,6 @@ use fnv::FnvHashSet; pub use generate_artifacts::generate_artifacts; pub use generate_artifacts::Artifact; pub use generate_artifacts::ArtifactContent; -use graphql_ir::ExecutableDefinitionName; use graphql_ir::FragmentDefinitionNameSet; use graphql_ir::Program; use log::debug; @@ -68,6 +67,7 @@ pub use self::project_asts::ProjectAstData; pub use self::project_asts::ProjectAsts; use super::artifact_content; use crate::artifact_map::ArtifactMap; +use crate::artifact_map::ArtifactSourceKey; use crate::compiler_state::ArtifactMapKind; use crate::compiler_state::CompilerState; use crate::compiler_state::ProjectName; @@ -310,8 +310,8 @@ pub async fn commit_project( programs: Programs, mut artifacts: Vec, artifact_map: Arc, - // Definitions that are removed from the previous artifact map - removed_definition_names: Vec, + // Definitions/Sources that are removed from the previous artifact map + removed_artifact_sources: Vec, // Dirty artifacts that should be removed if no longer in the artifacts map mut artifacts_to_remove: DashSet, source_control_update_status: Arc, @@ -404,7 +404,7 @@ pub async fn commit_project( if !existing_artifacts.remove(&artifact.path) { debug!( "[{}] new artifact {:?} from definitions {:?}", - project_config.name, &artifact.path, &artifact.source_definition_names + project_config.name, &artifact.path, &artifact.artifact_source_keys ); } } @@ -443,7 +443,7 @@ pub async fn commit_project( log_event.time("update_artifact_map_time", || { // All generated paths for removed definitions should be removed - for name in &removed_definition_names { + for name in &removed_artifact_sources { if let Some((_, artifacts)) = artifact_map.0.remove(name) { artifacts_to_remove.extend(artifacts.into_iter().map(|a| a.path)); } diff --git a/compiler/crates/relay-compiler/src/compiler.rs b/compiler/crates/relay-compiler/src/compiler.rs index ad18fb3c0f878..11ba2dec193ff 100644 --- a/compiler/crates/relay-compiler/src/compiler.rs +++ b/compiler/crates/relay-compiler/src/compiler.rs @@ -5,12 +5,14 @@ * LICENSE file in the root directory of this source tree. */ +use std::collections::HashSet; use std::sync::Arc; use common::Diagnostic; use common::PerfLogEvent; use common::PerfLogger; use common::WithDiagnostics; +use docblock_shared::ResolverSourceHash; use futures::future::join_all; use graphql_watchman::WatchmanFileSourceSubscriptionNextChange; use log::debug; @@ -20,16 +22,19 @@ use tokio::sync::Notify; use tokio::task; use tokio::task::JoinHandle; +use crate::artifact_map::ArtifactSourceKey; use crate::build_project::build_project; use crate::build_project::commit_project; use crate::build_project::BuildProjectFailure; use crate::compiler_state::ArtifactMapKind; use crate::compiler_state::CompilerState; +use crate::compiler_state::DocblockSources; use crate::config::Config; use crate::errors::Error; use crate::errors::Result; use crate::file_source::FileSource; use crate::file_source::FileSourceSubscriptionNextChange; +use crate::file_source::LocatedDocblockSource; use crate::graphql_asts::GraphQLAsts; use crate::red_to_green::RedToGreen; use crate::FileSourceResult; @@ -293,10 +298,11 @@ async fn build_projects( setup_event: &impl PerfLogEvent, compiler_state: &mut CompilerState, ) -> Result> { + let dirty_artifact_sources = compiler_state.get_dirty_artifact_sources(&config); let mut graphql_asts = setup_event.time("parse_sources_time", || { GraphQLAsts::from_graphql_sources_map( &compiler_state.graphql_sources, - &compiler_state.get_dirty_definitions(&config), + &dirty_artifact_sources, ) })?; @@ -361,10 +367,16 @@ async fn build_projects( .get(&project_name) .cloned() .unwrap_or_else(|| Arc::new(ArtifactMapKind::Unconnected(Default::default()))); - let removed_definition_names = graphql_asts + let mut removed_artifact_sources = graphql_asts .remove(&project_name) .expect("Expect GraphQLAsts to exist.") .removed_definition_names; + + let removed_docblock_artifact_sources = + get_removed_docblock_artifact_source_keys(compiler_state.docblocks.get(&project_name)); + + removed_artifact_sources.extend(removed_docblock_artifact_sources); + let dirty_artifact_paths = compiler_state .dirty_artifact_paths .get(&project_name) @@ -385,7 +397,7 @@ async fn build_projects( programs, artifacts, artifact_map, - removed_definition_names, + removed_artifact_sources, dirty_artifact_paths, source_control_update_status, ) @@ -433,3 +445,42 @@ async fn build_projects( Ok(all_diagnostics) } + +/// Get the list of removed docblock sources. +fn get_removed_docblock_artifact_source_keys( + docblock_sources: Option<&DocblockSources>, +) -> Vec { + let mut removed_docblocks: Vec = vec![]; + + if let Some(docblock_sources) = docblock_sources { + for (file_name, pending_docblock_sources_for_file) in docblock_sources.pending.iter() { + let mut docblocks_in_file = HashSet::new(); + + for LocatedDocblockSource { + docblock_source, .. + } in pending_docblock_sources_for_file + { + docblocks_in_file.insert(&docblock_source.text_source().text); + } + + if let Some(processed) = docblock_sources.processed.get(file_name) { + for LocatedDocblockSource { + docblock_source, .. + } in processed + { + // If new content of the file doesn't contain the docblock, we should remove + // the generated artifacts for this docblock. + if !docblocks_in_file.contains(&docblock_source.text_source().text) { + removed_docblocks.push(ArtifactSourceKey::ResolverHash( + ResolverSourceHash::new(&docblock_source.text_source().text), + )); + } + } + } + } + + removed_docblocks + } else { + vec![] + } +} diff --git a/compiler/crates/relay-compiler/src/compiler_state.rs b/compiler/crates/relay-compiler/src/compiler_state.rs index f19db00de470b..b77563951ff4c 100644 --- a/compiler/crates/relay-compiler/src/compiler_state.rs +++ b/compiler/crates/relay-compiler/src/compiler_state.rs @@ -26,7 +26,6 @@ use dashmap::DashSet; use fnv::FnvBuildHasher; use fnv::FnvHashMap; use fnv::FnvHashSet; -use graphql_ir::ExecutableDefinitionName; use intern::string_key::StringKey; use rayon::prelude::*; use relay_config::SchemaConfig; @@ -39,6 +38,7 @@ use zstd::stream::read::Decoder as ZstdDecoder; use zstd::stream::write::Encoder as ZstdEncoder; use crate::artifact_map::ArtifactMap; +use crate::artifact_map::ArtifactSourceKey; use crate::config::Config; use crate::errors::Error; use crate::errors::Result; @@ -553,11 +553,11 @@ impl CompilerState { self.dirty_artifact_paths.clear(); } - /// Calculate dirty definitions from dirty artifacts - pub fn get_dirty_definitions( + /// Calculate dirty definitions/sources from dirty artifacts + pub fn get_dirty_artifact_sources( &self, config: &Config, - ) -> FnvHashMap> { + ) -> FnvHashMap> { if self.dirty_artifact_paths.is_empty() { return Default::default(); } @@ -576,7 +576,7 @@ impl CompilerState { let mut added = false; for artifact_record in artifact_records { if paths.remove(&artifact_record.path).is_some() && !added { - dirty_definitions.push(*definition_name); + dirty_definitions.push(definition_name.clone()); if paths.is_empty() { break 'outer; } diff --git a/compiler/crates/relay-compiler/src/graphql_asts.rs b/compiler/crates/relay-compiler/src/graphql_asts.rs index 82e43c752111a..0c2c83fb64bc4 100644 --- a/compiler/crates/relay-compiler/src/graphql_asts.rs +++ b/compiler/crates/relay-compiler/src/graphql_asts.rs @@ -13,13 +13,13 @@ use std::path::PathBuf; use common::Diagnostic; use common::SourceLocationKey; use dependency_analyzer::ExecutableDefinitionNameSet; -use dependency_analyzer::ExecutableDefinitionNameVec; use fnv::FnvHashMap; use graphql_ir::ExecutableDefinitionName; use graphql_ir::FragmentDefinitionName; use graphql_ir::OperationDefinitionName; use graphql_syntax::ExecutableDefinition; +use crate::artifact_map::ArtifactSourceKey; use crate::compiler_state::GraphQLSources; use crate::compiler_state::ProjectName; use crate::errors::Error; @@ -32,7 +32,7 @@ pub struct GraphQLAsts { /// Names of fragments and operations that are updated or created pub pending_definition_names: ExecutableDefinitionNameSet, /// Names of fragments and operations that are deleted - pub removed_definition_names: ExecutableDefinitionNameVec, + pub removed_definition_names: Vec, } impl GraphQLAsts { @@ -49,14 +49,28 @@ impl GraphQLAsts { pub fn from_graphql_sources_map( graphql_sources_map: &FnvHashMap, - dirty_definitions_map: &FnvHashMap>, + dirty_artifact_sources: &FnvHashMap>, ) -> Result> { graphql_sources_map .iter() .map(|(&project_name, sources)| { let asts = GraphQLAsts::from_graphql_sources( sources, - dirty_definitions_map.get(&project_name), + dirty_artifact_sources + .get(&project_name) + .map(|dirty_artifacts| { + dirty_artifacts + .iter() + .filter_map(|artifact_source_key| match artifact_source_key { + ArtifactSourceKey::ExecutableDefinition(def_name) => { + Some(def_name) + } + // Dirty resolvers artifacts are handled separately + // and should not affect the list of affected document defintions + ArtifactSourceKey::ResolverHash(_) => None, + }) + .collect() + }), )?; Ok((project_name, asts)) }) @@ -68,7 +82,7 @@ impl GraphQLAsts { /// Additionally collects the set of definition names that updated, given the compiler state pub fn from_graphql_sources( graphql_sources: &GraphQLSources, - dirty_definitions: Option<&Vec>, + dirty_definitions: Option>, ) -> Result { let mut syntax_errors = Vec::new(); @@ -139,12 +153,18 @@ impl GraphQLAsts { if !definitions_for_file.iter().any(|def| def.name() == name) { match def { ExecutableDefinition::Operation(_) => { - removed_definition_names - .push(OperationDefinitionName(def_name).into()) + removed_definition_names.push( + ArtifactSourceKey::ExecutableDefinition( + OperationDefinitionName(def_name).into(), + ), + ) } ExecutableDefinition::Fragment(_) => { - removed_definition_names - .push(FragmentDefinitionName(def_name).into()) + removed_definition_names.push( + ArtifactSourceKey::ExecutableDefinition( + FragmentDefinitionName(def_name).into(), + ), + ) } } } diff --git a/compiler/crates/relay-compiler/src/lib.rs b/compiler/crates/relay-compiler/src/lib.rs index 2ccbcca9c5291..d6817d0e76d43 100644 --- a/compiler/crates/relay-compiler/src/lib.rs +++ b/compiler/crates/relay-compiler/src/lib.rs @@ -24,6 +24,7 @@ mod red_to_green; pub mod saved_state; pub mod status_reporter; +pub use artifact_map::ArtifactSourceKey; pub use build_project::add_to_mercurial; pub use build_project::artifact_writer::ArtifactDifferenceShardedWriter; pub use build_project::artifact_writer::ArtifactDifferenceWriter; diff --git a/compiler/crates/relay-docblock/src/docblock_ir.rs b/compiler/crates/relay-docblock/src/docblock_ir.rs index ae2dd8d62bc54..9be5bf0d28d66 100644 --- a/compiler/crates/relay-docblock/src/docblock_ir.rs +++ b/compiler/crates/relay-docblock/src/docblock_ir.rs @@ -14,6 +14,7 @@ use common::NamedItem; use common::SourceLocationKey; use common::Span; use common::WithLocation; +use docblock_shared::ResolverSourceHash; use docblock_shared::ARGUMENT_DEFINITIONS; use docblock_shared::ARGUMENT_TYPE; use docblock_shared::DEFAULT_VALUE; @@ -83,6 +84,7 @@ pub(crate) fn parse_docblock_ir( let UntypedDocblockRepresentation { description, mut fields, + source_hash, } = untyped_representation; let resolver_field = match fields.remove(&AllowedFieldName::RelayResolverField) { @@ -99,6 +101,7 @@ pub(crate) fn parse_docblock_ir( docblock_location, unpopulated_ir_field, parse_options, + source_hash, )?) } IrField::PopulatedIrField(populated_ir_field) => { @@ -109,6 +112,7 @@ pub(crate) fn parse_docblock_ir( populated_ir_field, definitions_in_file, docblock_location, + source_hash, )?) } else { match get_optional_unpopulated_field_named( @@ -122,12 +126,14 @@ pub(crate) fn parse_docblock_ir( docblock_location, populated_ir_field, weak_field, + source_hash, )?), None => DocblockIr::StrongObjectResolver(parse_strong_object_ir( &mut fields, description, docblock_location, populated_ir_field, + source_hash, )?), } } @@ -151,6 +157,7 @@ fn parse_relay_resolver_ir( location: Location, _resolver_field: UnpopulatedIrField, parse_options: &ParseOptions<'_>, + source_hash: ResolverSourceHash, ) -> DiagnosticsResult { let root_fragment = get_optional_populated_field_named(fields, AllowedFieldName::RootFragmentField)?; @@ -213,6 +220,7 @@ fn parse_relay_resolver_ir( field: field_definition_stub, output_type, fragment_arguments, + source_hash, }) } @@ -221,6 +229,7 @@ fn parse_strong_object_ir( description: Option>, location: Location, relay_resolver_field: PopulatedIrField, + source_hash: ResolverSourceHash, ) -> DiagnosticsResult { let type_str = relay_resolver_field.value; let (identifier, implements_interfaces) = parse_identifier_and_implements_interfaces( @@ -240,6 +249,7 @@ fn parse_strong_object_ir( live: get_optional_unpopulated_field_named(fields, AllowedFieldName::LiveField)?, location, implements_interfaces, + source_hash, }) } @@ -250,6 +260,7 @@ fn parse_weak_object_ir( location: Location, relay_resolver_field: PopulatedIrField, _weak_field: UnpopulatedIrField, + source_hash: ResolverSourceHash, ) -> DiagnosticsResult { // Validate that the right hand side of the @RelayResolver field is a valid identifier let identifier = assert_only_identifier(relay_resolver_field)?; @@ -261,6 +272,7 @@ fn parse_weak_object_ir( hack_source, deprecated: fields.remove(&AllowedFieldName::DeprecatedField), location, + source_hash, }) } @@ -270,6 +282,7 @@ fn parse_terse_relay_resolver_ir( relay_resolver_field: PopulatedIrField, definitions_in_file: Option<&Vec>, location: Location, + source_hash: ResolverSourceHash, ) -> DiagnosticsResult { let root_fragment = get_optional_populated_field_named(fields, AllowedFieldName::RootFragmentField)?; @@ -357,6 +370,7 @@ fn parse_terse_relay_resolver_ir( deprecated: fields.remove(&AllowedFieldName::DeprecatedField), live: get_optional_unpopulated_field_named(fields, AllowedFieldName::LiveField)?, fragment_arguments, + source_hash, }) } diff --git a/compiler/crates/relay-docblock/src/ir.rs b/compiler/crates/relay-docblock/src/ir.rs index 28a365848b885..81747d63815cf 100644 --- a/compiler/crates/relay-docblock/src/ir.rs +++ b/compiler/crates/relay-docblock/src/ir.rs @@ -18,6 +18,7 @@ use common::NamedItem; use common::ObjectName; use common::Span; use common::WithLocation; +use docblock_shared::ResolverSourceHash; use docblock_shared::FRAGMENT_KEY_ARGUMENT_NAME; use docblock_shared::GENERATED_FRAGMENT_ARGUMENT_NAME; use docblock_shared::HAS_OUTPUT_TYPE_ARGUMENT_NAME; @@ -28,6 +29,8 @@ use docblock_shared::KEY_RESOLVER_ID_FIELD; use docblock_shared::LIVE_ARGUMENT_NAME; use docblock_shared::RELAY_RESOLVER_DIRECTIVE_NAME; use docblock_shared::RELAY_RESOLVER_MODEL_DIRECTIVE_NAME; +use docblock_shared::RELAY_RESOLVER_SOURCE_HASH; +use docblock_shared::RELAY_RESOLVER_SOURCE_HASH_VALUE; use docblock_shared::RELAY_RESOLVER_WEAK_OBJECT_DIRECTIVE; use docblock_shared::RESOLVER_VALUE_SCALAR_NAME; use graphql_ir::FragmentDefinitionName; @@ -284,6 +287,7 @@ trait ResolverIr: Sized { fn deprecated(&self) -> Option; fn live(&self) -> Option; fn named_import(&self) -> Option; + fn source_hash(&self) -> ResolverSourceHash; fn to_graphql_schema_ast( self, @@ -302,7 +306,10 @@ trait ResolverIr: Sized { ) -> Vec { let location = self.location(); let span = location.span(); - let mut directives = vec![self.directive(object, schema_info)]; + let mut directives: Vec = vec![ + self.directive(object, schema_info), + resolver_source_hash_directive(self.source_hash()), + ]; if let Some(deprecated) = self.deprecated() { directives.push(ConstantDirective { @@ -409,7 +416,6 @@ trait ResolverIr: Sized { WithLocation::new(self.location(), name), )); } - ConstantDirective { span, at: dummy_token(span), @@ -618,6 +624,7 @@ pub struct TerseRelayResolverIr { pub live: Option, pub location: Location, pub fragment_arguments: Option>, + pub source_hash: ResolverSourceHash, } impl ResolverIr for TerseRelayResolverIr { @@ -703,6 +710,10 @@ impl ResolverIr for TerseRelayResolverIr { fn named_import(&self) -> Option { Some(self.field.name.value) } + + fn source_hash(&self) -> ResolverSourceHash { + self.source_hash + } } impl ResolverTypeDefinitionIr for TerseRelayResolverIr { @@ -739,6 +750,7 @@ pub struct RelayResolverIr { pub live: Option, pub location: Location, pub fragment_arguments: Option>, + pub source_hash: ResolverSourceHash, } impl ResolverIr for RelayResolverIr { @@ -870,6 +882,10 @@ impl ResolverIr for RelayResolverIr { fn named_import(&self) -> Option { Some(self.field.name.value) } + + fn source_hash(&self) -> ResolverSourceHash { + self.source_hash + } } impl ResolverTypeDefinitionIr for RelayResolverIr { @@ -909,6 +925,7 @@ pub struct StrongObjectIr { pub location: Location, /// The interfaces which the newly-created object implements pub implements_interfaces: Vec, + pub source_hash: ResolverSourceHash, } impl StrongObjectIr { @@ -1119,6 +1136,10 @@ impl ResolverIr for StrongObjectIr { fn named_import(&self) -> Option { Some(self.type_name.value) } + + fn source_hash(&self) -> ResolverSourceHash { + self.source_hash + } } /// Relay Resolver docblock representing a "model" type for a weak object @@ -1133,6 +1154,7 @@ pub struct WeakObjectIr { pub hack_source: Option>, pub deprecated: Option, pub location: Location, + pub source_hash: ResolverSourceHash, } impl WeakObjectIr { @@ -1182,7 +1204,7 @@ impl WeakObjectIr { self.model_type_name(), self.description.map(as_string_node), self.hack_source.map(as_string_node), - vec![], + vec![resolver_source_hash_directive(self.source_hash())], self.location(), )])), }) @@ -1279,6 +1301,10 @@ impl ResolverIr for WeakObjectIr { fn named_import(&self) -> Option { None } + + fn source_hash(&self) -> ResolverSourceHash { + self.source_hash + } } fn string_argument(name: StringKey, value: WithLocation) -> ConstantArgument { @@ -1410,3 +1436,16 @@ fn generate_model_instance_field( hack_source, } } + +fn resolver_source_hash_directive(source_hash: ResolverSourceHash) -> ConstantDirective { + let span = Span::empty(); + ConstantDirective { + span, + at: dummy_token(span), + name: string_key_as_identifier(RELAY_RESOLVER_SOURCE_HASH.0), + arguments: Some(List::generated(vec![string_argument( + RELAY_RESOLVER_SOURCE_HASH_VALUE.0, + WithLocation::generated(source_hash.value()), + )])), + } +} diff --git a/compiler/crates/relay-docblock/src/untyped_representation.rs b/compiler/crates/relay-docblock/src/untyped_representation.rs index df4d46c6d811c..15b7b79734028 100644 --- a/compiler/crates/relay-docblock/src/untyped_representation.rs +++ b/compiler/crates/relay-docblock/src/untyped_representation.rs @@ -12,6 +12,7 @@ use std::hash::Hash; use common::Diagnostic; use common::WithLocation; +use docblock_shared::ResolverSourceHash; use docblock_syntax::DocblockAST; use docblock_syntax::DocblockSection; use graphql_ir::reexport::StringKey; @@ -94,13 +95,15 @@ impl TryFrom> for AllowedFieldName { pub(crate) struct UntypedDocblockRepresentation { pub(crate) description: Option>, pub(crate) fields: HashMap, + pub(crate) source_hash: ResolverSourceHash, } impl UntypedDocblockRepresentation { - fn new() -> Self { + fn new(source_hash: ResolverSourceHash) -> Self { Self { description: None, fields: HashMap::new(), + source_hash, } } } @@ -108,7 +111,8 @@ impl UntypedDocblockRepresentation { pub(crate) fn parse_untyped_docblock_representation( ast: &DocblockAST, ) -> Result> { - let mut untyped_repr: UntypedDocblockRepresentation = UntypedDocblockRepresentation::new(); + let mut untyped_repr: UntypedDocblockRepresentation = + UntypedDocblockRepresentation::new(ast.source_hash); let mut errors = vec![]; for section in &ast.sections { match section { diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-deprecated-no-description.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-deprecated-no-description.expected index 5cb40b69cff06..6662dbec14164 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-deprecated-no-description.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-deprecated-no-description.expected @@ -83,5 +83,8 @@ RelayResolver( live: None, location: /path/to/test/fixture/relay-resolver-deprecated-no-description.js:0:130, fragment_arguments: None, + source_hash: ResolverSourceHash( + "eb46fd9d0828f318bc5613bca9e67e42", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-deprecated.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-deprecated.expected index 2a26f9d962aea..13641cfae20b0 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-deprecated.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-deprecated.expected @@ -87,5 +87,8 @@ RelayResolver( live: None, location: /path/to/test/fixture/relay-resolver-deprecated.js:0:160, fragment_arguments: None, + source_hash: ResolverSourceHash( + "01183f3ee51f5cb85eec42335548ae0f", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-live.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-live.expected index 1db46a0bec645..3a64794debe73 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-live.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-live.expected @@ -81,5 +81,8 @@ RelayResolver( ), location: /path/to/test/fixture/relay-resolver-live.js:0:124, fragment_arguments: None, + source_hash: ResolverSourceHash( + "e77e16ef96fd749a5894db7bcb685060", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-named-export.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-named-export.expected index a5b751ee4f63e..311fe248fdc19 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-named-export.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-named-export.expected @@ -67,5 +67,8 @@ RelayResolver( live: None, location: /path/to/test/fixture/relay-resolver-named-export.js:0:393, fragment_arguments: None, + source_hash: ResolverSourceHash( + "0a13488b7b321b8d7770f691a668ba44", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-strong-object-with-implements.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-strong-object-with-implements.expected index 1a450f568b6b4..a26893113d67d 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-strong-object-with-implements.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-strong-object-with-implements.expected @@ -41,5 +41,8 @@ StrongObjectResolver( value: "Foo", }, ], + source_hash: ResolverSourceHash( + "cbb959799c8b4d36262edfc0c4e8ad7f", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-strong-object.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-strong-object.expected index 5365e0791f40e..c1446279afaaa 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-strong-object.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-strong-object.expected @@ -32,5 +32,8 @@ StrongObjectResolver( live: None, location: /path/to/test/fixture/relay-resolver-strong-object.js:0:31, implements_interfaces: [], + source_hash: ResolverSourceHash( + "b1c8ae1937aed7425f5a87a4762ad83d", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-args.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-args.expected index d198f643cc874..91c6583b6f184 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-args.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-args.expected @@ -135,5 +135,8 @@ RelayResolver( }, ], ), + source_hash: ResolverSourceHash( + "0a13488b7b321b8d7770f691a668ba44", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-field-and-fragment-args.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-field-and-fragment-args.expected index d6979524c5ae3..8817c48c40508 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-field-and-fragment-args.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-field-and-fragment-args.expected @@ -173,5 +173,8 @@ RelayResolver( }, ], ), + source_hash: ResolverSourceHash( + "74022d4ca184b7d99e312af76420f20f", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-field-args.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-field-args.expected index c13328caafe10..5128a32defe67 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-field-args.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-field-args.expected @@ -105,5 +105,8 @@ RelayResolver( live: None, location: /path/to/test/fixture/relay-resolver-with-field-args.js:0:118, fragment_arguments: None, + source_hash: ResolverSourceHash( + "74022d4ca184b7d99e312af76420f20f", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-fragment.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-fragment.expected index 4d4c0bbb1d633..5a3adde02431b 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-fragment.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-fragment.expected @@ -57,5 +57,8 @@ RelayResolver( live: None, location: /path/to/test/fixture/relay-resolver-with-fragment.js:0:94, fragment_arguments: None, + source_hash: ResolverSourceHash( + "04fa2c09e68fca302832f1acfb74e2d3", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-output-type.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-output-type.expected index b7d1dbd5e8092..e8b72ff9f02fe 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-output-type.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver-with-output-type.expected @@ -88,5 +88,8 @@ RelayResolver( live: None, location: /path/to/test/fixture/relay-resolver-with-output-type.js:0:419, fragment_arguments: None, + source_hash: ResolverSourceHash( + "88293c3a51d22c37485f8fb1444eed2b", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver.expected index ae1ebf99d911e..7612dcda71977 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/relay-resolver.expected @@ -86,5 +86,8 @@ RelayResolver( live: None, location: /path/to/test/fixture/relay-resolver.js:0:409, fragment_arguments: None, + source_hash: ResolverSourceHash( + "eeac1664eff365a817d8a2446abe76ce", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver-non-nullable-list-item.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver-non-nullable-list-item.expected index ce6ef5320894f..525d87279e720 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver-non-nullable-list-item.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver-non-nullable-list-item.expected @@ -78,5 +78,8 @@ TerseRelayResolver( live: None, location: /path/to/test/fixture/terse-relay-resolver-non-nullable-list-item.js:0:71, fragment_arguments: None, + source_hash: ResolverSourceHash( + "12e28b8739ff3ab018186a28de3ca726", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver.expected b/compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver.expected index 612ee92ac0c7b..e1fd6a2726992 100644 --- a/compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver.expected +++ b/compiler/crates/relay-docblock/tests/parse/fixtures/terse-relay-resolver.expected @@ -73,5 +73,8 @@ TerseRelayResolver( live: None, location: /path/to/test/fixture/terse-relay-resolver.js:0:371, fragment_arguments: None, + source_hash: ResolverSourceHash( + "0a9950ad1f952f5777b27604738fcf91", + ), }, ) diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/client-edge-relay-resolver.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/client-edge-relay-resolver.expected index 52a00581b9078..eae14786aa94e 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/client-edge-relay-resolver.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/client-edge-relay-resolver.expected @@ -27,5 +27,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - favorite_page: Page @relay_resolver(import_path: "/path/to/test/fixture/client-edge-relay-resolver.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page: Page @relay_resolver(import_path: "/path/to/test/fixture/client-edge-relay-resolver.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "eeac1664eff365a817d8a2446abe76ce") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/legacy-relay-resolver-with-root-fragment-on-model.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/legacy-relay-resolver-with-root-fragment-on-model.expected index c420d9d5695a8..310a6b05cfc9d 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/legacy-relay-resolver-with-root-fragment-on-model.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/legacy-relay-resolver-with-root-fragment-on-model.expected @@ -25,10 +25,10 @@ graphql` ==================================== OUTPUT =================================== type MyType @__RelayResolverModel { id: ID! - __relay_model_instance: RelayResolverValue! @relay_resolver(import_path: "/path/to/test/fixture/legacy-relay-resolver-with-root-fragment-on-model.js", fragment_name: "MyType__id", generated_fragment: true, inject_fragment_data: "id", import_name: "MyType") @unselectable(reason: "This field is intended only for Relay's internal use") + __relay_model_instance: RelayResolverValue! @relay_resolver(import_path: "/path/to/test/fixture/legacy-relay-resolver-with-root-fragment-on-model.js", fragment_name: "MyType__id", generated_fragment: true, inject_fragment_data: "id", import_name: "MyType") @resolver_source_hash(value: "b81f253a757aaba36955be6d8e224c2a") @unselectable(reason: "This field is intended only for Relay's internal use") } extend type MyType { - my_field: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/legacy-relay-resolver-with-root-fragment-on-model.js", fragment_name: "myRootFragment", import_name: "my_field") + my_field: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/legacy-relay-resolver-with-root-fragment-on-model.js", fragment_name: "myRootFragment", import_name: "my_field") @resolver_source_hash(value: "6ea8e78f94a38ef98a44161e39f85f8d") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-deprecated-no-description.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-deprecated-no-description.expected index 12a1e152cfff5..207ae5baffc73 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-deprecated-no-description.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-deprecated-no-description.expected @@ -23,5 +23,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - favorite_page: Page @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-deprecated-no-description.js", fragment_name: "myRootFragment", import_name: "favorite_page") @deprecated + favorite_page: Page @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-deprecated-no-description.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "eb46fd9d0828f318bc5613bca9e67e42") @deprecated } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-deprecated.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-deprecated.expected index 82f503aacc921..43da87d591826 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-deprecated.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-deprecated.expected @@ -24,5 +24,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - favorite_page: Page @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-deprecated.js", fragment_name: "myRootFragment", import_name: "favorite_page") @deprecated(reason: "This one is not used any more") + favorite_page: Page @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-deprecated.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "01183f3ee51f5cb85eec42335548ae0f") @deprecated(reason: "This one is not used any more") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-named-export.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-named-export.expected index 8dd639991fd35..a9c157016f668 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-named-export.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-named-export.expected @@ -26,5 +26,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-named-export.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-named-export.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "0a13488b7b321b8d7770f691a668ba44") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-on-interface.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-on-interface.expected index 2923b568da8d2..d12194eebd7ad 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-on-interface.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-on-interface.expected @@ -27,30 +27,30 @@ graphql` ` ==================================== OUTPUT =================================== extend interface UserNameRenderable { - favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "a70ac21f287c26454cea41d6b9c1feee") } extend type PlainUserNameRenderer { - favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "a70ac21f287c26454cea41d6b9c1feee") } extend type MarkdownUserNameRenderer { - favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "a70ac21f287c26454cea41d6b9c1feee") } extend type ImplementsImplementsUserNameRenderableAndUserNameRenderable { - favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "a70ac21f287c26454cea41d6b9c1feee") } extend interface ImplementsUserNameRenderable { - favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "a70ac21f287c26454cea41d6b9c1feee") } extend type ImplementsImplementsUserNameRenderable { - favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-on-interface.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "a70ac21f287c26454cea41d6b9c1feee") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object-with-implements.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object-with-implements.expected index f3eeaf03e1461..7fee08c02694a 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object-with-implements.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object-with-implements.expected @@ -21,5 +21,5 @@ interface IFoo { ==================================== OUTPUT =================================== type ClientUser implements IFoo @__RelayResolverModel { id: ID! - __relay_model_instance: RelayResolverValue! @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-strong-object-with-implements.js", fragment_name: "ClientUser__id", generated_fragment: true, inject_fragment_data: "id", import_name: "ClientUser") @unselectable(reason: "This field is intended only for Relay's internal use") + __relay_model_instance: RelayResolverValue! @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-strong-object-with-implements.js", fragment_name: "ClientUser__id", generated_fragment: true, inject_fragment_data: "id", import_name: "ClientUser") @resolver_source_hash(value: "76be3b85f11135352a0d3a5726418956") @unselectable(reason: "This field is intended only for Relay's internal use") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object-with-multiple-implements.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object-with-multiple-implements.expected index 0b922279aa716..9f84f327614b1 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object-with-multiple-implements.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object-with-multiple-implements.expected @@ -27,5 +27,5 @@ interface IBar { ==================================== OUTPUT =================================== type ClientUser implements IFoo & IBar @__RelayResolverModel { id: ID! - __relay_model_instance: RelayResolverValue! @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-strong-object-with-multiple-implements.js", fragment_name: "ClientUser__id", generated_fragment: true, inject_fragment_data: "id", import_name: "ClientUser") @unselectable(reason: "This field is intended only for Relay's internal use") + __relay_model_instance: RelayResolverValue! @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-strong-object-with-multiple-implements.js", fragment_name: "ClientUser__id", generated_fragment: true, inject_fragment_data: "id", import_name: "ClientUser") @resolver_source_hash(value: "1b7346b6155a43514be2946721ff59fb") @unselectable(reason: "This field is intended only for Relay's internal use") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object.expected index 572f7eb5a86da..cf9e7d59aa132 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-strong-object.expected @@ -12,5 +12,5 @@ ==================================== OUTPUT =================================== type ClientUser @__RelayResolverModel { id: ID! - __relay_model_instance: RelayResolverValue! @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-strong-object.js", fragment_name: "ClientUser__id", generated_fragment: true, inject_fragment_data: "id", import_name: "ClientUser") @unselectable(reason: "This field is intended only for Relay's internal use") + __relay_model_instance: RelayResolverValue! @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-strong-object.js", fragment_name: "ClientUser__id", generated_fragment: true, inject_fragment_data: "id", import_name: "ClientUser") @resolver_source_hash(value: "b1c8ae1937aed7425f5a87a4762ad83d") @unselectable(reason: "This field is intended only for Relay's internal use") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-args.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-args.expected index 802db4376ecbb..7394d92d66636 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-args.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-args.expected @@ -26,5 +26,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - favorite_page(first: Int = 10, userID: ID!): RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-with-args.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page(first: Int = 10, userID: ID!): RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-with-args.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "0a13488b7b321b8d7770f691a668ba44") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-field-and-fragment-args.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-field-and-fragment-args.expected index 405d4c90dcd9e..bf15384401226 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-field-and-fragment-args.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-field-and-fragment-args.expected @@ -22,5 +22,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - greeting(first: Int = 10, userID: ID!, salutation: String!): RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-with-field-and-fragment-args.js", fragment_name: "myRootFragment", import_name: "greeting") + greeting(first: Int = 10, userID: ID!, salutation: String!): RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-with-field-and-fragment-args.js", fragment_name: "myRootFragment", import_name: "greeting") @resolver_source_hash(value: "74022d4ca184b7d99e312af76420f20f") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-field-args.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-field-args.expected index aa90b021292b9..ba2ba2d185eb0 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-field-args.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-field-args.expected @@ -22,5 +22,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - greeting(salutation: String!): RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-with-field-args.js", fragment_name: "myRootFragment", import_name: "greeting") + greeting(salutation: String!): RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-with-field-args.js", fragment_name: "myRootFragment", import_name: "greeting") @resolver_source_hash(value: "74022d4ca184b7d99e312af76420f20f") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-output-type.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-output-type.expected index 096b353a9ddef..850550699cda5 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-output-type.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver-with-output-type.expected @@ -37,5 +37,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - favorite_page: ClientPage @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-with-output-type.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "favorite_page") + favorite_page: ClientPage @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver-with-output-type.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "favorite_page") @resolver_source_hash(value: "88293c3a51d22c37485f8fb1444eed2b") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver.expected index e29cb6a1cd4b2..9a067aeb4e513 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/relay-resolver.expected @@ -26,5 +26,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page: RelayResolverValue @relay_resolver(import_path: "/path/to/test/fixture/relay-resolver.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "0a13488b7b321b8d7770f691a668ba44") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-interface.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-interface.expected index 5c867983c8d05..d6c152904a8da 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-interface.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-interface.expected @@ -35,35 +35,35 @@ ` ==================================== OUTPUT =================================== extend interface Node { - importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") + importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") @resolver_source_hash(value: "27c88753c4af8233f1e6e0c276cb42e9") } extend type Comment { - importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") + importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") @resolver_source_hash(value: "27c88753c4af8233f1e6e0c276cb42e9") } extend type Feedback { - importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") + importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") @resolver_source_hash(value: "27c88753c4af8233f1e6e0c276cb42e9") } extend type Page { - importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") + importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") @resolver_source_hash(value: "27c88753c4af8233f1e6e0c276cb42e9") } extend type PhotoStory { - importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") + importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") @resolver_source_hash(value: "27c88753c4af8233f1e6e0c276cb42e9") } extend type Story { - importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") + importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") @resolver_source_hash(value: "27c88753c4af8233f1e6e0c276cb42e9") } extend type User { - importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") + importantField: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-interface.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "importantField") @resolver_source_hash(value: "27c88753c4af8233f1e6e0c276cb42e9") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-with-output-type.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-with-output-type.expected index c770be034c81c..d5a280fa39736 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-with-output-type.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-with-output-type.expected @@ -31,5 +31,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - favorite_page: ClientPage @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-with-output-type.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "favorite_page") + favorite_page: ClientPage @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-with-output-type.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "favorite_page") @resolver_source_hash(value: "6debf0d3b679b66e8d0c58dbdb4d422d") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-with-root-fragment-on-model.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-with-root-fragment-on-model.expected index f3580bbed03d5..70c689e43a1b1 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-with-root-fragment-on-model.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver-with-root-fragment-on-model.expected @@ -23,10 +23,10 @@ graphql` ==================================== OUTPUT =================================== type MyType @__RelayResolverModel { id: ID! - __relay_model_instance: RelayResolverValue! @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-with-root-fragment-on-model.js", fragment_name: "MyType__id", generated_fragment: true, inject_fragment_data: "id", import_name: "MyType") @unselectable(reason: "This field is intended only for Relay's internal use") + __relay_model_instance: RelayResolverValue! @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-with-root-fragment-on-model.js", fragment_name: "MyType__id", generated_fragment: true, inject_fragment_data: "id", import_name: "MyType") @resolver_source_hash(value: "b81f253a757aaba36955be6d8e224c2a") @unselectable(reason: "This field is intended only for Relay's internal use") } extend type MyType { - my_field: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-with-root-fragment-on-model.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "my_field") + my_field: String @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver-with-root-fragment-on-model.js", fragment_name: "myRootFragment", has_output_type: true, import_name: "my_field") @resolver_source_hash(value: "c8ed0d9035e933a3b6544323724f5323") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver.expected index 44453d04c6b4c..a4ff9baa7b99d 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/terse-relay-resolver.expected @@ -23,5 +23,5 @@ graphql` ` ==================================== OUTPUT =================================== extend type User { - favorite_page: Page @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver.js", fragment_name: "myRootFragment", import_name: "favorite_page") + favorite_page: Page @relay_resolver(import_path: "/path/to/test/fixture/terse-relay-resolver.js", fragment_name: "myRootFragment", import_name: "favorite_page") @resolver_source_hash(value: "0a9950ad1f952f5777b27604738fcf91") } diff --git a/compiler/crates/relay-docblock/tests/to_schema/fixtures/weak-type.expected b/compiler/crates/relay-docblock/tests/to_schema/fixtures/weak-type.expected index f74c5333ba84e..3dde58df6c626 100644 --- a/compiler/crates/relay-docblock/tests/to_schema/fixtures/weak-type.expected +++ b/compiler/crates/relay-docblock/tests/to_schema/fixtures/weak-type.expected @@ -23,5 +23,5 @@ scalar MyClientTypeModel @__RelayCustomScalar(path: "/path/to/test/fixture/weak- type MyClientType @__RelayResolverModel @RelayOutputType @__RelayWeakObject @deprecated(reason: "Don't use this any more") { - __relay_model_instance: MyClientTypeModel! @unselectable(reason: "This field is intended only for Relay's internal use") + __relay_model_instance: MyClientTypeModel! @resolver_source_hash(value: "fdcf9d39b12f481b2f5a83f2aec8d922") @unselectable(reason: "This field is intended only for Relay's internal use") } diff --git a/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs b/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs index 571151852b609..f8abcf01ae1c5 100644 --- a/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs +++ b/compiler/crates/relay-lsp/src/server/lsp_state_resources.rs @@ -29,6 +29,7 @@ use relay_compiler::errors::BuildProjectError; use relay_compiler::errors::Error; use relay_compiler::transform_program; use relay_compiler::validate_program; +use relay_compiler::ArtifactSourceKey; use relay_compiler::BuildProjectFailure; use relay_compiler::FileSource; use relay_compiler::FileSourceResult; @@ -239,7 +240,7 @@ impl { let program = e.get_mut(); - let removed_definition_names = graphql_asts - .get(&project_config.name) - .map(|ast| ast.removed_definition_names.as_ref()); + let removed_definition_names = graphql_asts.get(&project_config.name).map(|ast| { + ast.removed_definition_names + .iter() + .filter_map(|artifact_source| match artifact_source { + ArtifactSourceKey::ExecutableDefinition(name) => Some(*name), + // For the resolver case, we don't really need to track removed resolver defintions + // here, as the documents for resolves are not accesible for the user + // in the LSP program. We only care about unused fragments/operations + // that are editable by the user. + // We also don't write artifacts from LSP so it is safe to skip these here. + ArtifactSourceKey::ResolverHash(_) => None, + }) + .collect::>() + }); program.merge_program(&base_program, removed_definition_names); } } diff --git a/compiler/crates/relay-transforms/src/generate_relay_resolvers_model_fragments.rs b/compiler/crates/relay-transforms/src/generate_relay_resolvers_model_fragments.rs index a898aaee983db..01018af15650c 100644 --- a/compiler/crates/relay-transforms/src/generate_relay_resolvers_model_fragments.rs +++ b/compiler/crates/relay-transforms/src/generate_relay_resolvers_model_fragments.rs @@ -9,7 +9,12 @@ use std::sync::Arc; use common::NamedItem; use common::WithLocation; +use docblock_shared::ResolverSourceHash; use docblock_shared::RELAY_RESOLVER_MODEL_DIRECTIVE_NAME; +use docblock_shared::RELAY_RESOLVER_SOURCE_HASH; +use docblock_shared::RELAY_RESOLVER_SOURCE_HASH_VALUE; +use graphql_ir::associated_data_impl; +use graphql_ir::Directive; use graphql_ir::FragmentDefinition; use graphql_ir::FragmentDefinitionName; use graphql_ir::Program; @@ -28,6 +33,14 @@ lazy_static! { "__relay_model_instance".intern(); } +/// Currently, this is a wrapper of the hash of the resolver source code. +/// But we can change this `ArtifactSourceKeyData` to be an +/// enum and also represent the `fragment` or `operation` names. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct ArtifactSourceKeyData(pub ResolverSourceHash); + +associated_data_impl!(ArtifactSourceKeyData); + pub fn generate_relay_resolvers_model_fragments( program: &Program, schema_config: &SchemaConfig, @@ -63,12 +76,14 @@ pub fn generate_relay_resolvers_model_fragments( .intern(), ); + let resolver_field = program.schema.field(model_instance_field_id); + let fragment_directives = directives_with_artifact_source(resolver_field); let fragment_definition = FragmentDefinition { name: WithLocation::new(object.name.location, model_fragment_name), variable_definitions: vec![], used_global_variables: vec![], type_condition: object_type, - directives: vec![], + directives: fragment_directives, selections: vec![Selection::ScalarField(Arc::new(ScalarField { alias: None, definition: WithLocation::generated(model_instance_field_id), @@ -99,7 +114,7 @@ pub fn generate_relay_resolvers_model_fragments( variable_definitions: vec![], used_global_variables: vec![], type_condition: object_type, - directives: vec![], + directives: directives_with_artifact_source(resolver_field), selections: vec![Selection::ScalarField(Arc::new(ScalarField { alias: None, definition: WithLocation::generated(id_field_id), @@ -115,3 +130,20 @@ pub fn generate_relay_resolvers_model_fragments( next_program } + +fn get_resolver_source_hash(field: &schema::Field) -> Option { + field + .directives + .named(*RELAY_RESOLVER_SOURCE_HASH) + .and_then(|directive| directive.arguments.named(*RELAY_RESOLVER_SOURCE_HASH_VALUE)) + .and_then(|source| source.value.get_string_literal()) + .map(ResolverSourceHash::from_raw) +} + +pub(crate) fn directives_with_artifact_source(field: &schema::Field) -> Vec { + if let Some(source_hash) = get_resolver_source_hash(field) { + vec![ArtifactSourceKeyData(source_hash).into()] + } else { + vec![] + } +} diff --git a/compiler/crates/relay-transforms/src/generate_relay_resolvers_operations_for_nested_objects.rs b/compiler/crates/relay-transforms/src/generate_relay_resolvers_operations_for_nested_objects.rs index e9fe8bcafa3f3..46531129021df 100644 --- a/compiler/crates/relay-transforms/src/generate_relay_resolvers_operations_for_nested_objects.rs +++ b/compiler/crates/relay-transforms/src/generate_relay_resolvers_operations_for_nested_objects.rs @@ -34,6 +34,7 @@ use schema::SDLSchema; use schema::Schema; use schema::Type; +use crate::generate_relay_resolvers_model_fragments::directives_with_artifact_source; use crate::get_normalization_operation_name; use crate::match_::RawResponseGenerationMode; use crate::relay_resolvers::get_bool_argument_is_true; @@ -498,24 +499,18 @@ pub fn generate_relay_resolvers_operations_for_nested_objects( let operation_name = generate_name_for_nested_object_operation(&program.schema, field); - let parent_documents = { - let mut parent_documents = HashSet::default(); - parent_documents.insert(operation_name.item.into()); - parent_documents - }; - - let directives = vec![ + let mut directives = directives_with_artifact_source(field); + directives.push( SplitOperationMetadata { location: field.name.location, - parent_documents, + parent_documents: Default::default(), derived_from: None, raw_response_type_generation_mode: Some( RawResponseGenerationMode::AllFieldsRequired, ), } .into(), - ]; - + ); let operation = OperationDefinition { name: operation_name, type_: field.type_.inner(), diff --git a/compiler/crates/relay-transforms/src/lib.rs b/compiler/crates/relay-transforms/src/lib.rs index 3b85a671a993b..e9f18c20ed49c 100644 --- a/compiler/crates/relay-transforms/src/lib.rs +++ b/compiler/crates/relay-transforms/src/lib.rs @@ -128,6 +128,7 @@ pub use generate_data_driven_dependency_metadata::generate_data_driven_dependenc pub use generate_data_driven_dependency_metadata::RelayDataDrivenDependencyMetadata; pub use generate_id_field::generate_id_field; pub use generate_live_query_metadata::generate_live_query_metadata; +pub use generate_relay_resolvers_model_fragments::ArtifactSourceKeyData; pub use generate_relay_resolvers_operations_for_nested_objects::generate_relay_resolvers_operations_for_nested_objects; pub use generate_typename::generate_typename; pub use generate_typename::TYPE_DISCRIMINATOR_DIRECTIVE_NAME; diff --git a/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-client-type.expected b/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-client-type.expected index f5d29acb29f36..91bc14c7263b8 100644 --- a/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-client-type.expected +++ b/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-client-type.expected @@ -30,13 +30,7 @@ query User__pop_star_name$normalization @__SplitOperationMetadata # SplitOperationMetadata { # derived_from: None, # location: output-type-client-type.graphql:81:94, -# parent_documents: { -# OperationDefinitionName( -# OperationDefinitionName( -# "User__pop_star_name$normalization", -# ), -# ), -# }, +# parent_documents: {}, # raw_response_type_generation_mode: Some( # AllFieldsRequired, # ), diff --git a/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-client-interface.expected b/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-client-interface.expected index a95e1223862fc..7b2a45485c51f 100644 --- a/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-client-interface.expected +++ b/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-client-interface.expected @@ -37,13 +37,7 @@ query User__pop_star_name$normalization @__SplitOperationMetadata # SplitOperationMetadata { # derived_from: None, # location: output-type-with-client-interface.graphql:195:208, -# parent_documents: { -# OperationDefinitionName( -# OperationDefinitionName( -# "User__pop_star_name$normalization", -# ), -# ), -# }, +# parent_documents: {}, # raw_response_type_generation_mode: Some( # AllFieldsRequired, # ), diff --git a/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-interface-recursion-but-lying-client-type.expected b/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-interface-recursion-but-lying-client-type.expected index 5931ba69b4e7e..b091b7e66b201 100644 --- a/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-interface-recursion-but-lying-client-type.expected +++ b/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-interface-recursion-but-lying-client-type.expected @@ -43,13 +43,7 @@ query User__pop_star_name$normalization @__SplitOperationMetadata # SplitOperationMetadata { # derived_from: None, # location: output-type-with-interface-recursion-but-lying-client-type.graphql:547:560, -# parent_documents: { -# OperationDefinitionName( -# OperationDefinitionName( -# "User__pop_star_name$normalization", -# ), -# ), -# }, +# parent_documents: {}, # raw_response_type_generation_mode: Some( # AllFieldsRequired, # ), diff --git a/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-relay-resolver-fields.expected b/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-relay-resolver-fields.expected index 5e5229c547d4f..512132c9c86c4 100644 --- a/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-relay-resolver-fields.expected +++ b/compiler/crates/relay-transforms/tests/generate_relay_resolvers_operations_for_nested_objects/fixtures/output-type-with-relay-resolver-fields.expected @@ -40,13 +40,7 @@ query User__pop_star_name$normalization @__SplitOperationMetadata # SplitOperationMetadata { # derived_from: None, # location: output-type-with-relay-resolver-fields.graphql:204:217, -# parent_documents: { -# OperationDefinitionName( -# OperationDefinitionName( -# "User__pop_star_name$normalization", -# ), -# ), -# }, +# parent_documents: {}, # raw_response_type_generation_mode: Some( # AllFieldsRequired, # ), diff --git a/compiler/test-project/src/__generated__/AppQuery.graphql.js b/compiler/test-project/src/__generated__/AppQuery.graphql.js index 5bbe3daa33018..0d80e43d1b4cf 100644 --- a/compiler/test-project/src/__generated__/AppQuery.graphql.js +++ b/compiler/test-project/src/__generated__/AppQuery.graphql.js @@ -4,7 +4,8 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> + * @flow * @lightSyntaxTransform * @nogrep */ @@ -13,7 +14,22 @@ 'use strict'; -var node = (function(){ +/*:: +import type { ConcreteRequest, Query } from 'relay-runtime'; +import type { Component_node$fragmentType } from "./Component_node.graphql"; +export type AppQuery$variables = {||}; +export type AppQuery$data = {| + +node: ?{| + +$fragmentSpreads: Component_node$fragmentType, + |}, +|}; +export type AppQuery = {| + response: AppQuery$data, + variables: AppQuery$variables, +|}; +*/ + +var node/*: ConcreteRequest*/ = (function(){ var v0 = [ { "kind": "Literal", @@ -96,6 +112,9 @@ return { }; })(); -node.hash = "942e72826c882d3a02cb0cfbf267dd83"; +(node/*: any*/).hash = "942e72826c882d3a02cb0cfbf267dd83"; -module.exports = node; +module.exports = ((node/*: any*/)/*: Query< + AppQuery$variables, + AppQuery$data, +>*/); diff --git a/compiler/test-project/src/__generated__/Component_node.graphql.js b/compiler/test-project/src/__generated__/Component_node.graphql.js index 961f909f02891..1519ba6c835c3 100644 --- a/compiler/test-project/src/__generated__/Component_node.graphql.js +++ b/compiler/test-project/src/__generated__/Component_node.graphql.js @@ -4,7 +4,8 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<264e4b506272789ae9a0f07604de0334>> + * @flow * @lightSyntaxTransform * @nogrep */ @@ -13,7 +14,22 @@ 'use strict'; -var node = { +/*:: +import type { Fragment, ReaderFragment } from 'relay-runtime'; +import type { FragmentType } from "relay-runtime"; +declare export opaque type Component_node$fragmentType: FragmentType; +export type Component_node$data = {| + +id: string, + +$fragmentType: Component_node$fragmentType, +|}; +export type Component_node$key = { + +$data?: Component_node$data, + +$fragmentSpreads: Component_node$fragmentType, + ... +}; +*/ + +var node/*: ReaderFragment*/ = { "argumentDefinitions": [], "kind": "Fragment", "metadata": null, @@ -31,6 +47,9 @@ var node = { "abstractKey": "__isNode" }; -node.hash = "c1076fdf6414be9f597194edf35d01a0"; +(node/*: any*/).hash = "c1076fdf6414be9f597194edf35d01a0"; -module.exports = node; +module.exports = ((node/*: any*/)/*: Fragment< + Component_node$fragmentType, + Component_node$data, +>*/);