[refactoring] refactored resource relocation and added CopyParticipant

This commit is contained in:
Jan Koehnlein 2017-09-11 09:57:35 +02:00 committed by Moritz Eysholdt
parent 25e2d9d381
commit c4d33d4186
18 changed files with 639 additions and 401 deletions

View file

@ -0,0 +1,85 @@
/*******************************************************************************
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.ide.refactoring
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import com.google.inject.Inject
import org.eclipse.xtext.resource.IResourceServiceProvider
import org.eclipse.emf.ecore.resource.Resource
/**
* Allows a language to execute side-effects when the URI of a resource changes.
*
* Such changes can be move, rename and copy operations, e.g. triggered by the
* user in a file browser. An example for a language in which such side-effects
* would make sense is Java, where the package name and the name of the first
* public top-level class must match the resource's path.
*
* Clients should not directly implement this interface but extend the
* {@link IResourceRelocationStrategy.AbstractImpl}.
*
* In Eclipse, {@link IResourceRelocationStrategy} are registered to an extension
* point.
*
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
interface IResourceRelocationStrategy {
def boolean canHandle(ResourceRelocationChange change)
def Resource loadAndWatchResource(ResourceRelocationChange change, ResourceRelocationContext context)
def void applyChange(ResourceRelocationChange change, Resource resource, ResourceRelocationContext context)
def void applySideEffects(ResourceRelocationChange change, Resource resource, ResourceRelocationContext context)
/**
* Clients should extend this class to register side-effects on resource relocation changes.
*/
abstract class AbstractImpl implements IResourceRelocationStrategy {
@Inject IResourceServiceProvider resourceServiceProvider
override boolean canHandle(ResourceRelocationChange change) {
resourceServiceProvider.canHandle(change.fromURI)
}
override Resource loadAndWatchResource(ResourceRelocationChange change, ResourceRelocationContext context) {
val fromResource = context.resourceSet.getResource(change.fromURI, true)
if (change.type === ResourceRelocationChange.Type.COPY) {
val copy = context.resourceSet.createResource(change.toURI)
return copy
} else {
context.changeSerializer.beginRecordChanges(fromResource)
return fromResource
}
}
override void applyChange(ResourceRelocationChange change, Resource resource, ResourceRelocationContext context) {
val fromResource = context.resourceSet.getResource(change.fromURI, false)
switch change.type {
case COPY: {
val buffer = new ByteArrayOutputStream
fromResource.save(buffer, null)
val copy = context.resourceSet.getResource(change.toURI, false)
copy.load(new ByteArrayInputStream(buffer.toByteArray), null)
context.changeSerializer.beginRecordChanges(copy)
}
case MOVE,
case RENAME: {
context.changeSerializer.beginRecordChanges(fromResource)
fromResource.URI = change.toURI
}
}
}
}
}

View file

