I am working on a program to consume Go source code and maintain a running
state of that program as a user edits that source in an IDE. I have a
working implementation that *loads* the program AST representation (inc.
all imports and standard library) and runs it through a type checker, but
my implementation is rudimentary (so much so that I'm hesitant to share the
source at this point; it's not terribly readable right now). Once the
program is loaded, I can do simple things such as locating where an Ident
is declared, but I haven't worked through finding all references to an
Ident yet. I have some fundamental questions before moving on to greater
tasks (such as handling edits to the program files). I hope that some of
the folks here can provide some insight.
1) My current implementation maintains a single `token.FileSet` for all
files in the program, across all packages. Is this correct, or is it
better to keep a file set per package?
2) Similar question for `types.Info`. I currently have a single instance
that is shared among all packages, but the source code comments say that it
holds data "for *a* type-checked package" (emphasis mine). Should I be
keeping a single instance per package instead?
3) I am keeping a `types.Checker` per package, but even so, I can only
check one package at a time. My program is highly concurrent, and as it
turns out, one checker may consuming a package "A", while package "A"'s
checker is processing some test files, which results in a concurrent
read/write panic from a map. (I am checking files from `build.Package` in
waves -- first all Go and Cgo files, then test files, and later I will add
external test files.) Are there any strategies to improve concurrency
here? I am thinking about keeping a `sync.RWMutex` per-package, which I
would write-lock when a package is getting checked, and claim a read-lock
when a package is returned from my `types.Importer` / `types.ImporterFrom`
implementation. Does this seem like a reasonable strategy?
4) When going through the type checker, what is the relationship between
* `type.Package` instances that are imported via my custom `types.Importer`
/ `types.ImporterFrom` implementation provides,
* the non-package-local tokens & identifiers,
* and the information that gets stored in the `types.Info`?
The thing that I'm really trying to understand is, if I have a complete
program representation, and an exported part of a Go source code file
changes, what will be the impact on packages that consume it? I know that
once I run the new file contents through `parser.ParseFile`, I will get a
completely new `ast.File`, which I will have to type-check again to get a
new `types.Package`. I don't want to walk the entire package dependency
tree if a low-level package changes; are there ways to avoid that?
Thanks for any insight. This is a pretty big & abstract subject matter to
ask a bunch of questions about all at once, and I apologize if I'm breaking
You received this message because you are subscribed to the Google Groups
To unsubscribe from this group and stop receiving emails from it, send an email
For more options, visit https://groups.google.com/d/optout.