Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2010 Zeeshan Ansari, Mark Chen, Burim Isai, Waseem Sheikh, Mumtaz Vauhkonen |
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 |
* UIUC - Initial API and implementation |
10 |
* Zeeshan Ansari |
11 |
* Mark Chen |
12 |
* Mumtaz Vauhkonen |
13 |
* Burim Isai |
14 |
* Waseem Sheikh |
15 |
*******************************************************************************/ |
16 |
package org.eclipse.photran.internal.core.refactoring; |
17 |
|
18 |
import java.util.ArrayList; |
19 |
import org.eclipse.core.runtime.CoreException; |
20 |
import org.eclipse.core.runtime.IProgressMonitor; |
21 |
import org.eclipse.core.runtime.OperationCanceledException; |
22 |
import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
23 |
import org.eclipse.photran.internal.core.parser.ASTIfConstructNode; |
24 |
import org.eclipse.photran.internal.core.parser.ASTIfStmtNode; |
25 |
import org.eclipse.photran.internal.core.parser.ASTNode; |
26 |
import org.eclipse.photran.internal.core.refactoring.infrastructure.FortranEditorRefactoring; |
27 |
import org.eclipse.photran.internal.core.reindenter.Reindenter; |
28 |
import org.eclipse.photran.internal.core.reindenter.Reindenter.Strategy; |
29 |
|
30 |
/** |
31 |
* Converts an IF construct to an IF statement and vice versa. User must select |
32 |
* the entire IF statement or IF construct block, and select the refactoring |
33 |
* option in the menu. |
34 |
* |
35 |
* @author Zeeshan Ansari |
36 |
* @author Mark Chen |
37 |
* @author Mumtaz Vauhkonen |
38 |
* @author Burim Isai |
39 |
* @author Waseem Sheikh |
40 |
*/ |
41 |
public class IfConstructStatementConversionRefactoring extends FortranEditorRefactoring |
42 |
{ |
43 |
private ASTNode selectedNode = null; |
44 |
private ASTNode ifStmtNode, ifConstructNode; |
45 |
private boolean shouldAddEmptyElseBlock = false; |
46 |
private ArrayList<String> commentList = new ArrayList<String>(); |
47 |
|
48 |
/** |
49 |
* Beyond the standard condition checks, this checks to ensure that a valid |
50 |
* IF statement or IF construct is selected and is refactorable. |
51 |
* |
52 |
* @param ifConstructNode |
53 |
* @throws PreconditionFailure |
54 |
* @author Zeeshan Ansari |
55 |
* @author Mark Chen |
56 |
* @author Burim Isai |
57 |
* @author Waseem Sheikh |
58 |
*/ |
59 |
@Override |
60 |
protected void doCheckInitialConditions(RefactoringStatus status, IProgressMonitor pm) |
61 |
throws PreconditionFailure |
62 |
{ |
63 |
ensureProjectHasRefactoringEnabled(status); |
64 |
|
65 |
if(!fileInEditor.exists()) |
66 |
fail(Messages.FortranEditorRefactoring_CantPerformRefactoringOnFileThatDoesNotExist); |
67 |
|
68 |
if(fileInEditor.isReadOnly()) |
69 |
fail(Messages.FortranEditorRefactoring_CantPerformRefactoringOnReadOnlyFile); |
70 |
|
71 |
ifStmtNode = getNode(this.astOfFileInEditor, this.selectedRegionInEditor, ASTIfStmtNode.class); |
72 |
ifConstructNode = getNode(this.astOfFileInEditor, this.selectedRegionInEditor, ASTIfConstructNode.class); |
73 |
|
74 |
if(ifStmtNode != null) |
75 |
selectedNode = ifStmtNode; |
76 |
else if(ifConstructNode != null) { |
77 |
checkRefactorableConstruct(ifConstructNode); |
78 |
selectedNode = ifConstructNode; |
79 |
} |
80 |
else |
81 |
fail(Messages.IfConstructStatementConversionRefactoring_SelectAValidIfStatement); |
82 |
} |
83 |
|
84 |
/** |
85 |
* Checks various conditions to see if the user-selected IF construct is refactorable to an |
86 |
* IF statement. This includes making sure there is only one valid statement line in the |
87 |
* construct and that the construct is not named. |
88 |
* |
89 |
* @param ifConstructNode |
90 |
* @throws PreconditionFailure |
91 |
* @author Mark Chen |
92 |
* @author Waseem Sheikh |
93 |
* @author Mumtaz Vauhkonen |
94 |
*/ |
95 |
private void checkRefactorableConstruct(ASTNode ifConstructNode) |
96 |
throws org.eclipse.rephraserengine.core.vpg.refactoring.VPGRefactoring.PreconditionFailure |
97 |
{ |
98 |
String constructParser = null; |
99 |
int validStatements = 0; |
100 |
|
101 |
//Checks for named construct |
102 |
if(!ifConstructNode.findFirstToken().getText().equals("if")) //$NON-NLS-1$ |
103 |
fail(Messages.IfConstructStatementConversionRefactoring_InvalidNamedConstruct); |
104 |
|
105 |
//Check for multiple statements within construct and stores comment lines |
106 |
constructParser = this.selectedRegionInEditor.getText(); |
107 |
constructParser = constructParser.substring(constructParser.indexOf("\n")+1).trim(); //$NON-NLS-1$ |
108 |
while(constructParser.contains("\n")) { //$NON-NLS-1$ |
109 |
constructParser = constructParser.substring(constructParser.indexOf("\n")+1).trim(); //$NON-NLS-1$ |
110 |
if(!constructParser.startsWith("!") && !constructParser.startsWith("end if")) //$NON-NLS-1$ //$NON-NLS-2$ |
111 |
++validStatements; |
112 |
if(constructParser.startsWith("!")) //$NON-NLS-1$ |
113 |
commentList.add(constructParser.substring(0, constructParser.indexOf("\n")).trim()); //$NON-NLS-1$ |
114 |
} |
115 |
if(validStatements > 1) |
116 |
fail(Messages.IfConstructStatementConversionRefactoring_TooManyStatements); |
117 |
} |
118 |
|
119 |
public boolean isStmtNode() { |
120 |
return ifStmtNode != null; |
121 |
} |
122 |
|
123 |
public void AddEmptyElseBlock() { |
124 |
shouldAddEmptyElseBlock = true; |
125 |
} |
126 |
|
127 |
@Override |
128 |
protected void doCheckFinalConditions(RefactoringStatus status, IProgressMonitor pm) |
129 |
throws PreconditionFailure |
130 |
{ |
131 |
// No final preconditions |
132 |
} |
133 |
|
134 |
/** |
135 |
* Determines whether an IF statement is selected or an IF construct is selected (done in pre-condition). |
136 |
* Depending on which, it will execute the appropriate refactoring (statement to construct or vise versa). |
137 |
* It will then reindent the entire section of refactored code based on the formating context of the code |
138 |
* around it. |
139 |
* |
140 |
* @param pm |
141 |
* @throws CoreException, OperationCanceledException |
142 |
* @author Zeeshan Ansari |
143 |
* @author Mark Chen |
144 |
* @author Mumtaz Vauhkonen |
145 |
*/ |
146 |
@Override |
147 |
protected void doCreateChange(IProgressMonitor pm) throws CoreException, |
148 |
OperationCanceledException |
149 |
{ |
150 |
if(selectedNode instanceof ASTIfStmtNode){ |
151 |
RefactorIfStmt(); |
152 |
} |
153 |
else if (selectedNode instanceof ASTIfConstructNode){ |
154 |
RefactorIfConstruct(); |
155 |
} |
156 |
else |
157 |
throw new OperationCanceledException(); |
158 |
|
159 |
Reindenter.reindent(selectedNode, this.astOfFileInEditor, Strategy.REINDENT_EACH_LINE); |
160 |
this.addChangeFromModifiedAST(this.fileInEditor, pm); |
161 |
vpg.releaseAST(this.fileInEditor); |
162 |
|
163 |
} |
164 |
|
165 |
protected void RefactorIfStmt(){ |
166 |
ASTIfStmtNode ifStmtNode = (ASTIfStmtNode)selectedNode; |
167 |
|
168 |
ifStmtNode.replaceWith(createNewIfConstruct(ifStmtNode)); |
169 |
} |
170 |
|
171 |
protected void RefactorIfConstruct(){ |
172 |
ASTIfConstructNode ifConstructNode = (ASTIfConstructNode)selectedNode; |
173 |
|
174 |
ifConstructNode.replaceWith(createNewIfStmt(ifConstructNode)); |
175 |
} |
176 |
|
177 |
/** |
178 |
* Creates a new IF statement from the selected IF construct |
179 |
* |
180 |
* @param ifConstructNode |
181 |
* @author Mark Chen |
182 |
* @author Waseem Sheikh |
183 |
* @author Mumtaz Vauhkonen |
184 |
*/ |
185 |
private ASTIfStmtNode createNewIfStmt(ASTIfConstructNode ifConstructNode) { |
186 |
StringBuilder sb = new StringBuilder(); |
187 |
|
188 |
sb.append(" if ("); //$NON-NLS-1$ |
189 |
sb.append(ifConstructNode.getIfThenStmt().getGuardingExpression().toString().trim()); |
190 |
sb.append(") "); //$NON-NLS-1$ |
191 |
sb.append(ifConstructNode.getConditionalBody().toString().trim()); |
192 |
for(String comment : commentList) |
193 |
sb.append(" " + comment); //$NON-NLS-1$ |
194 |
sb.append("\n"); //$NON-NLS-1$ |
195 |
|
196 |
ASTIfStmtNode newIfStmtNode = (ASTIfStmtNode)parseLiteralIfStmtNode(sb.toString()); |
197 |
|
198 |
return newIfStmtNode; |
199 |
} |
200 |
|
201 |
/** |
202 |
* Creates a new IF construct from the selected IF statement, with an option |
203 |
* to add an empty ELSE construct |
204 |
* |
205 |
* @param ifConstructNode |
206 |
* @author Zeeshan Ansari |
207 |
* @author Mark Chen |
208 |
* @author Burim Isai |
209 |
* @author Mumtaz Vauhkonen |
210 |
*/ |
211 |
private ASTIfConstructNode createNewIfConstruct(ASTIfStmtNode ifStmtNode){ |
212 |
StringBuilder sb = new StringBuilder(); |
213 |
|
214 |
sb.append(" if ("); //$NON-NLS-1$ |
215 |
sb.append(ifStmtNode.getGuardingExpression().toString()); |
216 |
sb.append(") then"); //$NON-NLS-1$ |
217 |
sb.append("\n "); //$NON-NLS-1$ |
218 |
sb.append(ifStmtNode.getActionStmt().toString().trim()); |
219 |
sb.append("\n !can add more statements here"); //$NON-NLS-1$ |
220 |
if(shouldAddEmptyElseBlock) |
221 |
{ |
222 |
sb.append("\n else"); //$NON-NLS-1$ |
223 |
sb.append("\n !can add more statements here"); //$NON-NLS-1$ |
224 |
} |
225 |
sb.append("\n end if"); //$NON-NLS-1$ |
226 |
|
227 |
ASTIfConstructNode newIfConstructNode = (ASTIfConstructNode)parseLiteralIfConstructNode(sb.toString()); |
228 |
|
229 |
return newIfConstructNode; |
230 |
} |
231 |
|
232 |
@Override |
233 |
public String getName() |
234 |
{ |
235 |
return Messages.IfConstructStatementConversionRefactoring_Name; |
236 |
} |
237 |
} |