Search code examples
javaeclipseeclipse-pluginxtext

Hide parent nodes in Xtext Outline View


I'm working on an Xtext parser, and have run into an issue: With the IDE plugin for Eclipse, specifically the Outline view, it tends to show <unnamed> nodes, which I don't want to display.

Currently, the nodes are as so:

  • SourceFile (simply the name of the file that I'm currently using)
    • TopLevelStatement
      • Declare
        • StructDeclaration
          • StructCreator
            • name=Identifier - Same identifier as below.
        • ClassDeclaration
          • ClassCreator
            • name=Identifier - Same identifier as below.
      • Identifier
        • ID (the terminal that comes with Xtext)

With all the mess above, if I do something such as:

class TestClass {}
struct TestStruct {}

I would expect:

  • SourceFile
    • TestClass
    • TestStruct

But what I really get, is this:

  • SourceFile
    • <unnamed>
      • <unnamed>
        • <unnamed>
          • <unnamed>
            • TestClass
    • <unnamed>
      • <unnamed>
        • <unnamed>
          • <unnamed>
            • TestStruct

I really just want to hide every <unnamed> node in my Xtext project, as it would be beneficial to every case where I don't want something to appear, however if not possible, I simply want the specific nodes above to be hidden. I've tried the documentation, but can't seem to find any information as towards hiding a specific node, especially when it has multiple types of children.

Here is my grammar code:

SourceFile:
    (statements+=TopLevelStatement)*
;

TopLevelStatement:
    statement=(Declaration)
;

Declaration:
    declare=(StructDeclaration|ClassDeclaration)
;

StructDeclaration:
    declare=StructCreator '{' '}' ';'?
;

ClassDeclaration:
    declare=ClassCreator '{' '}' ';'?
;

StructCreator:
    'struct' id=Identifier
;

ClassCreator:
    'class' id=Identifier
;

Identifier:
    ID
;

You may look at the above code and ask why I don't merge the class and struct creators into one, but I can't. I'm going to have a few more rules for both the class and struct, which I haven't added, as they don't contribute to the problem.


Solution

  • In the first place i dont understand this wired object structure you create. is there any reason to do this the way you do it?

    Step one: implement label provider

    class MyDslLabelProvider extends DefaultEObjectLabelProvider {
    
        @Inject
        new(AdapterFactoryLabelProvider delegate) {
            super(delegate);
        }
        // xtext does reflective polymorphic dispatch on params
        def text(StructCreator ele) {
            ele.id
        }
    
        def text(ClassCreator ele) {
            ele.id
        }
    
    }
    

    Step two: Implement Outline Tree Provider

    class MyDslOutlineTreeProvider extends DefaultOutlineTreeProvider {
    
        // xtext does reflective polymorphic dispatch on params
        def protected _createChildren(IOutlineNode parentNode, SourceFile modelElement) {
                for (s : modelElement.statements) {
                    val firstDecl = s.statement?.declare
                    if (firstDecl instanceof StructDeclaration) {
                        val secondDecl = firstDecl.declare
                        if (secondDecl !== null) {
                            createNode(parentNode, secondDecl)
                        }
                    } else if (firstDecl instanceof ClassDeclaration) {
                        val secondDecl = firstDecl.declare
                        if (secondDecl !== null) {
                            createNode(parentNode, secondDecl)
                        }
                    }
    
                }
        }
    
    }
    

    Alternative 0: Change Grammar and Naming Conventions

    SourceFile:
        (statements+=TopLevelStatement)*
    ;
    
    TopLevelStatement:
        Declaration
    ;
    
    Declaration:
        StructDeclaration|ClassDeclaration
    ;
    
    StructDeclaration:
        'struct' name=Identifier '{' '}' ';'?
    ;
    
    ClassDeclaration:
        'class' name=Identifier '{' '}' ';'?
    ;
    
    Identifier:
        ID
    ;