Karsten's Blog

March 14, 2012

How to limit proposed Java types to implementors of an interface

Filed under: Xtext — Tags: , , — kthoms @ 6:20 PM

When you develop a DSL that derives from Xbase you likely want to refer to Jvm types through a JvmTypeReference.

CustomBehavior :
    'custom' (name = ID | 'ref' realizedBy=JvmTypeReference) (label = STRING);

If you hit CTRL+SPACE at such a position in the editor, by default you will get all visible Java types proposed:

This is not really useful when it only makes sense to refer to specifc types. If you want to limit the proposals to just implementors of a specific interface, you can customize this in the proposal provider by overriding the method completeJvmParameterizedTypeReference_Type(). The following example from Spray shows limiting the types to implementors of Graphiti’s ICustomFeature interface in the context of Spray’s CustomBehavior:

public class SprayProposalProvider extends AbstractSprayProposalProvider {
    @Inject
    private IJvmTypeProvider.Factory      jvmTypeProviderFactory;
    @Inject
    private ITypesProposalProvider        typeProposalProvider;
    
    @Override
    public void completeJvmParameterizedTypeReference_Type(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
        if (EcoreUtil2.getContainerOfType(model, CustomBehavior.class) != null) {
            final IJvmTypeProvider jvmTypeProvider = jvmTypeProviderFactory.createTypeProvider(model.eResource().getResourceSet());
            // Graphiti specific
            final JvmType interfaceToImplement = jvmTypeProvider.findTypeByName(ICustomFeature.class.getName());
            typeProposalProvider.createSubTypeProposals(interfaceToImplement, this, context, SprayPackage.Literals.BEHAVIOR__REALIZED_BY, TypeMatchFilters.canInstantiate(), acceptor);
        } else {
            super.completeJvmParameterizedTypeReference_Type(model, assignment, context, acceptor);
        }
    }

Now you will get the desired subtypes as proposals:

Note that this does only limit proposals to certain types. It does not prevent you from actually referring to another type that you don’t get proposed. This needs to be restricted in your scope provider.
 

About these ads

6 Comments »

  1. Why not re-write the class as an Xtend class, for added clarity (and half the source) ;)

    Comment by meinte37 — March 15, 2012 @ 10:09 AM

    • This is just an option. The solution path would be the same ;-)

      Comment by kthoms — March 15, 2012 @ 10:39 AM

      • Obviously. But I have a hard time reading Java these days, now that I do almost all my programming in Xtend ;)

        Comment by meinte37 — March 15, 2012 @ 10:42 AM

      • I feel the same.

        Comment by kthoms — March 15, 2012 @ 10:45 AM

  2. Why not build it directly into the scope provider? It would influence the proposals to, wouldn’t it?

    Comment by Jan — July 19, 2012 @ 12:45 PM

    • It is harder to do this in the ScopeProvider, and might slow down also Scope resolution. Sebastian recommended at EclipseCon also not to do everything everything in scoping, but more with combination of proposals and validation. See his slides from EclipseCon2012: http://www.eclipsecon.org/2012/sessions/xtext-best-practices.
      Rule#9: Loose Scoping and Strict Validation
      Rule#12: Filter the ContentProposals instead of Scope Content

      Comment by Karsten Thoms — July 20, 2012 @ 7:35 AM


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Theme: Silver is the New Black. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 371 other followers

%d bloggers like this: