Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » How to format lists with new Xtext formatter?
How to format lists with new Xtext formatter? [message #1692650] Fri, 17 April 2015 08:24 Go to next message
Jan Rosczak is currently offline Jan RosczakFriend
Messages: 53
Registered: July 2009
Location: Hamburg, Germany
Member
Hello,

I am trying to format text for the following grammar snippet:

EventAction:
	name=STRING
;

CallServerProcedureCommand:
	'callServer' ('{'
		('additionalActions' '{' additionalActions+=EventAction* '}')?
         '}')?
;


The final text should look something like:

callServer {
       additionalActions {
		"onSave"
		"onLoad"
	}
}


No matter what I try I do not get the increase/decrease stuff for the curly braces to work correctly. Mostly it looks like:

callServer qi.X332 {
	additionalActions {
         	"onSave"
               "onLoad"
}   }


I find all regions for the braces and apply increase/decrease indentation to them, but with no luck.
What am I missing?

Thanks
Jan Rosczak
Re: How to format lists with new Xtext formatter? [message #1692658 is a reply to message #1692650] Fri, 17 April 2015 09:30 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Hi,

the problem is that you have the same keywords twice { }
the api for regionForKeyword cannot handle that.
it it missing a method

def ISemanticRegion regionForKeyword(EObject owner, Keyword keyword)
can you file a enhancement request for that?

additionally the eObjectTokens list should be available in the api as well => enhancement request for that

as a workaround

/*
 * generated by Xtext
 */
package org.xtext.example.mydsl1.formatting2

import com.google.common.collect.ImmutableMap
import java.util.Map
import javax.inject.Inject
import org.eclipse.emf.ecore.EObject
import org.eclipse.xtext.AbstractElement
import org.eclipse.xtext.Keyword
import org.eclipse.xtext.formatting2.AbstractFormatter2
import org.eclipse.xtext.formatting2.IFormattableDocument
import org.eclipse.xtext.formatting2.regionaccess.ISemanticRegion
import org.eclipse.xtext.formatting2.regionaccess.ITextRegionAccess
import org.eclipse.xtext.formatting2.regionaccess.internal.AbstractEObjectTokens
import org.eclipse.xtext.formatting2.regionaccess.internal.NodeModelBasedRegionAccess
import org.xtext.example.mydsl1.myDsl.CallServerProcedureCommand
import org.xtext.example.mydsl1.services.MyDslGrammarAccess
import org.xtext.example.mydsl1.myDsl.EventAction

// import com.google.inject.Inject;
// import org.xtext.example.mydsl1.services.MyDslGrammarAccess
/**
 * This class contains custom formatting declarations.
 * 
 * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#formatting
 * on how and when to use it.
 * 
 * Also see {@link org.eclipse.xtext.xtext.XtextFormattingTokenSerializer} as an example
 */
class MyDslFormatter extends AbstractFormatter2 {

	@Inject
	MyDslGrammarAccess ga

	def dispatch void format(CallServerProcedureCommand p, extension IFormattableDocument doc) {
		println("lala")
		if (regionAccess instanceof MyDslNodeModelBasedRegionAccess) {
//p.regionForKeyword("{").append [
//				setNewLines(1,1,1);
//				increaseIndentation
//			]
			p.regionForKeyword(ga.callServerProcedureCommandAccess.leftCurlyBracketKeyword_2_0, regionAccess).append [
				setNewLines(1,1,1);
				increaseIndentation
			]
			p.regionForKeyword(ga.callServerProcedureCommandAccess.leftCurlyBracketKeyword_2_1_1, regionAccess).append [
				setNewLines(1,1,1);
				increaseIndentation
			]
			for (EventAction element : p.additionalActions) {
				format(element, doc);
				//element.append[setNewLines(1,1,1)]
			}
//						p.regionForKeyword("}").prepend [
//				newLine;decreaseIndentation
//			].append[setNewLines(1,1,1)]
			p.regionForKeyword(ga.callServerProcedureCommandAccess.rightCurlyBracketKeyword_2_1_3, regionAccess).prepend [
				newLine;decreaseIndentation
			].append[setNewLines(1,1,1)]
			p.regionForKeyword(ga.callServerProcedureCommandAccess.rightCurlyBracketKeyword_2_2, regionAccess).prepend [
				newLine;decreaseIndentation
			].append[setNewLines(1,1,1)]

		}
	}

	def ISemanticRegion regionForKeyword(EObject owner, Keyword keyword, MyDslNodeModelBasedRegionAccess acc) {
		val AbstractEObjectTokens tokens = acc.eObjectToTokens.get(owner);
		if (tokens == null)
			return null;
		for (ISemanticRegion token : tokens.getTokens()) {
			val AbstractElement element = token.getGrammarElement();
			if (element instanceof Keyword) {
				val Keyword kw = element;
				if (kw.equals(keyword)) {
					return token;
				}
			}
		}
		return null;
	}

}

class MyDslNodeModelBasedRegionAccessBuilder extends NodeModelBasedRegionAccess.Builder {

	override public NodeModelBasedRegionAccess create() {
		val NodeModelBasedRegionAccess tokenAccess = new MyDslNodeModelBasedRegionAccess(this);
		// System.out.println(tokenAccess);
		return tokenAccess;
	}

	override public getEObjectToTokensMap(ITextRegionAccess tokenAccess) {
		super.getEObjectToTokensMap(tokenAccess)
	}

}

class MyDslNodeModelBasedRegionAccess extends NodeModelBasedRegionAccess {

	protected new(MyDslNodeModelBasedRegionAccessBuilder builder) {
		super(builder)
		this.eObjectToTokens = ImmutableMap.copyOf(builder.getEObjectToTokensMap(this));
	}

	public val Map<EObject, AbstractEObjectTokens> eObjectToTokens;

	def getEObjectTokens() {
		return eObjectToTokens;
	}

}




public class MyDslRuntimeModule extends org.xtext.example.mydsl1.AbstractMyDslRuntimeModule {
	
	public Class<? extends NodeModelBasedRegionAccess.Builder> bindNodeModelBasedRegionAccess$Builder() {
		return MyDslNodeModelBasedRegionAccessBuilder.class;
	}

}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to format lists with new Xtext formatter? [message #1692670 is a reply to message #1692658] Fri, 17 April 2015 10:02 Go to previous messageGo to next message
Jan Rosczak is currently offline Jan RosczakFriend
Messages: 53
Registered: July 2009
Location: Hamburg, Germany
Member
Hi,

thanks a lot for the workaround.
I filled an enhancement request: https://bugs.eclipse.org/bugs/show_bug.cgi?id=464867
Re: How to format lists with new Xtext formatter? [message #1692687 is a reply to message #1692670] Fri, 17 April 2015 10:59 Go to previous messageGo to next message
Jan Rosczak is currently offline Jan RosczakFriend
Messages: 53
Registered: July 2009
Location: Hamburg, Germany
Member
Hi,

I get a ConflictingRegionsException I do not understand.

The following code snippet works:
p.regionForKeyword(ga.callServerProcedureCommandAccess.callServerKeyword_0.value).prepend[newLine()]
p.regionForFeature(MyDslPackage.Literals.CALL_SERVER_PROCEDURE_COMMAND__SERVER).surround[oneSpace()]


The following code snippet does not work (looking up region by Keyword and not String):
p.regionForKeyword(ga.callServerProcedureCommandAccess.callServerKeyword_0, regionAccess).prepend[newLine()]
p.regionForFeature(MyDslPackage.Literals.CALL_SERVER_PROCEDURE_COMMAND__SERVER).surround[oneSpace()]


I checked that both methods return the same region object, but still I get a ConflictingRegionsException when using your proposed workaround.

Please note that my original grammar has a cross reference afer "callServer [Server|ID]".
Re: How to format lists with new Xtext formatter? [message #1692689 is a reply to message #1692687] Fri, 17 April 2015 11:05 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
sry i have no idea on that. maybe the problem is that i create a copy of the eobjecttoken stuff and do not use the same map.

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to format lists with new Xtext formatter? [message #1692693 is a reply to message #1692687] Fri, 17 April 2015 11:21 Go to previous messageGo to next message
Jan Rosczak is currently offline Jan RosczakFriend
Messages: 53
Registered: July 2009
Location: Hamburg, Germany
Member
Hi,

with Moritz workaround described in the bug, everything works

Thanks a lot!
Re: How to format lists with new Xtext formatter? [message #1692694 is a reply to message #1692689] Fri, 17 April 2015 11:21 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
can you try the other workaround moritz suggested.

or access the field by relfection

public class MyDslNodeModelBasedRegionAccess extends NodeModelBasedRegionAccess {

	public MyDslNodeModelBasedRegionAccess(MyDslNodeModelBasedRegionAccessBuilder builder) {
		super(builder);
	}


	public Map<EObject, AbstractEObjectTokens> getEObjectTokens() {
		Field field;
		try {
			Class<?> superclass = getClass().getSuperclass().getSuperclass();
			System.out.println(superclass);
			field = superclass.getDeclaredField("eObjectToTokens");
			field.setAccessible(true);;
			return (Map<EObject, AbstractEObjectTokens>)field.get(this); 
		} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: How to format lists with new Xtext formatter? [message #1692726 is a reply to message #1692694] Fri, 17 April 2015 13:07 Go to previous message
Jan Rosczak is currently offline Jan RosczakFriend
Messages: 53
Registered: July 2009
Location: Hamburg, Germany
Member
Hi,

before I saw Moritz workaround I did try reflection and it worked! Now I use Moritz workaround and I am happy Smile
I still use reflection to implement the regionsForCrossreference method which is also "missing".
Previous Topic:templates as a menu
Next Topic:multiple decisions warning
Goto Forum:
  


Current Time: Thu Apr 18 13:59:18 GMT 2024

Powered by FUDForum. Page generated in 0.02783 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top