in compiler/crates/relay-lsp/src/completion/mod.rs [201:333]
fn build_request_from_selections(
&self,
selections: &List<Selection>,
position_span: Span,
mut type_path: Vec<TypePathItem>,
) -> Option<CompletionRequest> {
for item in &selections.items {
if item.span().contains(position_span) {
return match item {
Selection::LinkedField(node) => {
if node.name.span.contains(position_span) {
return Some(self.new_request(
CompletionKind::FieldName {
existing_linked_field: true,
},
type_path,
));
}
let LinkedField {
name,
selections,
directives,
arguments,
..
} = node;
type_path.push(TypePathItem::LinkedField { name: name.value });
if let Some(arguments) = arguments {
if arguments.span.contains(position_span) {
return self.build_request_from_arguments(
arguments,
position_span,
type_path,
ArgumentKind::Field,
);
}
}
self.build_request_from_selection_or_directives(
selections,
directives,
DirectiveLocation::Field,
position_span,
type_path,
)
}
Selection::FragmentSpread(spread) => {
let FragmentSpread {
name, directives, ..
} = spread;
if name.span.contains(position_span) {
Some(self.new_request(CompletionKind::FragmentSpread, type_path))
} else {
self.build_request_from_directives(
directives,
DirectiveLocation::FragmentSpread,
position_span,
type_path,
Some(name.value),
)
}
}
Selection::InlineFragment(node) => {
let InlineFragment {
selections,
directives,
type_condition,
..
} = node;
if let Some(type_condition) = type_condition {
let type_name = type_condition.type_.value;
if type_condition.span.contains(position_span) {
return Some(self.new_request(
CompletionKind::InlineFragmentType {
existing_inline_fragment: selections.start.kind
!= TokenKind::Empty,
},
type_path,
));
}
type_path.push(TypePathItem::InlineFragment { type_name });
}
self.build_request_from_selection_or_directives(
selections,
directives,
DirectiveLocation::InlineFragment,
position_span,
type_path,
)
}
Selection::ScalarField(node) => {
if node.name.span.contains(position_span) {
return Some(self.new_request(
CompletionKind::FieldName {
existing_linked_field: false,
},
type_path,
));
}
let ScalarField {
directives,
name,
arguments,
..
} = node;
type_path.push(TypePathItem::ScalarField { name: name.value });
if let Some(arguments) = arguments {
if arguments.span.contains(position_span) {
return self.build_request_from_arguments(
arguments,
position_span,
type_path,
ArgumentKind::Field,
);
}
}
self.build_request_from_directives(
directives,
DirectiveLocation::Field,
position_span,
type_path,
None,
)
}
};
}
}
// The selection list is empty or the current cursor is out of any of the selection
Some(self.new_request(
CompletionKind::FieldName {
existing_linked_field: false,
},
type_path,
))
}