|
|
|
Re: Refactoring for xtextEditors [message #550502 is a reply to message #550436] |
Fri, 30 July 2010 14:21 |
Sebastian Zarnekow Messages: 3118 Registered: July 2009 |
Senior Member |
|
|
Hi John,
xtextDocument.readOnly(..) indicates that the resource should not be
modified in the UnitOfWork, doesn't it ;-)
Please use the IDocumentEditor instead. It offers a similar API:
IDocumentEditor.process(unitOfWork, xtextDocument);
Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com
Am 30.07.10 13:22, schrieb john_locke@gmx.de:
> Hi Sebastian,
>
> thanks for your answer.
> Here are some code snippets.
>
> First step: I use the IXtextDocument to get the EObject.
>
>
> xEditor.getDocument().readOnly(new IUnitOfWork.Void<XtextResource>() {
> public void process(XtextResource resource) throws Exception {
> IParseResult parseRes = resource.getParseResult();
> if(parseRes==null)
> return;
> CompositeNode rootNode = parseRes.getRootNode();
> int offset = tSelection.getOffset();
> AbstractNode node =
> ParseTreeUtil.getCurrentOrFollowingNodeByOffset(rootNode, offset);
> EObject object = NodeUtil.getNearestSemanticObject(node);
> // ...
> }
> });
>
>
> Second step: EMF Refactor(LTK) i needs the EditingDomain for the next step.
>
>
> ..
> ResourceSet synRset = selection.get(0).eResource()
> .getResourceSet();
> TransactionalEditingDomain domain =
> TransactionalEditingDomain.Factory.INSTANCE
> .createEditingDomain(synRset);
> ..
>
>
> Third step: EMF Refactor calls LTK with object and domain to generate
> the changes.
>
> Is this proceeding okay or not? The changes are applied to the synRset,
> but the changes are not visible in the xtextEditor. What is the problem
> of this approach?
>
> Regards,
> John
|
|
|
|
|
|
|
Re: Refactoring for xtextEditors [message #552850 is a reply to message #552840] |
Fri, 13 August 2010 19:01 |
Sebastian Zarnekow Messages: 3118 Registered: July 2009 |
Senior Member |
|
|
Hi John,
I guess you have to remove the editing domain after you performed the
refactoring. Furthermore it is strongly recommend - guess what - to
perform the changes by means of the IDocumentEditor. Why don't you just
put all your code into an IUnitOfWork (by the way: according to the
docs, you should never ever return an eObject from a unit of work).
@Inject
IDocumentEditor editor;
editor.process(new IUnitOfWork.Void<XtextResource>() {
void process(XtextResource res) {
try {
.. attach editing domain
.. find objects
.. perform refactoring
} finally {
.. remove editing domain
}
}
}, document);
Just as a sidenode: You should have a look at the EObjectAtOffsetHelper.
Hope that helps,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com
Am 13.08.10 19:23, schrieb John:
> Hi,
>
> here is my basic idea of the implementation for Xtext.
> I want to use EMFRefactor (uses internal Language Toolkit) to apply the
> refactorings.
> EMFRefactor needs the EObject on which the refactoring should be
> applied. The EditingDomain of this EObject is also needed.
>
> 1) I use the ParseTree to get the EObject of the selected text area in
> the XtextEditor.
>
> if (selection instanceof TextSelection) {
> final TextSelection tSelection = (TextSelection) selection;
> XtextEditor xEditor = EditorUtils.getActiveXtextEditor();
> if (xEditor != null) {
> final List<Object> list = new ArrayList<Object>();
> xEditor.getDocument().readOnly(new IUnitOfWork.Void<XtextResource>() {
> public void process(XtextResource resource) throws Exception {
> IParseResult parseRes = resource.getParseResult();
> if(parseRes==null)
> return;
> CompositeNode rootNode = parseRes.getRootNode();
> int offset = tSelection.getOffset();
> AbstractNode node =
> ParseTreeUtil.getCurrentOrFollowingNodeByOffset(rootNode, offset);
> EObject object = NodeUtil.getNearestSemanticObject(node);
> list.add(object);
> }
> });
> return list.toArray();
> }
> }
>
>
> 2) I create the EditingDomain for the given EObject.
>
> if(null == editingDomain){
> XtextResource xResource = (XtextResource) selection.get(0).eResource();
> editingDomain = TransactionalEditingDomain.Factory.INSTANCE
> .createEditingDomain(xResource.getResourceSet());
> }
>
> I use create, because getEdtingDomain(...) returns always "null".
>
> 3) EMFRefactor performs the changes with LTK.
> 4) I want to update the XtextEditor.
>
> XtextResource xResource = (XtextResource) selection.get(0).eResource();
> String erg =
> xResource.getSerializer().serialize(xResource.getContents(). get(0));
>
> XtextEditor xEditor = EditorUtils.getActiveXtextEditor();
> IXtextDocument xDocument = xEditor.getDocument();
> xDocument.replace(0, xDocument.getLength(), erg);
>
>
> The following exception appears after step 4).
>
> !ENTRY org.eclipse.core.jobs 4 2 2010-08-13 18:45:45.233
> !MESSAGE An internal error occurred during: "XtextReconcilerJob".
> !STACK 0
> java.lang.IllegalStateException: Cannot modify resource set without a
> write transaction
> at
> org.eclipse.emf.transaction.impl.TransactionChangeRecorder.a ssertWriting(TransactionChangeRecorder.java:348)
>
> at
> org.eclipse.emf.transaction.impl.TransactionChangeRecorder.a ppendNotification(TransactionChangeRecorder.java:302)
>
> at
> org.eclipse.emf.transaction.impl.TransactionChangeRecorder.p rocessResourceNotification(TransactionChangeRecorder.java:27 2)
>
> at
> org.eclipse.emf.transaction.impl.TransactionChangeRecorder.n otifyChanged(TransactionChangeRecorder.java:238)
>
> at
> org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify (BasicNotifierImpl.java:380)
>
> at
> org.eclipse.emf.common.notify.impl.NotifyingListImpl.dispatc hNotification(NotifyingListImpl.java:267)
>
> at
> org.eclipse.emf.common.notify.impl.NotifyingListImpl.clear(N otifyingListImpl.java:1120)
>
> at
> org.eclipse.xtext.resource.XtextResource.clearInternalState( XtextResource.java:230)
>
> at org.eclipse.xtext.resource.XtextResource.reparse(XtextResour ce.java:167)
> at
> org.eclipse.xtext.ui.editor.model.XtextDocument$XtextDocumen tLocker.modify(XtextDocument.java:152)
>
> at
> org.eclipse.xtext.ui.editor.model.XtextDocument.modify(Xtext Document.java:62)
>
> at
> org.eclipse.xtext.ui.editor.reconciler.XtextDocumentReconcil eStrategy.reconcile(XtextDocumentReconcileStrategy.java:27)
>
> at
> org.eclipse.xtext.ui.editor.reconciler.XtextReconciler.run(X textReconciler.java:179)
>
> at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
>
>
> What is the problem or the fault of my idea/implementation?
>
> I will be very thankful for any hints,
> John
|
|
|
|
Re: Refactoring for xtextEditors [message #554576 is a reply to message #554240] |
Mon, 23 August 2010 15:20 |
John Locke Messages: 23 Registered: July 2010 |
Junior Member |
|
|
Hi everybody,
i tried to solve my problem with the following code:
Injector injector = Guice.createInjector(new SimpleClassRuntimeModule());
final IDocumentEditor iDocEditor = injector.getInstance(IDocumentEditor.class);
XtextEditor xEditor = EditorUtils.getActiveXtextEditor();
iDocEditor.process(new IUnitOfWork.Void<XtextResource>() {
@Override
public void process(XtextResource state) throws Exception {
try {
//... doing some semantic model changes
String res = state.getSerializer().serialize(state.getContents().get(0));
xEditor.getDocument().set(res);
System.out.println("*.SimpleClass");
System.out.println(res);
}
}
}
The problem is no changes are applied to the IXtextDocument. The res string is exactly the result i need.
Are there any other possibilities to trigger the serializer without the save methode of the XtextResource?
If i use the following code the changes applied to the editor but also the XtextResource is saved.
Injector injector = Guice.createInjector(new SimpleClassRuntimeModule());
final IDocumentEditor iDocEditor = injector.getInstance(IDocumentEditor.class);
XtextEditor xEditor = EditorUtils.getActiveXtextEditor();
iDocEditor.process(new IUnitOfWork.Void<XtextResource>() {
@Override
public void process(XtextResource state) throws Exception {
try {
//... doing some semantic model changes
state.save(null);
}
}
}
How could i adapt the behavior of the save method without saving.
Regards,
John
[Updated on: Mon, 23 August 2010 15:23] Report message to a moderator
|
|
|
|
Re: Refactoring for xtextEditors [message #554585 is a reply to message #554584] |
Mon, 23 August 2010 15:42 |
Eclipse User |
|
|
|
Originally posted by: arendt.mathematik.uni-marburg.de
Hi Sebastian,
you wrote
> All this is nicely protected in a unit of work and your code has exclusive access to the resource. The idea is
> not to perform modifications on the document or on any other eobject
> that is not contained in the resource.
But John was performing modifications on an eobject that WAS contained
in the resource, I think. He only wants to write back the changes.
You further wrote
> You will not be able to perform cross-file refactorings inside of a single document edit action.
What do you mean by 'CROSS-FILE refactorings'?
Regards,
Thorsten
|
|
|
|
Re: Refactoring for xtextEditors [message #554612 is a reply to message #554576] |
Mon, 23 August 2010 16:50 |
Christian Schneider Messages: 23 Registered: July 2009 |
Junior Member |
|
|
Hi John,
hope I understood you right.
In case you want to modify the content of an active xtext editor
(not only a parsed model you loaded programmatically)
by means of updating the underlying semantic model try the following code:
XtextEditor xtextEditor = EditorUtils.getActiveXtextEditor();
IDocumentEditor documentEditor = MyDSLActivator.getInstance()
.getInjector(<<Name of your language>>)
.getInstance(IDocumentEditor.class);
documentEditor.process(<<your UnitOfWork>>, xtextEditor.getDocument());
MyDSLActivator is the activator class of the *.ui plugin generated by xtext.
Have a look on it for, e.g., the language name.
If the SWT toolkit is complaining you should let the code run by the Display thread:
PlatformUI
.getWorkbench()
.getDisplay()
.asyncExec(
new Runnable() {
public void run() {
XtextEditor xtextEditor = EditorUtils.getActiveXtextEditor();
IDocumentEditor documentEditor = MyDSLActivator.getInstance()
.getInjector(<<Name of your language>>)
.getInstance(IDocumentEditor.class);
documentEditor.process(<<your UnitOfWork>>, xtextEditor.getDocument());
}
});
Note: restrict yourself straightly on the transformation of the underlying model;
do not try to invoke the serialization manually! This will be done by the framework.
Best,
Christian
On 8/23/10 5:20 PM, John wrote:
> Hi everybody,
>
> i tried to solve my problem with the following code:
>
>
> Injector injector = Guice.createInjector(new SimpleClassRuntimeModule());
> final IDocumentEditor iDocEditor =
> injector.getInstance(IDocumentEditor.class);
> XtextEditor xEditor = EditorUtils.getActiveXtextEditor();
>
> iDocEditor.process(new IUnitOfWork.Void<XtextResource>() {
> @Override
> public void process(XtextResource state) throws Exception {
> try {
> //... doing some semantic model changes
> String res =
> state.getSerializer().serialize(state.getContents().get(0));
> xEditor.getDocument().set(res);
> System.out.println("*.SimpleClass");
> System.out.println(res);
> }
> }
> }
>
>
> The problem is no changes are applied to the IXtextDocument. Are there
> any other possibilities to trigger the serializer without the save
> methode of the XtextResource?
> If i use the following code the changes applied to the editor but also
> the XtextResource is saved.
> Injector injector = Guice.createInjector(new SimpleClassRuntimeModule());
> final IDocumentEditor iDocEditor =
> injector.getInstance(IDocumentEditor.class);
> XtextEditor xEditor = EditorUtils.getActiveXtextEditor();
>
> iDocEditor.process(new IUnitOfWork.Void<XtextResource>() {
> @Override
> public void process(XtextResource state) throws Exception {
> try {
> //... doing some semantic model changes
> state.save(null);
> }
> }
> }
>
> How could i adapt the behavior of the save method without saving.
>
> Regards,
> John
|
|
|
Re: Refactoring for xtextEditors [message #554617 is a reply to message #554612] |
Mon, 23 August 2010 17:27 |
Sebastian Zarnekow Messages: 3118 Registered: July 2009 |
Senior Member |
|
|
Hi John,
sounds good to me, although I'ld prefer to initialize the handler by
means of google guice and inject the document editor directly into the
handler class.
@Inject
IDocumentEditor docEditor;
public void ... {
XtextEditor xtextEditor = EditorUtils.getActiveXtextEditor();
docEditor.process(...);
}
Regards,
Sebastian
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com
Am 23.08.10 18:50, schrieb Christian Schneider:
> Hi John,
>
> hope I understood you right.
> In case you want to modify the content of an active xtext editor
> (not only a parsed model you loaded programmatically)
> by means of updating the underlying semantic model try the following code:
>
> XtextEditor xtextEditor = EditorUtils.getActiveXtextEditor();
>
> IDocumentEditor documentEditor = MyDSLActivator.getInstance()
> .getInjector(<<Name of your language>>)
> .getInstance(IDocumentEditor.class);
>
> documentEditor.process(<<your UnitOfWork>>, xtextEditor.getDocument());
>
> MyDSLActivator is the activator class of the *.ui plugin generated by xtext.
> Have a look on it for, e.g., the language name.
>
> If the SWT toolkit is complaining you should let the code run by the Display thread:
>
> PlatformUI
> .getWorkbench()
> .getDisplay()
> .asyncExec(
> new Runnable() {
> public void run() {
>
> XtextEditor xtextEditor = EditorUtils.getActiveXtextEditor();
>
> IDocumentEditor documentEditor = MyDSLActivator.getInstance()
> .getInjector(<<Name of your language>>)
> .getInstance(IDocumentEditor.class);
>
> documentEditor.process(<<your UnitOfWork>>, xtextEditor.getDocument());
> }
> });
>
> Note: restrict yourself straightly on the transformation of the underlying model;
> do not try to invoke the serialization manually! This will be done by the framework.
>
>
> Best,
> Christian
>
>
> On 8/23/10 5:20 PM, John wrote:
>> Hi everybody,
>>
>> i tried to solve my problem with the following code:
>>
>>
>> Injector injector = Guice.createInjector(new SimpleClassRuntimeModule());
>> final IDocumentEditor iDocEditor =
>> injector.getInstance(IDocumentEditor.class);
>> XtextEditor xEditor = EditorUtils.getActiveXtextEditor();
>>
>> iDocEditor.process(new IUnitOfWork.Void<XtextResource>() {
>> @Override
>> public void process(XtextResource state) throws Exception {
>> try {
>> //... doing some semantic model changes
>> String res =
>> state.getSerializer().serialize(state.getContents().get(0));
>> xEditor.getDocument().set(res);
>> System.out.println("*.SimpleClass");
>> System.out.println(res);
>> }
>> }
>> }
>>
>>
>> The problem is no changes are applied to the IXtextDocument. Are there
>> any other possibilities to trigger the serializer without the save
>> methode of the XtextResource?
>> If i use the following code the changes applied to the editor but also
>> the XtextResource is saved.
>> Injector injector = Guice.createInjector(new SimpleClassRuntimeModule());
>> final IDocumentEditor iDocEditor =
>> injector.getInstance(IDocumentEditor.class);
>> XtextEditor xEditor = EditorUtils.getActiveXtextEditor();
>>
>> iDocEditor.process(new IUnitOfWork.Void<XtextResource>() {
>> @Override
>> public void process(XtextResource state) throws Exception {
>> try {
>> //... doing some semantic model changes
>> state.save(null);
>> }
>> }
>> }
>>
>> How could i adapt the behavior of the save method without saving.
>>
>> Regards,
>> John
>
|
|
|
Re: Refactoring for xtextEditors [message #554819 is a reply to message #554617] |
Tue, 24 August 2010 13:28 |
|
Hi together,
I implemented a crossresourcerefactoring for xtext some time ago for a customer.
I was wondering why you do not use the org.eclipse.ltk.core.refactoring.DocumentChange to make changes on the IXtextDocument. For me it is the easiest way to implement refactorings. If there is no Editor open for a model that has to be changed you could use org.eclipse.ltk.core.refactoring.TextFileChange and if there is an editor open for a model you could use the class mentioned above. Inside that Refactoring you could use org.eclipse.text.edits.ReplaceEdit to replace the stuff that has to change. Xtext has excellent tooling (mentioned by Sebastian) to get the offset and length of Nodes that represents EObjects. Of course you could use the serializer to get the String for a changes EObject.
Regards,
Holger
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com
--
Need professional support for Eclipse Modeling?
Go visit: http://xtext.itemis.com
|
|
|
|
|
|
|
|
|
|
|