package com.redhat.ceylon.eclipse.code.correct; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.TextFileChange; import org.eclipse.text.edits.DeleteEdit; 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.compiler.typechecker.tree.Visitor; class ConvertToInterpolationProposal extends CorrectionProposal { private ConvertToInterpolationProposal(String name, Change change) { super(name, change, null); } private static List<Tree.Term> flatten(Tree.SumOp sum) { Tree.Term lt = sum.getLeftTerm(); Tree.Term rt = sum.getRightTerm(); List<Tree.Term> result; if (lt instanceof Tree.SumOp) { result = flatten((Tree.SumOp) lt); result.add(rt); } else { result = new ArrayList<Tree.Term>(); result.add(lt); result.add(rt); } return result; } static class ConcatenationVisitor extends Visitor { Node node; Tree.SumOp result; ConcatenationVisitor(Node node) { this.node = node; } @Override public void visit(Tree.SumOp that) { if (that.getStartIndex()<=node.getStartIndex() && that.getEndIndex()>=node.getEndIndex() && that.getTypeModel()!=null && that.getTypeModel().isString()) { result = that; return; } super.visit(that); } } static void addConvertToInterpolationProposal( Collection<ICompletionProposal> proposals, IFile file, Tree.CompilationUnit cu, Node node, IDocument doc) { ConcatenationVisitor tv = new ConcatenationVisitor(node); tv.visit(cu); Tree.SumOp sum = tv.result; if (sum!=null) { TextFileChange change = new TextFileChange( "Convert to Interpolation", file); change.setEdit(new MultiTextEdit()); List<Tree.Term> terms = flatten(sum); Tree.Term lt = terms.get(0); Tree.Term rt = terms.get(terms.size()-1); boolean expectingLiteral = lt instanceof Tree.StringLiteral || lt instanceof Tree.StringTemplate; if (!expectingLiteral) { change.addEdit(new InsertEdit(lt.getStartIndex(), "\"``")); } for (int i=0; i<terms.size(); i++) { Tree.Term term = terms.get(i); if (i>0) { Tree.Term previous = terms.get(i-1); int from = previous.getEndIndex(); int to = term.getStartIndex(); change.addEdit(new DeleteEdit(from, to-from)); } if (expectingLiteral && !(term instanceof Tree.StringLiteral || term instanceof Tree.StringTemplate)) { change.addEdit(new InsertEdit(term.getStartIndex(), "````")); expectingLiteral = false; } if (expectingLiteral) { if (i>0) { change.addEdit(new ReplaceEdit(term.getStartIndex(), 1, "``")); } if (i<terms.size()-1) { change.addEdit(new ReplaceEdit(term.getEndIndex()-1, 1, "``")); } expectingLiteral = false; } else { if (term instanceof Tree.QualifiedMemberExpression) { Tree.QualifiedMemberExpression lrt = (Tree.QualifiedMemberExpression) term; if (lrt.getDeclaration().getName().equals("string")) { int from = lrt.getMemberOperator().getStartIndex(); int to = lrt.getIdentifier().getEndIndex(); change.addEdit(new DeleteEdit(from, to-from)); } } expectingLiteral = true; } } if (expectingLiteral) { change.addEdit(new InsertEdit(rt.getEndIndex(), "``\"")); } proposals.add(new ConvertToInterpolationProposal( "Convert to string interpolation", change)); } } }