Skip to content

Commit 46044ba

Browse files
committed
Counting occurrences and test case for inner loop.
1 parent de0588c commit 46044ba

File tree

3 files changed

+63
-46
lines changed

3 files changed

+63
-46
lines changed

src/lang/java/refactoring/forloop/EnhancedForLoopRefactorer.rsc

+41-44
Original file line numberDiff line numberDiff line change
@@ -36,79 +36,76 @@ public void forLoopToFunctional(list[loc] locs, set[str] checkedExceptions) {
3636
}
3737

3838
// Losing formatting after a method is refactored.
39-
public CompilationUnit refactorEnhancedForStatements(CompilationUnit unit) {
39+
public tuple[CompilationUnit unit, int occurrences] refactorEnhancedForStatements(CompilationUnit unit) {
40+
int occurrences = 0;
4041
alreadyComputedClassFields = false;
4142
CompilationUnit refactoredUnit = visit(unit) {
4243
case (MethodDeclaration) `<MethodModifier* mds> <MethodHeader methodHeader> <MethodBody mBody>`: {
4344
MethodBody refactoredMethodBody = visit(mBody) {
44-
case MethodBody methodBody: insert refactorEnhancedForStatementsInMethodBody(unit, methodHeader, methodBody);
45+
case MethodBody methodBody: {
46+
refactored = refactorEnhancedForStatementsInMethodBody(unit, methodHeader, methodBody);
47+
occurrences += refactored.occurrences;
48+
insert refactored.body;
49+
}
4550
};
4651

4752
insert((MethodDeclaration) `<MethodModifier* mds> <MethodHeader methodHeader> <MethodBody refactoredMethodBody>`);
4853
}
4954
};
5055

51-
return refactoredUnit;
56+
return <refactoredUnit, occurrences>;
5257
}
5358

5459
// TODO What happens when two for statements are refactored inside the same method?
55-
public MethodBody refactorEnhancedForStatementsInMethodBody(CompilationUnit unit, MethodHeader methodHeader, MethodBody methodBody) {
60+
public tuple[MethodBody body, int occurrences] refactorEnhancedForStatementsInMethodBody(CompilationUnit unit, MethodHeader methodHeader, MethodBody methodBody) {
5661
set[MethodVar] availableVars = {};
5762
alreadyComputedCurrentMethodAvailableVars = false;
63+
occurrences = 0;
64+
5865
MethodBody refactoredMethodBody = methodBody;
5966

6067
top-down visit(methodBody) {
61-
case EnhancedForStatement forStmt: {
62-
if(PRINT_DEBUG) {
63-
println("for");
64-
println(forStmt);
65-
println();
66-
}
67-
68-
if(!alreadyComputedClassFields) {
69-
currentClassFields = findClassFields(unit);
70-
alreadyComputedClassFields = true;
71-
}
72-
73-
if(!alreadyComputedCurrentMethodAvailableVars) {
74-
methodVars = findLocalVariables(methodHeader, methodBody);
75-
availableVars = retainLocalVariablesIfDuplicates(currentClassFields, methodVars);
76-
alreadyComputedAvailableVars = true;
77-
}
68+
case EnhancedForStatement enhancedForStmt:
69+
visit(enhancedForStmt) {
7870

79-
top-down visit(forStmt) {
80-
case EnhancedForStatement enhancedForStmt: {
81-
visit(enhancedForStmt) {
82-
case (EnhancedForStatement) `for ( <VariableModifier* _> <UnannType _> <VariableDeclaratorId iteratedVarName>: <Expression collectionId> ) <Statement loopBody>`: {
83-
84-
if(isLoopRefactorable(availableVars, collectionId, loopBody)) {
85-
86-
try {
87-
refactoredMethodBody = refactorEnhancedToFunctional(availableVars, enhancedForStmt, methodBody, iteratedVarName, collectionId);
88-
refactoredCount += 1;
71+
case (EnhancedForStatement) `for ( <VariableModifier* _> <UnannType _> <VariableDeclaratorId iteratedVarName>: <Expression collectionId> ) <Statement loopBody>`: {
72+
73+
if(!alreadyComputedClassFields) {
74+
currentClassFields = findClassFields(unit);
75+
alreadyComputedClassFields = true;
76+
}
77+
78+
if(!alreadyComputedCurrentMethodAvailableVars) {
79+
methodVars = findLocalVariables(methodHeader, methodBody);
80+
availableVars = retainLocalVariablesIfDuplicates(currentClassFields, methodVars);
81+
alreadyComputedAvailableVars = true;
82+
}
8983

90-
if(PRINT_DEBUG) {
91-
println("refactored: " + toString(refactoredCount));
92-
println(enhancedForStmt);
93-
println("---");
94-
println(refactoredMethodBody);
95-
println();
96-
}
97-
} catch:
98-
continue;
99-
84+
if(isLoopRefactorable(availableVars, collectionId, loopBody)) {
85+
86+
try {
87+
refactoredMethodBody = refactorEnhancedToFunctional(availableVars, enhancedForStmt, methodBody, iteratedVarName, collectionId);
88+
occurrences += 1;
89+
90+
if(PRINT_DEBUG) {
91+
println("refactored: " + toString(occurrences));
92+
println(enhancedForStmt);
93+
println("---");
94+
println(refactoredMethodBody);
95+
println();
10096
}
101-
}
97+
} catch:
98+
continue;
10299
}
103100
}
101+
104102
}
105-
}
106103

107104
case (EnhancedForStatementNoShortIf) `for ( <VariableModifier* _> <UnannType _> <VariableDeclaratorId _> : <Expression _> ) <StatementNoShortIf stmt>`:
108105
println("TODO");
109106
}
110107

111-
return refactoredMethodBody;
108+
return <refactoredMethodBody, occurrences>;
112109
}
113110

114111
private bool isLoopRefactorable(set[MethodVar] availableVariables, Expression collectionId, Statement loopBody) {
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
module lang::java::refactoring::forloop::\test::EnhancedForLoopRefactorerTest
22

3+
import IO;
34
import lang::java::refactoring::forloop::EnhancedForLoopRefactorer;
45
import lang::java::refactoring::forloop::\test::resources::RefactorerTestResources;
56

6-
// comparing an entire file is not that practical
7+
// comparing an entire file is not that practical
78
// comparing methods then
89
// but definitely should automate test for entire compilation unit
910
public test bool shouldRefactorInnerLoopButNoutOuterLoop() {
1011
refactorable = innerLoopButNotOuterLoop();
1112

1213
refactored = refactorEnhancedForStatementsInMethodBody(refactorable.unit, refactorable.header, refactorable.body);
1314

14-
return refactored == refactorable.refactored;
15+
return refactored.body == refactorable.refactored &&
16+
refactored.occurrences == 1;
1517
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module lang::java::refactoring::forloop::\test::resources::RefactorerTestResources
2+
3+
import IO;
4+
import ParseTree;
5+
import lang::java::\syntax::Java18;
6+
7+
public data RefactorableFor = refactorableFor(CompilationUnit unit, MethodHeader header, MethodBody body, MethodBody refactored);
8+
9+
public RefactorableFor innerLoopButNotOuterLoop() {
10+
classLoc = |project://rascal-Java8//testes/forloop/Refactorer/ServletComponentRegisteringPostProcessor.java|;
11+
unit = parse(#CompilationUnit, readFile(classLoc));
12+
header = parse(#MethodHeader, "void scanPackage(\r\n\t\t\tClassPathScanningCandidateComponentProvider componentProvider,\r\n\t\t\tString packageToScan)");
13+
body = parse(#MethodBody, "{\r\n\t\tfor (BeanDefinition candidate : componentProvider\r\n\t\t\t\t.findCandidateComponents(packageToScan)) {\r\n\t\t\tif (candidate instanceof ScannedGenericBeanDefinition) {\r\n\t\t\t\tfor (ServletComponentHandler handler : HANDLERS) {\r\n\t\t\t\t\thandler.handle(((ScannedGenericBeanDefinition) candidate),\r\n\t\t\t\t\t\t\t(BeanDefinitionRegistry) this.applicationContext);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}");
14+
15+
refactored = parse(#MethodBody, "{\r\n\t\tfor (BeanDefinition candidate : componentProvider\r\n\t\t\t\t.findCandidateComponents(packageToScan)) {\r\n\t\t\tif (candidate instanceof ScannedGenericBeanDefinition) {\r\n\t\t\t\tHANDLERS.forEach(handler -\> {\nhandler.handle(((ScannedGenericBeanDefinition) candidate),\r\n\t\t\t\t\t\t\t(BeanDefinitionRegistry) this.applicationContext);\n});\r\n\t\t\t}\r\n\t\t}\r\n\t}");
16+
17+
return refactorableFor(unit, header, body, refactored);
18+
}

0 commit comments

Comments
 (0)