package com.redhat.ceylon.eclipse.code.correct; import static com.redhat.ceylon.eclipse.code.editor.Navigation.gotoFile; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.Region; import org.eclipse.ltk.core.refactoring.TextChange; import org.eclipse.ltk.core.refactoring.TextFileChange; import org.eclipse.swt.graphics.Point; import com.redhat.ceylon.eclipse.code.editor.CeylonEditor; import com.redhat.ceylon.ide.common.model.ModifiableSourceFile; import com.redhat.ceylon.model.typechecker.model.Unit; class ChangeTypeProposal extends CorrectionProposal { private Unit unit; ChangeTypeProposal(String desc, Region region, Unit unit, TextChange change) { super(desc, change, region); this.unit = unit; } @Deprecated ChangeTypeProposal(ProblemLocation problem, String name, String type, int offset, int len, Unit unit, TextFileChange change) { super("Change type of "+ name + " to '" + type + "'", change, new Region(offset, len)); this.unit = unit; } @Override public void apply(IDocument document) { CeylonEditor editor = null; if (unit instanceof ModifiableSourceFile) { ModifiableSourceFile<IProject,IResource,IFolder,IFile> msf = (ModifiableSourceFile<IProject,IResource,IFolder,IFile>) unit; IFile file = msf.getResourceFile(); if (file!=null) { editor = (CeylonEditor) gotoFile(file, 0, 0); //NOTE: the document we're given is the one //for the editor from which the quick fix was //invoked, not the one to which the fix applies IDocument ed = editor.getParseController() .getDocument(); if (ed!=document) { document = ed; } } } super.apply(document); if (editor!=null) { Point point = super.getSelection(document); editor.selectAndReveal(point.x, point.y); } } @Override public Point getSelection(IDocument document) { //we don't apply a selection because //the change might have been applied to //a different editor to the one from //which the quick fix was invoked. return null; } // @Deprecated // private static void addChangeTypeProposal(Node node, // ProblemLocation problem, // Collection<ICompletionProposal> proposals, // Declaration dec, // Type newType, // IFile file, // Tree.CompilationUnit cu) { // if (node.getStartIndex() == null || // node.getEndIndex() == null) { // return; // } // if (newType.isNothing()) { // return; // } // if (ModelUtil.isConstructor(dec)) { // return; // } // TextFileChange change = // new TextFileChange("Change Type", file); // change.setEdit(new MultiTextEdit()); // IDocument doc = getDocument(change); // int offset = node.getStartIndex(); // int length = node.getDistance(); // HashSet<Declaration> decs = // new HashSet<Declaration>(); // importProposals().importType(decs, newType, cu); // int il = (int) importProposals().applyImports(change, decs, cu, doc); // Unit unit = cu.getUnit(); // String newTypeName = // newType.asSourceCodeString(unit); // change.addEdit(new ReplaceEdit(offset, length, // newTypeName)); // String name; // if (dec.isParameter()) { // Declaration container = // (Declaration) // dec.getContainer(); // name = "parameter '" + // dec.getName() + "' of '" + // container.getName() + "'"; // } // else if (dec.isClassOrInterfaceMember()) { // ClassOrInterface container = // (ClassOrInterface) // dec.getContainer(); // name = "member '" + // dec.getName() + "' of '" + // container.getName() + "'"; // } // else { // name = "'" + dec.getName() + "'"; // } // proposals.add(new ChangeTypeProposal( // problem, name, // newType.asString(unit), // offset+il, newTypeName.length(), // unit, change)); // } // // @Deprecated // static void addChangeTypeArgProposals( // Tree.CompilationUnit rootNode, Node node, // ProblemLocation problem, // Collection<ICompletionProposal> proposals, // IProject project) { // if (node instanceof Tree.SimpleType) { // final Tree.SimpleType stn = (Tree.SimpleType) node; // TypeDeclaration dec = stn.getDeclarationModel(); // if (dec instanceof TypeParameter) { // class ArgumentListVisitor extends Visitor { // Declaration declaration; // Tree.TypeArgumentList typeArgs; // @Override // public void visit(Tree.StaticMemberOrTypeExpression that) { // super.visit(that); // Tree.TypeArguments args = // that.getTypeArguments(); // if (args instanceof Tree.TypeArgumentList) { // Tree.TypeArgumentList tal = // (Tree.TypeArgumentList) args; // if (tal.getTypes().contains(stn)) { // declaration = that.getDeclaration(); // typeArgs = tal; // } // } // } // @Override // public void visit(Tree.SimpleType that) { // super.visit(that); // Tree.TypeArguments args = // that.getTypeArgumentList(); // if (args instanceof Tree.TypeArgumentList) { // Tree.TypeArgumentList tal = // (Tree.TypeArgumentList) args; // if (tal.getTypes().contains(stn)) { // declaration = that.getDeclarationModel(); // typeArgs = tal; // } // } // } // } // ArgumentListVisitor vis = new ArgumentListVisitor(); // vis.visit(rootNode); // Declaration std = vis.declaration; // if (std instanceof Generic) { // Generic g = (Generic) std; // List<TypeParameter> tps = // g.getTypeParameters(); // Tree.TypeArgumentList tal = vis.typeArgs; // int i = tal.getTypes().indexOf(stn); // if (tps!=null && tps.size()>i) { // TypeParameter stTypeParam = tps.get(i); // List<Type> sts = // stTypeParam.getSatisfiedTypes(); // if (!sts.isEmpty()) { // IntersectionType it = // new IntersectionType( // rootNode.getUnit()); // it.setSatisfiedTypes(sts); // addChangeTypeProposals(proposals, // problem, project, node, // it.canonicalize().getType(), // dec, true); // } // } // } // } // } // } // // @Deprecated // static void addChangeTypeProposals( // Tree.CompilationUnit rootNode, Node node, // ProblemLocation problem, // Collection<ICompletionProposal> proposals, // IProject project) { // if (node instanceof Tree.SpecifierExpression) { // Tree.SpecifierExpression se = // (Tree.SpecifierExpression) node; // Tree.Expression e = se.getExpression(); // if (e!=null) { // node = e.getTerm(); // } // } // if (node instanceof Tree.Expression) { // Tree.Expression e = (Tree.Expression) node; // node = e.getTerm(); // } // if (node instanceof Tree.Term) { // Tree.Term term = (Tree.Term) node; // Type t = term.getTypeModel(); // if (t==null) return; // Type type = node.getUnit().denotableType(t); // FindInvocationVisitor fav = // new FindInvocationVisitor(node); // fav.visit(rootNode); // TypedDeclaration td = fav.parameter; // if (td!=null) { // if (node instanceof Tree.InvocationExpression) { // Tree.InvocationExpression ie = // (Tree.InvocationExpression) node; // node = ie.getPrimary(); // } // if (node instanceof Tree.BaseMemberExpression) { // Tree.BaseMemberExpression bme = // (Tree.BaseMemberExpression) node; // TypedDeclaration d = (TypedDeclaration) // bme.getDeclaration(); // addChangeTypeProposals(proposals, // problem, project, node, // td.getType(), d, true); // } // if (node instanceof Tree.QualifiedMemberExpression) { // Tree.QualifiedMemberExpression qme = // (Tree.QualifiedMemberExpression) node; // TypedDeclaration d = (TypedDeclaration) // qme.getDeclaration(); // addChangeTypeProposals(proposals, // problem, project, node, // td.getType(), d, true); // } // addChangeTypeProposals(proposals, // problem, project, node, // type, td, false); // } // } // } // // @Deprecated // private static void addChangeTypeProposals( // Collection<ICompletionProposal> proposals, // ProblemLocation problem, IProject project, // Node node, Type type, // Declaration dec, boolean intersect) { // if (dec!=null) { // Unit u = dec.getUnit(); // if (u instanceof ModifiableSourceFile) { // ModifiableSourceFile msf = // (ModifiableSourceFile) u; // ModifiablePhasedUnit<IProject,IResource,IFolder,IFile> phasedUnit = // msf.getPhasedUnit(); // Type t = null; // Node typeNode = null; // // if (dec instanceof TypeParameter) { // TypeParameter tp = // (TypeParameter) dec; // t = tp.getType(); // typeNode = node; // } // // if (dec instanceof TypedDeclaration) { // TypedDeclaration typedDec = // (TypedDeclaration) dec; // FindDeclarationNodeVisitor fdv = // new FindDeclarationNodeVisitor( // typedDec); // phasedUnit.getCompilationUnit() // .visit(fdv); // Tree.StatementOrArgument dn = // fdv.getDeclarationNode(); // if (dn instanceof Tree.TypedDeclaration) { // Tree.TypedDeclaration decNode = // (Tree.TypedDeclaration) dn; // if (decNode!=null) { // typeNode = decNode.getType(); // if (typeNode!=null) { // Tree.Type tn = // (Tree.Type) // typeNode; // t = tn.getTypeModel(); // } // } // } // } // // //TODO: fix this condition to properly // // distinguish between a method // // reference and an invocation // Unit nu = node.getUnit(); // if (dec instanceof Function && // nu.isCallableType(type)) { // type = nu.getCallableReturnType(type); // } // // IFile file = phasedUnit.getResourceFile(); // if (typeNode != null // && file != null // && !isTypeUnknown(type)) { // Tree.CompilationUnit rootNode = // phasedUnit.getCompilationUnit(); // addChangeTypeProposal(typeNode, // problem, proposals, dec, // type, file, rootNode); // if (t != null) { // Type newType = intersect ? // intersectionType(t, type, u) : // unionType(t, type, u); // if (!newType.isExactly(t) && // !newType.isExactly(type)) { // addChangeTypeProposal(typeNode, // problem, proposals, // dec, newType, file, // rootNode); // } // } // } // } // } // } // }