Scoping defines the visibility rules inside of a SADL file and across SADL file boundaries. For example, if a class C1 is defined in a SADL file with namespace (URI) http://sadl.org/ns1, the class C1 is visible anywhere in that SADL file and in any model that imports http://sadl.org/ns1. On the other hand, if a variable X is defined in a rule, query, or test in http://sadl.org/ns1, X is visible only within that rule, query, or test. If there is a variable X in another rule, query, or test in http://sadl.org/ns1, that X is entirely independent and in its turn visible only within its rule, query, or test.
Furthermore, scoping must differentiate the location of the definition of a class, property, instance, or variable from references to it. Consider this small model.
The instance i2 appears in the statements on lines 5 and 6. Even though the statement on line 5 appears first, it is the statement on line 6 that defines i2. Line 5 contains only a reference to i2. In order for the hyperlinking to definition and to references to work properly, scoping must correctly identify which occurrence is the definition and which occurrences are references.
Xtext scoping is a complex topic. Some references that may prove useful include the following.
A scope describes the visible names, which depends on the context, and maps names to the parse tree's EMF EObjects in a chain of scopes. Local scopes have to do with references within a Resource (SADL file). Global scopes have to do with those names that are visible from outside a Resource (SADL or OWL file), assuming that the Resource is imported.
The IScope class represents an element of a linked list of scopes. A scope can be nested within an outer scope. Each scope is like a symbol table or map where the keys are strings and the values are IEObjectDescription instances, abstract descriptions of real EObject instances.
In the SADL IDE, the following classes deal with scoping.Of particular interest to this discussion is the class SADLScopeProvider. this class contains a set of methods named localScope_01, localScope_02, ..., localScope06. These are the scope providers referred to below.
Scope processing in SADL has a nested iterative structure. The outer iteration is over the local scope providers, methods in SADLScopeProvider named localScope_01, localScope_02, ..., localScope06. The inner iteration is over the contents of the parse tree. Written as pseudo code, the overall outline of the scope processing looks something like this.
for (scopeProvider : scopeProviders) {
for (eObj : resource.allContents) {
// Check if this eObj's characteristics
are matched by the conditions of the current scopeProvider and if so
create a scope for the eObj if it is a SadlResource.
// This occurrence of eObj will be the definition of the identified
SadlResource. All other SadlResources with the same URI will be
references.
// Note that the conditions of the scope providers can only match
(return true) for an EObject which is a SadlResource.
}
}
In other words, each local scope provider checks for definitions. The scope providers are processed from highest priority statements that are definitions to lowest priority statements that might be definitions. For each local scope provider, go through the parse tree's EObjects and identify the definitions, then create scoping information for each one that qualifies.
Note: within the JenaBasedSadlModelProcessor, the method getNewVar uses an IScopeProvider to help determine whether to use an existing variable in the local scope or create a new one.
The logic for each of the six levels is described below. (The code in SADLScopeProvider is the ultimate truth; this is a snapshot for documentation purposes.)
All of the scoping providers only apply to SadlResource as that is the only EObject that is linked. The matches to scoping providers by SadlResource are: