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 
etiquette here.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to