Skip to content

Commit 5595825

Browse files
authored
Merge pull request #8827 from sid-srini/module-imports-in-organize-imports-etc
Partial handling of module imports - Organize and Add imports
2 parents 81def7e + a84f212 commit 5595825

File tree

9 files changed

+798
-48
lines changed

9 files changed

+798
-48
lines changed

java/java.hints/src/org/netbeans/modules/java/hints/OrganizeImports.java

Lines changed: 72 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,26 @@
2222
import java.awt.event.ActionEvent;
2323
import java.util.Collections;
2424
import java.util.Comparator;
25+
import java.util.HashMap;
2526
import java.util.HashSet;
2627
import java.util.LinkedList;
2728
import java.util.List;
29+
import java.util.Map;
2830
import java.util.Set;
2931
import java.util.concurrent.atomic.AtomicBoolean;
3032

3133
import javax.lang.model.element.Element;
3234
import javax.lang.model.element.Modifier;
35+
import javax.lang.model.element.ModuleElement;
36+
import javax.lang.model.element.PackageElement;
3337
import javax.lang.model.type.TypeKind;
3438
import javax.lang.model.util.Types;
3539
import javax.swing.text.JTextComponent;
3640
import javax.tools.Diagnostic;
3741

3842
import com.sun.source.tree.ClassTree;
3943
import com.sun.source.tree.CompilationUnitTree;
44+
import com.sun.source.tree.ExpressionTree;
4045
import com.sun.source.tree.IdentifierTree;
4146
import com.sun.source.tree.ImportTree;
4247
import com.sun.source.tree.MemberSelectTree;
@@ -80,6 +85,7 @@
8085
import org.netbeans.spi.java.hints.TriggerTreeKind;
8186
import org.openide.util.Exceptions;
8287
import org.openide.util.NbBundle;
88+
import org.openide.util.Pair;
8389