@ -1,73 +0,0 @@
/*******************************************************************************
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.ide.refactoring
import java.util.List
import java.util.Map
import org.apache.log4j.Logger
import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.xtend.lib.annotations.Accessors
import org.eclipse.xtend.lib.annotations.Data
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
import org.eclipse.xtext.ide.serializer.IChangeSerializer
import static org.eclipse.xtext.ide.refactoring.RefactoringIssueAcceptor.Severity.*
/**
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
@FinalFieldsConstructor
class MoveResourceContext {
static val LOG = Logger.getLogger(MoveResourceContext)
@Accessors(PUBLIC_GETTER) val List<ResourceURIChange> fileChanges
@Accessors(PUBLIC_GETTER) val List<ResourceURIChange> folderChanges
@Accessors(PUBLIC_GETTER) val RefactoringIssueAcceptor issueAcceptor
val IChangeSerializer changeSerializer
val ResourceSet resourceSet
val Map<Resource, ResourceModification> modifications = newHashMap
def addModification(URI uri, ResourceModification modification) {
try {
val resource = resourceSet.getResource(uri, true)
changeSerializer.beginRecordChanges(resource)
modifications.put(resource, modification)
} catch (Throwable t) {
issueAcceptor.add(ERROR, 'Error loading resource ' + uri?.toString, t)
LOG.error(t)
}
}
def executeModifications() {
modifications.entrySet.forEach [
try {
value.modify(key)
} catch (Throwable t) {
issueAcceptor.add(ERROR, 'Error executing modification on resource ' + key?.URI?.toString, t)
LOG.error(t)
}
]
}
}
/**
* URIs can also refer to folders and non-Xtext resources.
*
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
@Data
class ResourceURIChange {
URI oldURI
URI newURI
}

View file

@ -7,11 +7,23 @@
*******************************************************************************/
package org.eclipse.xtext.ide.refactoring
import org.eclipse.emf.common.util.URI
import org.eclipse.xtend.lib.annotations.Data
/**
* URIs can also refer to folders and non-Xtext resources.
*
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
interface XtextMoveResourceStrategy {
@Data
class ResourceRelocationChange {
URI fromURI
URI toURI
Type type
boolean isFile
def void applyMove(MoveResourceContext context)
}
enum Type {
COPY, MOVE, RENAME
}
}

View file

@ -7,12 +7,22 @@
*******************************************************************************/
package org.eclipse.xtext.ide.refactoring
import org.eclipse.emf.ecore.resource.Resource
import java.util.List
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.xtend.lib.annotations.Accessors
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
import org.eclipse.xtext.ide.serializer.IChangeSerializer
/**
* @author koehnlein - Initial contribution and API
*/
interface ResourceModification {
def void modify(Resource resource)
}
@FinalFieldsConstructor
@Accessors(PUBLIC_GETTER)
class ResourceRelocationContext {
val List<ResourceRelocationChange> changes
val RefactoringIssueAcceptor issueAcceptor
val IChangeSerializer changeSerializer
val ResourceSet resourceSet
}

View file

