]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-after/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/CastCorrectionProposal.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / ui / org / eclipse / jdt / internal / ui / text / correction / proposals / CastCorrectionProposal.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2000, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Benjamin Muskalla <bmuskalla@eclipsesource.com> - [quick fix] proposes wrong cast from Object to primitive int - https://bugs.eclipse.org/bugs/show_bug.cgi?id=100593
11 *******************************************************************************/
12
13package org.eclipse.jdt.internal.ui.text.correction.proposals;
14
15import org.eclipse.core.runtime.CoreException;
16
17import org.eclipse.jdt.core.ICompilationUnit;
18import org.eclipse.jdt.core.dom.AST;
19import org.eclipse.jdt.core.dom.ASTNode;
20import org.eclipse.jdt.core.dom.CastExpression;
21import org.eclipse.jdt.core.dom.CompilationUnit;
22import org.eclipse.jdt.core.dom.Expression;
23import org.eclipse.jdt.core.dom.FieldAccess;
24import org.eclipse.jdt.core.dom.IBinding;
25import org.eclipse.jdt.core.dom.ITypeBinding;
26import org.eclipse.jdt.core.dom.MethodInvocation;
27import org.eclipse.jdt.core.dom.ParenthesizedExpression;
28import org.eclipse.jdt.core.dom.QualifiedName;
29import org.eclipse.jdt.core.dom.Type;
30import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
31import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
32import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
33
34import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
35
36import org.eclipse.jdt.internal.ui.JavaPluginImages;
37import org.eclipse.jdt.internal.ui.text.correction.ASTResolving;
38
39public class CastCorrectionProposal extends LinkedCorrectionProposal {
40
41 public static final String ADD_CAST_ID= "org.eclipse.jdt.ui.correction.addCast"; //$NON-NLS-1$
42
43 private final Expression fNodeToCast;
44 private final ITypeBinding fCastType;
45
46 /**
47 * Creates a cast correction proposal.
48 *
49 * @param label the display name of the proposal
50 * @param targetCU the compilation unit that is modified
51 * @param nodeToCast the node to cast
52 * @param castType the type to cast to, may be <code>null</code>
53 * @param relevance the relevance of this proposal
54 */
55 public CastCorrectionProposal(String label, ICompilationUnit targetCU, Expression nodeToCast, ITypeBinding castType, int relevance) {
56 super(label, targetCU, null, relevance, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CAST));
57 fNodeToCast= nodeToCast;
58 fCastType= castType;
59 setCommandId(ADD_CAST_ID);
60 }
61
62 private Type getNewCastTypeNode(ASTRewrite rewrite, ImportRewrite importRewrite) {
63 AST ast= rewrite.getAST();
64
65 ImportRewriteContext context= new ContextSensitiveImportRewriteContext((CompilationUnit) fNodeToCast.getRoot(), fNodeToCast.getStartPosition(), importRewrite);
66
67 if (fCastType != null) {
68 return importRewrite.addImport(fCastType, ast,context);
69 }
70
71 ASTNode node= fNodeToCast;
72 ASTNode parent= node.getParent();
73 if (parent instanceof CastExpression) {
74 node= parent;
75 parent= parent.getParent();
76 }
77 while (parent instanceof ParenthesizedExpression) {
78 node= parent;
79 parent= parent.getParent();
80 }
81 if (parent instanceof MethodInvocation) {
82 MethodInvocation invocation= (MethodInvocation) node.getParent();
83 if (invocation.getExpression() == node) {
84 IBinding targetContext= ASTResolving.getParentMethodOrTypeBinding(node);
85 ITypeBinding[] bindings= ASTResolving.getQualifierGuess(node.getRoot(), invocation.getName().getIdentifier(), invocation.arguments(), targetContext);
86 if (bindings.length > 0) {
87 ITypeBinding first= getCastFavorite(bindings, fNodeToCast.resolveTypeBinding());
88
89 Type newTypeNode= importRewrite.addImport(first, ast, context);
90 addLinkedPosition(rewrite.track(newTypeNode), true, "casttype"); //$NON-NLS-1$
91 for (int i= 0; i < bindings.length; i++) {
92 addLinkedPositionProposal("casttype", bindings[i]); //$NON-NLS-1$
93 }
94 return newTypeNode;
95 }
96 }
97 }
98 Type newCastType= ast.newSimpleType(ast.newSimpleName("Object")); //$NON-NLS-1$
99 addLinkedPosition(rewrite.track(newCastType), true, "casttype"); //$NON-NLS-1$
100 return newCastType;
101 }
102
103 private ITypeBinding getCastFavorite(ITypeBinding[] suggestedCasts, ITypeBinding nodeToCastBinding) {
104 if (nodeToCastBinding == null) {
105 return suggestedCasts[0];
106 }
107 ITypeBinding favourite= suggestedCasts[0];
108 for (int i = 0; i < suggestedCasts.length; i++) {
109 ITypeBinding curr= suggestedCasts[i];
110 if (nodeToCastBinding.isCastCompatible(curr)) {
111 return curr;
112 }
113 if (curr.isInterface()) {
114 favourite= curr;
115 }
116 }
117 return favourite;
118 }
119
120
121 @Override
122 protected ASTRewrite getRewrite() throws CoreException {
123 AST ast= fNodeToCast.getAST();
124 ASTRewrite rewrite= ASTRewrite.create(ast);
125 ImportRewrite importRewrite= createImportRewrite((CompilationUnit) fNodeToCast.getRoot());
126
127 Type newTypeNode= getNewCastTypeNode(rewrite, importRewrite);
128
129 if (fNodeToCast.getNodeType() == ASTNode.CAST_EXPRESSION) {
130 CastExpression expression= (CastExpression) fNodeToCast;
131 rewrite.replace(expression.getType(), newTypeNode, null);
132 } else {
133 Expression expressionCopy= (Expression) rewrite.createCopyTarget(fNodeToCast);
134 if (needsInnerParantheses(fNodeToCast)) {
135 ParenthesizedExpression parenthesizedExpression= ast.newParenthesizedExpression();
136 parenthesizedExpression.setExpression(expressionCopy);
137 expressionCopy= parenthesizedExpression;
138 }
139
140 CastExpression castExpression= ast.newCastExpression();
141 castExpression.setExpression(expressionCopy);
142 castExpression.setType(newTypeNode);
143
144 ASTNode replacingNode= castExpression;
145 if (needsOuterParantheses(fNodeToCast)) {
146 ParenthesizedExpression parenthesizedExpression= ast.newParenthesizedExpression();
147 parenthesizedExpression.setExpression(castExpression);
148 replacingNode= parenthesizedExpression;
149 }
150
151 rewrite.replace(fNodeToCast, replacingNode, null);
152 }
153 return rewrite;
154 }
155
156 private static boolean needsInnerParantheses(ASTNode nodeToCast) {
157 int nodeType= nodeToCast.getNodeType();
158
159 // nodes have weaker precedence than cast
160 return nodeType == ASTNode.INFIX_EXPRESSION || nodeType == ASTNode.CONDITIONAL_EXPRESSION
161 || nodeType == ASTNode.ASSIGNMENT || nodeType == ASTNode.INSTANCEOF_EXPRESSION;
162 }
163
164 private static boolean needsOuterParantheses(ASTNode nodeToCast) {
165 ASTNode parent= nodeToCast.getParent();
166 if (parent instanceof MethodInvocation) {
167 if (((MethodInvocation)parent).getExpression() == nodeToCast) {
168 return true;
169 }
170 } else if (parent instanceof QualifiedName) {
171 if (((QualifiedName)parent).getQualifier() == nodeToCast) {
172 return true;
173 }
174 } else if (parent instanceof FieldAccess) {
175 if (((FieldAccess)parent).getExpression() == nodeToCast) {
176 return true;
177 }
178 }
179 return false;
180 }
181
182
183}