ITADN

Cross-file symbol resolution

#1148Openlionel- 创建于 2026-04-14
area: language server
L
lionel-commented
The semantic index (https://github.com/posit-dev/ark/issues/1141) implements file-local resolution. When a symbol is unbound (or maybe unbound in a control flow path), we need to look up the "global" definition instead. The cross-file layer will be in charge of doing that resolution. There are multiple things that feed into the resolution. For instance in packages: - The collation order of files determines what a file sees (e.g. symbols in `aaa.R` do not see those in `zzz.R`). - Declared imports in NAMESPACE, Depends field in DESCRIPTION - In test files, helpers are collated, as well as the parent test file (`tests/testthat.R`) And within R files: - `library()` and `source()` affect the search path and global env _after_ they have been called. We can model all of this using a chain of scopes: ```rs enum BindingSource { /// Bindings from a project file FileExports { file: Url, exports: Vec<(String, TextRange)> }, /// importFrom(pkg, name) ImportedNames(HashMap<String, PackageId>), /// All exports of an attached package (`library()` or NAMESPACE `import()`) PackageExports(PackageId), /// Full namespace, e.g. for `load_all()` semantics in tests PackageInternals(PackageId), /// Base R, the last scope in the chain Base, } ``` `FileExports` would be resolved from a file's semantic index. We already keep track of top-level definitions (ones in the 0th top-level scope). The index should also keep track of calls like `library()` and `require()` called at top-level. Note that these may not necessarily be called in the top-level scope, they can be called in NSE subscopes as long as they are called eagerly, e.g. `local(library(foo))`. The same `BindingSource` model works both for the cross-file chain and for within-file directive tracking. For resolution within a file, unbound symbols start with a default `Vec<BindingSource>` representing the initial search path state. Then for each `library()` or `source()` call, we push a layer on the stack. (We might want to use deque.) - [x] Add binding sources, semantic index directives (`library()` and `require()`) and the external resolution routine. https://github.com/posit-dev/ark/pull/1151 - [x] In packages, create a scope chain for files in `R/` (files in `tests/` and `tests/testthat` later on?). https://github.com/posit-dev/ark/pull/1152 - [ ] `source()` directives imports top-level definitions and inner directives (e.g. `library()` side effects). Related issue: https://github.com/posit-dev/positron/issues/11112. PR: https://github.com/posit-dev/ark/pull/1157
0 条评论