1

I am having trouble getting my proposal provider to work properly. My objective is to provide a list of all possible imports a user can create. I can verify that the class is bound properly and is getting called on assist request from the editor. I can even see proposals being created and passed to the acceptor but nothing shows up in the editor.

So my question may be two part:

  1. Can you see what I may be doing wrong in the following code as to explain content assist not showing in the editor
  2. Can you explain the difference between the dispatch methods for Assignment, RuleCall, and Keyword? I find that all three methods are hit for the same content assist request, so what exactly do I code differently and what do they do differently?

Also I am using CodeMirror if that has any effect.

    class mydslContentAssist extends IdeContentProposalProvider{
    @Inject extension mydslGrammarAccess stAccess
    @Inject mydslGlobalScopeProvider sp
    @Inject extension IQualifiedNameProvider

    override dispatch createProposals(Assignment assignment, ContentAssistContext context, IIdeContentProposalAcceptor acceptor) {
        switch(assignment) {
            case stAccess.libraryModelAccess.importsAssignment_0: {
                var libs = sp.descriptionData.getExportedObjectsByType(ModelPackage.eINSTANCE.libraryModel)
                for (lib : libs.filter[(EObjectOrProxy as LibraryModel).name.startsWith(context.prefix)]) {
                    var proposal = proposalCreator.createProposal('import ' + (lib.EObjectOrProxy as LibraryModel).name + ".*;", context) [
                        source = lib
                        description = "import entire library contents"
                    ]
                    acceptor.accept(proposal, proposalPriorities.getDefaultPriority(proposal))
                }
            }
            default : {
                super._createProposals(assignment, context, acceptor)
            }
        }
    }
    override dispatch createProposals(RuleCall rulecall, ContentAssistContext context, IIdeContentProposalAcceptor acceptor) {
        switch(rulecall.rule) {
            case importRule: {
                var libs = sp.descriptionData.getExportedObjectsByType(ModelPackage.eINSTANCE.libraryModel)
                for (lib : libs) {
                    var proposal = proposalCreator.createProposal('import ' + (lib.EObjectOrProxy as LibraryModel).name + ".*;", context) [
                        source = lib
                        description = "import entire library contents"
                    ]
                    acceptor.accept(proposal, proposalPriorities.getDefaultPriority(proposal))
                }
            }
            default : {
                super._createProposals(rulecall, context, acceptor)
            }
        }
    }

    override dispatch createProposals(Keyword keyword, ContentAssistContext context, IIdeContentProposalAcceptor acceptor) {
        switch (keyword) {
            case stAccess.importAccess.importKeyword_0: {
                var libs = sp.descriptionData.getExportedObjectsByType(ModelPackage.eINSTANCE.libraryModel)
                for (lib : libs) {
                    var proposal = proposalCreator.createProposal('import ' + (lib.EObjectOrProxy as LibraryModel).name + ".*;", context) [
                        source = lib
                        description = "import entire library contents"
                    ]
                    acceptor.accept(proposal, proposalPriorities.getDefaultPriority(proposal))
                }
            }
            default: {
                super._createProposals(keyword, context, acceptor)
            }

        }
    }
    }

EDIT: My code is only being hit when calling content assist when typing the 'import' keyword. But not when typing the importedNamespace string

Zannith
  • 429
  • 4
  • 21
  • do you test this with a complete empty file or does it at least contain one character? is your code called if you debug? – Christian Dietrich Oct 31 '18 at 15:13
  • Yes, i verfied the code is called and the proposal is passed to the acceptor. I have tested it with an empty file just adding an import as well as with a fully structured file adding in an additional import. I have tried calling the content assist before typing a character for the 'import' keyword, partially through the 'import' keyword, and after the 'import' keyword when typing out the actual importedNamespace string – Zannith Oct 31 '18 at 15:20
  • piece of information I missed, my code actually only gets hit when doing content assist while typing the 'import' keyword. It is not getting hit when typing the namespace string – Zannith Oct 31 '18 at 15:25
  • did you check for the prefix w.g. when debug the ContentAssistService class (there where contexts are calculated) – Christian Dietrich Oct 31 '18 at 15:28
  • yes, it gets the correct prefix while typing the 'import' keyword. so if i type `imp` then ctr-space the prefix will be `"imp"` – Zannith Oct 31 '18 at 15:31
  • no i mean in the usecase when it is not working – Christian Dietrich Oct 31 '18 at 15:33
  • => i assume if `import x` the prefix will be x. and the context is not keyword. but something else – Christian Dietrich Oct 31 '18 at 15:35
  • when typing the namespace string after the import keyword my code is not being hit on debug, I made an edit for that. Am I possibly misusing the cases? – Zannith Oct 31 '18 at 15:35
  • the grammar rule is a simple `Import: 'import' importedNamespace=QualifiedNameWithWildcard ';';` – Zannith Oct 31 '18 at 15:38
  • I was unclear with describing when my code was not hit. My class is still being called on but I am not entering my case statements. So from debugging the assignment dispatch, should I perhaps switch on the contexts currentModel field for my import class? – Zannith Oct 31 '18 at 15:48
  • As I said you should debug which contexts with which prefixes you get – Christian Dietrich Oct 31 '18 at 15:49
  • Thank you so much for your help by the way Christrian. So the context prefixes are correct. If I switch on the contexts currentModel and look for an import type I can create the proper proposal. Is this the proper way to do it? I was trying to follow the xtext Statemachine example. Also the proposals only work when there is one result and it autocompletes it. If multiple proposals match it does not show me anything at all in the editor. – Zannith Oct 31 '18 at 16:03
  • Will try to create a reproducible sample when I find the time . Or could you do – Christian Dietrich Oct 31 '18 at 16:04
  • I will try to do the same – Zannith Oct 31 '18 at 16:16

