Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Using Quickfix to add elements to imported ECore resource
Using Quickfix to add elements to imported ECore resource [message #1701102] Thu, 09 July 2015 10:33 Go to next message
Florian König is currently offline Florian KönigFriend
Messages: 30
Registered: June 2014
Member
Hello,

In my DSL I import ECore resources using importURI. Now I want to implement a quickfix for adding EOperations / EAttributes to an imported ECore resource in my DSL.

My DSL looks like this:
grammar org.xtext.example.importquickfix.MyDsl with org.eclipse.xtext.common.Terminals

import "http://www.eclipse.org/emf/2002/Ecore"

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

Model:
	'import' importURI=STRING
	'domain' domain=[EPackage]
	greetings+=Greeting*;

Greeting:
	'Hello' ec=[EClass] '.' op=[EOperation];


My scope looks like this:
class MyDslScopeProvider extends org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider {

	def IScope scope_Greeting_ec(Greeting greeting, EReference ref) {
		val model = greeting.eContainer as Model
		val domain = model.domain as EPackage
		return Scopes::scopeFor(domain.EClassifiers.filter(typeof(EClass)))
	}
	
	def IScope scope_Greeting_op(Greeting greeting, EReference ref) {
		return Scopes::scopeFor(greeting.ec.EOperations)
	}

}


My ECore resource looks like this:
index.php/fa/22450/0/

And my example looks like this:
index.php/fa/22451/0/

The EOperation 'myOperation2' does not exist and I want to have a quickfix to add it to the imported model.

How can I do that? For my own validator errors and warnings I can specify an ID to use for a Quickfix. Since this is a build in error, I do not know the ID. Is there an ID or another way to do this?

Thanks in advance,
Florian
Re: Using Quickfix to add elements to imported ECore resource [message #1701103 is a reply to message #1701102] Thu, 09 July 2015 10:45 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
adapt DiagnosticMessageProvider and provide a custom code and add the node text to the data of the issue and then write a normal quickfix

	@Override
		public DiagnosticMessage getUnresolvedProxyMessage(ILinkingDiagnosticContext context) {
			if (XXXXPackage.Literals.YYYY_REF.equals(context.getReference())) {

				final String msg = "Folgende Referenz kann nicht aufgelöst werden: " + " '" + context.getLinkText() + "'.";
				return new DiagnosticMessage(msg, Severity.ERROR, "MyCode", context.getLinkText());
			} else {
				return super.getUnresolvedProxyMessage(context);

			}
		}


to fix stuff in other files you may have to open the editor of that other file and call xtexteditor.getDocument.modify


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Using Quickfix to add elements to imported ECore resource [message #1707336 is a reply to message #1701103] Thu, 03 September 2015 19:51 Go to previous messageGo to next message
Florian König is currently offline Florian KönigFriend
Messages: 30
Registered: June 2014
Member
Hi Christian,

sorry for the late response.
I created a custom LinkingDiagnosticMessageProvider and implemented the getUnresolvedProxyMessage method as you said.
This works fine, thank you very much!

Then I implemented a quickfix like I would do for my xtext document.

@Fix(IssueCodes::OPERATION_NOT_FOUND)
	def fixOperationNotFound(Issue issue, IssueResolutionAcceptor acceptor) {
		createLinkingIssueResolutions(issue, acceptor);
		acceptor.accept(
			issue,
			'Add operation to model',
			'Add operation to model.',
			null,
			new ISemanticModification() {
				override apply(EObject element, IModificationContext context) throws Exception {

					// Retrieve 
					val greeting = element as Greeting
					val type = greeting.ec as EClass
					
					// Retrieve name of operation
					val operationName = context.xtextDocument.get(issue.offset, issue.length)

					// Create new operation
					val newOperation = EcoreFactory.eINSTANCE.createEOperation()
					newOperation.name = operationName 
					
					// Add to model
					type.EOperations.add(newOperation)
					// Save model
					type.eResource.save(Collections.EMPTY_MAP)
				}
			}
		)
	}


This works and adds the new operation to the model, but the Xtext editor still shows the error.
To refresh the editor I have to change something and then save the document.

How can I change the quickfix to refresh the editor automatically?
Re: Using Quickfix to add elements to imported ECore resource [message #1707338 is a reply to message #1707336] Thu, 03 September 2015 20:09 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
hmmm i have no idea on that.

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Using Quickfix to add elements to imported ECore resource [message #1707341 is a reply to message #1707338] Thu, 03 September 2015 20:11 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14661
Registered: July 2009
Senior Member
p.s. maybe you can tweak org.eclipse.xtext.resource.impl.DefaultResourceDescriptionManager.isAffected(Delta, IResourceDescription)
and report a change of the "type name" if the "operation" changes


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Using Quickfix to add elements to imported ECore resource [message #1707352 is a reply to message #1707341] Thu, 03 September 2015 22:23 Go to previous message
Florian König is currently offline Florian KönigFriend
Messages: 30
Registered: June 2014
Member
I don't really know how to tweak the DefaultResourceDescriptionManager..

I also tried to use EditingDomains to change the models and update the editor, but then I found out that Xtext does not use any EditingDomains (is that correct?).

But I found another way to modify xtext documents by using the modify method of the document (as you said before).
In this method I can set a "modified" flag that forces the editor to refresh.

context.xtextDocument.modify(
	new IUnitOfWork.Void<XtextResource>() {

		override process(XtextResource state) throws Exception {
			state.modified = true
		}

})


This works, but looks like a workaround though.. Does anyone know another way?
Previous Topic:How coud we bind XtextBuilder?
Next Topic:Runtime hovering
Goto Forum:
  


Current Time: Tue Mar 19 05:18:10 GMT 2024

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

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

Back to the top