8490
/**
8591
*
@@ -160,10 +166,11 @@ public static void doOrganizeImports(WorkingCopy copy, Set<Element> addImports,
160166
}
161167
}
162168
final CodeStyle cs = CodeStyle.getDefault(copy.getFileObject());
163-
Set<Element> starImports = new HashSet<Element>();
164-
Set<Element> staticStarImports = new HashSet<Element>();
165-
Set<Element> toImport = getUsedElements(copy, cu, starImports, staticStarImports);
166-
List<ImportTree> imps = new LinkedList<ImportTree>();
169+
final Set<Element> starImports = new HashSet<>();
170+
final Set<Element> staticStarImports = new HashSet<>();
171+
final Set<Element> moduleImports = new HashSet<>();
172+
Set<Element> toImport = getUsedElements(copy, cu, starImports, staticStarImports, moduleImports);
173+
final List<ImportTree> imps = new LinkedList<>();
167174
TreeMaker maker = copy.getTreeMaker();
168175

169176
if (addImports != null) {
@@ -173,6 +180,7 @@ public static void doOrganizeImports(WorkingCopy copy, Set<Element> addImports,
173180
} else if (!toImport.isEmpty() || isBulkMode) {
174181
// track import star import scopes, so only one star import/scope appears in imps - #251977
175182
Set<Element> starImportScopes = new HashSet<>();
183+
Map<ModuleElement, Pair<ExpressionTree, ModuleElement>> transitiveScopeToModuleImport = new HashMap<>();
176184
Trees trees = copy.getTrees();
177185
for (ImportTree importTree : cu.getImports()) {
178186
Tree qualIdent = importTree.getQualifiedIdentifier();
@@ -181,13 +189,13 @@ public static void doOrganizeImports(WorkingCopy copy, Set<Element> addImports,
181189
Element importedScope = trees.getElement(TreePath.getPath(cu, ((MemberSelectTree)qualIdent).getExpression()));
182190

183191
if (importTree.isStatic()) {
184-
if (staticStarImports != null &&
192+
if (!staticStarImports.isEmpty() &&
185193
staticStarImports.contains(importedScope) &&
186194
!starImportScopes.contains(importedScope)) {
187195
imp = maker.Import(qualIdent, true);
188196
}
189197
} else {
190-
if (starImports != null &&
198+
if (!starImports.isEmpty() &&
191199
starImports.contains(importedScope) &&
192200
!starImportScopes.contains(importedScope)) {
193201
imp = maker.Import(qualIdent, false);
@@ -197,6 +205,28 @@ public static void doOrganizeImports(WorkingCopy copy, Set<Element> addImports,
197205
starImportScopes.add(importedScope);
198206
imps.add(imp);
199207
}
208+
} else if (importTree.isModule()) {
209+
ModuleElement importedScope = copy.getElements().getModuleElement(qualIdent.toString());
210+
if (qualIdent instanceof ExpressionTree moduleIdentifier) {
211+
if (importedScope == null) {
212+
//do not mark unresolvable element imports as unused
213+
imps.add(maker.ImportModule(moduleIdentifier));
214+
} else if (!moduleImports.isEmpty() && !starImportScopes.contains(importedScope)) {
215+
if (moduleImports.contains(importedScope)) {
216+
imps.add(maker.ImportModule(moduleIdentifier));
217+
starImportScopes.add(importedScope);
218+
} else {
219+
collectTransitivelyUsedModules(importedScope, moduleIdentifier, moduleImports, copy, transitiveScopeToModuleImport);
220+
}
221+
}
222+
}
223+
}
224+
}
225+
// Add any used modules that are only referred by a transitive import
226+
for (Map.Entry<ModuleElement, Pair<ExpressionTree, ModuleElement>> t : transitiveScopeToModuleImport.entrySet()) {
227+
if (!starImportScopes.contains(t.getKey()) && !starImportScopes.contains(t.getValue().second())) {
228+
imps.add(maker.ImportModule(t.getValue().first()));
229+
starImportScopes.add(t.getValue().second());
200230
}
201231
}
202232
} else {
@@ -213,21 +243,42 @@ public int compare(ImportTree o1, ImportTree o2) {
213243
return 0;
214244
String s1 = o1.getQualifiedIdentifier().toString();
215245
String s2 = o2.getQualifiedIdentifier().toString();
216-
int bal = groups.getGroupId(s1, o1.isStatic()) - groups.getGroupId(s2, o2.isStatic());
246+
int bal;
247+
if (o1.isModule()) {
248+
bal = o2.isModule() ? 0 : 1; // Place element imports last
249+
} else if (o2.isModule()) {
250+
bal = -1; // Place element imports last
251+
} else {
252+
bal = groups.getGroupId(s1, o1.isStatic()) - groups.getGroupId(s2, o2.isStatic());
253+
}
217254
return bal == 0 ? s1.compareTo(s2) : bal;
218255
}
219256
});
220257
}
221258
CompilationUnitTree cut = maker.CompilationUnit(cu.getPackageAnnotations(), cu.getPackageName(), imps, cu.getTypeDecls(), cu.getSourceFile());
222259
((JCCompilationUnit)cut).packge = ((JCCompilationUnit)cu).packge;
223-
if (starImports != null || staticStarImports != null) {
224-
((JCCompilationUnit)cut).starImportScope = ((JCCompilationUnit)cu).starImportScope;
260+
((JCCompilationUnit)cut).starImportScope = ((JCCompilationUnit)cu).starImportScope;
261+
if (!moduleImports.isEmpty()) {
262+
((JCCompilationUnit)cut).moduleImportScope = ((JCCompilationUnit)cu).moduleImportScope;
225263
}
226264
CompilationUnitTree ncu = toImport.isEmpty() ? cut : GeneratorUtilities.get(copy).addImports(cut, toImport);
227265
copy.rewrite(cu, ncu);
228266
}
267+
268+
private static void collectTransitivelyUsedModules(final ModuleElement importedModule, final ExpressionTree importIdentifier, final Set<Element> usedModules, final CompilationInfo info, final Map<ModuleElement, Pair<ExpressionTree, ModuleElement>> transitiveModulesToImportingIdentifier) {
269+
if (importedModule != null) {
270+
if (usedModules.contains(importedModule))
271+
return;
272+
Pair<ExpressionTree, ModuleElement> root = Pair.of(importIdentifier, importedModule);
273+
for (PackageElement pack : info.getElementUtilities().transitivelyExportedPackages(importedModule)) {
274+
if ((pack.getEnclosingElement() instanceof ModuleElement transitiveModule) && transitiveModule != importedModule && usedModules.contains(transitiveModule)) {
275+
transitiveModulesToImportingIdentifier.putIfAbsent(transitiveModule, root);
276+
}
277+
}
278+
}
279+
}
229280

230-
private static Set<Element> getUsedElements(final CompilationInfo info, final CompilationUnitTree cut, final Set<Element> starImports, final Set<Element> staticStarImports) {
281+
private static Set<Element> getUsedElements(final CompilationInfo info, final CompilationUnitTree cut, final Set<Element> starImports, final Set<Element> staticStarImports, final Set<Element> moduleImports) {
231282
final Set<Element> ret = new HashSet<Element>();
232283
final Trees trees = info.getTrees();
233284
final Types types = info.getTypes();
@@ -273,7 +324,7 @@ private void addElement(Element element) {
273324
case FIELD:
274325
case METHOD:
275326
if (element.getModifiers().contains(Modifier.STATIC)) {
276-
Element glob = global(element, staticStarImports);
327+
Element glob = global(element, staticStarImports, moduleImports);
277328
if (glob != null)
278329
ret.add(glob);
279330
}
@@ -283,14 +334,14 @@ private void addElement(Element element) {
283334
case RECORD:
284335
case ENUM:
285336
case INTERFACE:
286-
Element glob = global(element, starImports);
337+
Element glob = global(element, starImports, moduleImports);
287338
if (glob != null)
288339
ret.add(glob);
289340
}
290341
}
291342
}
292343

293-
private Element global(Element element, Set<Element> stars) {
344+
private Element global(Element element, Set<Element> stars, Set<Element> modules) {
294345
for (Symbol sym : ((JCCompilationUnit)cut).namedImportScope.getSymbolsByName((Name)element.getSimpleName())) {
295346
if (element == sym || element.asType().getKind() == TypeKind.ERROR && element.getKind() == sym.getKind())
296347
return sym;
@@ -307,6 +358,14 @@ private Element global(Element element, Set<Element> stars) {
307358
return sym;
308359
}
309360
}
361+
for (Symbol sym : ((JCCompilationUnit)cut).moduleImportScope.getSymbolsByName((Name)element.getSimpleName())) {
362+
if (element == sym || element.asType().getKind() == TypeKind.ERROR && element.getKind() == sym.getKind()) {
363+
if (modules != null) {
364+
modules.add(sym.packge().modle);
365+
}
366+
return sym;
367+
}
368+
}
310369
return null;
311370
}
312371
}.scan(cut, null);

0 commit comments

Comments
 (0)