Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » [Xtext] Formatter2 usage when programmatically save Xtext resource
[Xtext] Formatter2 usage when programmatically save Xtext resource [message #1710808] Fri, 09 October 2015 12:47 Go to next message
Hauke Fuhrmann is currently offline Hauke FuhrmannFriend
Messages: 30
Registered: January 2015
Member
Hi there,

I implemented a Formatter2, which works nicely in the IDE when hitting
Strg-Shift-F. However, when I programmatically save a resource, the
serializer of the Xtext Resource is always the OneSpaceFormatter and not
my formatter 2.

My Code to save is

public static void writeXtextResource(Path target, EObject object)
throws IOException{
new org.eclipse.emf.mwe.utils.StandaloneSetup().setPlatformUri("../");
Injector injector = new
PkpConfigStandaloneSetup().createInjectorAndDoEMFRegistration();
XtextResourceSet resourceSet =
injector.getInstance(XtextResourceSet.class);
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
URI fileURI = URI.createFileURI(target.toAbsolutePath().toString());
Resource resource = resourceSet.createResource(fileURI);
resource.getContents().clear();
resource.getContents().add(object);

resource.save(SaveOptions.newBuilder().format().getOptions().toOptionsMap());
}

I debugged the Injector which actually has my formatter options taken
from the Module.

I enabled the Formatter2 in the mwe file

// formatter API
//fragment = formatting.FormatterFragment auto-inject {}
fragment = formatting2.Formatter2Fragment auto-inject {}

This leads to the corresponding binding in the abstract RuntimeModule
generated for my language:

// contributed by org.eclipse.xtext.generator.formatting2.Formatter2Fragment
public Class<? extends org.eclipse.xtext.formatting2.IFormatter2>
bindIFormatter2() {
return
de.scheidtbachmann.pkp.config.text.formatting2.PkpConfigFormatter.class;
}

// contributed by org.eclipse.xtext.generator.formatting2.Formatter2Fragment
public void configureFormatterPreferences(com.google.inject.Binder
binder) {

binder.bind(org.eclipse.xtext.preferences.IPreferenceValuesProvider.class).annotatedWith(org.eclipse.xtext.formatting2.FormatterPreferences.class).to(org.eclipse.xtext.formatting2.FormatterPreferenceValuesProvider.class);
}

Still, the formatter in the serializer of the XtextResource is the
OneSpaceFormatter...

How to change that?

Cheers,
Hauke
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1710811 is a reply to message #1710808] Fri, 09 October 2015 13:09 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Which xtext version?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1710832 is a reply to message #1710811] Fri, 09 October 2015 15:21 Go to previous messageGo to next message
aurel pestell is currently offline aurel pestellFriend
Messages: 90
Registered: October 2013
Location: Sweden
Member
Aren't you supposed to use the single instance of the injector that is hold by the Activator of your UI plugin ?
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1710838 is a reply to message #1710832] Fri, 09 October 2015 15:46 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
Yes never ever call standalonesetup from a runninh eclipse

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746670 is a reply to message #1710808] Wed, 02 November 2016 17:53 Go to previous messageGo to next message
Daniel Ford is currently offline Daniel FordFriend
Messages: 148
Registered: July 2009
Location: New York
Senior Member
Xtext Version 2.10.0

I have the same issue as the OP, basically that when programmatically trying to format using just the runtime project, not the UI, then the formatter that is used is always OneWhitespaceFormatter, even when an alternate Formatter2 is available.

More specifically, I have a single Xtext runtime project with Maven structure. The workflow is configured to generate Formatter2, and it does. I've implemented my Formatter2 formatter, and have implemented a unit test (in the same project under src/test/java) to test it. The test runs fine, but my Formatter2 implementation is never invoked. Using the debugger, I note that when I "format" DefaultNodeModelFormatter.format() is called, which then uses a dependency injected IFormatter (i.e., a OneWhitespaceFormatter instance). An instance of my Formatter2 implementation is created by the injection framework and available.

I dug around in some other Xtext projects that I have that do have UI's, some with Formatter2 implementations, and some without. The ones that do have this:

// contributed by org.eclipse.xtext.xtext.generator.formatting.Formatter2Fragment2
public Class<? extends IContentFormatterFactory> bindIContentFormatterFactory() {
return ContentFormatterFactory.class;
}

in their Abstract<MYDSL>UiModule, which would explain why it works in the UI.

I suspect that Formatter2 "handling" in just the runtime project is not implemented yet. One way forward would be for me to override bindINodeModelFormatter() in my DSL's RuntimeModule and return a custom implementation of INodeModelFromatter to support Formatter2.

Am I missing something?
Would this create problems if/when I do develop a UI?
Has this already been addressed in a new version?

Thanks
Dan
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746676 is a reply to message #1746670] Wed, 02 November 2016 20:35 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
How does your wf look like?

formatter { generateStub = true }

???


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746677 is a reply to message #1746676] Wed, 02 November 2016 20:37 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
And what do you actually do in your code?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746790 is a reply to message #1746677] Fri, 04 November 2016 15:42 Go to previous messageGo to next message
Daniel Ford is currently offline Daniel FordFriend
Messages: 148
Registered: July 2009
Location: New York
Senior Member
Here's the relevant part of the wf

language = XtextGeneratorLanguage {
name = "com.foo.bar"
fileExtensions = "zipzap"
resourceSet = theResourceSet

fragment = grammarAccess.GrammarAccessFragment2 {}
fragment = ecore.EMFGeneratorFragment2 {}
fragment = serializer.SerializerFragment2 {}
fragment = resourceFactory.ResourceFactoryFragment2 {}
fragment = parser.antlr.XtextAntlrGeneratorFragment2 {}
fragment = validation.ValidatorFragment2 {}
fragment = scoping.ImportNamespacesScopingFragment2 {}
//fragment = exporting.QualifiedNamesFragment2 {}
fragment = builder.BuilderIntegrationFragment2 {}
//fragment = generator.GeneratorFragment2 {}
fragment = formatting.Formatter2Fragment2 {
generateStub=true
generateXtendStub=true
}
//fragment = ui.labeling.LabelProviderFragment2 {}
//fragment = ui.outline.QuickOutlineFragment2 {}
//fragment = ui.outline.OutlineTreeProviderFragment2 {}
//fragment = ui.quickfix.QuickfixProviderFragment2 {}
//fragment = ui.contentAssist.ContentAssistFragment2 {}
fragment = junit.Junit4Fragment2 {}
//fragment = ui.refactoring.RefactorElementNameFragment2 {}
fragment = types.TypesGeneratorFragment2 {}
//fragment = xbase.XtypeGeneratorFragment2 {}
//fragment = xbase.XbaseGeneratorFragment2 {}
//fragment = ui.templates.CodetemplatesGeneratorFragment2 {}
//fragment = ui.compare.CompareFragment2 {}
//fragment = idea.parser.antlr.XtextAntlrIDEAGeneratorFragment {}
//fragment = idea.IdeaPluginGenerator {}
//fragment = web.WebIntegrationFragment {
// framework = "Ace"
//}
}

In code, the unit test I'm using to test formatting uses this utility method to perform the formatting and test that the result is as expected:

def void assertFormattedAs(CharSequence input, CharSequence expected) {
expected.toString.assertEquals(
(input.parse.eResource as XtextResource).parseResult.rootNode.format(0, input.length).formattedText)
}



Something I didn't mention, but could be important, is that formatting wasn't originally enabled when the workflow was first run to generate the project's artifacts. It was enabled later.

Maybe I need to delete some artifacts and have the workflow generate new versions that do enable formatting2?

Is that what' you're looking for?

Dan


[Updated on: Fri, 04 November 2016 15:51]

Report message to a moderator

Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746794 is a reply to message #1746790] Fri, 04 November 2016 16:04 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
no you dont. but i dont get why you have all these fragments in the workflow

if you create a new project it looks like

		language = StandardLanguage {
			name = "org.xtext.example.mydsl2.MyDsl"
			fileExtensions = "mydsl2"

			serializer = {
				generateStub = false
			}
			validator = {
				// composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
			}
		}


here you can simply add this

formatter { generateStub = true }

i dont know what your pile of customizations may have as a side effect.
thus i recommend this with a new project and a new workflow first.

and you should consider to use FormatterTester for such tests

if i enable formatter fragment i get following bindings

(check this with your in (abstract)yourdslruntimemodule

	// contributed by org.eclipse.xtext.xtext.generator.formatting.Formatter2Fragment2
	public Class<? extends IFormatter2> bindIFormatter2() {
		return MyDslFormatter.class;
	}
	
	// contributed by org.eclipse.xtext.xtext.generator.formatting.Formatter2Fragment2
	public void configureFormatterPreferences(Binder binder) {
		binder.bind(IPreferenceValuesProvider.class).annotatedWith(FormatterPreferences.class).to(FormatterPreferenceValuesProvider.class);
	}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746796 is a reply to message #1746794] Fri, 04 November 2016 16:13 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
p.s: NodeModelFormatter is for formatter 1 only

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746797 is a reply to message #1746796] Fri, 04 November 2016 16:26 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
and here is a example using the tester

	@Inject
	extension FormatterTester

	@Test 
	def void testIt() {
		assertFormatted[
			expectation = '''
			Hello A!
			Hello B!'''
			toBeFormatted = '''Hello A! Hello B!'''
		]
	}


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746803 is a reply to message #1746797] Fri, 04 November 2016 18:46 Go to previous messageGo to next message
Daniel Ford is currently offline Daniel FordFriend
Messages: 148
Registered: July 2009
Location: New York
Senior Member
..quick response...As a quick test, I dropped the two generated lines into my Abstract*RuntimeModule and added some breakpoints. They're both called, but it's still defaulting to the old OneSpace Formatter.

Maybe there's something else that's generated?

I switched to using XtextGeneratorLanguage to get as much control as I could on the generation process. The parser is being embedded in something else and I don't (currently) need all the extra stuff for a full-scale editor or IDE integration.

Thanks for the formatter tester tip.

Dan

Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746808 is a reply to message #1746803] Fri, 04 November 2016 19:35 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
As I said if the API you uses is formatter1 only configuring formatter 2 won't help

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746811 is a reply to message #1746808] Fri, 04 November 2016 20:05 Go to previous messageGo to next message
Daniel Ford is currently offline Daniel FordFriend
Messages: 148
Registered: July 2009
Location: New York
Senior Member
Nope, I'm using Formatter2. I don't have anything in the code base written or deliberately configured for Formatter1.
Dan
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746812 is a reply to message #1746811] Fri, 04 November 2016 20:36 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
The node model formatter you use in your test does use formatter 1 only

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746813 is a reply to message #1746811] Fri, 04 November 2016 21:50 Go to previous messageGo to next message
Daniel Ford is currently offline Daniel FordFriend
Messages: 148
Registered: July 2009
Location: New York
Senior Member
I've been going through the Xtext code looking for where the runtime guice bindings are produced, etc.

I see that the method org.eclipse.xtext.generator.formatting2.Formatter2Fragment.getGuiceBindingsRt() produces the bindings provided above for the Abstract RuntimeModule.

i.e.,:
// contributed by org.eclipse.xtext.xtext.generator.formatting.Formatter2Fragment2
public void configureFormatterPreferences(Binder binder) {
binder.bind(IPreferenceValuesProvider.class).annotatedWith(FormatterPreferences.class).to(FormatterPreferenceValuesProvider.class);
}

But, not surprisingly, I put some breakpoints in, and it never gets called. I dug around trying to find how the workflow would be configured to get it into the mix, but didn't find anything.

So, I started at StandardLanguage and looked around for how it might be configured and would eventually trigger the call to getGuiceBindingsRt() and couldn't find a path from there either.

In the right configuration, it obviously gets called, but I can't see how to conjure that up.

Any hints? Is there some obvious documentation that I've overlooked?

Thanks
Dan
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746814 is a reply to message #1746813] Fri, 04 November 2016 21:58 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
did you debug the workflow? i still have the feeling this has to do with your overcustoimized workflow. i dont know why you do this overcustomization

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746827 is a reply to message #1746790] Sat, 05 November 2016 09:20 Go to previous messageGo to next message
Lorenzo Bettini is currently offline Lorenzo BettiniFriend
Messages: 1812
Registered: July 2009
Location: Firenze, Italy
Senior Member
Daniel Ford wrote on Fri, 04 November 2016 15:42

In code, the unit test I'm using to test formatting uses this utility method to perform the formatting and test that the result is as expected:

def void assertFormattedAs(CharSequence input, CharSequence expected) {
expected.toString.assertEquals(
(input.parse.eResource as XtextResource).parseResult.rootNode.format(0, input.length).formattedText)
}


Daniel, this looks like the code snippet in the first edition of the Xtext book, and it is based on the old formatter, you can't use that with the new formatter. The second edition of the book deals with the new formatter, which is also much easier to test, as Christian showed.

Lorenzo


Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746899 is a reply to message #1746827] Mon, 07 November 2016 13:25 Go to previous messageGo to next message
Daniel Ford is currently offline Daniel FordFriend
Messages: 148
Registered: July 2009
Location: New York
Senior Member
Lorenzo,
thanks for the tip. BTW, I enjoyed your book, thought it was well written; better yet, I've ordered the second edition, it should be here this week.

The reason I'm using XtextGeneratorLanguage instead of StandardLanguage is because the documentation here: https://www.eclipse.org/Xtext/documentation/302_configuration.html#short-intro-to-mwe
says that it "is not possible to remove fragments from the StandardLanguage." At the moment, I'm generating the runtime project from an external ecore file, and am only interested in generating as little as possible.

From the documentation, it would seem that "fragment = formatting.Formatter2Fragment2()" would do the trick to produce Formatter2 support using XtextGeneratorLanguage in the runtime project, but I haven't found that to be the case. So, it would seem like there's either a bug in the code, or a bug in the documentation.

The guice bindings for the runtime project are produced in org.eclipse.xtext.generator.formatting2.Formatter2Fragment.getGuiceBindingsRt(), but it's never called during the XtextGeneratorLanguage workflow.

Dan
Re: [Xtext] Formatter2 usage when programmatically save Xtext resource [message #1746905 is a reply to message #1746899] Mon, 07 November 2016 14:21 Go to previous message
Daniel Ford is currently offline Daniel FordFriend
Messages: 148
Registered: July 2009
Location: New York
Senior Member
Ok, I'm making progress. The correct guice bindings are now being generated in the runtime project using the XtextGeneratorLanguage. I was convinced that they were not being generated, but now that is working. Who knows? Probably my mistake. Using the FormatterTester also now invokes my Formatter2 code.

Thanks for everyone's help.
Dan
Previous Topic:Generate syntax graph during automatic build
Next Topic:EMF registries and guice injection
Goto Forum:
  


Current Time: Thu Apr 18 00:55:01 GMT 2024

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

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

Back to the top