-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathreference-linking-design.txt
81 lines (60 loc) · 3.79 KB
/
reference-linking-design.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
design/code for linking service.
task references is different than any other references.
only task references can be absolute or relative and so
must support support namespace. other references
(resource, account) have a flat namespace.
two behaviors of scope providers are needed, one for task
and one for not-task references. In this design,
we choose a single scope provider with two different
behaviors, one for task and one for others.
xtext resolves links through scope (IScope) implementations which
are populated by scope providers. The linker service calls only one scope
provider which invokes others.
Any scope provider can be replaced by configuration of Guice dependency
injection. De default scope provider generated by xtext can be
extended by naming convention. The abstract class uses reflection
to satisfy a request for the scope.
By default, the first provider is an extensible facade. If not extended
by the develpper, it will by default call the second provider, known as
the delegate scope provider. xtext give a namespace aware local
scope provider implementation by default. The local scope provider reads from
the model objects that are in the same file as the link reference.
Once it reache the end of creating scopes within the file, the default
delegate scope provider calls the global scope provider.
The default global scope provider finds resources
in the workspace and creates scope from all. xtext has implemented
a global scope provider that observes 'import' statements.
Scope provider instantiate IScope implementations. The IScopes are
generated based on what names are visible, or in scope, relative
to the reference object. We see two different
kinds created by the default scope providers: ImportScope and SelectableBasedScope.
ImportScope contains names at one level of scope.
The default delegate scope provider would instantiate an ImportScope for
each level of scope in the file with the reference object and a SelectableBasedScope
for all names in the file. The default global scope provider would create
a SelectablebaseScope for all the names in files visible to the reference object.
The scope are chained together: if the first cannot resolve the referenced name, it
passes teh request to the second, until the end of the chain.
The scope providers rely on QualifiedName to identify objects in scope. A
Qualified name is a list of path segments from the top scope to the named object.
The default QualifiedNameProvider is used to build QualifiedName use by the
default scope providers.
The above default implementation works rather well for references that
are absolute. It can even resolve relative references. However,
it cannot resolve Task Jugglers task relative references. Also, it cannot
resolve the references of the flat namespace, like for account or resource.
We made the following extensions:
*) to resolve relative task references that use the '!' notation (e.g. !!task2.task3)
we extended ImportScope and SelectableBasedScope (ProjectImportScope and
ProjectSelectableBasedScope). These observe ProjectQualifiedName class which
knows how to interpret the '!' notation.
*) to resolve references in the flat names space (account and resource references),
we wrote a ProjectQualifiedNameProvider that provides a flat name,
instead of a.b.c.d, returns 'd'. And we extended the ProjectScopeProvider
to skip building ProjectImportScopes, only SelectableBasedScopes.
Issue: To resolve references, only those include files that appear before the
reference should be searched. Include files after the reference must
be ignored. There is no way to change the framework to support this feature because
the IScopeProvider and IGlobalScopeProvider getScope methods do not preserve
the original reference to the outer scope. We created our own interface
and our own implementation.