How much of this was how bazel works vs. starlark itself?
I find the starlark language is very simple (though inconsistent between the various implementations in bazel, go, and rust) but it takes a bit to understand how the magic between defining rules and implementations works in bazel. and TBH, that is also one place I've really needed auto-completion/static typing in starlark to understand what I can/cannot do.
bazel-lsp gives quite good autocompletion in my experience, for what that's worth. About the only trouble I have still is that sometimes paths in load() calls don't complete properly.