Skip to content

Commit 867b0e7

Browse files
committed
Prevent leaking of charset between source sets and after the last source set
1 parent 19890d3 commit 867b0e7

File tree

2 files changed

+75
-66
lines changed

2 files changed

+75
-66
lines changed

plugin/src/main/java/org/openrewrite/gradle/isolated/AndroidProjectParser.java

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import java.io.IOException;
4444
import java.io.UncheckedIOException;
4545
import java.nio.charset.Charset;
46+
import java.nio.charset.StandardCharsets;
4647
import java.nio.file.Files;
4748
import java.nio.file.Path;
4849
import java.nio.file.PathMatcher;
@@ -52,6 +53,7 @@
5253

5354
import static java.util.stream.Collectors.toList;
5455
import static java.util.stream.Collectors.toSet;
56+
import static org.openrewrite.tree.ParsingExecutionContextView.view;
5557

5658
class AndroidProjectParser {
5759
private static final Logger logger = Logging.getLogger(DefaultProjectParser.class);
@@ -70,7 +72,6 @@ class AndroidProjectParser {
7072
SourceFileStream parseProjectSourceSets(Project project,
7173
ProgressBar progressBar,
7274
Path buildDir,
73-
Charset sourceCharset,
7475
Set<Path> alreadyParsed,
7576
Collection<PathMatcher> exclusions,
7677
ExecutionContext ctx,
@@ -81,7 +82,7 @@ SourceFileStream parseProjectSourceSets(Project project,
8182

8283
for (AndroidProjectVariant variant : findAndroidProjectVariants(project)) {
8384
JavaVersion javaVersion = getJavaVersion(project);
84-
final Charset javaSourceCharset = getSourceFileEncoding(project, sourceCharset);
85+
final Charset javaSourceCharset = getSourceFileEncoding(project);
8586

8687
for (String sourceSetName : variant.getSourceSetNames()) {
8788
Stream<SourceFile> sourceSetSourceFiles = Stream.of();
@@ -155,7 +156,6 @@ SourceFileStream parseProjectSourceSets(Project project,
155156
ctx,
156157
buildDir,
157158
exclusions,
158-
javaSourceCharset,
159159
javaVersion,
160160
dependencyPaths,
161161
javaTypeCache);
@@ -253,7 +253,7 @@ private JavaVersion getJavaVersion(Project project) {
253253
targetCompatibility);
254254
}
255255

256-
Charset getSourceFileEncoding(Project project, Charset defaultCharset) {
256+
Charset getSourceFileEncoding(Project project) {
257257
Object extension = project.getExtensions().findByName("android");
258258
if (extension instanceof BaseExtension) {
259259
try {
@@ -265,7 +265,7 @@ Charset getSourceFileEncoding(Project project, Charset defaultCharset) {
265265
logger.warn("Unable to determine Java source file encoding", e);
266266
}
267267
}
268-
return defaultCharset;
268+
return StandardCharsets.UTF_8; // Android defaults to UTF-8
269269
}
270270

271271
private Stream<SourceFile> parseJavaFiles(List<Path> javaPaths,
@@ -276,43 +276,50 @@ private Stream<SourceFile> parseJavaFiles(List<Path> javaPaths,
276276
JavaVersion javaVersion,
277277
Set<Path> dependencyPaths,
278278
JavaTypeCache javaTypeCache) {
279-
ParsingExecutionContextView.view(ctx).setCharset(javaSourceCharset);
280-
281279
return Stream.of((Supplier<JavaParser>) () -> JavaParser.fromJavaVersion()
282-
.classpath(dependencyPaths)
283-
.styles(styles)
284-
.typeCache(javaTypeCache)
285-
.logCompilationWarningsAndErrors(rewriteExtension.getLogCompilationWarningsAndErrors())
286-
.build()).map(Supplier::get).flatMap(jp -> jp.parse(javaPaths, baseDir, ctx)).map(cu -> {
287-
if (DefaultProjectParser.isExcluded(repository, exclusions, cu.getSourcePath()) || cu.getSourcePath()
288-
.startsWith(buildDir)) {
289-
return null;
290-
}
291-
return cu;
292-
}).filter(Objects::nonNull).map(it -> it.withMarkers(it.getMarkers().add(javaVersion)));
280+
.classpath(dependencyPaths)
281+
.styles(styles)
282+
.typeCache(javaTypeCache)
283+
.logCompilationWarningsAndErrors(rewriteExtension.getLogCompilationWarningsAndErrors())
284+
.build())
285+
.map(Supplier::get)
286+
.flatMap(jp -> {
287+
view(ctx).setCharset(javaSourceCharset);
288+
return jp.parse(javaPaths, baseDir, ctx).onClose(() -> view(ctx).setCharset(null))
289+
})
290+
.map(cu -> {
291+
if (DefaultProjectParser.isExcluded(repository, exclusions, cu.getSourcePath()) || cu.getSourcePath()
292+
.startsWith(buildDir)) {
293+
return null;
294+
}
295+
return cu;
296+
}).filter(Objects::nonNull).map(it -> it.withMarkers(it.getMarkers().add(javaVersion)));
293297
}
294298

295299
private Stream<SourceFile> parseKotlinFiles(List<Path> kotlinPaths,
296300
ExecutionContext ctx,
297301
Path buildDir,
298302
Collection<PathMatcher> exclusions,
299-
Charset javaSourceCharset,
300303
JavaVersion javaVersion,
301304
Set<Path> dependencyPaths,
302305
JavaTypeCache javaTypeCache) {
303-
ParsingExecutionContextView.view(ctx).setCharset(javaSourceCharset);
304-
305306
return Stream.of((Supplier<KotlinParser>) () -> KotlinParser.builder()
306-
.classpath(dependencyPaths)
307-
.styles(styles)
308-
.typeCache(javaTypeCache)
309-
.logCompilationWarningsAndErrors(rewriteExtension.getLogCompilationWarningsAndErrors())
310-
.build()).map(Supplier::get).flatMap(kp -> kp.parse(kotlinPaths, baseDir, ctx)).map(cu -> {
311-
if (DefaultProjectParser.isExcluded(repository, exclusions, cu.getSourcePath()) || cu.getSourcePath()
312-
.startsWith(buildDir)) {
313-
return null;
314-
}
315-
return cu;
316-
}).filter(Objects::nonNull).map(it -> it.withMarkers(it.getMarkers().add(javaVersion)));
307+
.classpath(dependencyPaths)
308+
.styles(styles)
309+
.typeCache(javaTypeCache)
310+
.logCompilationWarningsAndErrors(rewriteExtension.getLogCompilationWarningsAndErrors())
311+
.build())
312+
.map(Supplier::get)
313+
.flatMap(kp -> {
314+
view(ctx).setCharset(StandardCharsets.UTF_8); // Kotlin requires UTF-8
315+
return kp.parse(kotlinPaths, baseDir, ctx).onClose(() -> view(ctx).setCharset(null));
316+
})
317+
.map(cu -> {
318+
if (DefaultProjectParser.isExcluded(repository, exclusions, cu.getSourcePath()) || cu.getSourcePath()
319+
.startsWith(buildDir)) {
320+
return null;
321+
}
322+
return cu;
323+
}).filter(Objects::nonNull).map(it -> it.withMarkers(it.getMarkers().add(javaVersion)));
317324
}
318325
}

plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
2222
import org.gradle.api.NamedDomainObjectContainer;
2323
import org.gradle.api.Project;
24+
import org.gradle.api.Task;
2425
import org.gradle.api.artifacts.Configuration;
2526
import org.gradle.api.file.SourceDirectorySet;
2627
import org.gradle.api.initialization.Settings;
@@ -31,6 +32,7 @@
3132
import org.gradle.api.plugins.JavaPluginExtension;
3233
import org.gradle.api.tasks.SourceSet;
3334
import org.gradle.api.tasks.compile.CompileOptions;
35+
import org.gradle.api.tasks.compile.GroovyCompile;
3436
import org.gradle.api.tasks.compile.JavaCompile;
3537
import org.gradle.internal.service.ServiceRegistry;
3638
import org.gradle.invocation.DefaultGradle;
@@ -686,8 +688,6 @@ public Stream<SourceFile> parse(Project subproject, Set<Path> alreadyParsed, Exe
686688
ctx));
687689
}
688690

689-
Charset sourceCharset = Charset.forName(System.getProperty("file.encoding", "UTF-8"));
690-
691691
Path buildDirPath = baseDir.relativize(subproject.getLayout()
692692
.getBuildDirectory()
693693
.get()
@@ -700,7 +700,6 @@ public Stream<SourceFile> parse(Project subproject, Set<Path> alreadyParsed, Exe
700700
subproject,
701701
progressBar,
702702
buildDirPath,
703-
sourceCharset,
704703
alreadyParsed,
705704
exclusions,
706705
ctx);
@@ -709,7 +708,6 @@ public Stream<SourceFile> parse(Project subproject, Set<Path> alreadyParsed, Exe
709708
subproject,
710709
progressBar,
711710
buildDirPath,
712-
sourceCharset,
713711
alreadyParsed,
714712
exclusions,
715713
ctx);
@@ -747,7 +745,6 @@ public Stream<SourceFile> parse(Project subproject, Set<Path> alreadyParsed, Exe
747745
private SourceFileStream parseGradleProjectSourceSets(Project subproject,
748746
ProgressBar progressBar,
749747
Path buildDir,
750-
Charset sourceCharset,
751748
Set<Path> alreadyParsed,
752749
Collection<PathMatcher> exclusions,
753750
ExecutionContext ctx) {
@@ -764,8 +761,6 @@ private SourceFileStream parseGradleProjectSourceSets(Project subproject,
764761
.getByName(sourceSet.getCompileJavaTaskName());
765762
JavaVersion javaVersion = getJavaVersion(javaCompileTask);
766763

767-
final Charset javaSourceCharset = getSourceFileEncoding(javaCompileTask, sourceCharset);
768-
769764
List<Path> unparsedSources = sourceSet.getAllSource()
770765
.getSourceDirectories()
771766
.filter(File::exists)
@@ -818,7 +813,7 @@ private SourceFileStream parseGradleProjectSourceSets(Project subproject,
818813
ctx,
819814
buildDir,
820815
exclusions,
821-
javaSourceCharset,
816+
getSourceFileEncoding(javaCompileTask.getOptions()),
822817
javaVersion,
823818
dependencyPaths,
824819
javaTypeCache);
@@ -845,7 +840,6 @@ private SourceFileStream parseGradleProjectSourceSets(Project subproject,
845840
ctx,
846841
buildDir,
847842
exclusions,
848-
javaSourceCharset,
849843
javaVersion,
850844
dependencyPaths,
851845
javaTypeCache);
@@ -873,11 +867,18 @@ private SourceFileStream parseGradleProjectSourceSets(Project subproject,
873867

874868
alreadyParsed.addAll(groovyPaths);
875869

870+
GroovyCompile groovyCompileTask = (GroovyCompile) subproject.getTasks()
871+
.getByName(sourceSet.getCompileTaskName("groovy"));
876872
Stream<SourceFile> cus = Stream.of((Supplier<GroovyParser>) () -> GroovyParser.builder()
877873
.classpath(dependenciesWithBuildDirs)
878874
.typeCache(javaTypeCache)
879875
.logCompilationWarningsAndErrors(false)
880-
.build()).map(Supplier::get).flatMap(gp -> gp.parse(groovyPaths, baseDir, ctx)).map(cu -> {
876+
.build())
877+
.map(Supplier::get)
878+
.flatMap(gp -> {
879+
view(ctx).setCharset(getSourceFileEncoding(groovyCompileTask.getOptions()));
880+
return gp.parse(groovyPaths, baseDir, ctx).onClose(() -> view(ctx).setCharset(null));
881+
}).map(cu -> {
881882
if (isExcluded(repository, exclusions, cu.getSourcePath()) || cu.getSourcePath().startsWith(buildDir)) {
882883
return null;
883884
}
@@ -923,15 +924,13 @@ private SourceFileStream parseAndroidProjectSourceSets(
923924
Project subproject,
924925
ProgressBar progressBar,
925926
Path buildDir,
926-
Charset sourceCharset,
927927
Set<Path> alreadyParsed,
928928
Collection<PathMatcher> exclusions,
929929
ExecutionContext ctx) {
930930
return getAndroidProjectParser().parseProjectSourceSets(
931931
subproject,
932932
progressBar,
933933
buildDir,
934-
sourceCharset,
935934
alreadyParsed,
936935
exclusions,
937936
ctx,
@@ -947,14 +946,17 @@ private Stream<SourceFile> parseJavaFiles(
947946
JavaVersion javaVersion,
948947
Set<Path> dependencyPaths,
949948
JavaTypeCache javaTypeCache) {
950-
view(ctx).setCharset(javaSourceCharset);
951-
952949
return Stream.of((Supplier<JavaParser>) () -> JavaParser.fromJavaVersion()
953950
.classpath(dependencyPaths)
954951
.typeCache(javaTypeCache)
955952
.logCompilationWarningsAndErrors(extension.getLogCompilationWarningsAndErrors())
956953
.build())
957-
.map(Supplier::get).flatMap(jp -> jp.parse(javaPaths, baseDir, ctx)).map(cu -> {
954+
.map(Supplier::get)
955+
.flatMap(jp -> {
956+
view(ctx).setCharset(javaSourceCharset);
957+
return jp.parse(javaPaths, baseDir, ctx).onClose(() -> view(ctx).setCharset(null));
958+
})
959+
.map(cu -> {
958960
if (isExcluded(repository, exclusions, cu.getSourcePath()) || cu.getSourcePath().startsWith(buildDir)) {
959961
return null;
960962
}
@@ -966,22 +968,25 @@ private Stream<SourceFile> parseKotlinFiles(List<Path> kotlinPaths,
966968
ExecutionContext ctx,
967969
Path buildDir,
968970
Collection<PathMatcher> exclusions,
969-
Charset javaSourceCharset,
970971
JavaVersion javaVersion,
971972
Set<Path> dependencyPaths,
972973
JavaTypeCache javaTypeCache) {
973-
view(ctx).setCharset(javaSourceCharset);
974-
975974
return Stream.of((Supplier<KotlinParser>) () -> KotlinParser.builder()
976-
.classpath(dependencyPaths)
977-
.typeCache(javaTypeCache)
978-
.logCompilationWarningsAndErrors(extension.getLogCompilationWarningsAndErrors())
979-
.build()).map(Supplier::get).flatMap(kp -> kp.parse(kotlinPaths, baseDir, ctx)).map(cu -> {
980-
if (isExcluded(repository, exclusions, cu.getSourcePath()) || cu.getSourcePath().startsWith(buildDir)) {
981-
return null;
982-
}
983-
return cu;
984-
}).filter(Objects::nonNull).map(it -> it.withMarkers(it.getMarkers().add(javaVersion)));
975+
.classpath(dependencyPaths)
976+
.typeCache(javaTypeCache)
977+
.logCompilationWarningsAndErrors(extension.getLogCompilationWarningsAndErrors())
978+
.build())
979+
.map(Supplier::get)
980+
.flatMap(kp -> {
981+
view(ctx).setCharset(StandardCharsets.UTF_8); // Kotlin requires UTF-8
982+
return kp.parse(kotlinPaths, baseDir, ctx).onClose(() -> view(ctx).setCharset(null));
983+
})
984+
.map(cu -> {
985+
if (isExcluded(repository, exclusions, cu.getSourcePath()) || cu.getSourcePath().startsWith(buildDir)) {
986+
return null;
987+
}
988+
return cu;
989+
}).filter(Objects::nonNull).map(it -> it.withMarkers(it.getMarkers().add(javaVersion)));
985990
}
986991

987992
private GradleParser gradleParser() {
@@ -1576,13 +1581,10 @@ private JavaVersion getJavaVersion(@Nullable JavaCompile javaCompileTask) {
15761581

15771582
}
15781583

1579-
private Charset getSourceFileEncoding(@Nullable JavaCompile javaCompileTask,
1580-
Charset defaultCharset) {
1581-
String sourceEncoding = null;
1582-
if (javaCompileTask != null) {
1583-
CompileOptions compileOptions = javaCompileTask.getOptions();
1584-
sourceEncoding = compileOptions.getEncoding();
1584+
private Charset getSourceFileEncoding(@Nullable CompileOptions compileOptions) {
1585+
if (compileOptions != null && compileOptions.getEncoding() != null) {
1586+
return Charset.forName(compileOptions.getEncoding());
15851587
}
1586-
return Optional.ofNullable(sourceEncoding).map(Charset::forName).orElse(defaultCharset);
1588+
return Charset.defaultCharset();
15871589
}
15881590
}

0 commit comments

Comments
 (0)