Skip to content

Pre-fill required registry module inputs on source completion #1029

Open
@dbanck

Description

@dbanck

Background

As part of #869 we introduced completion for registry module sources. The first version of the issue included resolving module inputs as well. After attempting this and running into a couple of nontrivial problems, we created this follow-up issue.

When a user requests auto-completion inside a module source, we send a search request to Algolia, returning all the matching modules. Furthermore, on selecting a completion item, VS Code will send a resolve request to the LS, which we intend to use for enriching the item with the module inputs fetched from the TF registry.

Expected User Experience

Fill the required module inputs when completing the module source:

2022-08-05 11 24 38

Provide a similar experience as for resources:
2022-08-05 11 26 59

This includes:

  • Using snippets with placeholders for tabbing through all inputs after insertion
  • Showing a preview if a user has editor.suggest.preview enabled

Challenges / Findings

  • While it's possible to set the insertTextFormat for the textEdit of a CompletionItem, it's ignored for additionalTextEdits. Without it, VS Code won't render any tabstops/placeholders.
  • A completionItem/resolve request can only update the following three properties:
    • documentation, detail, additionalTextEdits
    • Without being able to modify textEdit when resolving an item, all information must be part of the initial textDocument/completion request
    • Getting the module inputs requires a request to the registry. This would lead to a lot of overhead before we can even show any suggestions and 9/10 module inputs would be discarded afterwards, since the user picks only one item
  • The editor.suggest.preview feature only shows modifications done by the textEdit and doesn't show any modifications done by additionalTextEdits

Proposal

hashicorp/hcl-lang

To be able to build the additionalTextEdits, we need more context inside the resolve hook:

  • Extend UnresolvedCandidate
    • with the candidate label / insert text
    • the position (we can get this from the candidate's textEdit)

hashicorp/terraform-ls

  • Add a ResolveRegistryModuleSource hook
func (h *Hooks) ResolveRegistryModuleSource(ctx context.Context, unresolvedCandidate decoder.UnresolvedCandidate) (*decoder.ResolvedCandidate, error) {
	candidate := decoder.ResolvedCandidate{}

	source, err := strconv.Unquote(unresolvedCandidate.Label) // or use unresolvedCandidate.RawInsertText
	if err != nil {
		return &candidate, err
	}
	addr, err := tfaddr.ParseModuleSource(source)
	if err != nil {
		return &candidate, err
	}

	modMeta, err := h.RegistryClient.GetModuleData(ctx, addr, nil)
	if err != nil {
		return &candidate, err
	}

	inputs := convertInputs(modMeta.Root.Inputs)
	// TODO: generate snippet from inputs
	candidate.AdditionalTextEdits = ...

	return &candidate, nil
}
  • Extend CompletionItemResolve handler to add more context to the UnresolvedCandidate

Additional context / links

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions