Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Use IChangeSerializer for refactoring that changes multiple Xtext files(Problem with IChangeSerializer, if refactoring change multiple resources)
Use IChangeSerializer for refactoring that changes multiple Xtext files [message #1827408] Thu, 14 May 2020 08:21 Go to next message
Stefan Kapferer is currently offline Stefan KapfererFriend
Messages: 19
Registered: March 2020
Junior Member
Hi there

I have a question regarding the ChangeSerializer that I use to implement a refactoring for my Xtext language (Xtext LSP + VS code IDE).

My language uses imports, which means a user is able to reference objects in other files. Therefore, my refactoring potentially changes multiple files (Xtext resources).

In my language server I implement the refactoring as a command that creates a WorkspaceEdit.

I construct the WorkspaceEdit as follows:

private WorkspaceEdit createWorkspaceEdit(ILanguageServerAccess access, URI resourceURI, Document document, IChangeSerializer.IModification<Resource> mod) {
  ResourceSet rs = access.newLiveScopeResourceSet(resourceURI);
  Resource copy = rs.getResource(resourceURI, true);
  IChangeSerializer serializer = serializerProvider.get();
  EcoreUtil.resolveAll(copy); // resolve all imported resources (ensures that imported files are part of the ResourceSet)
  serializer.addModification(copy, mod);
  List<IEmfResourceChange> documentchanges = new ArrayList<>();
  serializer.applyModifications(CollectionBasedAcceptor.of(documentchanges));
  WorkspaceEdit workspaceEdit = new WorkspaceEdit();
  for (ITextDocumentChange documentchange : Iterables.filter(documentchanges, ITextDocumentChange.class)) {
    List<TextEdit> edits = ListExtensions.map(documentchange.getReplacements(), (ITextReplacement replacement) -> {
      TextEdit textEdit = new TextEdit();
      ...
      // I create the textEdit here
      ...
      return textEdit;
    });
    workspaceEdit.getChanges().put(documentchange.getNewURI().toString(), edits);
  }
  return workspaceEdit;
}


My problem: everything works fine as long as my modification (IChangeSerializer.IModification) only changes objects in a single file. If the modification changes objects that are spread accross multiple files, I get the following exception when calling serializer.applyModifications:

org.eclipse.emf.common.util.BasicEList$BasicIndexOutOfBoundsException: index=1, size=1
	at org.eclipse.emf.common.util.BasicEList.get(BasicEList.java:346)
	at org.eclipse.xtext.ide.serializer.impl.ReferenceUpdater.createUpdatableReference(ReferenceUpdater.java:90)
	at org.eclipse.xtext.ide.serializer.impl.ReferenceUpdater.updateAllReferences(ReferenceUpdater.java:215)
	at org.eclipse.xtext.ide.serializer.impl.ReferenceUpdater.update(ReferenceUpdater.java:203)
	at org.eclipse.xtext.ide.serializer.impl.RecordingXtextResourceUpdater.applyChange(RecordingXtextResourceUpdater.java:70)
	at org.eclipse.xtext.ide.serializer.impl.ChangeSerializer.endRecordChanges(ChangeSerializer.java:191)
	at org.eclipse.xtext.ide.serializer.impl.ChangeSerializer.applyModifications(ChangeSerializer.java:113)


Any ideas what I am doing wrong? Do I somehow have to register all affected resources manually?
Re: Use IChangeSerializer for refactoring that changes multiple Xtext files [message #1827409 is a reply to message #1827408] Thu, 14 May 2020 08:25 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
what i dont see:
do you put all changes to one file here

workspaceEdit.getChanges().put(documentchange.getNewURI().toString(), edits);


can you provide a reproducing unit test + hw dsl


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de

[Updated on: Thu, 14 May 2020 08:25]

Report message to a moderator

Re: Use IChangeSerializer for refactoring that changes multiple Xtext files [message #1827410 is a reply to message #1827409] Thu, 14 May 2020 08:33 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
p.s. which Xtext version do you use?

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Use IChangeSerializer for refactoring that changes multiple Xtext files [message #1827412 is a reply to message #1827409] Thu, 14 May 2020 08:33 Go to previous messageGo to next message
Stefan Kapferer is currently offline Stefan KapfererFriend
Messages: 19
Registered: March 2020
Junior Member
Actually the code at the end of the method that constructs the WorkspaceEdit is never reached, as the following line already throws the exception:

serializer.applyModifications(CollectionBasedAcceptor.of(documentchanges));


I'm not yet sure if my code at the end is correct, but I never came that far :)

I hoped I am doing something "obviously wrong" before calling the ChangeSerializer.
Given your answer I assume this is not the case... :) I have to prepare such a unit test...
Re: Use IChangeSerializer for refactoring that changes multiple Xtext files [message #1827414 is a reply to message #1827412] Thu, 14 May 2020 08:34 Go to previous messageGo to next message
Stefan Kapferer is currently offline Stefan KapfererFriend
Messages: 19
Registered: March 2020
Junior Member
I use Xtext 2.20.0.
Re: Use IChangeSerializer for refactoring that changes multiple Xtext files [message #1827415 is a reply to message #1827414] Thu, 14 May 2020 08:44 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
could be also a bug in the reference updater.
=> minimal reproducing example would be nice.


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Use IChangeSerializer for refactoring that changes multiple Xtext files [message #1827435 is a reply to message #1827415] Thu, 14 May 2020 12:19 Go to previous messageGo to next message
Stefan Kapferer is currently offline Stefan KapfererFriend
Messages: 19
Registered: March 2020
Junior Member
Seems to be a bug, from my perspective.

Problem update:
It has nothing to do with the fact that I use multiple files. I can now reproduce it with a single DSL file as well.
The problem occurs because my modification deletes EObjects from the model which are referenced in the original state.

Although I also delete the reference from the corresponding reference list, the exception occurs.

As I see it, there is a problem with this logic in the ReferenceUpdater (createUpdatableReference method):

List<?> targets = (List<?>) value;
int i = current.getIndexInContainingFeature();
EObject t = (EObject) targets.get(i);
if (t != null && !t.eIsProxy()) {
  return new UpdatableReference(owner, ref, i, t, crossRef, current);
}


And the problem with this code is that the index i is calculated based on the original model state. The index is correct for the state before the modification.
But the targets list corresponds to the state after the modification and does no longer contain the deleted reference.
My modification removes an EObject by calling EcoreUtil2.delete(object), which already cleans the references and removes it from the list.

Is it possible that the ReferenceUpdater cannot handle modifications which delete model parts?
Or formulated in another way: Does the ReferenceUpdater respect the fact that some references may have been deleted during a modification? It seems to me that it does not handle this case.
Re: Use IChangeSerializer for refactoring that changes multiple Xtext files [message #1827441 is a reply to message #1827435] Thu, 14 May 2020 14:31 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
yes for sure. can you please create a nug with steps / example at github.com/eclipse/xtext-core

Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Use IChangeSerializer for refactoring that changes multiple Xtext files [message #1827488 is a reply to message #1827441] Fri, 15 May 2020 15:28 Go to previous messageGo to next message
Stefan Kapferer is currently offline Stefan KapfererFriend
Messages: 19
Registered: March 2020
Junior Member
Hi Christian

Sure, I will create an issue there...

I also created an example with a unit test to reproduce the issue in your language server example project. You can find it here:
https://github.com/stefan-ka/xtext-languageserver-example

And here is the unit test: https://github.com/stefan-ka/xtext-languageserver-example/blob/master/org.xtext.example.mydsl.tests/src/org/xtext/example/mydsl/ide/tests/CommandServiceTest.xtend

The example is simple: I created a command which removes the "Hello Xtext!" greeting in the first line.
The first test method illustrates the case where the modification works, as there is no reference to the "Xtext" greeting.
The second test method throws the exception above, as there is a second greeting that references the first one (the modification removes the reference).

If you run the mentioned test you will see that the first method passes and the second method throws the exception.

Another question:
To test this, I let the command return the WorkspaceEdit. However, returning the edit is not necessary, as I call access.getLanguageClient().applyEdit() to apply the edit. But I don't know how to test this with the provided test tools. Is there a way to access the WorkspaceEdit that is passed to access.getLanguageClient().applyEdit() in the unit test?

Re: Use IChangeSerializer for refactoring that changes multiple Xtext files [message #1827489 is a reply to message #1827488] Fri, 15 May 2020 15:56 Go to previous message
Stefan Kapferer is currently offline Stefan KapfererFriend
Messages: 19
Registered: March 2020
Junior Member
I created the issue here:

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

Best regards,
Stefan
Previous Topic:Accessing resources in standalone mode
Next Topic:Saving/opening files is blocked while code generation
Goto Forum:
  


Current Time: Sat Apr 20 01:43:22 GMT 2024

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

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

Back to the top