Skip to content

feat(temporal): resolve executor struct-field dispatch#86

Draft
avfirsov wants to merge 1 commit into
zzet:mainfrom
avfirsov:feat/temporal-executor-dispatch
Draft

feat(temporal): resolve executor struct-field dispatch#86
avfirsov wants to merge 1 commit into
zzet:mainfrom
avfirsov:feat/temporal-executor-dispatch

Conversation

@avfirsov

Copy link
Copy Markdown
Contributor

What

Resolves Temporal dispatch where the activity/workflow name is a receiver field whose literal is set at struct construction:

type ActivityExecutor struct{ ActivityName string }
func (e ActivityExecutor) Run(ctx workflow.Context) {
    workflow.ExecuteActivity(ctx, e.ActivityName)        // name = receiver field
}
exec := ActivityExecutor{ActivityName: "ChargeCard"}     // the literal lives here

The dispatch only sees e.ActivityName (not a literal), so it never resolved. This joins the dispatch to the construction-site literal by (receiver type, field).

How

Extractor (golang.go / golang_temporal.go):

  • a fieldstr tree-sitter pattern collects Type{Field: "literal"} struct-field assignments, emitted as via=temporal.executor-field marker edges carrying executor_type / executor_field / executor_value;
  • the dispatch stub is stamped temporal_name_field + temporal_recv_type when the dispatch argument is <receiver>.<field>;
  • helper goCompositeLiteralType; a recvTypeByID map; and the call AST node on the deferred-call struct so the calls loop can inspect the dispatch arg.

Resolver (temporal_calls.go):

  • resolveTemporalExecutorFields joins a dispatch's (recv_type, field) to a construction literal and rewrites the dispatching method's stub name to that literal — so the existing sweep lands it on the registered handler and callers of the activity surface the dispatching method (not the constructor). Wired at the top of ResolveTemporalCalls; self-guards; recompute-safe; unique-or-nothing on conflicting literals (matching the const-deref policy).

Scope

  • Only executor-field resolution. Cross-language / const-deref / env-default / wrapper-following are untouched.

Tests

  • resolver unit (field-meta stub + executor-field marker → resolved edge),
  • extractor unit (temporal_name_field/temporal_recv_type on the stub; executor_* on the marker),
  • end-to-end index→resolve test on real Go source.

go build ./... and go test -race ./internal/resolver/... ./internal/parser/languages/... ./internal/indexer/... pass.

🤖 Generated with Claude Code

Resolve Temporal dispatch where the activity/workflow name is a receiver
field whose literal is set at struct construction:

    type ActivityExecutor struct{ ActivityName string }
    func (e ActivityExecutor) Run(ctx workflow.Context) {
        workflow.ExecuteActivity(ctx, e.ActivityName)        // name = recv field
    }
    exec := ActivityExecutor{ActivityName: "ChargeCard"}     // literal here

The dispatch sees `e.ActivityName` (not a literal) and the literal lives at
the construction site; this joins the two by (receiver type, field).

Extractor (golang.go / golang_temporal.go):
- a `fieldstr` tree-sitter pattern collects `Type{Field: "literal"}` struct
  field assignments; emitted as `via=temporal.executor-field` marker edges
  carrying executor_type / executor_field / executor_value;
- the dispatch stub is stamped `temporal_name_field` + `temporal_recv_type`
  when the dispatch arg is `<receiver>.<field>`;
- helper `goCompositeLiteralType`; `recvTypeByID` map; `callNode` on the
  deferred-call struct so the calls loop can inspect the dispatch arg.

Resolver (temporal_calls.go):
- `resolveTemporalExecutorFields` joins dispatch (recv_type, field) to a
  construction literal and rewrites the method's stub name to that literal,
  so the existing sweep lands it on the registered handler and callers of
  the activity surface the dispatching method. Wired at the top of
  `ResolveTemporalCalls`; self-guards; recompute-safe; unique-or-nothing on
  conflicting construction literals.

Cross-language / const-deref / env-default / wrapper-following untouched.

Tests: resolver unit, extractor unit (field meta + marker), e2e.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@avfirsov avfirsov force-pushed the feat/temporal-executor-dispatch branch from db1b05e to de36f95 Compare June 13, 2026 09: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.

1 participant