IResourceDescription's URI sync [message #1723220] |
Fri, 12 February 2016 09:55  |
Eclipse User |
|
|
|
Hi,
Within IResourceChangeListener that detects file moves, I get a handle on all the resource decriptions that way:
Iterable<IResourceDescription> descriptions = resourceDescriptions.getAllResourceDescriptions();
I iterate through each of them and extract the corresponding XtextResource given their URI, in such a way:
Resource currentResource = resourceSet.getResource(description.getURI(), true);
I was expecting description.getURI() to deliver the URI of the original file (before it moved) but it seems pretty unstable.
It randomly gives me the original or the new URI.
How can I ensure I always get the original URI ?
Thanks.
(small precision: the code above is executed in a WorkspaceJob context)
|
|
|
|
|
|
|
Re: IResourceDescription's URI sync [message #1723536 is a reply to message #1723240] |
Tue, 16 February 2016 08:23   |
Eclipse User |
|
|
|
Thank you Christian,
Not sure I undertsand, I tried to follow your hints and I came up with this code:
public class DesagnMoveParticipant extends MoveParticipant {
@Inject private IGlobalServiceProvider globalServiceProvider;
@Inject private StatusWrapper status;
@Inject @Named(Constants.LANGUAGE_NAME) private String languageName;
private Set<Object> disabledTargets = newHashSet();
@Inject private IRenameContextFactory renameContextFactory;
@Inject private RefactoringResourceSetProvider resourceSetProvider;
private static final Logger LOG = Logger.getLogger(AbstractProcessorBasedRenameParticipant.class);
@Inject private RefactoringPreferences preferences;
@Inject private SyncUtil syncUtil;
@Inject private ProjectUtil projectUtil;
private List<RenameProcessor> wrappedProcessors;
File sourceFile;
Folder destinationFolder;
@Override
protected boolean initialize(Object originalTargetElement) {
RefactoringProcessor p = this.getProcessor();
if (originalTargetElement instanceof File) {
sourceFile = (File) originalTargetElement;
MoveArguments mas = this.getArguments();
if (mas.getDestination() instanceof Folder) {
destinationFolder = (Folder) mas.getDestination();
}
}
try {
wrappedProcessors = getRenameProcessors(originalTargetElement);
if (wrappedProcessors != null) {
syncUtil.totalSync(preferences.isSaveAllBeforeRefactoring(), true, false);
return true;
}
} catch (InterruptedException e) {
return false;
} catch (Exception exc) {
status.add(ERROR, "Error initializing refactoring participant.", exc, LOG);
}
return false;
}
protected List<RenameProcessor> getRenameProcessors(Object originalTargetElement) {
List<? extends IRenameElementContext> participantContexts = createRenameElementContexts(originalTargetElement);
if (participantContexts != null) {
List<RenameProcessor> processors = newArrayList();
for (IRenameElementContext participantContext : participantContexts) {
RenameProcessor renameProcessor = getRenameProcessor(participantContext);
if (renameProcessor != null) {
processors.add(renameProcessor);
}
}
return processors;
}
return null;
}
protected RenameProcessor getRenameProcessor(IRenameElementContext participantContext) {
IRenameRefactoringProvider renameRefactoringProvider = getRenameRefactoringProvider(participantContext);
if (renameRefactoringProvider != null) {
return renameRefactoringProvider.getRenameProcessor(participantContext);
} else {
return null;
}
}
protected IRenameRefactoringProvider getRenameRefactoringProvider(IRenameElementContext renameElementContext) {
return globalServiceProvider.findService(renameElementContext.getTargetElementURI(), IRenameRefactoringProvider.class);
}
private String trimFileExtension(String fileName) {
if (fileName.lastIndexOf('.') == -1) {
return fileName;
}
return fileName.substring(0, fileName.lastIndexOf('.'));
}
protected List<? extends IRenameElementContext> createRenameElementContexts(Object element) {
IFile file = (IFile) element;
final IPath filePath = file.getFullPath();
String className = trimFileExtension(file.getName());
ResourceSet resourceSet = resourceSetProvider.get(file.getProject());
URI resourceURI = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
Resource resource = resourceSet.getResource(resourceURI, true);
if (resource != null && !resource.getContents().isEmpty()) {
for (ConceptDefinition type : EcoreUtil2.eAllOfType(resource.getContents().get(0), ConceptDefinition.class)) {
if (className.equals(type.getName())) {
IRenameElementContext renameElementContext = renameContextFactory.createRenameElementContext(type, null, null, (XtextResource) resource);
if (renameElementContext instanceof IChangeRedirector.Aware) {
((IChangeRedirector.Aware) renameElementContext).setChangeRedirector(new IChangeRedirector() {
@Override
public IPath getRedirectedPath(IPath source) {
return source.equals(filePath) ? /*just4testing*/destinationFolder.getFullPath().append("/InsertSeat.concept") : source;
}
});
}
return java.util.Collections.singletonList(renameElementContext);
}
}
}
return java.util.Collections.emptyList();
}
@Override
public String getName() {
return languageName;
}
@Override
public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) throws OperationCanceledException {
SubMonitor progress = SubMonitor.convert(pm).setWorkRemaining(100 * wrappedProcessors.size());
try {
for (RenameProcessor wrappedProcessor : wrappedProcessors) {
List<Object> targetElements = Arrays.asList(wrappedProcessor.getElements());
if (!disabledTargets.containsAll(targetElements)) {
setNewName(wrappedProcessor, getNewName());
status.merge(wrappedProcessor.checkInitialConditions(progress.newChild(20)));
if (!status.getRefactoringStatus().hasFatalError()) {
status.merge(wrappedProcessor.checkFinalConditions(progress.newChild(80), context));
}
}
}
} catch (OperationCanceledException e) {
throw e;
} catch (Exception ce) {
status.add(ERROR, "Error checking conditions in refactoring participant: {0}. See log for details", ce, LOG);
}
return status.getRefactoringStatus();
}
protected void setNewName(RenameProcessor processor, String newName) {
((AbstractRenameProcessor) processor).setNewName(newName);
}
protected String getNewName() {
return /*getArguments().getNewName()*/"Random_newname";
}
@Override
public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
CompositeChange compositeChange = null;
try {
SubMonitor subMonitor = SubMonitor.convert(pm, wrappedProcessors.size());
for (RenameProcessor wrappedProcessor : wrappedProcessors) {
if (!disabledTargets.containsAll(Arrays.asList(wrappedProcessor.getElements()))) {
Change processorChange = wrappedProcessor.createChange(subMonitor.newChild(1));
if (processorChange != null) {
if (compositeChange == null) {
compositeChange = new CompositeChange("Changes from participant: " + getName());
}
compositeChange.add(processorChange);
}
} else {
subMonitor.worked(1);
}
}
} catch (OperationCanceledException e) {
throw e;
} catch (Exception e) {
throw new CoreException(new Status(IStatus.ERROR, YbaseActivator.YAPP_YBASE_YBASE, "Error creating change", e));
} finally {
dispose();
}
return compositeChange;
/*RenameResourceChange rrc = new RenameResourceChange(sourceFile.getFullPath(), "SomeNAME");
return rrc;*/
}
protected void dispose() {
status = null;
wrappedProcessors = null;
disabledTargets.clear();
}
}
When I try out that code by moving the file
"a90/desagn/insertseat/InsertSeat.concept"
to this package:
"a90/desagn/insertscrew/"
I get the following error message:
"End position lies outside document range"
Is it because of those ChangDirectors that might interfer with Eclipse's Move refactoring ?
[Updated on: Tue, 16 February 2016 08:40] by Moderator
|
|
|
|
|
|
|
|
Re: IResourceDescription's URI sync [message #1723563 is a reply to message #1723550] |
Tue, 16 February 2016 10:32   |
Eclipse User |
|
|
|
Yes sorry it's just a temporaring implementation for a special testcase:
@Override
public IPath getRedirectedPath(IPath source) {
return source.equals(filePath) ? /*just4testing*/destinationFolder.getFullPath().append("/InsertSeat.concept") : source;
}
I tried if I could reproduce in the domain example, but it works very well with that code:
public class DmodelMoveParticipant extends MoveParticipant {
@Inject private IGlobalServiceProvider globalServiceProvider;
@Inject private StatusWrapper status;
@Inject @Named(Constants.LANGUAGE_NAME) private String languageName;
private Set<Object> disabledTargets = newHashSet();
@Inject private IRenameContextFactory renameContextFactory;
@Inject private RefactoringResourceSetProvider resourceSetProvider;
private static final Logger LOG = Logger.getLogger(AbstractProcessorBasedRenameParticipant.class);
@Inject private RefactoringPreferences preferences;
@Inject private SyncUtil syncUtil;
@Inject private ProjectUtil projectUtil;
private List<RenameProcessor> wrappedProcessors;
File sourceFile;
Folder destinationFolder;
@Override
protected boolean initialize(Object originalTargetElement) {
RefactoringProcessor p = this.getProcessor();
if (originalTargetElement instanceof File) {
sourceFile = (File) originalTargetElement;
MoveArguments mas = this.getArguments();
if (mas.getDestination() instanceof Folder) {
destinationFolder = (Folder) mas.getDestination();
}
}
try {
wrappedProcessors = getRenameProcessors(originalTargetElement);
if (wrappedProcessors != null) {
syncUtil.totalSync(preferences.isSaveAllBeforeRefactoring(), true, false);
return true;
}
} catch (InterruptedException e) {
return false;
} catch (Exception exc) {
status.add(ERROR, "Error initializing refactoring participant.", exc, LOG);
}
return false;
}
protected List<RenameProcessor> getRenameProcessors(Object originalTargetElement) {
List<? extends IRenameElementContext> participantContexts = createRenameElementContexts(originalTargetElement);
if (participantContexts != null) {
List<RenameProcessor> processors = newArrayList();
for (IRenameElementContext participantContext : participantContexts) {
RenameProcessor renameProcessor = getRenameProcessor(participantContext);
if (renameProcessor != null) {
processors.add(renameProcessor);
}
}
return processors;
}
return null;
}
protected RenameProcessor getRenameProcessor(IRenameElementContext participantContext) {
IRenameRefactoringProvider renameRefactoringProvider = getRenameRefactoringProvider(participantContext);
if (renameRefactoringProvider != null) {
return renameRefactoringProvider.getRenameProcessor(participantContext);
} else {
return null;
}
}
protected IRenameRefactoringProvider getRenameRefactoringProvider(IRenameElementContext renameElementContext) {
return globalServiceProvider.findService(renameElementContext.getTargetElementURI(), IRenameRefactoringProvider.class);
}
private String trimFileExtension(String fileName) {
if (fileName.lastIndexOf('.') == -1) {
return fileName;
}
return fileName.substring(0, fileName.lastIndexOf('.'));
}
protected List<? extends IRenameElementContext> createRenameElementContexts(Object element) {
IFile file = (IFile) element;
final IPath filePath = file.getFullPath();
String className = trimFileExtension(file.getName());
ResourceSet resourceSet = resourceSetProvider.get(file.getProject());
URI resourceURI = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
Resource resource = resourceSet.getResource(resourceURI, true);
if (resource != null && !resource.getContents().isEmpty()) {
for (Entity type : EcoreUtil2.eAllOfType(resource.getContents().get(0), Entity.class)) {
if (className.equals(type.getName())) {
IRenameElementContext renameElementContext = renameContextFactory.createRenameElementContext(type, null, null, (XtextResource) resource);
if (renameElementContext instanceof IChangeRedirector.Aware) {
((IChangeRedirector.Aware) renameElementContext).setChangeRedirector(new IChangeRedirector() {
@Override
public IPath getRedirectedPath(IPath source) {
return source.equals(filePath) ? /*newPath*/destinationFolder.getFullPath().append("/MyEntity.dmodel") : source;
}
});
}
return java.util.Collections.singletonList(renameElementContext);
}
}
}
return java.util.Collections.emptyList();
}
@Override
public String getName() {
return languageName;
}
@Override
public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) throws OperationCanceledException {
SubMonitor progress = SubMonitor.convert(pm).setWorkRemaining(100 * wrappedProcessors.size());
try {
for (RenameProcessor wrappedProcessor : wrappedProcessors) {
List<Object> targetElements = Arrays.asList(wrappedProcessor.getElements());
if (!disabledTargets.containsAll(targetElements)) {
setNewName(wrappedProcessor, getNewName());
status.merge(wrappedProcessor.checkInitialConditions(progress.newChild(20)));
if (!status.getRefactoringStatus().hasFatalError()) {
status.merge(wrappedProcessor.checkFinalConditions(progress.newChild(80), context));
}
}
}
} catch (OperationCanceledException e) {
throw e;
} catch (Exception ce) {
status.add(ERROR, "Error checking conditions in refactoring participant: {0}. See log for details", ce, LOG);
}
return status.getRefactoringStatus();
}
protected void setNewName(RenameProcessor processor, String newName) {
((AbstractRenameProcessor) processor).setNewName(newName);
}
protected String getNewName() {
return /*getArguments().getNewName()*/"InsertSeat2";
}
@Override
public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
CompositeChange compositeChange = null;
try {
SubMonitor subMonitor = SubMonitor.convert(pm, wrappedProcessors.size());
for (RenameProcessor wrappedProcessor : wrappedProcessors) {
if (!disabledTargets.containsAll(Arrays.asList(wrappedProcessor.getElements()))) {
Change processorChange = wrappedProcessor.createChange(subMonitor.newChild(1));
if (processorChange != null) {
if (compositeChange == null) {
compositeChange = new CompositeChange("Changes from participant: " + getName());
}
compositeChange.add(processorChange);
}
} else {
subMonitor.worked(1);
}
}
} catch (OperationCanceledException e) {
throw e;
} catch (Exception e) {
throw new CoreException(new Status(IStatus.ERROR, DomainmodelActivator.ORG_ECLIPSE_XTEXT_EXAMPLE_DOMAINMODEL_DOMAINMODEL, "Error creating change", e));
} finally {
dispose();
}
return compositeChange;
/*RenameResourceChange rrc = new RenameResourceChange(sourceFile.getFullPath(), "SomeNAME");
return rrc;*/
}
protected void dispose() {
status = null;
wrappedProcessors = null;
disabledTargets.clear();
}
}
The file to be tested for the package to package drag-and-drop is named "MyEntity.dmodel":
package mypackage {
entity MyEntity{
}
}
|
|
|
|
Re: IResourceDescription's URI sync [message #1723566 is a reply to message #1723564] |
Tue, 16 February 2016 10:38   |
Eclipse User |
|
|
|
can you please try without xbase as well
here is my grammar and impl
package org.xtext.example.mydsl2.ui;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.CompositeChange;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.MoveArguments;
import org.eclipse.ltk.core.refactoring.participants.MoveParticipant;
import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
import org.eclipse.ltk.core.refactoring.participants.RenameProcessor;
import org.eclipse.xtext.Constants;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.resource.IGlobalServiceProvider;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.refactoring.IChangeRedirector;
import org.eclipse.xtext.ui.refactoring.IRenameRefactoringProvider;
import org.eclipse.xtext.ui.refactoring.impl.AbstractProcessorBasedRenameParticipant;
import org.eclipse.xtext.ui.refactoring.impl.AbstractRenameProcessor;
import org.eclipse.xtext.ui.refactoring.impl.ProjectUtil;
import org.eclipse.xtext.ui.refactoring.impl.RefactoringResourceSetProvider;
import org.eclipse.xtext.ui.refactoring.impl.StatusWrapper;
import org.eclipse.xtext.ui.refactoring.ui.IRenameContextFactory;
import org.eclipse.xtext.ui.refactoring.ui.IRenameElementContext;
import org.eclipse.xtext.ui.refactoring.ui.RefactoringPreferences;
import org.eclipse.xtext.ui.refactoring.ui.SyncUtil;
import org.xtext.example.mydsl2.myDsl.Model;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.inject.name.Named;
public class DesagnMoveParticipant extends MoveParticipant {
@Inject private IGlobalServiceProvider globalServiceProvider;
@Inject private StatusWrapper status;
@Inject @Named(Constants.LANGUAGE_NAME) private String languageName;
private Set<Object> disabledTargets = Sets.newHashSet();
@Inject private IRenameContextFactory renameContextFactory;
@Inject private RefactoringResourceSetProvider resourceSetProvider;
private static final Logger LOG = Logger.getLogger(AbstractProcessorBasedRenameParticipant.class);
@Inject private RefactoringPreferences preferences;
@Inject private SyncUtil syncUtil;
@Inject private ProjectUtil projectUtil;
private List<RenameProcessor> wrappedProcessors;
IFile sourceFile;
IFolder destinationFolder;
@Override
protected boolean initialize(Object originalTargetElement) {
RefactoringProcessor p = this.getProcessor();
if (originalTargetElement instanceof IFile) {
sourceFile = (IFile) originalTargetElement;
MoveArguments mas = this.getArguments();
if (mas.getDestination() instanceof IFolder) {
destinationFolder = (IFolder) mas.getDestination();
}
}
try {
wrappedProcessors = getRenameProcessors(originalTargetElement);
if (wrappedProcessors != null) {
syncUtil.totalSync(preferences.isSaveAllBeforeRefactoring(), true, false);
return true;
}
} catch (InterruptedException e) {
return false;
} catch (Exception exc) {
status.add(IStatus.ERROR, "Error initializing refactoring participant.", exc, LOG);
}
return false;
}
protected List<RenameProcessor> getRenameProcessors(Object originalTargetElement) {
List<? extends IRenameElementContext> participantContexts = createRenameElementContexts(originalTargetElement);
if (participantContexts != null) {
List<RenameProcessor> processors = Lists.newArrayList();
for (IRenameElementContext participantContext : participantContexts) {
RenameProcessor renameProcessor = getRenameProcessor(participantContext);
if (renameProcessor != null) {
processors.add(renameProcessor);
}
}
return processors;
}
return null;
}
protected RenameProcessor getRenameProcessor(IRenameElementContext participantContext) {
IRenameRefactoringProvider renameRefactoringProvider = getRenameRefactoringProvider(participantContext);
if (renameRefactoringProvider != null) {
return renameRefactoringProvider.getRenameProcessor(participantContext);
} else {
return null;
}
}
protected IRenameRefactoringProvider getRenameRefactoringProvider(IRenameElementContext renameElementContext) {
return globalServiceProvider.findService(renameElementContext.getTargetElementURI(), IRenameRefactoringProvider.class);
}
private String trimFileExtension(String fileName) {
if (fileName.lastIndexOf('.') == -1) {
return fileName;
}
return fileName.substring(0, fileName.lastIndexOf('.'));
}
protected List<? extends IRenameElementContext> createRenameElementContexts(Object element) {
IFile file = (IFile) element;
final IPath filePath = file.getFullPath();
String className = file.getLocation().removeFileExtension().removeLastSegments(1).lastSegment();
ResourceSet resourceSet = resourceSetProvider.get(file.getProject());
URI resourceURI = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
Resource resource = resourceSet.getResource(resourceURI, true);
if (resource != null && !resource.getContents().isEmpty()) {
for (org.xtext.example.mydsl2.myDsl.Package type : EcoreUtil2.eAllOfType(resource.getContents().get(0), org.xtext.example.mydsl2.myDsl.Package.class)) {
if (className.equals(type.getName())) {
IRenameElementContext renameElementContext = renameContextFactory.createRenameElementContext(type, null, null, (XtextResource) resource);
if (renameElementContext instanceof IChangeRedirector.Aware) {
((IChangeRedirector.Aware) renameElementContext).setChangeRedirector(new IChangeRedirector() {
@Override
public IPath getRedirectedPath(IPath source) {
return source.equals(filePath) ? /*just4testing*/destinationFolder.getFullPath().append("/"+filePath.removeFileExtension().lastSegment()+ ".mydsl2") : source;
}
});
}
return java.util.Collections.singletonList(renameElementContext);
}
}
}
return java.util.Collections.emptyList();
}
@Override
public String getName() {
return languageName;
}
@Override
public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) throws OperationCanceledException {
SubMonitor progress = SubMonitor.convert(pm).setWorkRemaining(100 * wrappedProcessors.size());
try {
for (RenameProcessor wrappedProcessor : wrappedProcessors) {
List<Object> targetElements = Arrays.asList(wrappedProcessor.getElements());
if (!disabledTargets.containsAll(targetElements)) {
setNewName(wrappedProcessor, getNewName());
status.merge(wrappedProcessor.checkInitialConditions(progress.newChild(20)));
if (!status.getRefactoringStatus().hasFatalError()) {
status.merge(wrappedProcessor.checkFinalConditions(progress.newChild(80), context));
}
}
}
} catch (OperationCanceledException e) {
throw e;
} catch (Exception ce) {
status.add(IStatus.ERROR, "Error checking conditions in refactoring participant: {0}. See log for details", ce, LOG);
}
return status.getRefactoringStatus();
}
protected void setNewName(RenameProcessor processor, String newName) {
((AbstractRenameProcessor) processor).setNewName(newName);
}
protected String getNewName() {
Object destination = getArguments().getDestination();
if (destination instanceof IFolder) {
return ((IFolder) destination).getLocation().lastSegment();
}
return /*getArguments().getNewName()*/"Random_newname";
}
@Override
public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
CompositeChange compositeChange = null;
try {
SubMonitor subMonitor = SubMonitor.convert(pm, wrappedProcessors.size());
for (RenameProcessor wrappedProcessor : wrappedProcessors) {
if (!disabledTargets.containsAll(Arrays.asList(wrappedProcessor.getElements()))) {
Change processorChange = wrappedProcessor.createChange(subMonitor.newChild(1));
if (processorChange != null) {
if (compositeChange == null) {
compositeChange = new CompositeChange("Changes from participant: " + getName());
}
compositeChange.add(processorChange);
}
} else {
subMonitor.worked(1);
}
}
} catch (OperationCanceledException e) {
throw e;
} catch (Exception e) {
throw new CoreException(new Status(IStatus.ERROR, "org.xtext.example.mydsl2.ui", "Error creating change", e));
} finally {
dispose();
}
return compositeChange;
/*RenameResourceChange rrc = new RenameResourceChange(sourceFile.getFullPath(), "SomeNAME");
return rrc;*/
}
protected void dispose() {
status = null;
wrappedProcessors = null;
disabledTargets.clear();
}
}
Package:
"package" name=ID";"
model=Model
;
Model:
"model" name=ID
"refs" refs+=Ref*
;
Ref:
ref=[Model|FQN]
;
|
|
|
|
|
|
|
|
|
|
|
|
|