Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » IAutoWrapFormatter with indent ignores newline under certain conditions
IAutoWrapFormatter with indent ignores newline under certain conditions [message #1755819] Wed, 08 March 2017 12:19 Go to next message
Florian Schwarz is currently offline Florian SchwarzFriend
Messages: 4
Registered: March 2017
Junior Member
Hello,

I'm trying to implement a formatter which indents lines which are autowrapped. Similiar to slide 128 from de.slideshare.net/meysholdt/xtexts-new-formatter-api. So e.g. a model like
if: "CONDITION" = "VALUE1", "VALUE2", "VALUE3", "VALUE4", "VALUE5", "VALUE6", "VALUE7"  ("RESULT")

should be displayed as
if: "CONDITION" = "VALUE1", "VALUE2",
      "VALUE3", "VALUE4", "VALUE5",
      "VALUE6", "VALUE7"
("RESULT")

Since I don't have any terminating keyword, I use regionForEObject.nextHiddenRegion to get the end hidden region for the indent. Everything works fine as long as the last part of the multi-wrapped line contains more than one element. So e.g. the example above works fine. But if the last part contains only one element, the indentation seems to cause a conflict with the newline for the result element.
E.g.
if: "CONDITION" = "VALUE1", "VALUE2", "VALUE3", "VALUE4", "VALUE5", "VALUE6"  ("RESULT1")

if: "CONDITION" = "VALUE7", "VALUE8", "VALUE9", "VALUE10", "VALUE11", "VALUE12"  ("RESULT2")

will be displayed as
if: "CONDITION" = "VALUE1", "VALUE2",
      "VALUE3", "VALUE4", "VALUE5",
      "VALUE6" ("RESULT1")

if: "CONDITION" = "VALUE7", "VALUE8",
            "VALUE9", "VALUE10", "VALUE11",
            "VALUE12" ("RESULT2")

The instruction for a newline seems to be ignored and the second entry is indented twice.
My DSL is very simple:
Model:
  rules+=Rules*;
	
Rules:
  condition = Condition
  result = Result
;

Result:
  "(" values += STRING ("," values += STRING)* ")"
;

Condition:
  "if:" condition = ConditionAtom
;

ConditionAtom: 
  name = STRING "=" 
  values += STRING ("," values += STRING)*
;

The formatter is also quite simple:
class MyDslFormatter extends AbstractFormatter2 {
	
	@Inject extension MyDslGrammarAccess
	
	def dispatch void format(Model model, extension IFormattableDocument document) {
		for (Rules rules : model.getRules()) {
			rules.format;
		}
	}

	def dispatch void format(Rules rules, extension IFormattableDocument document) {
		rules.getCondition.format;
		rules.getResult.format;
	}
	
	def dispatch void format(Result result, extension IFormattableDocument document){
		result.regionFor.keyword("(").prepend[newLine]
	}
	
	def dispatch void format(Condition condition, extension IFormattableDocument document) {
		format(condition.condition, document);
	}

	private static class BooleanWrapper {
		boolean first = true;
		
		def isFirst(){
			return first;
		}
		
		def setIsFirst(boolean value){
			first = value;
		}
	}
	
	def dispatch void format(ConditionAtom conditionatom, extension IFormattableDocument document) {
		val firstIndent = new BooleanWrapper() // needed to prevent double indent if line is autowrapped twice
		val access = conditionAtomAccess
		val IAutowrapFormatter autoWrapIndent  = [region, wrapped, doc |
			if (firstIndent.isFirst){
				firstIndent.isFirst = false
				val first = (region as IWhitespace).hiddenRegion
				val last = conditionatom.regionForEObject.nextHiddenRegion
				println("indent white for " + first.offset + " to " + last.offset + " (" + region.textRegionAccess.regionForDocument.text.substring(first.offset, last.offset) + ") ")
				doc.set(first, last, [indent])
			}
		]
		conditionatom.allRegionsFor.keywords(",").forEach[append[autowrap; onAutowrap = autoWrapIndent]]
	}
}

I have attached my workspace with the dsl and a simple test to show the problem. The test testLongLastLinePart runs fine but the test testShortLastLinePart has the problem described above.
Any help would be greatly appreciated.

Best regards
Florian Schwarz
Re: IAutoWrapFormatter with indent ignores newline under certain conditions [message #1755881 is a reply to message #1755819] Wed, 08 March 2017 21:24 Go to previous messageGo to next message
Christian Dietrich is currently online Christian DietrichFriend
Messages: 10333
Registered: July 2009
Senior Member
Hi,

can you please file a bug at

https://github.com/eclipse/xtext-core/issues

as a workaround you may try some restructuring of the code



import com.google.inject.Inject
import org.eclipse.xtext.formatting2.AbstractFormatter2
import org.eclipse.xtext.formatting2.IFormattableDocument
import org.xtext.example.mydsl.myDsl.Model
import org.xtext.example.mydsl.myDsl.Rules
import org.xtext.example.mydsl.services.MyDslGrammarAccess

class MyDslFormatter extends AbstractFormatter2 {
	
	@Inject extension MyDslGrammarAccess
	
	def dispatch void format(Model model, extension IFormattableDocument document) {
		for (Rules rules : model.getRules()) {
			rules.format;
		}
	}

	def dispatch void format(Rules rules, extension IFormattableDocument document) {
		val conditionatom =rules.condition.condition
			conditionatom.allRegionsFor.keywords(",").forEach[append[oneSpace; autowrap]]
		interior(conditionatom.regionFor.keyword(","), rules.result.regionFor.keyword("("))[indent]
		conditionatom.append[oneSpace;newLine]
		
		
		rules.getResult.format;
		rules.getCondition.format;
	}
	
	
	
}
Re: IAutoWrapFormatter with indent ignores newline under certain conditions [message #1756027 is a reply to message #1755819] Fri, 10 March 2017 09:10 Go to previous message
Florian Schwarz is currently offline Florian SchwarzFriend
Messages: 4
Registered: March 2017
Junior Member
Hi Christian,

thank you very much for your reply.
I filed the bug (has you have already noticed).
The workaround you provided works well for the small example project, but my original project involved a boolean condition tree which should be indented correctly, e.g.
	if: businessProcessType = APPLICATION_CREATE, PROPOSAL_CREATE, APPLICATION_MODIFY
		and: (
			entity = ct:DokNwVar, ct:HvGruppe
			or: entity = ct:SteuAuftReg
				and: dataField = SteuAuftReg.auftlgFormel, SteuAuftReg.beitragsTyp, SteuAuftReg.betragsArt, 
					SteuAuftReg.kzAktBearb, SteuAuftReg.kzInitialKBF, SteuAuftReg.parAnteil
			or: entity = ct:DokNw
				and: dataField = ctAttrGroup:DokNwAttrs
		)
	(RESULT)

From my understanding of your workaround, this wouldn't work for my project as it is not necessarily the last element of my condition that needs a line wrapping (and the rules.result.regionFor.keyword("(") would work only for the last). So I guess I have to live without the indentation of the wrapped line until the bug is fixed.

Best regards
Florian
Previous Topic:Overloaded method determination
Next Topic:Integration in VS Code
Goto Forum:
  


Current Time: Thu Mar 30 07:03:10 GMT 2017

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

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