package com.redhat.ceylon.eclipse.code.refactor; import static com.redhat.ceylon.eclipse.util.Nodes.getIdentifyingNode; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.antlr.runtime.CommonToken; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; 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.MultiTextEdit; 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.Visitor; import com.redhat.ceylon.model.typechecker.model.Module; public class ChangeVersionRefactoring extends AbstractRefactoring { private static class FindVersionReferenceVisitor extends Visitor { private Module module; private final Set<Node> nodes = new HashSet<Node>(); public Set<Node> getNodes() { return nodes; } private FindVersionReferenceVisitor(Module module) { this.module = module; } @Override public void visit(Tree.ImportModule that) { super.visit(that); Tree.ImportPath ip = that.getImportPath(); String name = module.getNameAsString(); Tree.QuotedLiteral version = that.getVersion(); if (version!=null) { if (ip!=null && ip.getModel()!=null && ip.getModel().getNameAsString() .equals(name)) { nodes.add(version); } Tree.QuotedLiteral ql = that.getQuotedLiteral(); if (ql!=null && ql.getText().equals('"' + name + '"')) { nodes.add(version); } } } @Override public void visit(Tree.ModuleDescriptor that) { super.visit(that); Tree.QuotedLiteral version = that.getVersion(); if (version!=null) { Tree.ImportPath ip = that.getImportPath(); if (ip!=null && ip.getModel()!=null && ip.getModel().getNameAsString() .equals(module.getNameAsString())) { nodes.add(version); } } } } private String newVersion; private final Module module; public Node getNode() { return node; } public ChangeVersionRefactoring(IEditorPart editor) { super(editor); if (rootNode!=null) { module = rootNode.getUnit().getPackage().getModule(); newVersion = module.getVersion(); } else { module = null; } } @Override public boolean getEnabled() { return module!=null && project != null; } public int getCount() { return module==null ? 0 : countDeclarationOccurrences(); } @Override int countReferences(Tree.CompilationUnit cu) { FindVersionReferenceVisitor frv = new FindVersionReferenceVisitor(module); cu.visit(frv); return frv.getNodes().size(); } public String getName() { return "Change Module Version"; } public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { // Check parameters retrieved from editor context return new RefactoringStatus(); } public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException, OperationCanceledException { return new RefactoringStatus(); } @Override protected void refactorInFile(TextChange tfc, CompositeChange cc, Tree.CompilationUnit root, List<CommonToken> tokens) { tfc.setEdit(new MultiTextEdit()); if (module!=null) { for (Node node: getNodesToRename(root)) { renameNode(tfc, node, root); } } if (tfc.getEdit().hasChildren()) { cc.add(tfc); } } public List<Node> getNodesToRename(Tree.CompilationUnit root) { ArrayList<Node> list = new ArrayList<Node>(); FindVersionReferenceVisitor frv = new FindVersionReferenceVisitor(module); root.visit(frv); list.addAll(frv.getNodes()); return list; } protected void renameNode(TextChange tfc, Node node, Tree.CompilationUnit root) { Node identifyingNode = getIdentifyingNode(node); int start = identifyingNode.getStartIndex() + 1; int length = identifyingNode.getText().length() - 2; tfc.addEdit(new ReplaceEdit(start, length, newVersion)); } public void setNewVersion(String text) { newVersion = text; } public String getNewVersion() { return newVersion; } public Module getModule() { return module; } @Override protected boolean isAffectingOtherFiles() { return true; } }