Home » Modeling » TMF (Xtext) » Linking with custom bind algorithm
Linking with custom bind algorithm [message #891838] |
Tue, 26 June 2012 09:00 |
|
Hi,
I'm wondering how to best implement a custom bind (aka linking)
algorithm. With "custom bind algorithm" I mean a linking algorithm not
only using a qualified name, but other information, such as types of
arguments and parameters of a method call. To make the issue easy, let's
assume I want to implement the binding of a method call to a method
declaration, taking overloading etc. into account.
Let's assume a simple language, in which a method call does include the
type. Such as:
----------------------------------------------------------------------
1: foo() {}
2: foo(A,A)
3: foo(A,B) {}
4:
5: bar() {
6: foo(A,B)
7: }
----------------------------------------------------------------------
In this example, the method call (line 6) should bind to the declaration
in line 3.
How can that be implemented with Xtext. Actually, there are several
ways, I'm asking for the best solution ;-)
One trick would be to use qualified names internally, adding the type
information to the name. E.g., foo(A,A) becomes "foo_A_A" or foo(A,B)
"foo_A_B". However, this will probably cause some problematic side
effects, such as showing the weird qualified name in content assist.
Moreover, it does not work if the binding has to consider things like
type hierarchies (e.g., B could extend A).
I tried to provide a custom scope provider, filtering out non-matching
declarations. E.g.
----------------------------------------------------------------------
01: public IScope getScope(EObject context, EReference reference) {
02: if (context instanceof FunctionCall
03: && "func".equals(reference.getName())) {
04: final FunctionCall functionCall = (FunctionCall) context;
05: EObject container = functionCall.eContainer();
06: IScope scope = super.getScope(container, reference);
07:
08: Predicate<IEObjectDescription> filter =
09: new Predicate<IEObjectDescription>() {
10: public boolean apply(IEObjectDescription input) {
11: if (input.getEObjectOrProxy()
12: instanceof FunctionDecl) {
13: FunctionDecl functionDecl = (FunctionDecl)
14: input.getEObjectOrProxy();
15: return match(functionCall, functionDecl);
16: }
17: return false;
18: }
19: };
20: return new FilteringScope(scope, filter);
21: }
22: return super.getScope(context, reference);
23: }
----------------------------------------------------------------------
The match function used for filtering here (line 15) does then implement
the custom algorithm. Alternatively, this filtering could have been
implemented in the linking service.
Unfortunately, this does only work if only one match is found. That is,
in the example given, it would work if A and B are independent types. It
won't work if B is a subtype of A, which means that the function call
could bind to foo(A,A) and foo(A,B). So, while this solution would work
in certain cases, it does not work if the actual binding has to be
selected from a set of possible matches.
I was thinking about implementing my matching algorithm in the linking
resource. The ideal method would be
org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(String).
It already handles the cases of 0 or n (n>1) possible matches (by
throwing exceptions) -- all I have to to would be to adjust the n>1 case
little bit.
Unfortunately, this method does not look like intended to be overridden,
and if I try to override it, copy and paste the existing code, I run
into the problem that the it accesses some private fields.
(Besides, I'm not sure how to inject my custom resource implementation,
but I'd assume this is possible somehow).
Actually, at the moment I have a working version, using Xtext 1.x (in
which I have written a whole bunch of custom providers, services etc.).
However, I want to minimize my custom code, and since Xtext 2 provides
this nice "importedNamespace=QualifiedNameWithWildcard" feature, more or
less solving all of my problems, I'm looking for "best practice"
solution with Xtext 2.
Cheers,
Jens
|
|
| |
Re: Linking with custom bind algorithm [message #891854 is a reply to message #891847] |
Tue, 26 June 2012 09:50 |
|
Hi Vlad,
On 26.06.12 11:34, Vlad Dumitrescu wrote:
> This is no authoritative answer, but I think you should define and bind
> your own ILinkingService (inheriting from DefaultLinkingService and
> overriding getLinkedObjects).
Yeah, that's what I'm doing at this very moment ;-) However, I'm not
sure how to deal with error handling. That is, how do I best propagate
nice error messages in case of ambiguous calls, or if no method is found
at all (due to wrong types, in my case). The LazyLinkingResource has
some methods for propagating error messages to the user. How did you
solved that issue? (And thank you for the fast reply!)
Cheers,
Jens
|
|
| |
Re: Linking with custom bind algorithm [message #891869 is a reply to message #891860] |
Tue, 26 June 2012 11:38 |
|
On 26.06.12 12:48, Vlad Dumitrescu wrote:
> I am also extending LinkingDiagnosticMessageProvider, where the messages
> can be customized.
Thanks for that hint, I will have a look at this class.
> In my case, it's easier because I just suppress any
> messages: the code will get through a proper compiler anyway where all
> messages will be generated.
That's what I have done so far as well. However, I want to "optimize" my
code and remove redundant things, such as redundant error checking.
Cheers,
Jens
|
|
| |
Goto Forum:
Current Time: Sat Apr 27 00:46:05 GMT 2024
Powered by FUDForum. Page generated in 0.02783 seconds
|