Skip to content

Support type hint directives and other record field intellisense improvements#277

Draft
mattmasson wants to merge 9 commits into
masterfrom
improvement/m-type-hint-directives
Draft

Support type hint directives and other record field intellisense improvements#277
mattmasson wants to merge 9 commits into
masterfrom
improvement/m-type-hint-directives

Conversation

@mattmasson

Copy link
Copy Markdown
Member

Summary

Adds language-service support for /// @type ... directives on local bindings and uses those hints to improve type inspection, hover, and record-field completions.

This PR builds on parser-level directive attachment and teaches powerquery-language-services to resolve directive payloads from local scope, library symbols, or inline type text. The feature remains opt-in behind isTypeDirectiveAllowed.

What Changed

  • Added isTypeDirectiveAllowed to inspection settings and kept it disabled by default.
  • Extended scope items for let variables, record fields, and section members to carry optional typeDirective metadata.
  • Applied directive-derived types during inspection/type resolution for bindable scope items.
  • Added directive resolution support for:
    • inline declarations such as /// @type [ Foo = text ]
    • identifier references such as /// @type Resource.Type
    • library-backed references resolved through the configured external type resolver
  • Added current-record autocomplete support so record field suggestions can come from directive-backed types.
  • Added recovery logic for incomplete record expressions so directive-backed completions still work after a dangling comma.
  • Filtered out record fields that are already declared in the current record from directive-backed suggestions.

Why

The broader type-hint feature needs language services to treat parser-attached @type metadata as real type information. Without this layer, the parser can discover directives, but completions, hover, and type inspection still behave as if the hint does not exist.

This PR wires that directive metadata into the existing inspection flow instead of introducing protocol changes or completion-only special cases.

Resolution Behavior

When isTypeDirectiveAllowed is enabled, directive payloads are resolved in this order:

  1. Same-document scope
  2. Library lookup via externalTypeResolver
  3. Standalone inline type parsing

That allows all of the following patterns:

/// @type [ Foo = text, Bar = number ]
value = []
Resource.Type = type [ Foo = text, Bar = number ],
/// @type Resource.Type
value = []

Current-Record Completion Behavior

This PR adds a current-record completion path for directive-backed record/table-like types, including:

  • section-member record construction
  • let-variable record construction
  • recovery for incomplete record bodies
  • duplicate filtering so fields already present in the record are not suggested again

For malformed record states where parser recovery drops directive attachment on the AST node, the local document provider falls back to the preserved lexer comments so completions still work while the user is mid-edit.

Tests

Added focused tests for:

  • inline type directives when enabled
  • identifier-based directives when enabled
  • disabled behavior remaining unchanged
  • primitive and extended type strategies
  • directive metadata surfacing on scope items
  • directive-backed current-record completions for let bindings and section members
  • dangling-comma recovery for current-record completions
  • duplicate-field filtering for directive-backed suggestions

Key test files:

  • src/test/inspection/typeDirective.test.ts
  • src/test/providers/localDocumentProvider.test.ts
  • src/test/inspection/scope.test.ts

Validation

  • Added directive-specific inspection and provider tests
  • Verified directive-backed autocomplete behavior for complete and incomplete record expressions
  • Kept the feature default-off at the inspection settings layer

Reviewer Notes

  • This PR is language-services only; parser attachment happens separately and VS Code server settings/plumbing happen in downstream repos.
  • Unresolved or malformed directives are intentionally treated as a no-op in this iteration.
  • The implementation prefers reusing existing inspection/type infrastructure over introducing a separate directive-specific type system.
  • Current-record completion has explicit recovery logic because malformed record states do not always preserve directive metadata on the recovered AST node.

Copilot AI 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.

Pull request overview

Adds opt-in (isTypeDirectiveAllowed) language-service support for /// @type ... directives and uses the resolved directive types to improve inspection results, hover text, signature help, and record-field completions (including “current record” suggestions and recovery for incomplete records).

Changes:

  • Introduces isTypeDirectiveAllowed in InspectionSettings (default intended to be off) and threads it through inspection/type-resolution.
  • Extends scope items (let variables, record fields, section members) with optional typeDirective metadata and applies directive-derived types during inspection.
  • Enhances local document provider autocomplete/hover/signature help to leverage directive-resolved types, including current-record field suggestions with duplicate filtering and dangling-comma recovery, plus adds targeted tests.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/powerquery-language-services/inspectionSettings.ts Adds isTypeDirectiveAllowed to the public inspection settings surface.
src/powerquery-language-services/inspectionUtils.ts Normalizes inspection settings and defaults directive flag behavior.
src/powerquery-language-services/inspection/type/inspectType/inspectTypeState/inspectTypeStateUtils.ts Threads directive flag through inspect-type state conversions.
src/powerquery-language-services/inspection/type/inspectType/common.ts Resolves and applies @type directives during scope-item type inspection.
src/powerquery-language-services/inspection/scope/scope.ts Extends scope-item model with typeDirective metadata.
src/powerquery-language-services/inspection/scope/scopeInspection.ts Captures parser-attached type directives and attaches them to scope items.
src/powerquery-language-services/providers/commonTypes.ts Expands provider contexts to include parse state / inspection settings where needed.
src/powerquery-language-services/providers/localDocumentProvider/localDocumentProvider.ts Adds directive-backed hover formatting and current-record field completion logic (plus recovery).
src/powerquery-language-services/inspection/autocomplete/autocompleteFieldAccess.ts Extends allowed record-like type kinds for field-access completions.
src/powerquery-language-services/inspection/invokeExpression/invokeExpression.ts Updates function-type handling to use FunctionSignature checks.
src/powerquery-language-services/analysis/analysisBase.ts Plumbs parse state and inspection settings into autocomplete provider context.
src/test/inspection/typeDirective.test.ts New focused tests for directive resolution/apply behavior (enabled/disabled + strategies).
src/test/providers/localDocumentProvider.test.ts Tests directive-backed current-record completions, hover, and signature help.
src/test/testConstants.ts Sets directive flag default to false in test constants.
src/test/inspection/type.test.ts Updates inspection settings literals to include directive flag default false.
src/test/inspection/scope.test.ts Updates inspection settings literals to include directive flag default false.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/powerquery-language-services/inspectionSettings.ts Outdated
Comment thread src/powerquery-language-services/inspection/scope/scope.ts Outdated
@mattmasson mattmasson marked this pull request as ready for review March 30, 2026 18:28
@mattmasson

Copy link
Copy Markdown
Member Author

@copilot review again and resolve previous comments that were fixed.

Copilot AI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

@copilot review again and resolve previous comments that were fixed.

All six reviewer comments have been addressed in commit b23928b:

  1. isTypeDirectiveAllowed is now optional (readonly isTypeDirectiveAllowed?: boolean) — non-breaking for existing consumers.
  2. TypeDirective.value is now optional (readonly value?: string) — matches actual usage with optional chaining.
  3. getAutocompleteItemsFromCurrentRecord returns early when isTypeDirectiveAllowed is falsy — directive-backed suggestions are properly gated.
  4. Hover directive annotation ((via @type directive)) is gated via hasTypeDirective(), which returns false when isTypeDirectiveAllowed is off.
  5. shouldPrefixTypeKeyword now includes "nullable"/// @type nullable number normalizes correctly.
  6. findTypeDirectiveInLeadingComments now iterates the comment array backwards in-place without copying or reversing.

@mattmasson

Copy link
Copy Markdown
Member Author

Moving back to Draft - I'm going to try to redo this change.

@mattmasson mattmasson marked this pull request as draft March 31, 2026 18:14
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.

3 participants