1 Answers1

2

i gave it a try and could not reproduce

grammar:

Model:
    imports+=Import*;

Import: 'import' importedNamespace=QualifiedNameWithWildcard ';'
    ;
    QualifiedNameWithWildcard:
        ID ("." ID)* (".*")?
;

and impl

    package org.xtext.example.mydsl.web

import com.google.inject.Inject
import org.eclipse.xtext.Assignment
import org.eclipse.xtext.Keyword
import org.eclipse.xtext.RuleCall
import org.eclipse.xtext.ide.editor.contentassist.ContentAssistContext
import org.eclipse.xtext.ide.editor.contentassist.IIdeContentProposalAcceptor
import org.eclipse.xtext.ide.editor.contentassist.IdeContentProposalProvider
import org.eclipse.xtext.naming.IQualifiedNameProvider
import org.xtext.example.mydsl.services.MyDslGrammarAccess

class MydslContentAssist extends IdeContentProposalProvider {
        @Inject extension MyDslGrammarAccess stAccess
        static val LIBS = #[
            "XX1", "XX2", "YY1", "YY2"
        ]

        override dispatch createProposals(Assignment assignment, ContentAssistContext context, IIdeContentProposalAcceptor acceptor) {
            switch(assignment) {
                case stAccess.importAccess.importedNamespaceAssignment_1: {
                    for (lib : LIBS.filter[it.startsWith(context.prefix)]) {
                        var proposal = proposalCreator.createProposal(lib + ".*;", context) [
                            source = lib
                            description = "import entire library contents"
                        ]
                        acceptor.accept(proposal, proposalPriorities.getDefaultPriority(proposal))
                    }
                }
                default : {
                    super._createProposals(assignment, context, acceptor)
                }
            }
        }
        override dispatch createProposals(RuleCall rulecall, ContentAssistContext context, IIdeContentProposalAcceptor acceptor) {
            switch(rulecall.rule) {
                case importRule: {
                    for (lib : LIBS) {
                        var proposal = proposalCreator.createProposal('import ' + lib + ".*;", context) [
                            source = lib
                            description = "import entire library contents"
                        ]
                        acceptor.accept(proposal, proposalPriorities.getDefaultPriority(proposal))
                    }
                }
                default : {
                    super._createProposals(rulecall, context, acceptor)
                }
            }
        }

        override dispatch createProposals(Keyword keyword, ContentAssistContext context, IIdeContentProposalAcceptor acceptor) {
            switch (keyword) {
                case stAccess.importAccess.importKeyword_0: {
                    for (lib : LIBS) {
                        var proposal = proposalCreator.createProposal('import ' + lib + ".*;", context) [
                            source = lib
                            description = "import entire library contents"
                        ]
                        acceptor.accept(proposal, proposalPriorities.getDefaultPriority(proposal))
                    }
                }
                default: {
                    super._createProposals(keyword, context, acceptor)
                }

            }
        }
    }
Christian Dietrich
  • 11,778
  • 4
  • 24
  • 32
  • What editor framework did you use? ace? I couldn't reproduce it with Ace, but when i switched framework to codemirror I couldn't even type in the text area. Not sure what is going on there. – Zannith Oct 31 '18 at 17:48
  • Did you adapt the gradle or Pom – Christian Dietrich Oct 31 '18 at 17:55
  • Ah ya, gradle. Well I removed all of our custom ui and just used the generated ui and the recommendations worked on the full project. Unfortunately that means there is nothing I can do about it right now. – Zannith Oct 31 '18 at 17:59
  • Thank you so much for your time, it is good to know that I was doing things correctly for the most part. – Zannith Oct 31 '18 at 18:02
  • No I mean do you get any errors in browser console eg about missing webjars – Christian Dietrich Oct 31 '18 at 18:06
  • oh yes, on the minimal example using just the generated web stuff (Only change I did was switch framework to codemirror in the workflow). I get a ton of 404's eg. `GET http://localhost:8084/webjars/codemirror/5.13.2/addon/mode/simple.js net::ERR_ABORTED 404 (Not Found)` – Zannith Oct 31 '18 at 18:34
  • but ya that was just because I hadn't added codemirror to the gradle file. After working with our UI guy we found that the hints div was being created on content assist, but styling on it was screwed up, which is weird because he had not made any adjustments to it. He added some css styling and its all good now – Zannith Oct 31 '18 at 18:38
  • I would say the real root of the problem was an interaction somewhere between custom UI and default codemirror UI – Zannith Oct 31 '18 at 18:39