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