diff --git a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacCompiler.java b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacCompiler.java index ef6299476a7..866a8130a98 100644 --- a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacCompiler.java +++ b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/JavacCompiler.java @@ -15,11 +15,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Queue; +import java.util.Set; import java.util.stream.Stream; +import javax.tools.Diagnostic; import javax.tools.DiagnosticListener; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; @@ -54,10 +57,12 @@ import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Context.Key; import com.sun.tools.javac.util.Options; import com.sun.tools.javac.util.Pair; public class JavacCompiler extends Compiler { + public static final Key> FILES_WITH_ERRORS_KEY = new Key<>(); JavacConfig compilerConfig; IProblemFactory problemFactory; @@ -107,8 +112,13 @@ public void compile(ICompilationUnit[] sourceUnits) { ProceedOnErrorTransTypes.preRegister(javacContext); ProceedOnErrorGen.preRegister(javacContext); JavacProblemConverter problemConverter = new JavacProblemConverter(this.compilerConfig.compilerOptions(), javacContext); + Set sourceWithErrors = new HashSet<>(); + javacContext.put(FILES_WITH_ERRORS_KEY, sourceWithErrors); javacContext.put(DiagnosticListener.class, diagnostic -> { if (diagnostic.getSource() instanceof JavaFileObject fileObject) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { + sourceWithErrors.add(fileObject); + } JavacProblem javacProblem = problemConverter.createJavacProblem(diagnostic); if (javacProblem != null) { ICompilationUnit originalUnit = this.fileObjectToCUMap.get(fileObject); diff --git a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/ProceedOnErrorTransTypes.java b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/ProceedOnErrorTransTypes.java index 5a4b341a89d..554a64db3e6 100644 --- a/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/ProceedOnErrorTransTypes.java +++ b/org.eclipse.jdt.core.javac/src/org/eclipse/jdt/internal/javac/ProceedOnErrorTransTypes.java @@ -13,8 +13,9 @@ import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.comp.TransTypes; -import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; +import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Context.Factory; @@ -24,20 +25,46 @@ public static void preRegister(Context context) { context.put(transTypesKey, (Factory) c -> new ProceedOnErrorTransTypes(c)); } + private boolean needsProceedOnError; + private Context context; + protected ProceedOnErrorTransTypes(Context context) { super(context); + this.context = context; + } + + @Override + public void visitClassDef(JCClassDecl def) { + this.needsProceedOnError = hasErrors(def); + super.visitClassDef(def); + this.needsProceedOnError = false; + } + + private boolean hasErrors(JCClassDecl def) { + return this.context.get(JavacCompiler.FILES_WITH_ERRORS_KEY).contains(def.sym.sourcefile); } @Override public void visitApply(JCMethodInvocation tree) { - if (tree.type.isErroneous()) { - return; - } - tree.meth = translate(tree.meth, null); - Symbol meth = TreeInfo.symbol(tree.meth); - if (!(meth.baseSymbol() instanceof MethodSymbol)) { - //workaround: guard against ClassCastException when referencing non existing member - return; + if (this.needsProceedOnError) { + // The next lines of code should allow to generate + // classes with errors, but they are sometimes + // causing infinite processing for files that + // have no errors (eg with XLargeTests). + // So at the moment we guard them by `needProceedOnError` + // but those lines must be considered fragile and made + // more bullet proof; concretely then need to work with + // XLargeTest. + // Cf https://github.com/eclipse-jdtls/eclipse-jdt-core-incubator/issues/1008 + if (tree.type.isErroneous()) { + return; + } + tree.meth = translate(tree.meth, null); + Symbol meth = TreeInfo.symbol(tree.meth); + if (!(meth.baseSymbol() instanceof MethodSymbol)) { + //workaround: guard against ClassCastException when referencing non existing member + return; + } } super.visitApply(tree); }