Skip to content

Commit

Permalink
Add cancelation support to JDT frontend.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 725716910
  • Loading branch information
gkdn authored and copybara-github committed Feb 11, 2025
1 parent d1e2aa8 commit c7c846c
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.j2cl.common.FilePosition;
import com.google.j2cl.common.Problems;
import com.google.j2cl.common.SourcePosition;
import com.google.j2cl.transpiler.ast.ArrayAccess;
import com.google.j2cl.transpiler.ast.ArrayCreationReference;
Expand Down Expand Up @@ -134,6 +135,7 @@
public class CompilationUnitBuilder extends AbstractCompilationUnitBuilder {

private final JdtEnvironment environment;
private final Problems problems;

private class ASTConverter {
private org.eclipse.jdt.core.dom.CompilationUnit jdtCompilationUnit;
Expand Down Expand Up @@ -224,6 +226,7 @@ private Type convertType(

private void convertTypeBody(Type type, List<BodyDeclaration> bodyDeclarations) {
for (BodyDeclaration bodyDeclaration : bodyDeclarations) {
problems.abortIfCancelled();
if (bodyDeclaration instanceof FieldDeclaration) {
FieldDeclaration fieldDeclaration = (FieldDeclaration) bodyDeclaration;
type.addMembers(convert(fieldDeclaration));
Expand Down Expand Up @@ -252,6 +255,7 @@ private void convertTypeBody(Type type, List<BodyDeclaration> bodyDeclarations)
bodyDeclaration.getClass().getName(), type.getDeclaration().getQualifiedSourceName());
}
}
problems.abortIfCancelled();
}

private Field convert(EnumConstantDeclaration enumConstantDeclaration) {
Expand Down Expand Up @@ -1452,8 +1456,11 @@ CompilationUnit buildCompilationUnit(
return converter.convert(sourceFilePath, compilationUnit);
}

CompilationUnitBuilder(List<ITypeBinding> wellKnownTypeBindings, JdtEnvironment environment) {
CompilationUnitBuilder(
List<ITypeBinding> wellKnownTypeBindings, JdtEnvironment environment, Problems problems) {
this.environment = environment;
this.problems = problems;
environment.initWellKnownTypes(wellKnownTypeBindings);
this.problems.abortIfCancelled();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.BindingKey;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.compiler.IProblem;
Expand Down Expand Up @@ -88,13 +89,12 @@ public Library parseFiles(FrontendOptions options) {
compilationUnitsAndTypeBindings.getCompilationUnitsByFilePath();
List<ITypeBinding> wellKnownTypeBindings = compilationUnitsAndTypeBindings.getTypeBindings();
CompilationUnitBuilder compilationUnitBuilder =
new CompilationUnitBuilder(wellKnownTypeBindings, environment);
new CompilationUnitBuilder(wellKnownTypeBindings, environment, problems);

ImmutableList.Builder<com.google.j2cl.transpiler.ast.CompilationUnit> compilationUnits =
ImmutableList.builder();
for (var e : jdtUnitsByFilePath.entrySet()) {
compilationUnits.add(compilationUnitBuilder.buildCompilationUnit(e.getKey(), e.getValue()));
problems.abortIfCancelled();
}
return Library.newBuilder().setCompilationUnits(compilationUnits.build()).build();
}
Expand All @@ -109,6 +109,17 @@ private CompilationUnitsAndTypeBindings parseFiles(

// Parse and create a compilation unit for every file.
ASTParser parser = newASTParser(classpathEntries);
problems.abortIfCancelled();

var sources =
filePaths.stream()
.map(FileInfo::sourcePath)
// Skip module-info in JDT to avoid NPEs. They are not used regardless...
.filter(f -> !f.endsWith("module-info.java"))
.toArray(String[]::new);
var encodings = getEncodings(sources.length);
var bindingKeys =
binaryNamesToResolve.stream().map(BindingKey::createTypeBindingKey).toArray(String[]::new);

// The map must be ordered because it will be iterated over later and if it was not ordered then
// our output would be unstable
Expand Down Expand Up @@ -140,16 +151,23 @@ public void acceptBinding(String bindingKey, IBinding binding) {
wellKnownTypeBindings.add((ITypeBinding) binding);
}
};

// We don't know how soon JDT will be able to check for cancellation, so we check here too.
problems.abortIfCancelled();

parser.createASTs(
filePaths.stream()
.map(FileInfo::sourcePath)
// Skip module-info in JDT to avoid NPEs. They are not used regardless...
.filter(f -> !f.endsWith("module-info.java"))
.toArray(String[]::new),
getEncodings(filePaths.size()),
binaryNamesToResolve.stream().map(BindingKey::createTypeBindingKey).toArray(String[]::new),
sources,
encodings,
bindingKeys,
astRequestor,
null);
new NullProgressMonitor() {
@Override
public boolean isCanceled() {
problems.abortIfCancelled();
return false;
}
});

return new CompilationUnitsAndTypeBindings(compilationUnitsByFilePath, wellKnownTypeBindings);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ private static boolean compare(String actual, String expected) {

private static Problems transpile(ImmutableList<String> args) {
List<String> delayedCalls = new ArrayList<>();
List<String> slightlyDelayedCalls = new ArrayList<>();
Problems problems =
new Problems() {
long lastCall = System.nanoTime();
Expand All @@ -496,7 +497,12 @@ private static Problems transpile(ImmutableList<String> args) {
public boolean isCancelled() {
long delay = (System.nanoTime() - lastCall) / 1_000_000;
if (delay > MAX_DELAY) {
delayedCalls.add(Throwables.getStackTraceAsString(new Throwable("Delay: " + delay)));
var stackTrace = Throwables.getStackTraceAsString(new Throwable("Delay: " + delay));
if (delay > MAX_DELAY * 2) {
delayedCalls.add(stackTrace);
} else {
slightlyDelayedCalls.add(stackTrace);
}
}
lastCall = System.nanoTime();
return false;
Expand All @@ -508,16 +514,26 @@ public boolean isCancelled() {

final String[] knownDelayedCalls = {
"com.google.j2cl.transpiler.frontend.javac.JavacParser.parseFiles",
"com.google.j2cl.transpiler.frontend.jdt.JdtParser.parseFiles",
"com.google.j2cl.transpiler.frontend.kotlin.KotlinParser.parseFiles",
"com.google.j2cl.transpiler.J2clCommandLineRunner.createOptions",
"com.google.j2cl.transpiler.J2clTranspiler.checkLibrary",
};
for (String delayedCall : knownDelayedCalls) {
delayedCalls.removeIf(t -> t.contains(delayedCall));
for (String knownDelayedCall : knownDelayedCalls) {
delayedCalls.removeIf(t -> t.contains(knownDelayedCall));
// Remove from slightly delayed calls as well since they are a subset.
slightlyDelayedCalls.removeIf(t -> t.contains(knownDelayedCall));
}
assertThat(delayedCalls).isEmpty();

final String[] knownSlightlyDelayedCalls = {
// Jdt is slow to do the check and we can't do much about it.
"org.eclipse.core.runtime.SubMonitor.isCanceled",
};
for (String knownSlightlyDelayedCall : knownSlightlyDelayedCalls) {
slightlyDelayedCalls.removeIf(t -> t.contains(knownSlightlyDelayedCall));
}
assertThat(slightlyDelayedCalls).isEmpty();

return problems;
}

Expand Down

0 comments on commit c7c846c

Please sign in to comment.