[java-import] IDEA-364508 support optimize imports

- new options are added
- changes for optimize imports

(cherry picked from commit 82b0223f9e7e2972d13ab182ea651cdccd28a5d3)

GitOrigin-RevId: 99f0276e1d9464f75f5bbce91ad09727582d208b
This commit is contained in:
Mikhail Pyltsin
2024-12-09 19:11:04 +01:00
committed by intellij-monorepo-bot
parent dc032bf4a7
commit 46bfa503aa
33 changed files with 693 additions and 40 deletions

View File

@@ -21,7 +21,7 @@ public abstract class CodeStyleImportsPanelBase extends JPanel {
protected final ImportLayoutPanel myImportLayoutPanel;
public CodeStyleImportsPanelBase() {
myImportLayoutPanel = new ImportLayoutPanel(isShowLayoutOnDemandImportFromSamePackageFirstCheckbox()) {
myImportLayoutPanel = new ImportLayoutPanel(isShowLayoutOnDemandImportFromSamePackageFirstCheckbox(), isSupportModule()) {
@Override
public void refresh() {
refreshTable(myPackageTable, myPackageList);
@@ -139,4 +139,8 @@ public abstract class CodeStyleImportsPanelBase extends JPanel {
protected boolean isShowLayoutOnDemandImportFromSamePackageFirstCheckbox() {
return false;
}
protected boolean isSupportModule() {
return false;
}
}

View File

@@ -30,6 +30,8 @@ import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author Max Medvedev
@@ -38,6 +40,8 @@ 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();
@@ -59,7 +63,17 @@ public abstract class ImportLayoutPanel extends JPanel {
return myCbLayoutOnDemandImportsFromSamePackageFirst;
}
public ImportLayoutPanel(boolean showLayoutOnDemandImportFromSamePackageFirstCheckbox) {
@Nullable
public JBCheckBox getCbModuleImportFirst() {
return myCbModuleImportFirst;
}
@Nullable
public JBCheckBox getCbSpaceBetweenModuleAndOther() {
return myCbSpaceBetweenModuleAndOther;
}
public ImportLayoutPanel(boolean showLayoutOnDemandImportFromSamePackageFirstCheckbox, boolean supportModuleImport) {
super(new BorderLayout());
myCbLayoutStaticImportsSeparately.addItemListener(e -> {
@@ -118,8 +132,16 @@ public abstract class ImportLayoutPanel extends JPanel {
showLayoutOnDemandImportFromSamePackageFirstCheckbox
? 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,
myCbLayoutOnDemandImportsFromSamePackageFirst,
additionalCheckBoxes,
importLayoutPanel);
add(UI.getPanel(), BorderLayout.CENTER);
}
@@ -231,6 +253,14 @@ 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"),

View File

@@ -7,10 +7,12 @@ import com.intellij.ui.dsl.builder.Align
import com.intellij.ui.dsl.builder.panel
import javax.swing.JPanel
internal class ImportLayoutPanelUI(staticImportsCb: JBCheckBox, onDemandBeforeSingleClassCb: JBCheckBox?, importLayoutPanel: JPanel) {
internal class ImportLayoutPanelUI(staticImportsCb: JBCheckBox, additionalCheckBoxes: List<JBCheckBox?>, importLayoutPanel: JPanel) {
val panel = panel {
group(JavaBundle.message("title.import.layout")) {
if (onDemandBeforeSingleClassCb != null) row { cell(onDemandBeforeSingleClassCb) }
for (box in additionalCheckBoxes) {
if (box != null) row { cell(box) }
}
row { cell(staticImportsCb) }
row { cell(importLayoutPanel).align(Align.FILL) }.resizableRow()
}.resizableRow()

View File

@@ -11,6 +11,7 @@ import com.intellij.ui.table.TableView;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.table.TableCellEditor;
@@ -19,6 +20,8 @@ import java.util.List;
class JavaCodeStyleImportsPanel extends CodeStyleImportsPanelBase {
private FullyQualifiedNamesInJavadocOptionProvider myFqnInJavadocOption;
@Nullable
private JCheckBox myCbPreserveModuleImports;
private ListTableModel<InnerClassItem> doNotInsertInnerListModel;
private static final ColumnInfo<?, ?>[] INNER_CLASS_COLUMNS = {
@@ -36,13 +39,17 @@ class JavaCodeStyleImportsPanel extends CodeStyleImportsPanelBase {
};
private TableView<InnerClassItem> mydoNotInsertInnerTable;
JavaCodeStyleImportsPanel() {
super();
}
@Override
protected CodeStyleImportsBaseUI createKotlinUI(JComponent packages, JComponent importLayout) {
createDoNotImportInnerList();
myCbPreserveModuleImports = new JBCheckBox(JavaBundle.message("checkbox.preserve.module.import"));
myFqnInJavadocOption = new FullyQualifiedNamesInJavadocOptionProvider();
JavaCodeStyleImportsUI result =
new JavaCodeStyleImportsUI(packages, importLayout, mydoNotInsertInnerTable, myFqnInJavadocOption.getPanel());
new JavaCodeStyleImportsUI(packages, importLayout, mydoNotInsertInnerTable, myCbPreserveModuleImports, myFqnInJavadocOption.getPanel());
result.init();
return result;
}
@@ -52,8 +59,12 @@ class JavaCodeStyleImportsPanel extends CodeStyleImportsPanelBase {
final JavaCodeStyleSettings javaSettings = getJavaSettings(settings);
applyLayoutSettings(javaSettings);
myFqnInJavadocOption.apply(settings);
JCheckBox cbPreserveModuleImports = myCbPreserveModuleImports;
if(cbPreserveModuleImports!=null) javaSettings.setPreserveModuleImports(cbPreserveModuleImports.isSelected());
javaSettings.setDoNotImportInner(getInnerClassesNames());
javaSettings.setLayoutOnDemandImportFromSamePackageFirst(myImportLayoutPanel.isLayoutOnDemandImportsFromSamePackageFirst());
javaSettings.setModuleImportFirst(myImportLayoutPanel.isModuleImportFirst());
javaSettings.setSpaceBetweenModuleAndOtherImports(myImportLayoutPanel.isSpaceBetweenModuleAndOther());
}
@Override
@@ -64,8 +75,18 @@ class JavaCodeStyleImportsPanel extends CodeStyleImportsPanelBase {
for (String name : javaSettings.getDoNotImportInner()) {
doNotInsertInnerListModel.addRow(new InnerClassItem(name));
}
JBCheckBox checkBox = myImportLayoutPanel.getCbLayoutOnDemandImportsFromSamePackageFirst();
if (checkBox != null) checkBox.setSelected(javaSettings.isLayoutOnDemandImportFromSamePackageFirst());
JCheckBox cbPreserveModuleImports = myCbPreserveModuleImports;
if (cbPreserveModuleImports != null) cbPreserveModuleImports.setSelected(javaSettings.isPreserveModuleImports());
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
@@ -74,8 +95,18 @@ class JavaCodeStyleImportsPanel extends CodeStyleImportsPanelBase {
boolean isModified = isModifiedLayoutSettings(javaSettings);
isModified |= myFqnInJavadocOption.isModified(settings);
isModified |= !javaSettings.getDoNotImportInner().equals(getInnerClassesNames());
JBCheckBox checkBox = myImportLayoutPanel.getCbLayoutOnDemandImportsFromSamePackageFirst();
if (checkBox != null) isModified |= isModified(checkBox, javaSettings.isLayoutOnDemandImportFromSamePackageFirst());
JCheckBox cbPreserveModuleImports = myCbPreserveModuleImports;
if (cbPreserveModuleImports != null) isModified |= isModified(cbPreserveModuleImports, javaSettings.isPreserveModuleImports());
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;
}
@@ -107,6 +138,11 @@ class JavaCodeStyleImportsPanel extends CodeStyleImportsPanelBase {
return true;
}
@Override
protected boolean isSupportModule() {
return true;
}
private abstract static class MyColumnInfo extends ColumnInfo<InnerClassItem, String> {
MyColumnInfo(final @NlsContexts.ColumnName String name) {
super(name);

View File

@@ -12,10 +12,13 @@ import com.intellij.ui.dsl.builder.Panel
import com.intellij.ui.dsl.gridLayout.UnscaledGaps
import com.intellij.ui.table.TableView
import com.intellij.util.ui.JBDimension
import javax.swing.JCheckBox
import javax.swing.JComponent
internal class JavaCodeStyleImportsUI(packages: JComponent, importLayout: JComponent,
internal class JavaCodeStyleImportsUI(packages: JComponent,
importLayout: JComponent,
private val doNotInsertInnerTable: TableView<InnerClassItem>,
private val preserveModuleImports: JCheckBox,
private val fqnInJavadocOption: JComponent) : CodeStyleImportsBaseUI(packages, importLayout) {
override fun init() {
@@ -26,6 +29,11 @@ internal class JavaCodeStyleImportsUI(packages: JComponent, importLayout: JCompo
}
override fun Panel.fillCustomOptions() {
row {
cell(preserveModuleImports).applyToComponent {
isOpaque = false
}
}
indent {
row {
val decorator = ToolbarDecorator.createDecorator(doNotInsertInnerTable)

View File

@@ -221,7 +221,7 @@ public final class AddSingleMemberStaticImportAction extends PsiUpdateModCommand
if (existingImport == null && resolved instanceof PsiClass) {
((PsiImportHolder) file).importClass((PsiClass) resolved);
}
else if (existingImport == null || existingImport.isOnDemand() && resolvedClass != null && ImportHelper.hasConflictingOnDemandImport((PsiJavaFile)file, resolvedClass, referenceName)) {
else if (existingImport == null || existingImport.isOnDemand() && resolvedClass != null && ImportHelper.hasConflictingOnStaticDemandImport((PsiJavaFile)file, resolvedClass, referenceName)) {
PsiReferenceExpressionImpl.bindToElementViaStaticImport(resolvedClass, referenceName, ((PsiJavaFile)file).getImportList());
}

View File

@@ -101,7 +101,9 @@ public final class ImportHelper {
List<Import> resultList = sortItemsAccordingToSettings(imports, mySettings);
Map<String, Boolean> classesOrPackagesToImportOnDemand = new HashMap<>();
collectOnDemandImports(resultList, mySettings, classesOrPackagesToImportOnDemand);
List<PsiImportModuleStatement> previousModuleStatements = collectModuleImports(file, mySettings);
Map<String, PsiImportModuleStatement> moduleStatementMap = collectNamesImportedByModules(file, previousModuleStatements, resultList);
collectOnDemandImports(resultList, mySettings, classesOrPackagesToImportOnDemand, moduleStatementMap);
MultiMap<String, String> conflictingMemberNames = new MultiMap<>();
for (Import anImport : resultList) {
@@ -120,14 +122,23 @@ public final class ImportHelper {
}
ImportUtils.ImplicitImportChecker checker = ImportUtils.createImplicitImportChecker(file);
Set<String> classesToUseSingle = findSingleImports(file, resultList, classesOrPackagesToImportOnDemand.keySet(), checker);
Set<String> toReimport = calculateOnDemandImportConflicts(file, classesOrPackagesToImportOnDemand);
Set<String> classesToUseSingle = findSingleImports(file, resultList, classesOrPackagesToImportOnDemand.keySet(),
moduleStatementMap.keySet(), checker);
Set<String> toReimport = calculateOnDemandImportConflicts(file, classesOrPackagesToImportOnDemand, moduleStatementMap.values(),
moduleStatementMap.keySet());
classesToUseSingle.addAll(toReimport);
try {
boolean onDemandFirst = mySettings.isLayoutOnDemandImportFromSamePackageFirst();
boolean moduleImportFirst = mySettings.isModuleImportFirst();
StringBuilder text =
buildImportListText(resultList, classesOrPackagesToImportOnDemand.keySet(), classesToUseSingle, checker, onDemandFirst);
buildImportListText(resultList,
classesOrPackagesToImportOnDemand.keySet(),
classesToUseSingle,
checker,
moduleStatementMap,
onDemandFirst,
moduleImportFirst);
for (PsiElement nonImport : nonImports) {
text.append("\n").append(nonImport.getText());
}
@@ -149,12 +160,67 @@ public final class ImportHelper {
}
}
/**
* Collects the names of classes that are imported by modules specified implicitly in the given Java file and in import list.
*
* @param file the Java file for which imported class names are being collected.
* @param statements a list of import module statements that specify the modules from which classes are imported.
* @param list a list of import objects representing the imports from which class names need to be collected.
* @return a map of class names and used module imports.
*/
@NotNull
private static Map<String, PsiImportModuleStatement> collectNamesImportedByModules(@NotNull PsiJavaFile file,
@NotNull List<PsiImportModuleStatement> statements,
@NotNull List<Import> list) {
List<PsiImportStatementBase> implicitImports = ImportsUtil.getAllImplicitImports(file);
List<PsiImportModuleStatement> moduleImports =
new ArrayList<>(ContainerUtil.filterIsInstance(implicitImports, PsiImportModuleStatement.class));
moduleImports.addAll(statements);
Map<String, PsiImportModuleStatement> usedClasses = new HashMap<>();
for (Import anImport : list) {
if (anImport.isStatic) continue;
String qualifiedName = anImport.name();
String referencePackageName = StringUtil.getPackageName(qualifiedName);
String referenceShortName = StringUtil.getShortName(qualifiedName);
if (referencePackageName.isEmpty() || referenceShortName.isEmpty()) continue;
for (PsiImportModuleStatement statement : moduleImports) {
PsiPackageAccessibilityStatement importedPackage = statement.findImportedPackage(referencePackageName);
if (importedPackage == null) continue;
PsiJavaCodeReferenceElement packageReference = importedPackage.getPackageReference();
if (packageReference == null) continue;
PsiElement resolved = packageReference.resolve();
if (!(resolved instanceof PsiPackage psiPackage)) continue;
if (!psiPackage.containsClassNamed(referenceShortName)) continue;
usedClasses.put(anImport.name, statement);
}
}
return usedClasses;
}
/**
* Collects the module import statements from the specified Java file, considering the code style settings, to insert in the new import list
*
* @param file the Java file from which module import statements are collected.
* @param settings the code style settings that determine whether module imports should be preserved.
* @return a list of module import statements present in the Java file.
*/
@NotNull
private static List<PsiImportModuleStatement> collectModuleImports(@NotNull PsiJavaFile file, JavaCodeStyleSettings settings) {
if (!settings.isPreserveModuleImports()) return Collections.emptyList();
PsiImportList importList = file.getImportList();
if (importList == null) return Collections.emptyList();
return Arrays.asList(importList.getImportModuleStatements());
}
public static void collectOnDemandImports(@NotNull List<Import> resultList,
@NotNull JavaCodeStyleSettings settings,
@NotNull Map<String, Boolean> outClassesOrPackagesToImportOnDemand) {
@NotNull Map<String, Boolean> outClassesOrPackagesToImportOnDemand,
@NotNull Map<String, PsiImportModuleStatement> moduleStatementMap) {
Object2IntMap<String> packageToCountMap = new Object2IntOpenHashMap<>();
Object2IntMap <String> classToCountMap = new Object2IntOpenHashMap<>();
for (Import anImport : resultList) {
if (!anImport.isStatic() && moduleStatementMap.containsKey(anImport.name)) continue;
String packageOrClassName = StringUtil.getPackageName(anImport.name());
if (packageOrClassName.isEmpty()) continue;
Object2IntMap<String> map = anImport.isStatic() ? classToCountMap : packageToCountMap;
@@ -200,6 +266,7 @@ public final class ImportHelper {
private static @NotNull Set<String> findSingleImports(@NotNull PsiJavaFile file,
@NotNull Collection<Import> imports,
@NotNull Set<String> onDemandImports,
@NotNull Set<String> namesImportedByModuleStatements,
@NotNull ImportUtils.ImplicitImportChecker checker) {
GlobalSearchScope resolveScope = file.getResolveScope();
String thisPackageName = file.getPackageName();
@@ -213,7 +280,7 @@ public final class ImportHelper {
String prefix = StringUtil.getPackageName(name);
if (prefix.isEmpty()) continue;
boolean isImplicitlyImported = checker.isImplicitlyImported(name, anImport.isStatic());
if (!onDemandImports.contains(prefix) && !isImplicitlyImported) continue;
if (!onDemandImports.contains(prefix) && !isImplicitlyImported && !namesImportedByModuleStatements.contains(name)) continue;
String shortName = PsiNameHelper.getShortClassName(name);
String thisPackageClass = !thisPackageName.isEmpty() ? thisPackageName + "." + shortName : shortName;
@@ -280,11 +347,16 @@ public final class ImportHelper {
return false;
}
private static Set<String> calculateOnDemandImportConflicts(@NotNull PsiJavaFile file, @NotNull Map<String, Boolean> onDemandImports) {
private static Set<String> calculateOnDemandImportConflicts(@NotNull PsiJavaFile file,
@NotNull Map<String, Boolean> onDemandImports,
@NotNull Collection<PsiImportModuleStatement> usedModuleStatements,
@NotNull Set<String> namesImportedByModuleStatements) {
if (file instanceof PsiCompiledElement) return Collections.emptySet();
List<PsiImportStatementBase> implicitImports = ImportsUtil.getAllImplicitImports(file);
List<PsiImportModuleStatement> implicitModuleImports =
ContainerUtil.filterIsInstance(implicitImports, PsiImportModuleStatement.class);
List<PsiImportModuleStatement> moduleImports =
new ArrayList<>(ContainerUtil.filterIsInstance(implicitImports, PsiImportModuleStatement.class));
moduleImports.addAll(usedModuleStatements);
List<String> onDemands =
StreamEx.of(implicitImports)
.filter(implicit -> implicit.isOnDemand() &&
@@ -296,7 +368,7 @@ public final class ImportHelper {
onDemands.add(onDemand);
}
}
if (implicitModuleImports.isEmpty() && onDemands.size() < 2) return Collections.emptySet();
if (moduleImports.isEmpty() && onDemands.size() < 2) return Collections.emptySet();
// if we have classes x.A, x.B and there is an "import x.*" then classNames = {"x" -> ("A", "B")}
GlobalSearchScope resolveScope = file.getResolveScope();
@@ -339,7 +411,7 @@ public final class ImportHelper {
conflicts.addAll(intersection);
}
}
if (implicitModuleImports.isEmpty() && conflicts.isEmpty()) return Collections.emptySet();
if (moduleImports.isEmpty() && conflicts.isEmpty()) return Collections.emptySet();
Set<String> result = new HashSet<>();
String filePackageName = file.getPackageName();
@@ -360,14 +432,13 @@ public final class ImportHelper {
//conflict with packages
boolean hasConflict = conflicts.contains(psiClass.getName());
if (!hasConflict) {
//check conflict only with implicit module imports
//explicit module imports should be checked separately, right now it is not supported
//if it is already imported by on demands, there is no conflict with modules
if (!(PsiUtil.isAvailable(JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS, file) &&
classNames.getOrDefault(referencePackageName, Collections.emptySet()).contains(referenceShortName))) {
hasConflict = !implicitModuleImports.isEmpty() &&
ImportUtils.hasOnDemandImportConflictWithImports(file, implicitModuleImports, qualifiedName, false, true);
classNames.getOrDefault(referencePackageName, Collections.emptySet()).contains(referenceShortName)) ||
//with PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS conflicts are possible only between modules, other types of imports should be more important
namesImportedByModuleStatements.contains(qualifiedName)) {
hasConflict = !moduleImports.isEmpty() &&
ImportUtils.hasOnDemandImportConflictWithImports(file, moduleImports, qualifiedName, false, true);
}
}
if (!hasConflict) return;
@@ -392,9 +463,14 @@ public final class ImportHelper {
@NotNull Set<String> packagesOrClassesToImportOnDemand,
@NotNull Set<String> namesToUseSingle,
@NotNull ImportUtils.ImplicitImportChecker implicitImportContext,
boolean onDemandImportsFirst) {
@NotNull Map<String, PsiImportModuleStatement> moduleStatementMap,
boolean onDemandImportsFirst,
boolean moduleImportFirst) {
Set<String> importedPackagesOrClasses = new HashSet<>();
@NonNls StringBuilder buffer = new StringBuilder();
Set<PsiImportModuleStatement> usedModuleImports = new HashSet<>();
for (Import importedName : imports) {
String name = importedName.name();
boolean isStatic = importedName.isStatic();
@@ -412,10 +488,31 @@ public final class ImportHelper {
appendImportStatement(name, isStatic, buffer);
}
}
else if (!implicitlyImported && !importedPackagesOrClasses.contains(packageOrClassName)) {
else if (!implicitlyImported && !importedPackagesOrClasses.contains(packageOrClassName) && !moduleStatementMap.containsKey(name)) {
appendImportStatement(name, isStatic, buffer);
}
else if (!implicitlyImported && !importedPackagesOrClasses.contains(packageOrClassName) && moduleStatementMap.containsKey(name)) {
usedModuleImports.add(moduleStatementMap.get(name));
}
}
StringBuilder moduleStatements = new StringBuilder();
for (String importModuleStatement : usedModuleImports.stream()
.map(m->m.getText())
.sorted(Comparator.naturalOrder())
.toList()) {
moduleStatements.append(importModuleStatement).append("\n");
}
if (!moduleStatements.isEmpty()) {
if (moduleImportFirst) {
buffer.insert(0, moduleStatements);
}
else {
buffer.append(moduleStatements);
}
}
return buffer;
}
@@ -782,6 +879,12 @@ 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;
@@ -798,7 +901,8 @@ public final class ImportHelper {
//noinspection AssignmentToForLoopParameter
do {
space++;
} while (entries[++i] == PackageEntry.BLANK_LINE_ENTRY);
}
while (entries[++i] == PackageEntry.BLANK_LINE_ENTRY);
maxSpace = Math.max(maxSpace, space);
}
}
@@ -848,11 +952,12 @@ public final class ImportHelper {
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,
mySettings.IMPORT_LAYOUT_TABLE.getEntries());
}
public static boolean hasConflictingOnDemandImport(@NotNull PsiJavaFile file, @NotNull PsiClass psiClass, @NotNull String referenceName) {
public static boolean hasConflictingOnStaticDemandImport(@NotNull PsiJavaFile file, @NotNull PsiClass psiClass, @NotNull String referenceName) {
Collection<Import> resultList = collectNamesToImport(file, new ArrayList<>());
String qualifiedName = psiClass.getQualifiedName();
for (Import anImport : resultList) {
@@ -875,7 +980,7 @@ public final class ImportHelper {
.collect(Collectors.toSet());
String newImport = StringUtil.getQualifiedName(qualifiedName, referenceName);
Set<String> singleImports = findSingleImports(file, Collections.singletonList(new Import(newImport, true)), onDemandImportedClasses,
ImportUtils.createImplicitImportChecker(file));
Collections.emptySet(), ImportUtils.createImplicitImportChecker(file));
return singleImports.contains(newImport);
}

View File

@@ -130,7 +130,7 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
@Override
public boolean hasConflictingOnDemandImport(@NotNull PsiJavaFile file, @NotNull PsiClass psiClass, @NotNull String referenceName) {
return ImportHelper.hasConflictingOnDemandImport(file, psiClass, referenceName);
return ImportHelper.hasConflictingOnStaticDemandImport(file, psiClass, referenceName);
}
@Override