1+ /*
2+ * Copyright 2020 the original author or authors.
3+ * <p>
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ * <p>
8+ * https://www.apache.org/licenses/LICENSE-2.0
9+ * <p>
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
116package org .openrewrite .java .testing .junit5 ;
217
18+ import org .openrewrite .AutoConfigure ;
319import org .openrewrite .Formatting ;
4- import org .openrewrite .Incubating ;
520import org .openrewrite .java .AutoFormat ;
621import org .openrewrite .java .JavaIsoRefactorVisitor ;
22+ import org .openrewrite .java .JavaRefactorVisitor ;
723import org .openrewrite .java .tree .Expression ;
824import org .openrewrite .java .tree .J ;
925import org .openrewrite .java .tree .JavaType ;
2036/**
2137 * Translates JUnit4's org.junit.rules.TemporaryFolder into JUnit 5's org.junit.jupiter.api.io.TempDir
2238 */
23- @ Incubating (since = "0.1.2" )
24- // Keeping this commented out until this class is finished
25- //@AutoConfigure
39+ @ AutoConfigure
2640public class TemporaryFolderToTempDir extends JavaIsoRefactorVisitor {
2741
2842 private static final String RuleFqn = "org.junit.Rule" ;
@@ -31,6 +45,8 @@ public class TemporaryFolderToTempDir extends JavaIsoRefactorVisitor {
3145 private static final J .Ident TempDirIdent = J .Ident .build (randomId (), "TempDir" , TempDirType , Formatting .EMPTY );
3246 private static final JavaType .Class FileType = JavaType .Class .build ("java.io.File" );
3347 private static final J .Ident FileIdent = J .Ident .build (randomId (), "File" , FileType , Formatting .EMPTY );
48+ private static final JavaType .Class PathType = JavaType .Class .build ("java.nio.file.Path" );
49+ private static final JavaType .Class FilesType = JavaType .Class .build ("java.nio.file.Files" );
3450 private static final String IOExceptionFqn = "java.io.IOException" ;
3551 private static final JavaType .Class IOExceptionType = JavaType .Class .build (IOExceptionFqn );
3652 private static final JavaType .Class StringType = JavaType .Class .build ("java.lang.String" );
@@ -109,28 +125,25 @@ private J convertTempFolderField(J statement) {
109125 }
110126
111127 /**
112- * This visitor replaces these methods from TemporaryFolder with a JUnit5-compatible alternative :
128+ * This visitor replaces these methods from TemporaryFolder with JUnit5-compatible alternatives :
113129 *
130+ * File getRoot()
114131 * File newFile()
115132 * File newFile(String fileName)
116- *
117- * When complete it will also replace these TemporaryFolder methods:
118- * File getRoot()
119133 * File newFolder()
120134 * File newFolder(String... folderNames)
121135 * File newFolder(String folder)
122- *
123136 */
124- private static class ReplaceTemporaryFolderMethods extends JavaIsoRefactorVisitor {
137+ private static class ReplaceTemporaryFolderMethods extends JavaRefactorVisitor {
125138 private final String fieldName ;
126139 ReplaceTemporaryFolderMethods (String fieldName ) {
127140 this .fieldName = fieldName ;
128141 setCursoringOn ();
129142 }
130143
131144 @ Override
132- public J . MethodInvocation visitMethodInvocation (J .MethodInvocation method ) {
133- J .MethodInvocation m = super . visitMethodInvocation (method );
145+ public J visitMethodInvocation (J .MethodInvocation method ) {
146+ J .MethodInvocation m = refactor (method , super :: visitMethodInvocation );
134147 if (!(m .getSelect () instanceof J .Ident )) {
135148 return m ;
136149 }
@@ -142,32 +155,62 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) {
142155 assert getCursor ().getParent () != null ;
143156 List <Expression > args = m .getArgs ().getArgs ();
144157 // handle TemporaryFolder.newFile() and TemporaryFolder.newFile(String)
145- if (m .getName ().getSimpleName ().equals ("newFile" )) {
146- if (args .size () == 1 && args .get (0 ) instanceof J .Empty ) {
147- m = treeBuilder .buildSnippet (
148- getCursor ().getParent (),
149- "File.createTempFile(\" junit\" , null, " + fieldName + ");" ,
150- FileType
151- ).get (0 ).withFormatting (Formatting .format (" " ));
152- } else {
153- andThen (new AddNewFileFunction ());
154- m = treeBuilder .buildSnippet (
155- getCursor ().getParent (),
156- "newFile(" + fieldName + ", " + args .get (0 ).printTrimmed () +")" ,
157- FileType , args .get (0 ).getType ()
158- ).get (0 ).withFormatting (Formatting .format (" " ));
159- }
158+ switch (m .getName ().getSimpleName ()) {
159+ case "newFile" :
160+ if (args .size () == 1 && args .get (0 ) instanceof J .Empty ) {
161+ m = treeBuilder .buildSnippet (
162+ getCursor ().getParent (),
163+ "File.createTempFile(\" junit\" , null, " + fieldName + ");" ,
164+ FileType
165+ ).get (0 ).withFormatting (Formatting .format (" " ));
166+ } else {
167+ andThen (new AddNewFileFunction ());
168+ m = treeBuilder .buildSnippet (
169+ getCursor ().getParent (),
170+ "newFile(" + fieldName + ", " + args .get (0 ).printTrimmed () + ");" ,
171+ FileType , args .get (0 ).getType ()
172+ ).get (0 ).withFormatting (Formatting .format (" " ));
173+ }
174+ break ;
175+ case "getRoot" :
176+ return J .Ident .build (randomId (), fieldName , FileType , m .getFormatting ());
177+ case "newFolder" :
178+ if (args .size () == 1 && args .get (0 ) instanceof J .Empty ) {
179+ m = treeBuilder .buildSnippet (
180+ getCursor ().getParent (),
181+ "Files.createTempDirectory(" + fieldName + ".toPath(), \" junit\" ).toFile();" ,
182+ FileType , FilesType , PathType
183+ ).get (0 ).withFormatting (Formatting .format (" " ));
184+ maybeAddImport (FilesType );
185+ } else {
186+ andThen (new AddNewFolderFunction ());
187+ String argsString = printArgs (m .getArgs ().getArgs ());
188+ m = treeBuilder .buildSnippet (
189+ getCursor ().getParent (),
190+ "newFolder(" + fieldName + ", " + argsString + ");" ,
191+ FileType
192+ ).get (0 ).withFormatting (Formatting .format (" " ));
193+ }
194+ break ;
160195 }
161196
162197 }
163198 return m ;
164199 }
200+
201+ /**
202+ * As of rewrite 5.5.0, J.MethodInvocation.Arguments.print() returns an empty String
203+ * Roll our own good-enough print() method here
204+ */
205+ private static String printArgs (List <Expression > args ) {
206+ return args .stream ().map (J ::print ).collect (Collectors .joining ("," ));
207+ }
165208 }
166209
167210 /**
168211 * Adds a method like this one to the target class:
169- * private File newFile(File dir , String fileName) throws IOException {
170- * File file = new File(getRoot() , fileName);
212+ * private File newFile(File root , String fileName) throws IOException {
213+ * File file = new File(root , fileName);
171214 * file.createNewFile();
172215 * return file;
173216 * }
@@ -176,8 +219,7 @@ public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method) {
176219 */
177220 private static class AddNewFileFunction extends JavaIsoRefactorVisitor {
178221 @ Override
179- public J .ClassDecl visitClassDecl (J .ClassDecl classDecl ) {
180- J .ClassDecl cd = super .visitClassDecl (classDecl );
222+ public J .ClassDecl visitClassDecl (J .ClassDecl cd ) {
181223 boolean methodAlreadyExists = cd .getMethods ().stream ()
182224 .filter (m -> {
183225 List <Statement > params = m .getParams ().getParams ();
@@ -192,18 +234,69 @@ public J.ClassDecl visitClassDecl(J.ClassDecl classDecl) {
192234 List <J > statements = new ArrayList <>(cd .getBody ().getStatements ());
193235 J .MethodDecl newFileMethod = treeBuilder .buildMethodDeclaration (
194236 cd ,
195- "private File newFile(File dir , String fileName) throws IOException {\n " +
196- " File file = new File(getRoot() , fileName);\n " +
237+ "private static File newFile(File root , String fileName) throws IOException {\n " +
238+ " File file = new File(root , fileName);\n " +
197239 " file.createNewFile();\n " +
198240 " return file;\n " +
199241 "}\n " ,
200242 FileType ,
201243 IOExceptionType );
202244 statements .add (newFileMethod );
245+ maybeAddImport (FileType );
246+ maybeAddImport (IOExceptionType );
203247 cd = cd .withBody (cd .getBody ().withStatements (statements ));
204248 andThen (new AutoFormat (newFileMethod ));
205249 }
206250 return cd ;
207251 }
208252 }
253+
254+ /**
255+ * Adds a method like this one to the target class:
256+ *
257+ * private static File newFolder(File root, String ... folders) throws IOException {
258+ * File result = new File(root, String.join("/", folders));
259+ * if(!result.mkdirs()) {
260+ * throw new IOException("Couldn't create folders " + root);
261+ * }
262+ * return result;
263+ * }
264+ */
265+ private static class AddNewFolderFunction extends JavaIsoRefactorVisitor {
266+ @ Override
267+ public J .ClassDecl visitClassDecl (J .ClassDecl cd ) {
268+ boolean methodAlreadyExists = cd .getMethods ().stream ()
269+ .filter (m -> {
270+ List <Statement > params = m .getParams ().getParams ();
271+
272+ return m .getSimpleName ().equals ("newFolder" )
273+ && params .size () == 2
274+ && params .get (0 ).hasClassType (FileType )
275+ && params .get (1 ).hasClassType (StringType )
276+ && params .get (1 ) instanceof J .VariableDecls
277+ && ((J .VariableDecls ) params .get (1 )).getVarargs () != null ;
278+ })
279+ .findAny ().isPresent ();
280+ if (!methodAlreadyExists ) {
281+ List <J > statements = new ArrayList <>(cd .getBody ().getStatements ());
282+ J .MethodDecl newFolderMethod = treeBuilder .buildMethodDeclaration (
283+ cd ,
284+ "private static File newFolder(File root, String ... folders) throws IOException {\n " +
285+ " File result = new File(root, String.join(\" /\" , folders));\n " +
286+ " if(!result.mkdirs()) {\n " +
287+ " throw new IOException(\" Couldn't create folders \" + root);\n " +
288+ " }\n " +
289+ " return result;\n " +
290+ "}" ,
291+ FileType ,
292+ IOExceptionType );
293+ statements .add (newFolderMethod );
294+ maybeAddImport (FileType );
295+ maybeAddImport (IOExceptionType );
296+ cd = cd .withBody (cd .getBody ().withStatements (statements ));
297+ andThen (new AutoFormat (newFolderMethod ));
298+ }
299+ return cd ;
300+ }
301+ }
209302}
0 commit comments