package com.redhat.ceylon.eclipse.code.correct; import static com.redhat.ceylon.eclipse.util.EditorUtil.getDocument; import java.util.Collection; import java.util.List; import org.antlr.runtime.CommonToken; import org.eclipse.core.resources.IFile; import org.eclipse.jface.text.BadLocationException; 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.TextChange; import org.eclipse.ltk.core.refactoring.TextFileChange; import org.eclipse.text.edits.ReplaceEdit; import com.redhat.ceylon.compiler.typechecker.tree.Tree; import com.redhat.ceylon.compiler.typechecker.tree.Visitor; import com.redhat.ceylon.eclipse.code.editor.CeylonEditor; import com.redhat.ceylon.eclipse.util.Nodes; import com.redhat.ceylon.model.typechecker.model.Parameter; import com.redhat.ceylon.model.typechecker.model.ParameterList; class ConvertToPositionalArgumentsProposal extends CorrectionProposal { public ConvertToPositionalArgumentsProposal(int offset, Change change) { super("Convert to positional arguments", change, new Region(offset, 0)); } public static void addConvertToPositionalArgumentsProposal( Collection<ICompletionProposal> proposals, IFile file, Tree.CompilationUnit cu, CeylonEditor editor, int currentOffset) { Tree.NamedArgumentList nal = findNamedArgumentList(currentOffset, cu); if (nal==null) { return; } final TextChange tc = new TextFileChange( "Convert to Positional Arguments", file); Integer start = nal.getStartIndex(); try { if (getDocument(tc).getChar(start-1)==' ') { start--; } } catch (BadLocationException e1) { e1.printStackTrace(); } int length = nal.getEndIndex()-start; StringBuilder result = new StringBuilder().append("("); List<CommonToken> tokens = editor.getParseController() .getTokens(); List<Tree.NamedArgument> args = nal.getNamedArguments(); Tree.SequencedArgument sa = nal.getSequencedArgument(); ParameterList parameterList = nal.getNamedArgumentList() .getParameterList(); if (parameterList==null) { return; } for (Parameter p: parameterList.getParameters()) { boolean found = false; if (sa!=null) { Parameter param = sa.getParameter(); if (param==null) { return; } if (param.getModel().equals(p.getModel())) { found = true; result.append("{ ") .append(Nodes.text(sa, tokens)) .append(" }"); } } for (Tree.NamedArgument na: args) { Parameter param = na.getParameter(); if (param==null) { return; } if (param.getModel().equals(p.getModel())) { found = true; if (na instanceof Tree.SpecifiedArgument) { Tree.SpecifiedArgument sna = (Tree.SpecifiedArgument) na; Tree.SpecifierExpression se = sna.getSpecifierExpression(); if (se!=null && se.getExpression()!=null) { result.append(Nodes.text(se.getExpression(), tokens)); } break; } else if (na instanceof Tree.MethodArgument) { Tree.MethodArgument ma = (Tree.MethodArgument) na; if (ma.getDeclarationModel().isDeclaredVoid()) { result.append("void "); } for (Tree.ParameterList pl: ma.getParameterLists()) { result.append(Nodes.text(pl, tokens)); } Tree.Block block = ma.getBlock(); if (block!=null) { result.append(" ") .append(Nodes.text(block, tokens)); } Tree.SpecifierExpression se = ma.getSpecifierExpression(); if (se!=null) { result.append(" ") .append(Nodes.text(se, tokens)); } } else { return; } } } if (found) { result.append(", "); } } if (result.length()>1) { result.setLength(result.length()-2); } result.append(")"); tc.setEdit(new ReplaceEdit(start, length, result.toString())); int offset = start+result.toString().length(); proposals.add(new ConvertToPositionalArgumentsProposal(offset, tc)); } private static Tree.NamedArgumentList findNamedArgumentList( int currentOffset, Tree.CompilationUnit cu) { FindNamedArgumentsVisitor fpav = new FindNamedArgumentsVisitor(currentOffset); fpav.visit(cu); return fpav.getArgumentList(); } private static class FindNamedArgumentsVisitor extends Visitor { Tree.NamedArgumentList argumentList; int offset; private Tree.NamedArgumentList getArgumentList() { return argumentList; } private FindNamedArgumentsVisitor(int offset) { this.offset = offset; } @Override public void visit(Tree.NamedArgumentList that) { if (offset>=that.getStartIndex() && offset<=that.getEndIndex()) { argumentList = that; } super.visit(that); } } }