@ -0,0 +1,67 @@
/*******************************************************************************
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.xtext.ide.refactoring
import com.google.common.collect.LinkedHashMultimap
import java.util.List
import org.apache.log4j.Logger
import static org.eclipse.xtext.ide.refactoring.RefactoringIssueAcceptor.Severity.*
/**
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
class ResourceRelocationStrategyExecutor {
static val LOG = Logger.getLogger(ResourceRelocationStrategyExecutor)
def executeParticipants(List<? extends IResourceRelocationStrategy> strategies, ResourceRelocationContext context) {
val change2strategies = LinkedHashMultimap.create
for (change: context.changes) {
for (strategy: strategies) {
if (strategy.canHandle(change))
change2strategies.put(change, strategy)
}
}
val change2resource = newHashMap
for (change : change2strategies.keySet) {
val primaryStrategy = change2strategies.get(change).head
try {
val resource = primaryStrategy.loadAndWatchResource(change, context)
change2resource.put(change, resource)
} catch (Throwable t) {
context.issueAcceptor.add(ERROR, 'Error loading resource ' + change?.fromURI?.toString, t)
LOG.error(t)
}
}
for (change : change2strategies.keySet) {
var changeApplied = false
val resource = change2resource.get(change)
for (strategy: change2strategies.get(change)) {
if (!changeApplied) {
try {
strategy.applyChange(change, resource, context)
changeApplied = true
} catch (Throwable t) {
context.issueAcceptor.add(ERROR, 'Error applying relocation change to ' + change?.fromURI?.toString, t)
LOG.error(t)
}
}
if (changeApplied) {
try {
strategy.applySideEffects(change, resource, context)
} catch (Throwable t) {
context.issueAcceptor.add(ERROR, 'Error applying side effect to ' + change?.fromURI?.toString, t)
LOG.error(t)
}
}
}
}
}
}

View file

@ -0,0 +1,102 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.xtext.ide.refactoring;
import com.google.inject.Inject;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.ide.refactoring.ResourceRelocationChange;
import org.eclipse.xtext.ide.refactoring.ResourceRelocationContext;
import org.eclipse.xtext.resource.IResourceServiceProvider;
import org.eclipse.xtext.xbase.lib.Exceptions;
/**
* Allows a language to execute side-effects when the URI of a resource changes.
*
* Such changes can be move, rename and copy operations, e.g. triggered by the
* user in a file browser. An example for a language in which such side-effects
* would make sense is Java, where the package name and the name of the first
* public top-level class must match the resource's path.
*
* Clients should not directly implement this interface but extend the
* {@link IResourceRelocationStrategy.AbstractImpl}.
*
* In Eclipse, {@link IResourceRelocationStrategy} are registered to an extension
* point.
*
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
@SuppressWarnings("all")
public interface IResourceRelocationStrategy {
/**
* Clients should extend this class to register side-effects on resource relocation changes.
*/
public static abstract class AbstractImpl implements IResourceRelocationStrategy {
@Inject
private IResourceServiceProvider resourceServiceProvider;
@Override
public boolean canHandle(final ResourceRelocationChange change) {
return this.resourceServiceProvider.canHandle(change.getFromURI());
}
@Override
public Resource loadAndWatchResource(final ResourceRelocationChange change, final ResourceRelocationContext context) {
final Resource fromResource = context.getResourceSet().getResource(change.getFromURI(), true);
ResourceRelocationChange.Type _type = change.getType();
boolean _tripleEquals = (_type == ResourceRelocationChange.Type.COPY);
if (_tripleEquals) {
final Resource copy = context.getResourceSet().createResource(change.getToURI());
return copy;
} else {
context.getChangeSerializer().beginRecordChanges(fromResource);
return fromResource;
}
}
@Override
public void applyChange(final ResourceRelocationChange change, final Resource resource, final ResourceRelocationContext context) {
try {
final Resource fromResource = context.getResourceSet().getResource(change.getFromURI(), false);
ResourceRelocationChange.Type _type = change.getType();
if (_type != null) {
switch (_type) {
case COPY:
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
fromResource.save(buffer, null);
final Resource copy = context.getResourceSet().getResource(change.getToURI(), false);
byte[] _byteArray = buffer.toByteArray();
ByteArrayInputStream _byteArrayInputStream = new ByteArrayInputStream(_byteArray);
copy.load(_byteArrayInputStream, null);
context.getChangeSerializer().beginRecordChanges(copy);
break;
case MOVE:
case RENAME:
context.getChangeSerializer().beginRecordChanges(fromResource);
fromResource.setURI(change.getToURI());
break;
default:
break;
}
}
} catch (Throwable _e) {
throw Exceptions.sneakyThrow(_e);
}
}
}
public abstract boolean canHandle(final ResourceRelocationChange change);
public abstract Resource loadAndWatchResource(final ResourceRelocationChange change, final ResourceRelocationContext context);
public abstract void applyChange(final ResourceRelocationChange change, final Resource resource, final ResourceRelocationContext context);
public abstract void applySideEffects(final ResourceRelocationChange change, final Resource resource, final ResourceRelocationContext context);
}

View file

