11/*******************************************************************************
2- * Copyright (c) 2000, 2024 IBM Corporation and others.
2+ * Copyright (c) 2000, 2025 IBM Corporation and others.
33 *
44 * This program and the accompanying materials
55 * are made available under the terms of the Eclipse Public License 2.0
3939import org .eclipse .jdt .core .ICompilationUnit ;
4040import org .eclipse .jdt .core .IJavaElement ;
4141import org .eclipse .jdt .core .IJavaProject ;
42+ import org .eclipse .jdt .core .IModuleDescription ;
4243import org .eclipse .jdt .core .IPackageFragment ;
4344import org .eclipse .jdt .core .IPackageFragmentRoot ;
4445import org .eclipse .jdt .core .ISourceRange ;
46+ import org .eclipse .jdt .core .IType ;
4547import org .eclipse .jdt .core .JavaModelException ;
4648import org .eclipse .jdt .core .Signature ;
4749import org .eclipse .jdt .core .SourceRange ;
4850import org .eclipse .jdt .core .compiler .IProblem ;
51+ import org .eclipse .jdt .core .dom .AST ;
4952import org .eclipse .jdt .core .dom .ASTNode ;
5053import org .eclipse .jdt .core .dom .AbstractTypeDeclaration ;
5154import org .eclipse .jdt .core .dom .CompilationUnit ;
5255import org .eclipse .jdt .core .dom .IBinding ;
56+ import org .eclipse .jdt .core .dom .IModuleBinding ;
5357import org .eclipse .jdt .core .dom .ITypeBinding ;
5458import org .eclipse .jdt .core .dom .ImportDeclaration ;
5559import org .eclipse .jdt .core .dom .MethodInvocation ;
7781import org .eclipse .jdt .internal .corext .util .JdtFlags ;
7882import org .eclipse .jdt .internal .corext .util .StaticImportFavoritesCompletionInvoker ;
7983
84+ import org .eclipse .jdt .internal .ui .text .correction .proposals .AddImportCorrectionProposalCore ;
8085
8186
8287/**
@@ -220,6 +225,7 @@ public void addInfo(TypeNameMatch info) {
220225
221226 private Set <String > fOldSingleImports ;
222227 private Set <String > fOldDemandImports ;
228+ private Map <String , Set <String >> fOldModuleImports ;
223229
224230 private Set <String > fImplicitImports ;
225231
@@ -235,13 +241,16 @@ public void addInfo(TypeNameMatch info) {
235241
236242 private Map <String , UnresolvedTypeData > fUnresolvedTypes ;
237243 private Set <String > fImportsAdded ;
244+ private Set <String > fModuleImportsAdded ;
238245 private TypeNameMatch [][] fOpenChoices ;
239246 private SourceRange [] fSourceRanges ;
240247
241248
242- public TypeReferenceProcessor (Set <String > oldSingleImports , Set <String > oldDemandImports , CompilationUnit root , ImportRewrite impStructure , boolean ignoreLowerCaseNames , UnresolvableImportMatcher unresolvableImportMatcher ) {
249+ public TypeReferenceProcessor (Set <String > oldSingleImports , Set <String > oldDemandImports , Map <String , Set <String >> oldModuleImports ,
250+ CompilationUnit root , ImportRewrite impStructure , boolean ignoreLowerCaseNames , UnresolvableImportMatcher unresolvableImportMatcher ) {
243251 fOldSingleImports = oldSingleImports ;
244252 fOldDemandImports = oldDemandImports ;
253+ fOldModuleImports = oldModuleImports ;
245254 fImpStructure = impStructure ;
246255 fDoIgnoreLowerCaseNames = ignoreLowerCaseNames ;
247256 fUnresolvableImportMatcher = unresolvableImportMatcher ;
@@ -253,11 +262,32 @@ public TypeReferenceProcessor(Set<String> oldSingleImports, Set<String> oldDeman
253262 fImplicitImports .add ("java.lang" ); //$NON-NLS-1$
254263 fImplicitImports .add (cu .getParent ().getElementName ());
255264
265+ if (root .getAST ().apiLevel () >= AST .JLS25 ) {
266+ try {
267+ IType [] types = cu .getAllTypes ();
268+ if (types .length > 0 && types [0 ].isImplicitlyDeclared ()) {
269+ IJavaProject javaProject = cu .getJavaProject ();
270+ if (javaProject != null ) {
271+ IModuleDescription module = javaProject .findModule (AddImportCorrectionProposalCore .JAVA_BASE , cu .getOwner ());
272+ if (module != null ) {
273+ for (String packageName : module .getExportedPackageNames (null )) {
274+ fImplicitImports .add (packageName );
275+ }
276+ }
277+ }
278+ }
279+ } catch (JavaModelException e ) {
280+ // ignore
281+ }
282+ }
283+
284+
256285 fAnalyzer = new ScopeAnalyzer (root );
257286
258287 fCurrPackage = (IPackageFragment ) cu .getParent ();
259288
260289 fImportsAdded = new HashSet <>();
290+ fModuleImportsAdded = new HashSet <>();
261291 fUnresolvedTypes = new HashMap <>();
262292 }
263293
@@ -323,6 +353,23 @@ public void add(SimpleName ref) {
323353 }
324354 typeBinding = typeBinding .getTypeDeclaration ();
325355 if (!typeBinding .isRecovered ()) {
356+ String qualifiedTypeName = typeBinding .getQualifiedName ();
357+ if (qualifiedTypeName .indexOf ('.' ) > 0 ) {
358+ String qualifier = qualifiedTypeName .substring (0 , qualifiedTypeName .lastIndexOf ('.' ));
359+ Entry <String , Set <String >> entry = getModuleImportsEntryForQualifier (qualifier );
360+ if (entry != null ) {
361+ if (fModuleImportsAdded .contains (entry .getKey ())) {
362+ fImportsAdded .add (typeName );
363+ return ;
364+ }
365+ fImpStructure .addModuleImport (entry .getKey (), new ArrayList <>(entry .getValue ()));
366+ fModuleImportsAdded .add (entry .getKey ());
367+ return ;
368+ }
369+ if (fImplicitImports .contains (qualifier )) {
370+ return ;
371+ }
372+ }
326373 if (needsImport (typeBinding , ref )) {
327374 fImpStructure .addImport (typeBinding );
328375 fImportsAdded .add (typeName );
@@ -408,7 +455,9 @@ private TypeNameMatch[] processTypeInfo(List<TypeNameMatch> typeRefsFound) {
408455 return null ;
409456 } else if (nFound == 1 ) {
410457 TypeNameMatch typeRef = typeRefsFound .get (0 );
411- fImpStructure .addImport (typeRef .getFullyQualifiedName ());
458+ if (getModuleImportsEntryForQualifier (typeRef .getTypeContainerName ()) == null ) {
459+ fImpStructure .addImport (typeRef .getFullyQualifiedName ());
460+ }
412461 return null ;
413462 } else {
414463 String typeToImport = null ;
@@ -429,6 +478,8 @@ private TypeNameMatch[] processTypeInfo(List<TypeNameMatch> typeRefsFound) {
429478 } else { // more than one import-on-demand
430479 ambiguousImports = true ;
431480 }
481+ } else if (getModuleImportsEntryForQualifier (containerName ) != null ) {
482+ return null ; // we don't reimport
432483 }
433484 }
434485
@@ -441,6 +492,17 @@ private TypeNameMatch[] processTypeInfo(List<TypeNameMatch> typeRefsFound) {
441492 }
442493 }
443494
495+ private Entry <String , Set <String >> getModuleImportsEntryForQualifier (String qualifier ) {
496+ for (Entry <String , Set <String >> entry : fOldModuleImports .entrySet ()) {
497+ Set <String > packageNames = entry .getValue ();
498+ if (packageNames .contains (qualifier )) {
499+ return entry ;
500+ }
501+ }
502+ return null ;
503+ }
504+
505+
444506 private boolean isOfKind (TypeNameMatch curr , int typeKinds ) {
445507 int flags = curr .getModifiers ();
446508 if (Flags .isAnnotation (flags )) {
@@ -587,10 +649,11 @@ public TextEdit createTextEdit(IProgressMonitor m) throws CoreException, Operati
587649
588650 Set <String > oldSingleImports = new HashSet <>();
589651 Set <String > oldDemandImports = new HashSet <>();
652+ Map <String , Set <String >> oldModulePackages = new HashMap <>();
590653 List <SimpleName > typeReferences = new ArrayList <>();
591654 List <SimpleName > staticReferences = new ArrayList <>();
592655
593- if (!collectReferences (astRoot , typeReferences , staticReferences , oldSingleImports , oldDemandImports ))
656+ if (!collectReferences (astRoot , typeReferences , staticReferences , oldSingleImports , oldDemandImports , oldModulePackages ))
594657 return null ;
595658
596659 subMonitor .split (1 );
@@ -600,6 +663,7 @@ public TextEdit createTextEdit(IProgressMonitor m) throws CoreException, Operati
600663 TypeReferenceProcessor processor = new TypeReferenceProcessor (
601664 oldSingleImports ,
602665 oldDemandImports ,
666+ oldModulePackages ,
603667 astRoot ,
604668 importsRewrite ,
605669 fIgnoreLowerCaseNames ,
@@ -650,6 +714,7 @@ private void determineImportDifferences(ImportRewrite importsStructure, Set<Stri
650714 List <String > importsAdded = new ArrayList <>(importsStructure .getCreatedImports ().length + importsStructure .getCreatedStaticImports ().length );
651715 importsAdded .addAll (Arrays .asList (importsStructure .getCreatedImports ()));
652716 importsAdded .addAll (Arrays .asList (importsStructure .getCreatedStaticImports ()));
717+ importsAdded .addAll (Arrays .asList (importsStructure .getCreatedModuleImports ()));
653718
654719 for (Object element : oldSingleImports .toArray ()) {
655720 String importName = (String ) element ;
@@ -734,7 +799,8 @@ private void addStaticImports(
734799
735800
736801 // find type references in a compilation unit
737- private boolean collectReferences (CompilationUnit astRoot , List <SimpleName > typeReferences , List <SimpleName > staticReferences , Set <String > oldSingleImports , Set <String > oldDemandImports ) {
802+ private boolean collectReferences (CompilationUnit astRoot , List <SimpleName > typeReferences , List <SimpleName > staticReferences , Set <String > oldSingleImports ,
803+ Set <String > oldDemandImports , Map <String , Set <String >> oldModuleImports ) {
738804 if (!fAllowSyntaxErrors ) {
739805 for (IProblem curr : astRoot .getProblems ()) {
740806 if (curr .isError () && (curr .getID () & IProblem .Syntax ) != 0 ) {
@@ -744,16 +810,24 @@ private boolean collectReferences(CompilationUnit astRoot, List<SimpleName> type
744810 }
745811 }
746812 List <ImportDeclaration > imports = astRoot .imports ();
813+ IJavaProject project = fCompilationUnit .getJavaProject ();
747814 for (ImportDeclaration curr : imports ) {
748815 String id = ASTResolving .getFullName (curr .getName ());
749- if (curr .isOnDemand ()) {
816+ if (Modifier .isModule (curr .getModifiers ())) {
817+ Set <String > oldModulePackages = new HashSet <>();
818+ oldModuleImports .put (id , oldModulePackages );
819+ if (curr .resolveBinding () instanceof IModuleBinding binding ) {
820+ List <String > exportedPackageNames =
821+ ImportRewrite .getPackageNamesForModule (binding , project );
822+ oldModulePackages .addAll (exportedPackageNames );
823+ }
824+ } else if (curr .isOnDemand ()) {
750825 oldDemandImports .add (id );
751826 } else {
752827 oldSingleImports .add (id );
753828 }
754829 }
755830
756- IJavaProject project = fCompilationUnit .getJavaProject ();
757831 ImportReferencesCollector .collect (astRoot , project , null , typeReferences , staticReferences );
758832
759833 return true ;
0 commit comments