An ASProjectScope is the topmost scope for a particular project.
A project scope keeps track of, but does not own, all the externally-visible definitions for all the compilation units of a single project, so that multiple compilation units can resolve an identifier to the same definition.
For example, the ClassDefinition for the Sprite class in playerglobal.swc is owned by a single ASFileScope produced from that SWC. But this definition is then shared into the ASProjectScope for each project that uses playerglobal.swc.
Note that a workspace might have some projects whose project scope maps "flash.display.Sprite" to the Sprite class in playerglobal.swc and other projects whose project scope maps this same qualified name to the Sprite class in airglobal.swc.
Unlike other ASScopes, an ASProjectScope does not store information about import
or use namespace
directives.
Since multiple compilation units need to concurrently access a project scope, it uses a ReadWriteLock to allow either multiple readers with no writer or a single writer with no readers.
A project scope can store a special kind of definition called a definition promise, represented by ASProjectScope.DefinitionPromise
. A definition promise is a small object that serves as a placeholder for an actual definition, which it can produce on demand but at significant expense. A promise knows only its qualified name and the compilation unit that produced it; it has no idea whether the actual definition it can produce will turn out to be a class definition, an interface definition, a function/getter/setter definition, a variable/constant definition, or a namespace definition. Promises are created by compilation units corresponding to files on the source path or library path, but not for files on the source list. The files on the source path and library path are recursively enumerated, compilation units are created for each source file and each SWC script, and each such compilation unit produces a promise to initially populate the project scope. For example, the file com/whatever/Foo.as
will produce a promise named com.whatever.Foo
. If code refers to Foo
, the promise will be converted to an actual definition by parsing the file com/whatever/Foo.as
, building a syntax tree, building a file scope, etc.
Project scopes support definition shadowing since multiple definitions with the same qualified name can exist in them without this being an error. (For example, monkey-patching UIComponent would cause it to be on the source path and also in framework.swc.) Definition priorities, represented by IDefinitionPriority
, determine which one of the definitions is made visible to the name resolution algorithm by being stored in the scope's definition store. The others are stored, invisible to name resolution, in shadow sets of definitions, in a map that maps a qualified name to a shadow set. As definitions with a given qualified name are added to and removed from the scope, which definition is visible, and which are shadowed, can change. If a compilation unit initially produces definition promises rather than actual definitions, then it puts promises into the shadow sets rather than actual definitions; this allows the removeDefinition
method to be able to remove a definition promise from the project scope without it ever being converted to an actual definition.