fn resolve_completion_items_from_fields()

in compiler/crates/relay-lsp/src/completion/mod.rs [790:881]


fn resolve_completion_items_from_fields<T: TypeWithFields + Named>(
    type_: &T,
    schema: &SDLSchema,
    schema_documentation: impl SchemaDocumentation,
    existing_linked_field: bool,
) -> Vec<CompletionItem> {
    type_
        .fields()
        .iter()
        .map(|field_id| {
            let field = schema.field(*field_id);
            let field_name = field.name.item.to_string();
            let deprecated = field.deprecated();
            let is_deprecated = deprecated.is_some();
            let deprecated_reason = deprecated
                .and_then(|deprecated| deprecated.reason)
                .map(|reason| format!("Deprecated: {}", reason));
            let args = create_arguments_snippets(field.arguments.iter(), schema);
            let insert_text = match (
                existing_linked_field
                    || matches!(field.type_.inner(), Type::Scalar(_) | Type::Enum(_)), // don't insert { }
                args.is_empty(), // don't insert arguments
            ) {
                (true, true) => None,
                (true, false) => Some(format!("{}({})", field_name, args.join(", "))),
                (false, true) => Some(format!("{} {{\n\t$1\n}}", field_name)),
                (false, false) => Some(format!(
                    "{}({}) {{\n\t${}\n}}",
                    field_name,
                    args.join(", "),
                    args.len() + 1
                )),
            };
            let (insert_text_format, command) = if insert_text.is_some() {
                (
                    Some(lsp_types::InsertTextFormat::Snippet),
                    Some(lsp_types::Command::new(
                        "Suggest".into(),
                        "editor.action.triggerSuggest".into(),
                        None,
                    )),
                )
            } else {
                (None, None)
            };

            let type_description = schema_documentation
                .get_type_description(schema.get_type_name(field.type_.inner()).lookup());

            let field_description = schema_documentation
                .get_field_description(type_.name().lookup(), field.name.item.lookup());

            let type_name = schema.get_type_string(&field.type_);
            let documentation = make_markdown_table_documentation(
                field.name.item.lookup(),
                &type_name,
                field_description.unwrap_or(""),
                type_description.unwrap_or(""),
            );

            let kind = match field.type_.inner() {
                Type::Enum(_) => Some(CompletionItemKind::Enum),
                Type::Interface(_) => Some(CompletionItemKind::Interface),
                // There is no Kind for union, so we'll use interface
                Type::Union(_) => Some(CompletionItemKind::Interface),
                Type::Object(_) => Some(CompletionItemKind::Struct),
                Type::InputObject(_) => Some(CompletionItemKind::Struct),
                type_ if schema.is_string(type_) => Some(CompletionItemKind::Text),
                _ => Some(CompletionItemKind::Value),
            };

            CompletionItem {
                label: field_name,
                kind,
                detail: deprecated_reason.or(Some(type_name)),
                documentation: Some(documentation),
                deprecated: Some(is_deprecated),
                preselect: None,
                sort_text: None,
                filter_text: None,
                insert_text,
                insert_text_format,
                text_edit: None,
                additional_text_edits: None,
                command,
                data: None,
                tags: None,
                ..Default::default()
            }
        })
        .collect()
}