From 3cadc596bac64577baa3ddd8cd1057594eac7200 Mon Sep 17 00:00:00 2001 From: Stephan Herrmann Date: Sun, 1 Dec 2024 00:44:03 +0100 Subject: [PATCH] java.lang.StackOverflowError during "Requesting Java AST from selection" change of strategy: + better hiding of modules seen via the classpath Fixes https://github.com/eclipse-jdt/eclipse.jdt.core/issues/3273 --- .../internal/compiler/env/ICompilationUnit.java | 8 ++++++-- .../env/IModuleAwareNameEnvironment.java | 12 +++++++++++- .../jdt/core/tests/dom/ASTConverter9Test.java | 2 +- .../eclipse/jdt/internal/core/JavaProject.java | 10 +--------- .../eclipse/jdt/internal/core/NameLookup.java | 4 ++-- .../internal/core/SearchableEnvironment.java | 17 +++++++++++++++++ 6 files changed, 38 insertions(+), 15 deletions(-) diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java index 7d846729cf7..d9b3318b6b7 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -61,7 +61,11 @@ default boolean ignoreOptionalProblems() { * @return the binding representing the module. */ default ModuleBinding module(LookupEnvironment environment) { - return environment.getModule(getModuleName()); + if (environment.nameEnvironment instanceof IModuleAwareNameEnvironment modEnv) { + char[] moduleName = modEnv.isOnModulePath(this) ? getModuleName() : ModuleBinding.UNNAMED; + return environment.getModule(moduleName); + } + return null; } /** * Returns the name of the module to which this compilation unit is associated. diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java index 093af6cf389..594ed13bc08 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/env/IModuleAwareNameEnvironment.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2017 IBM Corporation and others. + * Copyright (c) 2016, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -132,6 +132,16 @@ default char[][] getUniqueModulesDeclaringPackage(char[][] packageName, char[] m IModule getModule(char[] moduleName); char[][] getAllAutomaticModules(); + /** + * If this environment focusses on one IJavaProject answer if the given + * compilation unit is found on the module path, rather than the class path. + * @param unit compilation unit to test + * @return true iff unit is on the module path. + */ + default boolean isOnModulePath(ICompilationUnit unit) { + return true; // TODO: should more / all implementors implement this method? + } + /** * Ask the name environment to perform any updates (add-exports or add-reads) to the given module. * @param module the compiler representation of the module to updates diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java index 0e60d007374..e5a5461d8aa 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter9Test.java @@ -1589,7 +1589,7 @@ public class Client { IVariableBinding c1 = type.getDeclaredFields()[0]; IModuleBinding module = c1.getType().getModule(); assertNotNull(module); - assertEquals("first", module.getName()); + assertEquals("", module.getName()); } finally { deleteProject("P0"); deleteProject("P1"); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java index bbd6995b52d..68e785cb289 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2024 IBM Corporation and others. + * Copyright (c) 2000, 2020 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -3741,14 +3741,6 @@ public IModuleDescription getModuleDescription() throws JavaModelException { return null; } - public boolean isModular() { - try { - return getModuleDescription() != null; - } catch (JavaModelException e) { - return false; - } - } - @Override public IModuleDescription getOwnModuleDescription() throws JavaModelException { JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo(); diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java index c1cdd7d649a..c9d9c3a101a 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2024 IBM Corporation and others. + * Copyright (c) 2000, 2021 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -904,7 +904,7 @@ static IModuleDescription getModuleDescription(JavaProject project, IPackageFrag IModuleDescription module = cache.get(root); if (module != null) return module != NO_MODULE ? module : null; - if (!Objects.equals(project, root.getJavaProject()) && project.isModular()) { + if (!Objects.equals(project, root.getJavaProject())) { IClasspathEntry classpathEntry2 = rootToEntry.apply(root); if (classpathEntry2 instanceof ClasspathEntry) { if (!((ClasspathEntry) classpathEntry2).isModular()) { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java index 1cf884c5e0d..740bb197452 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java @@ -22,6 +22,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; @@ -301,6 +302,22 @@ public void findModules(char[] prefix, ISearchRequestor requestor, IJavaProject this.nameLookup.seekModule(prefix, true, new SearchableEnvironmentRequestor(requestor)); } + @Override + public boolean isOnModulePath(ICompilationUnit unit) { + if (unit instanceof CompilationUnit cUnit) { + IPackageFragmentRoot root = cUnit.originalFromClone().getPackageFragmentRoot(); + if (Objects.equals(root.getJavaProject(), this.project)) + return true; // current project: modular if it contains module-info :) + IClasspathEntry entry = this.nameLookup.rootToResolvedEntries.get(root); + if (entry instanceof ClasspathEntry cpEntry) + return cpEntry.isModular(); + return true; // out-of-band resolution / transitive dependency? + } else if (unit instanceof BasicCompilationUnit bUnit) { + return bUnit.moduleName != null; + } + return false; + } + /** * Find the packages that start with the given prefix. * A valid prefix is a qualified name separated by periods