package com.redhat.ceylon.eclipse.code.correct;
import static com.redhat.ceylon.eclipse.ui.CeylonResources.COMPOSITE_CHANGE;
import static java.util.Collections.emptyList;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
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.TextChange;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.ui.IEditorPart;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.CompilationUnit;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Identifier;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDeclaration;
import com.redhat.ceylon.eclipse.code.editor.CeylonEditor;
import com.redhat.ceylon.eclipse.code.refactor.RenameRefactoring;
import com.redhat.ceylon.ide.common.correct.FindInvocationVisitor;
import com.redhat.ceylon.model.typechecker.model.Function;
class ConvertFunctionToGetterProposal extends CorrectionProposal {
private ConvertToGetterRefactoring refactoring;
private static final class ConvertToGetterRefactoring extends RenameRefactoring {
private ConvertToGetterRefactoring(IEditorPart editor) {
super(editor);
}
@Override
public String getName() {
return "Convert to Getter";
}
@Override
public RefactoringStatus checkFinalConditions(IProgressMonitor pm)
throws CoreException, OperationCanceledException {
return new RefactoringStatus();
}
@Override
protected void refactorJavaReferences(IProgressMonitor pm, CompositeChange cc) {
// TODO!
}
@Override
protected void renameIdentifier(TextChange tfc, Identifier id, CompilationUnit root) {}
@Override
protected void renameRegion(TextChange tfc, Region region, CompilationUnit root) {}
@Override
public List<Identifier> getIdentifiersToRename(CompilationUnit root) {
return emptyList();
}
@Override
public List<Region> getStringsToReplace(CompilationUnit root) {
return emptyList();
}
@Override
protected void renameNode(TextChange tfc, Node node, Tree.CompilationUnit root) {
Integer startIndex = null;
Integer endIndex = null;
if (node instanceof Tree.AnyMethod) {
Tree.AnyMethod am = (Tree.AnyMethod) node;
Tree.Type type = am.getType();
if (type instanceof Tree.FunctionModifier) {
tfc.addEdit(new ReplaceEdit(
type.getStartIndex(),
type.getDistance(),
"value"));
}
Tree.ParameterList parameterList =
am.getParameterLists().get(0);
startIndex = parameterList.getStartIndex();
endIndex = parameterList.getEndIndex();
}
else {
FindInvocationVisitor fiv =
new FindInvocationVisitor(node);
fiv.visit(root);
if (fiv.getResult() != null &&
fiv.getResult().getPrimary() == node) {
Tree.PositionalArgumentList pal =
fiv.getResult().getPositionalArgumentList();
startIndex = pal.getStartIndex();
endIndex = pal.getEndIndex();
}
}
if (startIndex != null && endIndex != null) {
tfc.addEdit(new DeleteEdit(startIndex, endIndex - startIndex));
}
}
}
static void addConvertFunctionToGetterProposal(
Collection<ICompletionProposal> proposals,
CeylonEditor editor, Node node) {
Function method;
if (node instanceof Tree.MethodDefinition) {
Tree.MethodDefinition md =
(Tree.MethodDefinition) node;
method = md.getDeclarationModel();
}
else if (node instanceof Tree.MethodDeclaration) {
MethodDeclaration md =
(Tree.MethodDeclaration) node;
if (md.getSpecifierExpression()
instanceof Tree.LazySpecifierExpression) {
method = md.getDeclarationModel();
}
else {
return;
}
}
else {
return;
}
if (method!=null
&& !method.isDeclaredVoid()
&& method.getParameterLists().size()==1
&& method.getParameterLists().get(0).getParameters().isEmpty()) {
addConvertFunctionToGetterProposal(proposals, editor, method);
}
}
private static void addConvertFunctionToGetterProposal(
Collection<ICompletionProposal> proposals,
CeylonEditor editor, Function method) {
ConvertToGetterRefactoring refactoring =
new ConvertToGetterRefactoring(editor);
try {
if (refactoring.getDeclaration() == null
|| !refactoring.getDeclaration().equals(method)
|| !refactoring.getEnabled()
|| !refactoring.checkAllConditions(new NullProgressMonitor()).isOK()) {
return;
}
}
catch (OperationCanceledException e) {
// noop
return;
}
catch (CoreException e) {
e.printStackTrace();
return;
}
String desc =
"Convert " +
(method.isToplevel() ? "function" : "method") +
" '" + method.getName() + "()' to getter";
ConvertFunctionToGetterProposal proposal =
new ConvertFunctionToGetterProposal(
desc, method, refactoring);
if (!proposals.contains(proposal)) {
proposals.add(proposal);
}
}
@Override
protected Change createChange() throws CoreException {
CompositeChange change =
refactoring.createChange(
new NullProgressMonitor());
// if (change.getChildren().length == 0) {
// return;
// }
return change;
}
private ConvertFunctionToGetterProposal(
String desc, Function method,
ConvertToGetterRefactoring refactoring) {
super(desc, null, null, COMPOSITE_CHANGE);
this.refactoring = refactoring;
}
}