Skip to content

Add do snippet, structural snippets, and use-injection dedup (#73)#76

Open
JesseHerrick wants to merge 3 commits into
mainfrom
fix/do-completion-snippets
Open

Add do snippet, structural snippets, and use-injection dedup (#73)#76
JesseHerrick wants to merge 3 commits into
mainfrom
fix/do-completion-snippets

Conversation

@JesseHerrick

@JesseHerrick JesseHerrick commented Jun 7, 2026

Copy link
Copy Markdown
Member

Closes #73

  • Add "do" to elixirFormSnippets: expands to do..end block with tab stop
    when snippet support is enabled; falls back to plain keyword with
    Preselect when snippet support is off.
  • Add structural snippets with parameter slots:
    defmodule, def, defp, defmacro, defmacrop
  • Update if snippet to include else clause.
  • Add test and describe snippets for ExUnit.
  • Add elixirKeywords list: do and end appear as plain keyword completions
    to prevent VS Code from falling back to word-based suggestions.
  • Add form-snippet dedup in addCompletionsFromUsing: use-injected
    functions (e.g. ExUnit.Case.test/1) no longer duplicate with their
    form snippet counterpart.

Note

Low Risk
Changes are limited to LSP completion insert text and parser token validation for def names; no runtime or security-sensitive paths.

Overview
Improves Dexter LSP completions so Elixir editing in VS Code feels closer to built-in language support: richer snippets, fewer duplicates, and more idiomatic insert text.

Special forms and keywords: elixirFormSnippets now covers structural macros (defmodule, def/defp, defstruct, guards, etc.), adds a doend snippet, and extends if with an else branch. do and end also appear as plain keyword items (elixirKeywords with Preselect) so Enter does not swap them for word-based suggestions when snippets are off.

Use-chain dedup: When snippet support is on, addCompletionsFromUsing (and import listing) skips functions whose names already have a global form snippet (e.g. Kernel if vs snippet if).

Imported macros: doBlockSnippets (e.g. test, describe, setup) override generic arg-list snippets; noParenFuncs formats ExUnit-style macros as assert expr instead of assert(expr).

Parser: isValidFuncNameToken treats defstruct / defprotocol-style tokens as valid names after defmacro, matching Kernel definitions for indexing.

Tests cover snippets, dedup, do keyword behavior, do-block snippets, and no-paren call style.

Reviewed by Cursor Bugbot for commit c66c424. Bugbot is set up for automated code reviews on this repo. Configure here.

- Add "do" to elixirFormSnippets: expands to do..end block with tab stop
  when snippet support is enabled; falls back to plain keyword with
  Preselect when snippet support is off.
- Add structural snippets with parameter slots:
  defmodule, def, defp, defmacro, defmacrop
- Update if snippet to include else clause.
- Add test and describe snippets for ExUnit.
- Add elixirKeywords list: do and end appear as plain keyword completions
  to prevent VS Code from falling back to word-based suggestions.
- Add form-snippet dedup in addCompletionsFromUsing: use-injected
  functions (e.g. ExUnit.Case.test/1) no longer duplicate with their
  form snippet counterpart.
@JesseHerrick JesseHerrick changed the title feat: add do snippet, structural snippets, and use-injection dedup (#73) Add do snippet, structural snippets, and use-injection dedup (#73) Jun 7, 2026
…no-paren call style

- Add 8 new Elixir form snippets: defstruct, defexception, defprotocol,
  defimpl, defdelegate, defguard, defguardp, defoverridable
- Fix parser bug: defmacro defstruct(fields) (and defexception, defprotocol,
  defimpl) were silently skipped because the tokenizer emits dedicated token
  types (TokDefstruct etc.) but the def* handler only accepted TokIdent.
  Add isValidFuncNameToken() to also accept these four def-related tokens.
- Add noParenFuncs map for ExUnit macros conventionally written without
  parentheses (assert, refute, test, describe, etc.)
- Add doBlockSnippets map for function-specific do/end block templates
  (test, describe, setup, setup_all, assert_raise), scoped to import/use-chain
- Extend applySnippet and buildCallText with noParen parameter for
  no-paren call style (name arg1, arg2 instead of name(arg1, arg2))
- Keep descriptive placeholder hints (e.g. ${1:name}) on all snippets;
  defstruct/defexception use ${1:fields} as a hint, not hardcoded values
- Add 6 new tests: DoBlockSnippets (with/without snippet support),
  NoParenCallStyle (with/without snippet support), DoKeyword,
  UseInjectedSkippedForFormSnippet
- Extend existing tests: 8 new sub-tests in ElixirFormSnippets,
  refactored NoDuplicateWithKernel to loop-driven checks

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit cf0b685. Configure here.

Comment thread internal/lsp/server.go
item.InsertTextFormat = protocol.InsertTextFormatSnippet
item.InsertText = tmpl
return
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doBlockSnippets ignore definition kind

Medium Severity

applySnippet selects doBlockSnippets using only the function name, so any in-scope completion named test, describe, setup, setup_all, or assert_raise gets an ExUnit-style do/end insert even when the indexed definition is an ordinary def (or a non-macro export), producing invalid or surprising insert text.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit cf0b685. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

VS Code: Autocomplete for do keyword is defoverridable

2 participants