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

@@ -10,6 +10,7 @@ import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings.WrapConstant;
import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
@@ -171,8 +172,6 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
// Imports
public boolean LAYOUT_STATIC_IMPORTS_SEPARATELY = true;
public boolean LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST = true;
public boolean MODULE_IMPORT_FIRST = true;
public boolean SPACE_BETWEEN_MODULE_AND_OTHER_IMPORTS = false;
public boolean PRESERVE_MODULE_IMPORTS = true;
public boolean USE_FQ_CLASS_NAMES;
public boolean USE_SINGLE_CLASS_IMPORTS = true;
@@ -298,27 +297,10 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
return LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST;
}
public boolean isModuleImportFirst() {
return MODULE_IMPORT_FIRST;
}
public boolean isSpaceBetweenModuleAndOtherImports() {
return SPACE_BETWEEN_MODULE_AND_OTHER_IMPORTS;
}
public void setLayoutOnDemandImportFromSamePackageFirst(boolean value) {
this.LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST = value;
}
public void setModuleImportFirst(boolean value) {
this.MODULE_IMPORT_FIRST = value;
}
public void setSpaceBetweenModuleAndOtherImports(boolean value) {
SPACE_BETWEEN_MODULE_AND_OTHER_IMPORTS = value;
}
@Override
public int getNamesCountToUseImportOnDemand() {
return NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND;
@@ -394,6 +376,7 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
private void initImportsByDefault() {
PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false, "java.awt", false));
PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false,"javax.swing", false));
IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_MODULE_IMPORTS);
IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "javax", true));
@@ -470,6 +453,10 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
readExternalCollection(parentElement, myDoNotImportInner, DO_NOT_IMPORT_INNER, DO_NOT_IMPORT_INNER_ITEM);
myOldVersion = myVersion = CustomCodeStyleSettingsUtils.readVersion(parentElement.getChild(getTagName()));
myIsInitialized = true;
PackageEntry[] entries = IMPORT_LAYOUT_TABLE.getEntries();
if (!ContainerUtil.exists(entries, entry -> entry == PackageEntry.ALL_MODULE_IMPORTS)) {
IMPORT_LAYOUT_TABLE.setEntryAt(PackageEntry.ALL_MODULE_IMPORTS, 0);
}
}
@Override

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());
}

View File