@ -1,129 +0,0 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.xtext.ide.refactoring;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtend.lib.annotations.AccessorType;
import org.eclipse.xtend.lib.annotations.Accessors;
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor;
import org.eclipse.xtext.ide.refactoring.RefactoringIssueAcceptor;
import org.eclipse.xtext.ide.refactoring.ResourceModification;
import org.eclipse.xtext.ide.refactoring.ResourceURIChange;
import org.eclipse.xtext.ide.serializer.IChangeSerializer;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.Pure;
/**
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
@FinalFieldsConstructor
@SuppressWarnings("all")
public class MoveResourceContext {
private final static Logger LOG = Logger.getLogger(MoveResourceContext.class);
@Accessors(AccessorType.PUBLIC_GETTER)
private final List<ResourceURIChange> fileChanges;
@Accessors(AccessorType.PUBLIC_GETTER)
private final List<ResourceURIChange> folderChanges;
@Accessors(AccessorType.PUBLIC_GETTER)
private final RefactoringIssueAcceptor issueAcceptor;
private final IChangeSerializer changeSerializer;
private final ResourceSet resourceSet;
private final Map<Resource, ResourceModification> modifications = CollectionLiterals.<Resource, ResourceModification>newHashMap();
public ResourceModification addModification(final URI uri, final ResourceModification modification) {
ResourceModification _xtrycatchfinallyexpression = null;
try {
ResourceModification _xblockexpression = null;
{
final Resource resource = this.resourceSet.getResource(uri, true);
this.changeSerializer.beginRecordChanges(resource);
_xblockexpression = this.modifications.put(resource, modification);
}
_xtrycatchfinallyexpression = _xblockexpression;
} catch (final Throwable _t) {
if (_t instanceof Throwable) {
final Throwable t = (Throwable)_t;
String _string = null;
if (uri!=null) {
_string=uri.toString();
}
String _plus = ("Error loading resource " + _string);
this.issueAcceptor.add(RefactoringIssueAcceptor.Severity.ERROR, _plus, t);
MoveResourceContext.LOG.error(t);
} else {
throw Exceptions.sneakyThrow(_t);
}
}
return _xtrycatchfinallyexpression;
}
public void executeModifications() {
final Consumer<Map.Entry<Resource, ResourceModification>> _function = (Map.Entry<Resource, ResourceModification> it) -> {
try {
it.getValue().modify(it.getKey());
} catch (final Throwable _t) {
if (_t instanceof Throwable) {
final Throwable t = (Throwable)_t;
Resource _key = it.getKey();
URI _uRI = null;
if (_key!=null) {
_uRI=_key.getURI();
}
String _string = null;
if (_uRI!=null) {
_string=_uRI.toString();
}
String _plus = ("Error executing modification on resource " + _string);
this.issueAcceptor.add(RefactoringIssueAcceptor.Severity.ERROR, _plus, t);
MoveResourceContext.LOG.error(t);
} else {
throw Exceptions.sneakyThrow(_t);
}
}
};
this.modifications.entrySet().forEach(_function);
}
public MoveResourceContext(final List<ResourceURIChange> fileChanges, final List<ResourceURIChange> folderChanges, final RefactoringIssueAcceptor issueAcceptor, final IChangeSerializer changeSerializer, final ResourceSet resourceSet) {
super();
this.fileChanges = fileChanges;
this.folderChanges = folderChanges;
this.issueAcceptor = issueAcceptor;
this.changeSerializer = changeSerializer;
this.resourceSet = resourceSet;
}
@Pure
public List<ResourceURIChange> getFileChanges() {
return this.fileChanges;
}
@Pure
public List<ResourceURIChange> getFolderChanges() {
return this.folderChanges;
}
@Pure
public RefactoringIssueAcceptor getIssueAcceptor() {
return this.issueAcceptor;
}
}

View file

@ -1,18 +0,0 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.xtext.ide.refactoring;
import org.eclipse.emf.ecore.resource.Resource;
/**
* @author koehnlein - Initial contribution and API
*/
@SuppressWarnings("all")
public interface ResourceModification {
public abstract void modify(final Resource resource);
}

View file

