Skip to content

Promote FunctionParameter.type to TPowerQueryType; fix isCompatible left-side Any/AnyUnion and two related bugs - #414

Open
JordanBoltonMN wants to merge 4 commits into
masterfrom
dev/jobolton/function-parameter-type-refactor
Open

Promote FunctionParameter.type to TPowerQueryType; fix isCompatible left-side Any/AnyUnion and two related bugs#414
JordanBoltonMN wants to merge 4 commits into
masterfrom
dev/jobolton/function-parameter-type-refactor

Conversation

@JordanBoltonMN

@JordanBoltonMN JordanBoltonMN commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Promotes FunctionParameter.type from TypeKind | undefined to the full TPowerQueryType | undefined, and fixes a family of latent bugs in isCompatible around bare Any/AnyUnion on the left-hand side (plus two additional pre-existing bugs discovered nearby during review).

Motivation

isValidInvocation/typeCheckInvocation previously collapsed isCompatible's three-state result (true / false / undefined) incorrectly in several branches, and FunctionParameter could only express a primitive TypeKind, losing nullability/extended-type fidelity (e.g. list, record, table parameter types). This blocked a downstream ask from powerquery-language-services for richer parameter type information in hover/signature-help/diagnostics.

Changes

  • isCompatible.ts: Added explicit handling for Any/AnyUnion on the left-hand side.
    • Bare Any on the left → undefined (indeterminate) in general — it represents absence of constraint, not proof of compatibility, so it must not short-circuit to true. Two deterministic exceptions are special-cased: right = AnyNonNulltrue (a non-nullable Any trivially satisfies "anything but null"), right = Nullfalse (bare Any can never be exactly null).
    • AnyUnion on the left → new isAnyUnionCompatibleWith helper using all-semantics (false on any definite mismatch, undefined if any member is indeterminate, else true).
    • Renamed isCompatibleWithAnyUnionisRightAnyUnionCompatible for clarity (unioned type on the right retains existing some-semantics), and fixed a pre-existing bug: it previously used a truthy check that collapsed an indeterminate member to a hard false; it now correctly returns undefined when no member is definitely true but at least one is indeterminate.
    • Deleted isCompatibleWithFunctionParameter (superseded by direct isCompatible calls in typeCheckInvocation).
    • Fixed a pre-existing bug in isDefinedListTypeCompatibleWithListType: it used Boolean(array.find(v => v === undefined || v === false)), which is unconditionally false regardless of input (Array.find returns undefined on "not found," and Boolean of undefined/false is always false). Replaced with .every(v => v === true), so this compatibility check — previously non-functional — now actually reports true when every list item type matches.
  • type.ts: FunctionParameter.type is now TPowerQueryType | undefined; isNullable is removed and folded into type — an optional parameter's implied nullability is now baked into the constructed type (optional implies nullable).
  • typeUtils.ts: inspectAstParameter/inspectContextParameter updated to construct full types per the above. Removed isValidInvocation — dead code with zero callers in this repo and in powerquery-language-services (superseded entirely by typeCheckInvocation).
  • typeCheck.ts: CheckedInvocation gained an indeterminate: ReadonlyArray<number> bucket. typeCheckInvocation rewritten to explicitly bucket each argument index into valid/invalid/missing/indeterminate based on isCompatible's tri-state result, rather than conflating them via isCompatibleWithFunctionParameter. Also made two pre-existing truthiness collapses explicit (=== true) now that isCompatible can return undefined.
  • nameOf.ts / isEqualType.ts: Updated to work against the new FunctionParameter.type shape.
  • Test suites updated across isCompatible.test.ts, isEqualType.test.ts, nameOf.test.ts, typeCheck.test.ts, typeUtils.test.ts to match, including new coverage for the Any/AnyUnion-on-the-left fix and both additional bug fixes above.

Compatibility note

CheckedInvocation's new indeterminate field and FunctionParameter's shape change are public API surface changes. powerquery-language-services pins a specific parser version, so this is non-breaking until it explicitly bumps its dependency (tracked separately).

Testing

  • npm run build — clean
  • npm run lint — clean
  • npm test — 705 passing, 0 failing, 1 pending

Jordan Bolton (jobolton) and others added 2 commits August 24, 2026 14:10
…eft-side Any/AnyUnion handling

- isCompatible: bare Any and AnyUnion on the left now resolve correctly
  instead of short-circuiting to true/false (fixes several latent
  isValidInvocation bugs around indeterminate results).
- FunctionParameter.type is now TPowerQueryType | undefined instead of
  TypeKind | undefined; isNullable is folded into type (optional implies
  nullable).
- typeCheckInvocation/CheckedInvocation gained an indeterminate bucket
  for arguments that can't be definitively ruled valid or invalid.
- Migrated nameOf/isEqualType/typeCheck consumers and all affected
  parser test literals to the new model.
- Removed isValidInvocation (dead code, superseded by
  typeCheckInvocation, zero callers in this repo or powerquery-language-services).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 39041e13-1ee5-4083-a312-1101ec33bc23
…mpatible bugs

- isCompatible: bare Any on the left now special-cases right=AnyNonNull
  (true) and right=Null (false) before falling back to indeterminate,
  restoring precise pre-refactor results for these two deterministic
  cases.
- isRightAnyUnionCompatible: fixed truthy-check collapsing an
  indeterminate union member to a hard false; now correctly returns
  undefined when no member is definitely true but one is indeterminate.
- isDefinedListTypeCompatibleWithListType: fixed an always-false
  Boolean(array.find(...)) result; now uses .every() so a defined list
  type can actually be reported compatible with a list type.
- Removed inline D1/D2/D3 planning-phase labels from code comments.
- Added regression tests for all of the above.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 39041e13-1ee5-4083-a312-1101ec33bc23
@JordanBoltonMN JordanBoltonMN changed the title Promote FunctionParameter.type to TPowerQueryType; fix isCompatible left-side Any/AnyUnion Promote FunctionParameter.type to TPowerQueryType; fix isCompatible left-side Any/AnyUnion and two related bugs Aug 24, 2026
Jordan Bolton (jobolton) and others added 2 commits August 24, 2026 16:18
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 39041e13-1ee5-4083-a312-1101ec33bc23
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 39041e13-1ee5-4083-a312-1101ec33bc23
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.

1 participant