Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » [Formatter2] unable to align list line start offsets
[Formatter2] unable to align list line start offsets [message #1800344] Tue, 25 December 2018 09:28
ayman salah is currently offline ayman salahFriend
Messages: 131
Registered: June 2015
Senior Member
Hi all,

I am facing an issue where I would like to align the start position of list items.

I want to align the list items using spaces and not indentation, because indentation is smaller than what is required for them to be aligned.

Problem occurs if the unformatted text exists on a line where a newLine will be added elsewhere and this results in miscalculation of lineoffset of first element which is used to align the rest of the list.

Grammar:
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

DSL returns XTDSL:
	models+=Model*
;

Model returns XTModel:
	{XTModel} 'startList' '(' greetings+=Greeting*')'';';
	
Greeting returns XTGreeting:
	'list' ids_list=identifier_list ':' 'endlist' ';';

identifier_list returns XTIdentifierList:
	ids+=identifier (',' ids+=identifier)*
;

identifier returns XTIdentifier:
	{XTIdentifier} ID
;


Formatter:
def dispatch void format(XTDSL xtdsl, extension IFormattableDocument document) {
		xtdsl.models.forEach[format]
	}

	def dispatch void format(XTModel xtmodel, extension IFormattableDocument document) {
		xtmodel.greetings.forEach[format]
		xtmodel.regionFor.keyword("startList").append[oneSpace]
		xtmodel.regionFor.keyword("(").append[noSpace]
		xtmodel.regionFor.keyword(")").prepend[noSpace]
		xtmodel.regionFor.keyword(";").prepend[noSpace]
		xtmodel.append[newLine]
		alignGreetingsOnColon(xtmodel.greetings, document)
		alignGreetingsStartOffset(xtmodel.greetings, document)
	}
	
	def dispatch void format(XTGreeting xTGreeting, extension IFormattableDocument document) {
		xTGreeting.regionFor.keyword("list").append[oneSpace]
		xTGreeting.regionFor.keyword(":").prepend[oneSpace]
		xTGreeting.regionFor.keyword("endlist").prepend[oneSpace].append[noSpace]
		xTGreeting.ids_list.format
	}
	
	def dispatch void format(XTIdentifierList xTIdentifierList, extension IFormattableDocument document) {
		xTIdentifierList.regionFor.keywords(",").forEach[prepend[noSpace]append[oneSpace]]
	}
	
	def void alignGreetingsOnColon(EList<XTGreeting> greetings, extension IFormattableDocument document) {
		var width = -1
		for (greeting : greetings) {
			val colonSemanticRegion = greeting.regionFor.keyword(":")
			if (colonSemanticRegion != null) {
				width = Math.max(width, colonSemanticRegion.previousSemanticRegion.endOffset - greeting.allSemanticRegions.get(0).offset + 1);
			}
		}
		println("Width = " + width)
		if (width > 0) {
			for (greeting : greetings) {
				val colonRegion = greeting.regionFor.keyword(":")
				if (colonRegion != null) {
					val numberOfSpaces = width - (colonRegion.previousSemanticRegion.endOffset - greeting.allSemanticRegions.get(0).offset);
					colonRegion.prepend[space = Strings.repeat(" ", numberOfSpaces); highPriority]
				}
			}
		}
	}
	
	def void alignGreetingsStartOffset(EList<XTGreeting> greetings, extension IFormattableDocument document) {
		if (greetings.length > 0) {
			val firstElement = greetings.get(0)
			val firstSR = firstElement.allSemanticRegions.get(0)
			val lineOffsetOfFirstElement = firstSR.offset - firstSR.textRegionAccess.regionForLineAtOffset(firstSR.offset).offset
			for (element : greetings) {
				if (element != firstElement && lineOffsetOfFirstElement > 0) {
					element.allSemanticRegions.get(0).prepend[space = System.lineSeparator + Strings.repeat(" ", lineOffsetOfFirstElement)]
				}
			}
		}
	}


Testcase:
startList (); startList (list A, B, C, D : endlist;list E    : endlist;
list F, G       : endlist;);


Actual:
startList ();
startList (list A, B, C, D : endlist;
                         list E          : endlist;
                         list F, G       : endlist;);


Expected:
startList ();
startList (list A, B, C, D : endlist;
           list E          : endlist;
           list F, G       : endlist;);


Because the Testcase text will have newLine added after the first startList ();, the result is lineOffsetOfFirstElement has 13 added to it which is the length of the first startList();

If I execute the format action twice I reach the expected result.

My questions are:


  1. Is there a better way to achieve this?
  2. Can I reformat after the first format pass is done?
  3. Can I apply the added replacements before doing the alignment because the alignment is dependent on the formatted text?
  4. Can I have multiple formatters executed sequentially?

Previous Topic:Importing a xtext file to another xtext file in the same package
Next Topic:BUILD Failed for 2.10.0 version of Xtext
Goto Forum:
  


Current Time: Wed Sep 25 17:23:27 GMT 2024

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

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

Back to the top