@@ -106,6 +106,7 @@
"generate_use_type_annotation_before_type": true,
"if_brace_force": "never",
"imports_layout": [
"@*",
"*",
"|",
"javax.**",
@@ -147,7 +148,6 @@
"method_parameters_right_paren_on_new_line": false,
"method_parameters_wrap": "normal",
"modifier_list_wrap": false,
"module_import_first": true,
"multi_catch_types_wrap": "normal",
"names_count_to_use_import_on_demand": 3,
"new_line_after_lparen_in_annotation": false,
@@ -224,7 +224,6 @@
"space_before_while_keyword": true,
"space_before_while_left_brace": true,
"space_before_while_parentheses": true,
"space_between_module_and_other_imports": false,
"space_inside_one_line_enum_braces": false,
"space_within_empty_array_initializer_braces": false,
"space_within_empty_method_call_parentheses": false,

View File

@@ -3,8 +3,8 @@ package main;
import module java.base;
import aaa.AAA;
import aaa.CCC;
import aaa.BBB;
import ccc.CCC;
import bbb.BBB;
import java.util.ArrayList;

View File

@@ -3,8 +3,8 @@ package main;
import module java.base;
import aaa.AAA;
import aaa.BBB;
import aaa.CCC;
import bbb.BBB;
import ccc.CCC;
public class Main {
void usage() {

View File

@@ -0,0 +1,17 @@
package main;
import aaa.AAA;
import bbb.BBB;
import ccc.CCC;
import module java.base;
public class Main {
void usage() {
new ArrayList<>();
new AAA();
new BBB();
new CCC();
x();
}
}

View File

@@ -1,9 +1,9 @@
package main;
import module java.base;
import aaa.AAA;
import aaa.BBB;
import aaa.CCC;
import module java.base;
import bbb.BBB;
import ccc.CCC;
public class Main {
void usage() {

View File

@@ -3,8 +3,8 @@ package main;
import module java.base;
import aaa.AAA;
import aaa.CCC;
import aaa.BBB;
import ccc.CCC;
import bbb.BBB;
import java.util.ArrayList;

View File

@@ -0,0 +1,16 @@
package main;
import aaa.AAA;
import bbb.BBB;
import ccc.CCC;
import module java.base;
public class Main {
void usage() {
new ArrayList<>();
new AAA();
new BBB();
new CCC();
x();
}
}

View File

@@ -1,6 +1,7 @@
package aaa;
import module java.base;
import java.util.List;
public class Main {

View File

@@ -5,8 +5,8 @@ import module java.base;
import java.util.List;
import java.util.*;
import aaa.AAA;
import aaa.CCC;
import aaa.BBB;
import ccc.CCC;
import bbb.BBB;
import java.util.ArrayList;

View File

@@ -2,8 +2,8 @@ package main;
import module java.base;
import aaa.AAA;
import aaa.BBB;
import aaa.CCC;
import bbb.BBB;
import ccc.CCC;
public class Main {
void usage() {

View File

@@ -203,6 +203,7 @@ public class ImportHelperTest extends LightDaemonAnalyzerTestCase {
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
javaSettings.LAYOUT_STATIC_IMPORTS_SEPARATELY = true;
PackageEntryTable table = new PackageEntryTable();
table.addEntry(PackageEntry.ALL_MODULE_IMPORTS);
table.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
table.addEntry(PackageEntry.BLANK_LINE_ENTRY);
table.addEntry(new PackageEntry(false, "javax", true));

View File

@@ -84,6 +84,8 @@ public class LightOptimizeImportsTest extends LightJavaCodeInsightFixtureTestCas
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
javaSettings.LAYOUT_STATIC_IMPORTS_SEPARATELY = false;
javaSettings.IMPORT_LAYOUT_TABLE = new PackageEntryTable();
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_MODULE_IMPORTS);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "aaa", true));
@@ -135,7 +137,8 @@ public class LightOptimizeImportsTest extends LightJavaCodeInsightFixtureTestCas
myFixture.configureByText(JavaFileType.INSTANCE, text);
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
javaSettings.IMPORT_LAYOUT_TABLE.insertEntryAt(new PackageEntry(false, "bbb", false), 1);
//1 is module import
javaSettings.IMPORT_LAYOUT_TABLE.insertEntryAt(new PackageEntry(false, "bbb", false), 1 + 1);
WriteCommandAction.runWriteCommandAction(getProject(), () -> JavaCodeStyleManager.getInstance(getProject()).optimizeImports(getFile()));
@Language("JAVA") String result = """

View File

@@ -1108,8 +1108,8 @@ public class AddImportActionTest extends LightJavaCodeInsightFixtureTestCase {
myFixture.addClass("package a; public class List {}");
myFixture.configureByText("Test.java", """
import a.*;
import module java.base;
import a.*;
class Test{
void main(){
java.util.L<caret>ist x;
@@ -1119,8 +1119,9 @@ public class AddImportActionTest extends LightJavaCodeInsightFixtureTestCase {
reimportClass();
myFixture.checkResult("""
import a.*;
import module java.base;
import a.*;
import java.util.List;
class Test{

View File

@@ -60,14 +60,12 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase {
super.setUp();
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
boolean preserveModuleImports = javaSettings.isPreserveModuleImports();
boolean moduleImportFirst = javaSettings.isModuleImportFirst();
boolean spaceBetweenModuleAndOtherImports = javaSettings.isSpaceBetweenModuleAndOtherImports();
PackageEntryTable table = javaSettings.IMPORT_LAYOUT_TABLE;
Disposer.register(getTestRootDisposable(), new Disposable() {
@Override
public void dispose() {
javaSettings.setPreserveModuleImports(preserveModuleImports);
javaSettings.setModuleImportFirst(moduleImportFirst);
javaSettings.setSpaceBetweenModuleAndOtherImports(spaceBetweenModuleAndOtherImports);
javaSettings.IMPORT_LAYOUT_TABLE = table;
}
});
myFixture.enableInspections(new UnusedDeclarationInspection());
@@ -514,6 +512,7 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase {
settings -> {
JavaCodeStyleSettings javaSettings = settings.getCustomSettings(JavaCodeStyleSettings.class);
javaSettings.IMPORT_LAYOUT_TABLE = new PackageEntryTable();
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_MODULE_IMPORTS);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
@@ -541,15 +540,42 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase {
}
public void testImportModuleFirstWithoutSpace() {
public void testImportModuleLastWithoutSpace() {
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
myFixture.addClass("package aaa; public class AAA {}");
myFixture.addClass("package bbb; public class BBB {}");
myFixture.addClass("package ccc; public class CCC {}");
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
javaSettings.IMPORT_LAYOUT_TABLE = new PackageEntryTable();
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_MODULE_IMPORTS);
javaSettings.setPreserveModuleImports(true);
doTest();
});
}
public void testImportModuleInTheMiddleWithoutSpace() {
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
myFixture.addClass("package aaa; public class AAA {}");
myFixture.addClass("package bbb; public class BBB {}");
myFixture.addClass("package ccc; public class CCC {}");
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
javaSettings.IMPORT_LAYOUT_TABLE = new PackageEntryTable();
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "aaa", false));
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_MODULE_IMPORTS);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "bbb", false));
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
javaSettings.setPreserveModuleImports(true);
javaSettings.setModuleImportFirst(true);
javaSettings.setSpaceBetweenModuleAndOtherImports(false);
doTest();
});
}
@@ -561,8 +587,14 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase {
myFixture.addClass("package aaa; public class CCC {}");
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
javaSettings.setPreserveModuleImports(true);
javaSettings.setModuleImportFirst(true);
javaSettings.setSpaceBetweenModuleAndOtherImports(true);
javaSettings.IMPORT_LAYOUT_TABLE = new PackageEntryTable();
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_MODULE_IMPORTS);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
javaSettings.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
doTest();
});
}

View File

@@ -366,8 +366,6 @@ ignore.imports.and.formatting=Ignore imports and formatting
illegal.name.validation.info=Illegal name: {0}
import.layout.static.imports.separately=Layout static imports separately
import.layout.on.demand.import.from.same.package.first=Place on-demand import before single-class imports from the same package
import.layout.module.import.first=Place module imports at the beginning of import table (otherwise at the end of import table)
import.layout.space.between.module.import.other=Put empty line between module imports and other imports
import.statically=Import statically
include.accessors=&Include Accessors
infer.nullity.progress=Post-processing results\u2026

View File

@@ -26,6 +26,8 @@ c:com.intellij.openapi.editor.EditorModificationUtilEx
- a:indent(com.intellij.psi.PsiFile,I):java.lang.String
- s:indentLine(com.intellij.psi.PsiFile,I):java.lang.String
- s:useExternalFormatter(com.intellij.psi.PsiFile):Z
c:com.intellij.psi.codeStyle.PackageEntry
- *sf:ALL_MODULE_IMPORTS:com.intellij.psi.codeStyle.PackageEntry
*:com.intellij.psi.codeStyle.modifier.CodeStyleSettingsModifier
- sf:EP_NAME:com.intellij.openapi.extensions.ExtensionPointName
- getDisablingFunction(com.intellij.openapi.project.Project):java.util.function.Consumer

View File

@@ -3,6 +3,7 @@ package com.intellij.psi.codeStyle;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -74,8 +75,16 @@ public class PackageEntry {
}
};
@ApiStatus.Experimental
public static final PackageEntry ALL_MODULE_IMPORTS = new PackageEntry(false, "<all module imports>", true){
@Override
public boolean matchesPackageName(String packageName) {
return false;
}
};
public boolean isSpecial() {
return this == BLANK_LINE_ENTRY || this == ALL_OTHER_IMPORTS_ENTRY || this == ALL_OTHER_STATIC_IMPORTS_ENTRY;
return this == BLANK_LINE_ENTRY || this == ALL_OTHER_IMPORTS_ENTRY || this == ALL_OTHER_STATIC_IMPORTS_ENTRY || this == ALL_MODULE_IMPORTS;
}
public boolean isBetterMatchForPackageThan(@Nullable PackageEntry entry, @NotNull String packageName, boolean isStatic) {

View File

@@ -110,13 +110,19 @@ public class PackageEntryTable implements JDOMExternalizable, Cloneable {
if ("package".equals(name)) {
String packageName = e.getAttributeValue("name");
boolean isStatic = Boolean.parseBoolean(e.getAttributeValue("static"));
boolean isModule = Boolean.parseBoolean(e.getAttributeValue("module"));
boolean withSubpackages = Boolean.parseBoolean(e.getAttributeValue("withSubpackages"));
if (packageName == null) {
throw new InvalidDataException();
}
PackageEntry entry;
if (packageName.isEmpty()) {
entry = isStatic ? PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY : PackageEntry.ALL_OTHER_IMPORTS_ENTRY;
if (isModule) {
entry = PackageEntry.ALL_MODULE_IMPORTS;
}
else {
entry = isStatic ? PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY : PackageEntry.ALL_OTHER_IMPORTS_ENTRY;
}
}
else {
entry = new PackageEntry(isStatic, packageName, withSubpackages);
@@ -142,9 +148,14 @@ public class PackageEntryTable implements JDOMExternalizable, Cloneable {
@NonNls Element element = new Element("package");
parentNode.addContent(element);
String packageName = entry.getPackageName();
element.setAttribute("name", entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY || entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY ? "": packageName);
element.setAttribute("name", entry == PackageEntry.ALL_OTHER_IMPORTS_ENTRY ||
entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY ||
entry == PackageEntry.ALL_MODULE_IMPORTS ? "": packageName);
element.setAttribute("withSubpackages", entry.isWithSubpackages() ? "true" : "false");
element.setAttribute("static", entry.isStatic() ? "true" : "false");
if (entry == PackageEntry.ALL_MODULE_IMPORTS) {
element.setAttribute("module", "true");
}
}
}
}

View File

@@ -33,8 +33,6 @@ public class EclipseCodeStylePropertiesImporter implements EclipseFormatterOptio
importStarImportThresholds(uiPreferences, javaSettings);
javaSettings.LAYOUT_STATIC_IMPORTS_SEPARATELY = true;
javaSettings.LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST = true;
javaSettings.MODULE_IMPORT_FIRST = true;
javaSettings.SPACE_BETWEEN_MODULE_AND_OTHER_IMPORTS = false;
javaSettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(new PackageEntryTable());
}
@@ -42,6 +40,7 @@ public class EclipseCodeStylePropertiesImporter implements EclipseFormatterOptio
String oderOfImportsValue = uiPreferences.getProperty(OPTION_IMPORT_ORDER);
if (oderOfImportsValue != null) {
PackageEntryTable importLayoutTable = new PackageEntryTable();
importLayoutTable.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
importLayoutTable.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
String[] chunks = oderOfImportsValue.split(";");
for (String importString : chunks) {