package com.redhat.ceylon.eclipse.code.correct;
import static com.redhat.ceylon.eclipse.code.correct.DestructureProposal.getItemProposals;
import static com.redhat.ceylon.eclipse.code.correct.DestructureProposal.getKeyProposals;
import static com.redhat.ceylon.eclipse.code.correct.LinkedModeCompletionProposal.getNameProposals;
import java.util.Collection;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.link.ProposalPosition;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.ltk.core.refactoring.DocumentChange;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.eclipse.code.editor.CeylonEditor;
import com.redhat.ceylon.eclipse.util.LinkedMode;
import com.redhat.ceylon.eclipse.util.Nodes;
import com.redhat.ceylon.model.typechecker.model.Class;
import com.redhat.ceylon.model.typechecker.model.Type;
import com.redhat.ceylon.model.typechecker.model.Unit;
class AssignToForProposal extends LocalProposal {
protected DocumentChange createChange(IDocument document, Node expanse,
int endIndex) {
DocumentChange change =
new DocumentChange("Assign to For", document);
change.setEdit(new MultiTextEdit());
Unit unit = expanse.getUnit();
String text;
int adjust = 0;
if (getEntryType(unit)==null) {
text = "for (" + initialName + " in ";
}
else {
text = "for (key -> item in ";
adjust = 4;
}
change.addEdit(new InsertEdit(offset, text));
String terminal = expanse.getEndToken().getText();
if (!terminal.equals(";")) {
change.addEdit(new InsertEdit(endIndex, ") {}"));
exitPos = endIndex+3+adjust;
}
else {
change.addEdit(new ReplaceEdit(endIndex-1, 1, ") {}"));
exitPos = endIndex+2+adjust;
}
return change;
}
Type getEntryType(Unit unit) {
Class ed = unit.getEntryDeclaration();
Type est = unit.getIteratedType(type).getSupertype(ed);
return est;
}
public AssignToForProposal(CeylonEditor ceylonEditor, Tree.CompilationUnit cu,
Node node, int currentOffset) {
super(ceylonEditor, cu, node, currentOffset);
}
protected void addLinkedPositions(IDocument document, Unit unit)
throws BadLocationException {
Type entryType = getEntryType(unit);
if (entryType==null) {
ProposalPosition namePosition =
new ProposalPosition(document, offset+5, initialName.length(), 0,
getNameProposals(offset+5, 0, nameProposals));
LinkedMode.addLinkedPosition(linkedModeModel, namePosition);
}
else {
ProposalPosition keyPosition =
new ProposalPosition(document, offset+5, 3, 0,
getNameProposals(offset+5, 0,
getKeyProposals(unit, entryType)));
LinkedMode.addLinkedPosition(linkedModeModel, keyPosition);
ProposalPosition itemPosition =
new ProposalPosition(document, offset+12, 4, 1,
getNameProposals(offset+5, 1,
getItemProposals(unit, entryType)));
LinkedMode.addLinkedPosition(linkedModeModel, itemPosition);
}
}
@Override
String[] computeNameProposals(Node expression) {
return Nodes.nameProposals(expression, true);
}
@Override
public String getDisplayString() {
return "Iterate expression in 'for' loop";
}
@Override
public StyledString getStyledDisplayString() {
String hint =
CorrectionUtil.shortcut(
"com.redhat.ceylon.eclipse.ui.action.assignToFor");
return new StyledString()
.append(super.getStyledDisplayString())
.append(hint, StyledString.QUALIFIER_STYLER);
}
@Override
boolean isEnabled(Type resultType) {
Unit unit = rootNode.getUnit();
return resultType!=null &&
(unit.isIterableType(resultType) ||
unit.isJavaIterableType(resultType) ||
unit.isJavaArrayType(resultType));
}
static void addAssignToForProposal(CeylonEditor ceylonEditor, Tree.CompilationUnit cu,
Collection<ICompletionProposal> proposals,
Node node, int currentOffset) {
AssignToForProposal prop =
new AssignToForProposal(ceylonEditor, cu, node, currentOffset);
if (prop.isEnabled()) {
proposals.add(prop);
}
}
}