@ -0,0 +1,120 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.xtext.ide.refactoring;
import org.eclipse.emf.common.util.URI;
import org.eclipse.xtend.lib.annotations.Data;
import org.eclipse.xtext.xbase.lib.Pure;
import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;
/**
* URIs can also refer to folders and non-Xtext resources.
*
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
@Data
@SuppressWarnings("all")
public class ResourceRelocationChange {
public enum Type {
COPY,
MOVE,
RENAME;
}
private final URI fromURI;
private final URI toURI;
private final ResourceRelocationChange.Type type;
private final boolean isFile;
public ResourceRelocationChange(final URI fromURI, final URI toURI, final ResourceRelocationChange.Type type, final boolean isFile) {
super();
this.fromURI = fromURI;
this.toURI = toURI;
this.type = type;
this.isFile = isFile;
}
@Override
@Pure
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.fromURI== null) ? 0 : this.fromURI.hashCode());
result = prime * result + ((this.toURI== null) ? 0 : this.toURI.hashCode());
result = prime * result + ((this.type== null) ? 0 : this.type.hashCode());
result = prime * result + (this.isFile ? 1231 : 1237);
return result;
}
@Override
@Pure
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ResourceRelocationChange other = (ResourceRelocationChange) obj;
if (this.fromURI == null) {
if (other.fromURI != null)
return false;
} else if (!this.fromURI.equals(other.fromURI))
return false;
if (this.toURI == null) {
if (other.toURI != null)
return false;
} else if (!this.toURI.equals(other.toURI))
return false;
if (this.type == null) {
if (other.type != null)
return false;
} else if (!this.type.equals(other.type))
return false;
if (other.isFile != this.isFile)
return false;
return true;
}
@Override
@Pure
public String toString() {
ToStringBuilder b = new ToStringBuilder(this);
b.add("fromURI", this.fromURI);
b.add("toURI", this.toURI);
b.add("type", this.type);
b.add("isFile", this.isFile);
return b.toString();
}
@Pure
public URI getFromURI() {
return this.fromURI;
}
@Pure
public URI getToURI() {
return this.toURI;
}
@Pure
public ResourceRelocationChange.Type getType() {
return this.type;
}
@Pure
public boolean isFile() {
return this.isFile;
}
}

View file

@ -0,0 +1,62 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.xtext.ide.refactoring;
import java.util.List;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtend.lib.annotations.AccessorType;
import org.eclipse.xtend.lib.annotations.Accessors;
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor;
import org.eclipse.xtext.ide.refactoring.RefactoringIssueAcceptor;
import org.eclipse.xtext.ide.refactoring.ResourceRelocationChange;
import org.eclipse.xtext.ide.serializer.IChangeSerializer;
import org.eclipse.xtext.xbase.lib.Pure;
/**
* @author koehnlein - Initial contribution and API
*/
@FinalFieldsConstructor
@Accessors(AccessorType.PUBLIC_GETTER)
@SuppressWarnings("all")
public class ResourceRelocationContext {
private final List<ResourceRelocationChange> changes;
private final RefactoringIssueAcceptor issueAcceptor;
private final IChangeSerializer changeSerializer;
private final ResourceSet resourceSet;
public ResourceRelocationContext(final List<ResourceRelocationChange> changes, final RefactoringIssueAcceptor issueAcceptor, final IChangeSerializer changeSerializer, final ResourceSet resourceSet) {
super();
this.changes = changes;
this.issueAcceptor = issueAcceptor;
this.changeSerializer = changeSerializer;
this.resourceSet = resourceSet;
}
@Pure
public List<ResourceRelocationChange> getChanges() {
return this.changes;
}
@Pure
public RefactoringIssueAcceptor getIssueAcceptor() {
return this.issueAcceptor;
}
@Pure
public IChangeSerializer getChangeSerializer() {
return this.changeSerializer;
}
@Pure
public ResourceSet getResourceSet() {
return this.resourceSet;
}
}

View file

