Skip to content

Commit

Permalink
Improve fragment and fragment spread hover
Browse files Browse the repository at this point in the history
Summary: Fragments and fragment spreads have access to documentation and source links for parent types but we don't currently display them. Improve the on hover information to include both a description of the parent type and a link to the source definition if possible.

Reviewed By: ginfung

Differential Revision: D46812089

fbshipit-source-id: da2d4634bce22690646b45e2541fbfb567ac4f15
  • Loading branch information
Catherine Chen authored and facebook-github-bot committed Jun 26, 2023
1 parent 091a4f0 commit 699b0ab
Showing 1 changed file with 81 additions and 37 deletions.
118 changes: 81 additions & 37 deletions compiler/crates/relay-lsp/src/hover/with_resolution_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ fn get_hover_contents<'a>(
fragment_spread_path,
schema,
schema_name,
schema_documentation,
program,
content_consumer_type,
),
Expand All @@ -492,6 +493,7 @@ fn get_hover_contents<'a>(
fragment_definition,
schema,
schema_name,
schema_documentation,
content_consumer_type,
),

Expand Down Expand Up @@ -689,8 +691,9 @@ fn get_scalar_or_linked_field_hover_content(

if let Some(field_type_hack_source) = schema_documentation.get_hack_source(field_type_name) {
hover_contents.push(MarkedString::String(format!(
"Type: [**{}**](https://www.internalfb.com/code/symbol/www/php/{})",
type_name, field_type_hack_source,
"Type: [**{}**]({})",
type_name,
codex_url_for_symbol(field_type_hack_source),
)));
} else {
hover_contents.push(MarkedString::String(format!("Type: **{}**", type_name,)));
Expand Down Expand Up @@ -754,12 +757,10 @@ fn get_scalar_or_linked_field_hover_content(
if let Some(field_hack_source) =
schema_documentation.get_field_hack_source(parent_type_name, field.name.item.lookup())
{
// replace instances of "::" with "/" to avoid breaking codex links
let field_hack_source_url_path = str::replace(field_hack_source, "::", "/");

hover_contents.push(MarkedString::String(format!(
"View [**{}**](https://www.internalfb.com/code/symbol/www/php/{}) in Codex",
field_hack_source, field_hack_source_url_path,
"View [**{}**]({}) in Codex",
field_hack_source,
codex_url_for_symbol(field_hack_source),
)));
}

Expand Down Expand Up @@ -825,8 +826,9 @@ fn on_hover_inline_fragment(

if let Some(hack_source) = schema_documentation.get_hack_source(inline_fragment_condition) {
let codex_link = MarkedString::String(format!(
"View [**{}**](https://www.internalfb.com/code/symbol/www/php/{}) in Codex",
hack_source, hack_source,
"View [**{}**]({}) in Codex",
hack_source,
codex_url_for_symbol(hack_source),
));
hover_contents.push(codex_link);
}
Expand All @@ -838,6 +840,7 @@ fn on_hover_fragment_spread<'a>(
fragment_spread_path: &'a FragmentSpreadPath<'a>,
schema: &SDLSchema,
schema_name: StringKey,
schema_documentation: &impl SchemaDocumentation,
program: &Program,
content_consumer_type: ContentConsumerType,
) -> Option<HoverContents> {
Expand All @@ -858,17 +861,19 @@ fn on_hover_fragment_spread<'a>(
.get_type_name(fragment_definition.type_condition)
.lookup();

let rendered_fragment_type_name = content_consumer_type.render_text_with_params(
fragment_type_name,
&GraphQLSchemaExplorerParams {
path: vec![fragment_type_name],
schema_name: schema_name.lookup(),
filter: None,
},
);

hover_contents.push(MarkedString::String(format!(
"fragment {} on {}",
fragment_spread.name.value.lookup(),
content_consumer_type.render_text_with_params(
fragment_type_name,
&GraphQLSchemaExplorerParams {
path: vec![fragment_type_name],
schema_name: schema_name.lookup(),
filter: None
}
)
rendered_fragment_type_name,
)));

if !fragment_definition.variable_definitions.is_empty() {
Expand Down Expand Up @@ -926,6 +931,23 @@ For example:
));
}

if let Some(type_description) = schema_documentation.get_type_description(fragment_type_name) {
if let Some(hack_source) = schema_documentation.get_hack_source(fragment_type_name) {
hover_contents.push(MarkedString::String(format!(
"Type Condition: on [**{}**]({})",
rendered_fragment_type_name,
codex_url_for_symbol(hack_source),
)));
} else {
hover_contents.push(MarkedString::String(format!(
"Type Condition: on **{}**",
rendered_fragment_type_name,
)));
}

hover_contents.push(MarkedString::String(type_description.to_string()));
}

Some(HoverContents::Array(hover_contents))
}

Expand Down Expand Up @@ -970,6 +992,7 @@ fn on_hover_fragment_definition(
fragment_definition: &FragmentDefinition,
schema: &SDLSchema,
schema_name: StringKey,
schema_documentation: &impl SchemaDocumentation,
content_consumer_type: ContentConsumerType,
) -> Option<HoverContents> {
let fragment_name = fragment_definition.name.value;
Expand All @@ -978,35 +1001,56 @@ fn on_hover_fragment_definition(

let type_name = schema.get_type_name(fragment_type);

let rendered_parent_type_name = content_consumer_type.render_text_with_params(
type_name.lookup(),
&GraphQLSchemaExplorerParams {
path: vec![type_name.lookup()],
schema_name: schema_name.lookup(),
filter: None,
},
);

let title = MarkedString::from_markdown(format!(
"fragment {} on {}",
fragment_name,
content_consumer_type.render_text_with_params(
type_name.lookup(),
&GraphQLSchemaExplorerParams {
path: vec![type_name.lookup()],
schema_name: schema_name.lookup(),
filter: None
}
)
fragment_name, rendered_parent_type_name
));

let hover_contents = if matches!(content_consumer_type, ContentConsumerType::Relay) {
HoverContents::Array(vec![
title,
MarkedString::String(
r#"Fragments let you select fields,
let mut hover_contents: Vec<MarkedString> = vec![title];

if matches!(content_consumer_type, ContentConsumerType::Relay) {
hover_contents.push(MarkedString::String(
r#"Fragments let you select fields,
and then include them in queries where you need to.
---
@see: https://graphql.org/learn/queries/#fragments
"#
.to_string(),
),
])
} else {
HoverContents::Scalar(title)
.to_string(),
))
};

Some(hover_contents)
if let Some(type_description) = schema_documentation.get_type_description(type_name.lookup()) {
if let Some(hack_source) = schema_documentation.get_hack_source(type_name.lookup()) {
hover_contents.push(MarkedString::String(format!(
"Type Condition: on [**{}**]({})",
rendered_parent_type_name,
codex_url_for_symbol(hack_source),
)));
} else {
hover_contents.push(MarkedString::String(format!(
"Type Condition: on **{}**",
rendered_parent_type_name
)));
}

hover_contents.push(MarkedString::String(type_description.to_string()));
}

Some(HoverContents::Array(hover_contents))
}

fn codex_url_for_symbol(symbol: &str) -> String {
// sanitize the symbol first by replacing instances of "::" with "/" to avoid breaking codex links
let sanitized_symbol = str::replace(symbol, "::", "/");
format!("https://www.internalfb.com/code/symbol/www/php/{sanitized_symbol}")
}

0 comments on commit 699b0ab

Please sign in to comment.