Skip to content

Commit 20c9af0

Browse files
author
hujian06
committed
using executeService to do the format job
1 parent a4c7d39 commit 20c9af0

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed

core/src/main/java/com/google/googlejavaformat/java/Formatter.java

+153
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616

1717
import static java.nio.charset.StandardCharsets.UTF_8;
1818

19+
import com.google.common.base.Strings;
1920
import com.google.common.collect.ImmutableList;
2021
import com.google.common.collect.Iterables;
2122
import com.google.common.collect.Iterators;
23+
import com.google.common.collect.Lists;
2224
import com.google.common.collect.Range;
2325
import com.google.common.collect.RangeSet;
2426
import com.google.common.collect.TreeRangeSet;
@@ -31,12 +33,28 @@
3133
import com.google.googlejavaformat.Newlines;
3234
import com.google.googlejavaformat.Op;
3335
import com.google.googlejavaformat.OpsBuilder;
36+
37+
import java.io.File;
3438
import java.io.IOError;
3539
import java.io.IOException;
3640
import java.net.URI;
41+
import java.nio.file.Files;
42+
import java.nio.file.Path;
43+
import java.nio.file.Paths;
3744
import java.util.ArrayList;
3845
import java.util.Collection;
46+
import java.util.Collections;
3947
import java.util.List;
48+
import java.util.concurrent.CompletableFuture;
49+
import java.util.concurrent.ExecutionException;
50+
import java.util.concurrent.ExecutorService;
51+
import java.util.concurrent.Future;
52+
import java.util.concurrent.LinkedBlockingQueue;
53+
import java.util.concurrent.ThreadPoolExecutor;
54+
import java.util.concurrent.TimeUnit;
55+
import java.util.concurrent.TimeoutException;
56+
import java.util.stream.Collectors;
57+
4058
import org.openjdk.javax.tools.Diagnostic;
4159
import org.openjdk.javax.tools.DiagnosticCollector;
4260
import org.openjdk.javax.tools.DiagnosticListener;
@@ -86,6 +104,13 @@
86104
*/
87105
@Immutable
88106
public final class Formatter {
107+
static final ExecutorService EXECUTOR_SERVICE = new ThreadPoolExecutor(
108+
Runtime.getRuntime().availableProcessors(),
109+
Math.min(Runtime.getRuntime().availableProcessors() * 2, 50),
110+
60,
111+
TimeUnit.SECONDS,
112+
new LinkedBlockingQueue<>()
113+
);
89114

90115
static final Range<Integer> EMPTY_RANGE = Range.closedOpen(-1, -1);
91116

@@ -189,6 +214,134 @@ public void formatSource(CharSource input, CharSink output)
189214
output.write(formatSource(input.read()));
190215
}
191216