@ -0,0 +1,130 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.xtext.ide.refactoring;
import com.google.common.collect.LinkedHashMultimap;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.ide.refactoring.IResourceRelocationStrategy;
import org.eclipse.xtext.ide.refactoring.RefactoringIssueAcceptor;
import org.eclipse.xtext.ide.refactoring.ResourceRelocationChange;
import org.eclipse.xtext.ide.refactoring.ResourceRelocationContext;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
/**
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
@SuppressWarnings("all")
public class ResourceRelocationStrategyExecutor {
private final static Logger LOG = Logger.getLogger(ResourceRelocationStrategyExecutor.class);
public void executeParticipants(final List<? extends IResourceRelocationStrategy> strategies, final ResourceRelocationContext context) {
final LinkedHashMultimap<ResourceRelocationChange, IResourceRelocationStrategy> change2strategies = LinkedHashMultimap.<ResourceRelocationChange, IResourceRelocationStrategy>create();
List<ResourceRelocationChange> _changes = context.getChanges();
for (final ResourceRelocationChange change : _changes) {
for (final IResourceRelocationStrategy strategy : strategies) {
boolean _canHandle = strategy.canHandle(change);
if (_canHandle) {
change2strategies.put(change, strategy);
}
}
}
final HashMap<ResourceRelocationChange, Resource> change2resource = CollectionLiterals.<ResourceRelocationChange, Resource>newHashMap();
Set<ResourceRelocationChange> _keySet = change2strategies.keySet();
for (final ResourceRelocationChange change_1 : _keySet) {
{
final IResourceRelocationStrategy primaryStrategy = IterableExtensions.<IResourceRelocationStrategy>head(change2strategies.get(change_1));
try {
final Resource resource = primaryStrategy.loadAndWatchResource(change_1, context);
change2resource.put(change_1, resource);
} catch (final Throwable _t) {
if (_t instanceof Throwable) {
final Throwable t = (Throwable)_t;
URI _fromURI = null;
if (change_1!=null) {
_fromURI=change_1.getFromURI();
}
String _string = null;
if (_fromURI!=null) {
_string=_fromURI.toString();
}
String _plus = ("Error loading resource " + _string);
context.getIssueAcceptor().add(RefactoringIssueAcceptor.Severity.ERROR, _plus, t);
ResourceRelocationStrategyExecutor.LOG.error(t);
} else {
throw Exceptions.sneakyThrow(_t);
}
}
}
}
Set<ResourceRelocationChange> _keySet_1 = change2strategies.keySet();
for (final ResourceRelocationChange change_2 : _keySet_1) {
{
boolean changeApplied = false;
final Resource resource = change2resource.get(change_2);
Set<IResourceRelocationStrategy> _get = change2strategies.get(change_2);
for (final IResourceRelocationStrategy strategy_1 : _get) {
{
if ((!changeApplied)) {
try {
strategy_1.applyChange(change_2, resource, context);
changeApplied = true;
} catch (final Throwable _t) {
if (_t instanceof Throwable) {
final Throwable t = (Throwable)_t;
URI _fromURI = null;
if (change_2!=null) {
_fromURI=change_2.getFromURI();
}
String _string = null;
if (_fromURI!=null) {
_string=_fromURI.toString();
}
String _plus = ("Error applying relocation change to " + _string);
context.getIssueAcceptor().add(RefactoringIssueAcceptor.Severity.ERROR, _plus, t);
ResourceRelocationStrategyExecutor.LOG.error(t);
} else {
throw Exceptions.sneakyThrow(_t);
}
}
}
if (changeApplied) {
try {
strategy_1.applySideEffects(change_2, resource, context);
} catch (final Throwable _t_1) {
if (_t_1 instanceof Throwable) {
final Throwable t_1 = (Throwable)_t_1;
URI _fromURI_1 = null;
if (change_2!=null) {
_fromURI_1=change_2.getFromURI();
}
String _string_1 = null;
if (_fromURI_1!=null) {
_string_1=_fromURI_1.toString();
}
String _plus_1 = ("Error applying side effect to " + _string_1);
context.getIssueAcceptor().add(RefactoringIssueAcceptor.Severity.ERROR, _plus_1, t_1);
ResourceRelocationStrategyExecutor.LOG.error(t_1);
} else {
throw Exceptions.sneakyThrow(_t_1);
}
}
}
}
}
}
}
}
}

View file

@ -1,85 +0,0 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.xtext.ide.refactoring;
import org.eclipse.emf.common.util.URI;
import org.eclipse.xtend.lib.annotations.Data;
import org.eclipse.xtext.xbase.lib.Pure;
import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;
/**
* URIs can also refer to folders and non-Xtext resources.
*
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
@Data
@SuppressWarnings("all")
public class ResourceURIChange {
private final URI oldURI;
private final URI newURI;
public ResourceURIChange(final URI oldURI, final URI newURI) {
super();
this.oldURI = oldURI;
this.newURI = newURI;
}
@Override
@Pure
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.oldURI== null) ? 0 : this.oldURI.hashCode());
result = prime * result + ((this.newURI== null) ? 0 : this.newURI.hashCode());
return result;
}
@Override
@Pure
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ResourceURIChange other = (ResourceURIChange) obj;
if (this.oldURI == null) {
if (other.oldURI != null)
return false;
} else if (!this.oldURI.equals(other.oldURI))
return false;
if (this.newURI == null) {
if (other.newURI != null)
return false;
} else if (!this.newURI.equals(other.newURI))
return false;
return true;
}
@Override
@Pure
public String toString() {
ToStringBuilder b = new ToStringBuilder(this);
b.add("oldURI", this.oldURI);
b.add("newURI", this.newURI);
return b.toString();
}
@Pure
public URI getOldURI() {
return this.oldURI;
}
@Pure
public URI getNewURI() {
return this.newURI;
}
}

View file

@ -1,19 +0,0 @@
/**
* Copyright (c) 2017 TypeFox GmbH (http://www.typefox.io) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.xtext.ide.refactoring;
import org.eclipse.xtext.ide.refactoring.MoveResourceContext;
/**
* @author koehnlein - Initial contribution and API
* @since 2.13
*/
@SuppressWarnings("all")
public interface XtextMoveResourceStrategy {
public abstract void applyMove(final MoveResourceContext context);
}

