IJ-CR-151305 [java-import] IDEA-364508 support optimize imports

- use layout table

(cherry picked from commit 6862419acc2beb72f87cca6b93612f9afe81f698)

GitOrigin-RevId: af86c63fa16f760ad3fd0b66fc9f86f7a21de7c7
This commit is contained in:
Mikhail Pyltsin
2024-12-19 13:31:51 +01:00
committed by intellij-monorepo-bot
parent 46bfa503aa
commit cd9a60ab8f
24 changed files with 196 additions and 116 deletions

View File

@@ -40,8 +40,6 @@ public abstract class ImportLayoutPanel extends JPanel {
private final JBCheckBox myCbLayoutStaticImportsSeparately =
new JBCheckBox(JavaBundle.message("import.layout.static.imports.separately"));
@Nullable private final JBCheckBox myCbLayoutOnDemandImportsFromSamePackageFirst;
@Nullable private final JBCheckBox myCbModuleImportFirst;
@Nullable private final JBCheckBox myCbSpaceBetweenModuleAndOther;
private final JBTable myImportLayoutTable;
private final PackageEntryTable myImportLayoutList = new PackageEntryTable();
@@ -63,16 +61,6 @@ public abstract class ImportLayoutPanel extends JPanel {
return myCbLayoutOnDemandImportsFromSamePackageFirst;
}
@Nullable
public JBCheckBox getCbModuleImportFirst() {
return myCbModuleImportFirst;
}
@Nullable
public JBCheckBox getCbSpaceBetweenModuleAndOther() {
return myCbSpaceBetweenModuleAndOther;
}
public ImportLayoutPanel(boolean showLayoutOnDemandImportFromSamePackageFirstCheckbox, boolean supportModuleImport) {
super(new BorderLayout());
@@ -119,7 +107,10 @@ public abstract class ImportLayoutPanel extends JPanel {
.setRemoveActionUpdater(e -> {
int selectedImport = myImportLayoutTable.getSelectedRow();
PackageEntry entry = selectedImport < 0 ? null : myImportLayoutList.getEntryAt(selectedImport);
return entry != null && entry != PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY && entry != PackageEntry.ALL_OTHER_IMPORTS_ENTRY;
return entry != null &&
entry != PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY &&
entry != PackageEntry.ALL_OTHER_IMPORTS_ENTRY &&
entry != PackageEntry.ALL_MODULE_IMPORTS;
})
.setButtonComparator(JavaBundle.message("button.add"),
IdeBundle.message("action.remove"),
@@ -133,13 +124,8 @@ public abstract class ImportLayoutPanel extends JPanel {
? new JBCheckBox(JavaBundle.message("import.layout.on.demand.import.from.same.package.first"))
: null;
myCbModuleImportFirst = supportModuleImport ? new JBCheckBox(JavaBundle.message("import.layout.module.import.first")) : null;
myCbSpaceBetweenModuleAndOther =
supportModuleImport ? new JBCheckBox(JavaBundle.message("import.layout.space.between.module.import.other")) : null;
List<@Nullable JBCheckBox> additionalCheckBoxes = new ArrayList<>();
additionalCheckBoxes.add(myCbLayoutOnDemandImportsFromSamePackageFirst);
additionalCheckBoxes.add(myCbModuleImportFirst);
additionalCheckBoxes.add(myCbSpaceBetweenModuleAndOther);
final ImportLayoutPanelUI UI = new ImportLayoutPanelUI(myCbLayoutStaticImportsSeparately,
additionalCheckBoxes,
importLayoutPanel);
@@ -198,7 +184,9 @@ public abstract class ImportLayoutPanel extends JPanel {
return;
}
PackageEntry entry = myImportLayoutList.getEntryAt(selected);
if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY || entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY) {
if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY ||
entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY ||
entry == PackageEntry.ALL_MODULE_IMPORTS) {
return;
}
TableUtil.stopEditing(myImportLayoutTable);
@@ -253,14 +241,6 @@ public abstract class ImportLayoutPanel extends JPanel {
return myCbLayoutOnDemandImportsFromSamePackageFirst != null && myCbLayoutOnDemandImportsFromSamePackageFirst.isSelected();
}
public boolean isModuleImportFirst() {
return myCbModuleImportFirst != null && myCbModuleImportFirst.isSelected();
}
public boolean isSpaceBetweenModuleAndOther() {
return myCbSpaceBetweenModuleAndOther != null && myCbSpaceBetweenModuleAndOther.isSelected();
}
public static JBTable createTableForPackageEntries(final PackageEntryTable packageTable, final ImportLayoutPanel panel) {
final String[] names = {
JavaBundle.message("listbox.import.package"),
@@ -396,6 +376,9 @@ public abstract class ImportLayoutPanel extends JPanel {
if (entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY || entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) {
append(JavaBundle.message("import.layout.panel.all.other.imports"), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
else if (entry == PackageEntry.ALL_MODULE_IMPORTS) {
append(JavaBundle.message("import.layout.panel.module.imports"), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
else {
append(entry.getPackageName() + ".*", SimpleTextAttributes.REGULAR_ATTRIBUTES);
}

View File

@@ -63,8 +63,6 @@ class JavaCodeStyleImportsPanel extends CodeStyleImportsPanelBase {
if(cbPreserveModuleImports!=null) javaSettings.setPreserveModuleImports(cbPreserveModuleImports.isSelected());
javaSettings.setDoNotImportInner(getInnerClassesNames());
javaSettings.setLayoutOnDemandImportFromSamePackageFirst(myImportLayoutPanel.isLayoutOnDemandImportsFromSamePackageFirst());
javaSettings.setModuleImportFirst(myImportLayoutPanel.isModuleImportFirst());
javaSettings.setSpaceBetweenModuleAndOtherImports(myImportLayoutPanel.isSpaceBetweenModuleAndOther());
}
@Override
@@ -81,12 +79,6 @@ class JavaCodeStyleImportsPanel extends CodeStyleImportsPanelBase {
JBCheckBox cbLayoutOnDemandImportsFromSamePackageFirst = myImportLayoutPanel.getCbLayoutOnDemandImportsFromSamePackageFirst();
if (cbLayoutOnDemandImportsFromSamePackageFirst != null) cbLayoutOnDemandImportsFromSamePackageFirst.setSelected(javaSettings.isLayoutOnDemandImportFromSamePackageFirst());
JBCheckBox cbModuleImportFirst = myImportLayoutPanel.getCbModuleImportFirst();
if (cbModuleImportFirst != null) cbModuleImportFirst.setSelected(javaSettings.isModuleImportFirst());
JBCheckBox cbSpaceBetweenModuleAndOther = myImportLayoutPanel.getCbSpaceBetweenModuleAndOther();
if (cbSpaceBetweenModuleAndOther != null) cbSpaceBetweenModuleAndOther.setSelected(javaSettings.isSpaceBetweenModuleAndOtherImports());
}
@Override
@@ -101,12 +93,6 @@ class JavaCodeStyleImportsPanel extends CodeStyleImportsPanelBase {
JBCheckBox cbLayoutOnDemandImportsFromSamePackageFirst = myImportLayoutPanel.getCbLayoutOnDemandImportsFromSamePackageFirst();
if (cbLayoutOnDemandImportsFromSamePackageFirst != null) isModified |= isModified(cbLayoutOnDemandImportsFromSamePackageFirst, javaSettings.isLayoutOnDemandImportFromSamePackageFirst());
JBCheckBox cbModuleImportFirst = myImportLayoutPanel.getCbModuleImportFirst();
if (cbModuleImportFirst != null) isModified |= isModified(cbModuleImportFirst, javaSettings.isModuleImportFirst());
JBCheckBox cbSpaceBetweenModuleAndOther = myImportLayoutPanel.getCbSpaceBetweenModuleAndOther();
if (cbSpaceBetweenModuleAndOther != null) isModified |= isModified(cbSpaceBetweenModuleAndOther, javaSettings.isSpaceBetweenModuleAndOtherImports());
return isModified;
}

View File

@@ -15,6 +15,7 @@ public class JavaPackageEntryTableAccessor extends ValueListPropertyAccessor<Pac
public static final char BLANK_LINE_CHAR = '|';
public static final String STATIC_PREFIX = "$";
public static final String MODULE_PREFIX = "@";
public JavaPackageEntryTableAccessor(@NotNull Object object, @NotNull Field field) {
super(object, field);
@@ -35,17 +36,27 @@ public class JavaPackageEntryTableAccessor extends ValueListPropertyAccessor<Pac
else {
boolean isStatic = false;
boolean isWithSubpackages = false;
boolean isModule = false;
if (parseStr.startsWith(STATIC_PREFIX)) {
parseStr = parseStr.substring(STATIC_PREFIX.length()).trim();
isStatic = true;
}
if (parseStr.startsWith(MODULE_PREFIX)) {
parseStr = parseStr.substring(MODULE_PREFIX.length()).trim();
isModule = true;
}
parseStr = parseStr.trim();
if (parseStr.endsWith("**")) {
isWithSubpackages = true;
parseStr = parseStr.substring(0, parseStr.length() - 1);
}
if ("*".equals(parseStr)) {
entryTable.addEntry(isStatic ? PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY : PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
if (isModule) {
entryTable.addEntry(PackageEntry.ALL_MODULE_IMPORTS);
}
else {
entryTable.addEntry(isStatic ? PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY : PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
}
}
else {
entryTable.addEntry(new PackageEntry(isStatic, parseStr, isWithSubpackages));
@@ -65,7 +76,10 @@ public class JavaPackageEntryTableAccessor extends ValueListPropertyAccessor<Pac
else {
StringBuilder entryBuilder = new StringBuilder();
if (entry.isStatic()) {
entryBuilder.append("$");
entryBuilder.append(STATIC_PREFIX);
}
if (entry == PackageEntry.ALL_MODULE_IMPORTS) {
entryBuilder.append(MODULE_PREFIX);
}
if (entry.isSpecial()) {
entryBuilder.append("*");

View File

@@ -98,8 +98,8 @@ public final class ImportHelper {
.sorted(Comparator.comparing(o -> o.name()))
.collect(Collectors.toList());
List<Import> resultList = sortItemsAccordingToSettings(imports, mySettings);
SortedImportItems items = sortItemsWithModulesAccordingToSettings(imports, mySettings);
List<Import> resultList = items.imports();
Map<String, Boolean> classesOrPackagesToImportOnDemand = new HashMap<>();
List<PsiImportModuleStatement> previousModuleStatements = collectModuleImports(file, mySettings);
Map<String, PsiImportModuleStatement> moduleStatementMap = collectNamesImportedByModules(file, previousModuleStatements, resultList);
@@ -130,7 +130,6 @@ public final class ImportHelper {
try {
boolean onDemandFirst = mySettings.isLayoutOnDemandImportFromSamePackageFirst();
boolean moduleImportFirst = mySettings.isModuleImportFirst();
StringBuilder text =
buildImportListText(resultList,
classesOrPackagesToImportOnDemand.keySet(),
@@ -138,7 +137,7 @@ public final class ImportHelper {
checker,
moduleStatementMap,
onDemandFirst,
moduleImportFirst);
items.moduleIndex());
for (PsiElement nonImport : nonImports) {
text.append("\n").append(nonImport.getText());
}
@@ -239,17 +238,31 @@ public final class ImportHelper {
});
}
public static @NotNull List<Import> sortItemsAccordingToSettings(@NotNull List<Import> imports, @NotNull JavaCodeStyleSettings settings) {
private record SortedImportItems(@NotNull List<Import> imports, int moduleIndex) { }
public static @NotNull List<Import> sortItemsAccordingToSettings(@NotNull List<Import> imports,
@NotNull JavaCodeStyleSettings settings) {
return sortItemsWithModulesAccordingToSettings(imports, settings).imports;
}
private static @NotNull ImportHelper.SortedImportItems sortItemsWithModulesAccordingToSettings(@NotNull List<Import> imports,
@NotNull JavaCodeStyleSettings settings) {
int[] entryForName = ArrayUtil.newIntArray(imports.size());
PackageEntry[] entries = settings.IMPORT_LAYOUT_TABLE.getEntries();
int moduleEntryIndex = findEntryIndex("", false, true, entries);
for (int i = 0; i < imports.size(); i++) {
Import anImport = imports.get(i);
entryForName[i] = findEntryIndex(StringUtil.getPackageName(anImport.name()),
settings.LAYOUT_STATIC_IMPORTS_SEPARATELY && anImport.isStatic(), entries);
settings.LAYOUT_STATIC_IMPORTS_SEPARATELY && anImport.isStatic(), false, entries);
}
List<Import> resultList = new ArrayList<>(imports.size());
int moduleIndex = 0;
for (int i = 0; i < entries.length; i++) {
if (i == moduleEntryIndex) {
moduleIndex = resultList.size();
continue;
}
for (int j = 0; j < imports.size(); j++) {
if (entryForName[j] == i) {
resultList.add(imports.get(j));
@@ -260,7 +273,7 @@ public final class ImportHelper {
for (Import name : imports) {
if (name != null) resultList.add(name);
}
return resultList;
return new SortedImportItems(resultList, moduleIndex);
}
private static @NotNull Set<String> findSingleImports(@NotNull PsiJavaFile file,
@@ -465,13 +478,17 @@ public final class ImportHelper {
@NotNull ImportUtils.ImplicitImportChecker implicitImportContext,
@NotNull Map<String, PsiImportModuleStatement> moduleStatementMap,
boolean onDemandImportsFirst,
boolean moduleImportFirst) {
int moduleIndex) {
Set<String> importedPackagesOrClasses = new HashSet<>();
@NonNls StringBuilder buffer = new StringBuilder();
Set<PsiImportModuleStatement> usedModuleImports = new HashSet<>();
for (Import importedName : imports) {
int indexModuleString = -1;
for (int i = 0; i < imports.size(); i++) {
if (i == moduleIndex) {
indexModuleString = buffer.length();
}
Import importedName = imports.get(i);
String name = importedName.name();
boolean isStatic = importedName.isStatic();
String packageOrClassName = StringUtil.getPackageName(name);
@@ -505,8 +522,8 @@ public final class ImportHelper {
}
if (!moduleStatements.isEmpty()) {
if (moduleImportFirst) {
buffer.insert(0, moduleStatements);
if (indexModuleString != -1) {
buffer.insert(indexModuleString, moduleStatements);
}
else {
buffer.append(moduleStatements);
@@ -879,12 +896,6 @@ public final class ImportHelper {
}
public int getEmptyLinesBetween(@NotNull PsiImportStatementBase statement1, @NotNull PsiImportStatementBase statement2) {
boolean spaceBetweenModuleAndOtherImports = mySettings.SPACE_BETWEEN_MODULE_AND_OTHER_IMPORTS;
boolean isModule1 = statement1 instanceof PsiImportModuleStatement;
boolean isModule2 = statement2 instanceof PsiImportModuleStatement;
if (((isModule1 && !isModule2) || (!(isModule1) && isModule2))) {
return spaceBetweenModuleAndOtherImports ? 1 : 0;
}
int index1 = findEntryIndex(statement1);
int index2 = findEntryIndex(statement2);
if (index1 == index2) return 0;
@@ -922,7 +933,7 @@ public final class ImportHelper {
return table.contains(packageName);
}
private static int findEntryIndex(@NotNull String packageName, boolean isStatic, PackageEntry @NotNull [] entries) {
private static int findEntryIndex(@NotNull String packageName, boolean isStatic, boolean isModule, PackageEntry @NotNull [] entries) {
PackageEntry bestEntry = null;
int bestEntryIndex = -1;
int allOtherStaticIndex = -1;
@@ -939,6 +950,10 @@ public final class ImportHelper {
bestEntry = entry;
bestEntryIndex = i;
}
if (isModule && entry == PackageEntry.ALL_MODULE_IMPORTS) {
bestEntry = entry;
bestEntryIndex = i;
}
}
if (bestEntryIndex == -1 && isStatic && allOtherStaticIndex == -1 && allOtherIndex != -1) {
// if no layout for static imports specified, put them among all others
@@ -949,11 +964,17 @@ public final class ImportHelper {
int findEntryIndex(@NotNull PsiImportStatementBase statement) {
PsiJavaCodeReferenceElement ref = statement.getImportReference();
if (statement instanceof PsiImportModuleStatement) {
return findEntryIndex("",
mySettings.LAYOUT_STATIC_IMPORTS_SEPARATELY && statement instanceof PsiImportStaticStatement,
true,
mySettings.IMPORT_LAYOUT_TABLE.getEntries());
}
if (ref == null) return -1;
String packageName = statement.isOnDemand() ? ref.getCanonicalText() : StringUtil.getPackageName(ref.getCanonicalText());
return findEntryIndex(packageName,
mySettings.LAYOUT_STATIC_IMPORTS_SEPARATELY && statement instanceof PsiImportStaticStatement,
false,
mySettings.IMPORT_LAYOUT_TABLE.getEntries());
}