217+
/**
218+
* Format an input file (or dir), this method will judge the input {@code file}, if it is
219+
* A directory, then this method will scan the directory to find all of the java source files.
220+
* Then format every java file. if the {@code useExecutor} is true, then this method will use
221+
* The ExecuteService {@link Formatter#EXECUTOR_SERVICE} to submit a {@link FormatFileCallable}.
222+
* You should check the result list's element. if the element is empty, you should do not overwrite
223+
* it to source file path.
224+
*
225+
* @param file the input
226+
* @param useExecutor whether multi-thread mode
227+
* @return the formatted java source
228+
*/
229+
public List<String> formatSourceFile(String file, boolean useExecutor)
230+
throws IOException, FormatterException {
231+
if (Strings.isNullOrEmpty(file)) {
232+
return Collections.emptyList();
233+
}
234+
File sourceFile = new File(file);
235+
if (sourceFile.isFile()) {
236+
// this is a file
237+
if (useExecutor) {
238+
CompletableFuture<List<String>> formattedFuture = CompletableFuture.supplyAsync(()->{
239+
Path path = Paths.get(file);
240+
String formatted;
241+
try {
242+
formatted = formatSource(new String(Files.readAllBytes(path), UTF_8));
243+
} catch (FormatterException | IOException e) {
244+
formatted = "";
245+
}
246+
return ImmutableList.of(formatted); // do not update the file source.
247+
}, EXECUTOR_SERVICE);
248+
try {
249+
if (formattedFuture.get(1, TimeUnit.SECONDS) == null) {
250+
return Collections.emptyList();
251+
} else {
252+
return formattedFuture.getNow(Collections.emptyList());
253+
}
254+
} catch (InterruptedException | ExecutionException | TimeoutException e) {
255+
return Collections.emptyList();
256+
}
257+
} else {
258+
Path path = Paths.get(file);
259+
String formatted = formatSource(new String(Files.readAllBytes(path), UTF_8));
260+
return ImmutableList.of(formatted); // do not update the file source.
261+
}
262+
} else if (sourceFile.isDirectory()) {
263+
// this is a directory
264+
List<String> filePathLit = Lists.newArrayList();
265+
scanDirectory(file, filePathLit);
266+
if (filePathLit.isEmpty()) {
267+
return Collections.emptyList();
268+
}
269+
if (useExecutor) {
270+
List<CompletableFuture<String>> formattedFutureList = Lists.newArrayList();
271+
for (String p : filePathLit) {
272+
formattedFutureList.add(CompletableFuture.supplyAsync(() -> {
273+
Path path = Paths.get(p);
274+
String formatted;
275+
try {
276+
formatted = formatSource(new String(Files.readAllBytes(path), UTF_8));
277+
} catch (FormatterException | IOException e) {
278+
formatted = "";
279+
}
280+
return formatted;
281+
}, EXECUTOR_SERVICE));
282+
}
283+
// check the status.
284+
CompletableFuture<List<String>> formattedResultFuture =
285+
CompletableFuture
286+
.allOf(formattedFutureList.toArray(new CompletableFuture[formattedFutureList.size()]))
287+
.thenApply(formattedFuture -> formattedFutureList
288+
.stream()
289+
.map(CompletableFuture::join)
290+
.collect(Collectors.toList()));
291+
try {
292+
if (formattedResultFuture.get(formattedFutureList.size(), TimeUnit.SECONDS) == null) {
293+
return Collections.emptyList();
294+
} else {
295+
return formattedResultFuture.getNow(Collections.emptyList());
296+
}
297+
} catch (InterruptedException | ExecutionException | TimeoutException e) {
298+
return Collections.emptyList();
299+
}
300+
} else {
301+
List<String> formattedList = Lists.newArrayList();
302+
for (String p : filePathLit) {
303+
Path path = Paths.get(p);
304+
String formatted = formatSource(new String(Files.readAllBytes(path), UTF_8));
305+
formattedList.add(formatted);
306+
}
307+
return formattedList;
308+
}
309+
} else {
310+
// doNothing.
311+
return Collections.emptyList();
312+
}
313+
}
314+
315+
/**
316+
* Scan the directory {@code directory} to find all of the java files.
317+
*
318+
* @param directory the scan directory
319+
* @param filePathList the result.
320+
*/
321+
private void scanDirectory(String directory, List<String> filePathList) {
322+
if (Strings.isNullOrEmpty(directory)) {
323+
return;
324+
}
325+
File sourceFile = new File(directory);
326+
if (sourceFile.isFile()) {
327+
// this is a file
328+
filePathList.add(directory);
329+
return;
330+
}
331+
// this is a directory.
332+
File[] fileList = sourceFile.listFiles();
333+
if (fileList == null) {
334+
return; // no file
335+
}
336+
for (File file : fileList) {
337+
if (file.isFile()) {
338+
filePathList.add(file.getAbsolutePath());
339+
} else if (file.isDirectory()) {
340+
scanDirectory(directory, filePathList);
341+
}
342+
}
343+
}
344+
192345
/**
193346
* Format an input string (a Java compilation unit) into an output string.
194347
*

0 commit comments

Comments
 (0)