View file

@ -3,18 +3,18 @@
*/
package org.eclipse.xtext.testlanguages.fileAware.ide;
import org.eclipse.xtext.ide.refactoring.XtextMoveResourceStrategy;
import org.eclipse.xtext.ide.refactoring.IResourceRelocationStrategy;
import org.eclipse.xtext.ide.serializer.hooks.IReferenceUpdater;
import org.eclipse.xtext.testlanguages.fileAware.ide.refactoring.FileAwareTestLanguageMoveResourceStrategy;
import org.eclipse.xtext.testlanguages.fileAware.ide.refactoring.FileAwareTestLanguageReferenceUpdater;
import org.eclipse.xtext.testlanguages.fileAware.ide.refactoring.FileAwareTestLanguageResourceRelocationStrategy;
/**
* Use this class to register ide components.
*/
public class FileAwareTestLanguageIdeModule extends AbstractFileAwareTestLanguageIdeModule {
public Class<? extends XtextMoveResourceStrategy> bindXtextMoveParticipantStrategy() {
return FileAwareTestLanguageMoveResourceStrategy.class;
public Class<? extends IResourceRelocationStrategy> bindIResourceRelocationStrategy() {
return FileAwareTestLanguageResourceRelocationStrategy.class;
}
public Class<? extends IReferenceUpdater> bindReferenceUpdater() {

View file

@ -1,27 +0,0 @@
package org.eclipse.xtext.testlanguages.fileAware.ide.refactoring
import org.eclipse.xtext.ide.refactoring.MoveResourceContext
import org.eclipse.xtext.ide.refactoring.XtextMoveResourceStrategy
import org.eclipse.xtext.testlanguages.fileAware.fileAware.PackageDeclaration
import com.google.inject.Inject
import org.eclipse.xtext.resource.IResourceServiceProvider
class FileAwareTestLanguageMoveResourceStrategy implements XtextMoveResourceStrategy {
@Inject IResourceServiceProvider resourceServiceProvider
override applyMove(MoveResourceContext context) {
for (change : context.fileChanges) {
if(resourceServiceProvider.canHandle(change.newURI)) {
context.addModification(change.oldURI, [ resource |
resource.URI = change.newURI
val rootElement = resource.contents.head
if (rootElement instanceof PackageDeclaration) {
val newPackage = change.newURI.trimSegments(1).segmentsList.drop(2).join('.')
rootElement.name = newPackage
}
])
}
}
}
}

View file

@ -0,0 +1,18 @@
package org.eclipse.xtext.testlanguages.fileAware.ide.refactoring
import org.eclipse.xtext.ide.refactoring.IResourceRelocationStrategy
import org.eclipse.xtext.ide.refactoring.ResourceRelocationChange
import org.eclipse.xtext.ide.refactoring.ResourceRelocationContext
import org.eclipse.xtext.testlanguages.fileAware.fileAware.PackageDeclaration
import org.eclipse.emf.ecore.resource.Resource
class FileAwareTestLanguageResourceRelocationStrategy extends IResourceRelocationStrategy.AbstractImpl {
override applySideEffects(ResourceRelocationChange change, Resource resource, ResourceRelocationContext context) {
val rootElement = resource.contents.head
if (rootElement instanceof PackageDeclaration) {
val newPackage = change.toURI.trimSegments(1).segmentsList.drop(2).join('.')
rootElement.name = newPackage
}
}
}

View file

@ -1,38 +0,0 @@
package org.eclipse.xtext.testlanguages.fileAware.ide.refactoring;
import com.google.inject.Inject;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.ide.refactoring.MoveResourceContext;
import org.eclipse.xtext.ide.refactoring.ResourceModification;
import org.eclipse.xtext.ide.refactoring.ResourceURIChange;
import org.eclipse.xtext.ide.refactoring.XtextMoveResourceStrategy;
import org.eclipse.xtext.resource.IResourceServiceProvider;
import org.eclipse.xtext.testlanguages.fileAware.fileAware.PackageDeclaration;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
@SuppressWarnings("all")
public class FileAwareTestLanguageMoveResourceStrategy implements XtextMoveResourceStrategy {
@Inject
private IResourceServiceProvider resourceServiceProvider;
@Override
public void applyMove(final MoveResourceContext context) {
List<ResourceURIChange> _fileChanges = context.getFileChanges();
for (final ResourceURIChange change : _fileChanges) {
boolean _canHandle = this.resourceServiceProvider.canHandle(change.getNewURI());
if (_canHandle) {
final ResourceModification _function = (Resource resource) -> {
resource.setURI(change.getNewURI());
final EObject rootElement = IterableExtensions.<EObject>head(resource.getContents());
if ((rootElement instanceof PackageDeclaration)) {
final String newPackage = IterableExtensions.join(IterableExtensions.<String>drop(change.getNewURI().trimSegments(1).segmentsList(), 2), ".");
((PackageDeclaration)rootElement).setName(newPackage);
}
};
context.addModification(change.getOldURI(), _function);
}
}
}
}

View file

@ -0,0 +1,21 @@
package org.eclipse.xtext.testlanguages.fileAware.ide.refactoring;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.ide.refactoring.IResourceRelocationStrategy;
import org.eclipse.xtext.ide.refactoring.ResourceRelocationChange;
import org.eclipse.xtext.ide.refactoring.ResourceRelocationContext;
import org.eclipse.xtext.testlanguages.fileAware.fileAware.PackageDeclaration;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
@SuppressWarnings("all")
public class FileAwareTestLanguageResourceRelocationStrategy extends IResourceRelocationStrategy.AbstractImpl {
@Override
public void applySideEffects(final ResourceRelocationChange change, final Resource resource, final ResourceRelocationContext context) {
final EObject rootElement = IterableExtensions.<EObject>head(resource.getContents());
if ((rootElement instanceof PackageDeclaration)) {
final String newPackage = IterableExtensions.join(IterableExtensions.<String>drop(change.getToURI().trimSegments(1).segmentsList(), 2), ".");
((PackageDeclaration)rootElement).setName(newPackage);
}
}
}