mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 11:53:49 +07:00
[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:
committed by
intellij-monorepo-bot
parent
dc032bf4a7
commit
46bfa503aa
@@ -171,6 +171,9 @@ 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;
|
||||
public boolean INSERT_INNER_CLASS_IMPORTS;
|
||||
@@ -295,10 +298,27 @@ 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;
|
||||
@@ -338,6 +358,14 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
|
||||
return USE_SINGLE_CLASS_IMPORTS;
|
||||
}
|
||||
|
||||
public boolean isPreserveModuleImports() {
|
||||
return PRESERVE_MODULE_IMPORTS;
|
||||
}
|
||||
|
||||
public void setPreserveModuleImports(boolean value) {
|
||||
PRESERVE_MODULE_IMPORTS = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseSingleClassImports(boolean value) {
|
||||
USE_SINGLE_CLASS_IMPORTS = value;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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"),
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -147,6 +147,7 @@
|
||||
"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,
|
||||
@@ -163,6 +164,7 @@
|
||||
"place_assignment_sign_on_next_line": false,
|
||||
"prefer_longer_names": true,
|
||||
"prefer_parameters_wrap": false,
|
||||
"preserve_module_imports": true,
|
||||
"record_components_wrap": "normal",
|
||||
"repeat_annotations": [
|
||||
"com.jetbrains.First",
|
||||
@@ -222,6 +224,7 @@
|
||||
"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,
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import module my.source.moduleB;
|
||||
import module my.source.moduleA;
|
||||
|
||||
import my.source.moduleA.*;
|
||||
|
||||
class ModuleImportWithPackageImport {
|
||||
Imported module;
|
||||
A a;
|
||||
B b;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import module my.source.moduleA;
|
||||
import module my.source.moduleB;
|
||||
import my.source.moduleA.Imported;
|
||||
|
||||
class ModuleImportWithPackageImport {
|
||||
Imported module;
|
||||
A a;
|
||||
B b;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import module java.base;
|
||||
|
||||
public class beforeSimpleModuleImport {
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import module java.base;
|
||||
|
||||
import one.Super;
|
||||
import two.*;
|
||||
import three.*;
|
||||
|
||||
class DoNotInsertImportForClassVisibleByInheritanceWithModuleConflict implements Super {
|
||||
One one;
|
||||
Two two;
|
||||
Three three;
|
||||
Four four;
|
||||
Five five;
|
||||
Six six;
|
||||
Seven seven;
|
||||
Eight eight;
|
||||
Nine nine;
|
||||
Ten ten;
|
||||
|
||||
Result x() {
|
||||
return new Result();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import one.Super;
|
||||
import three.*;
|
||||
import two.*;
|
||||
|
||||
class DoNotInsertImportForClassVisibleByInheritanceWithModuleConflict implements Super {
|
||||
One one;
|
||||
Two two;
|
||||
Three three;
|
||||
Four four;
|
||||
Five five;
|
||||
Six six;
|
||||
Seven seven;
|
||||
Eight eight;
|
||||
Nine nine;
|
||||
Ten ten;
|
||||
|
||||
Result x() {
|
||||
return new Result();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package main;
|
||||
|
||||
import module java.base;
|
||||
|
||||
import aaa.*;
|
||||
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
new DDD();
|
||||
new EEE();
|
||||
List a = null;
|
||||
Date da =new Date();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package main;
|
||||
|
||||
import module java.base;
|
||||
import aaa.*;
|
||||
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
new DDD();
|
||||
new EEE();
|
||||
List a = null;
|
||||
Date da =new Date();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package aaa;
|
||||
|
||||
import module java.base;
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
new DDD();
|
||||
new EEE();
|
||||
List a = null;
|
||||
Date da =new Date();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package aaa;
|
||||
|
||||
import module java.base;
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
new DDD();
|
||||
new EEE();
|
||||
List a = null;
|
||||
Date da =new Date();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package main;
|
||||
|
||||
import module java.base;
|
||||
|
||||
import aaa.AAA;
|
||||
import aaa.CCC;
|
||||
import aaa.BBB;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
x();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package main;
|
||||
|
||||
import module java.base;
|
||||
|
||||
import aaa.AAA;
|
||||
import aaa.BBB;
|
||||
import aaa.CCC;
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
x();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package main;
|
||||
|
||||
import module java.base;
|
||||
|
||||
import aaa.AAA;
|
||||
import aaa.CCC;
|
||||
import aaa.BBB;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
x();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package main;
|
||||
|
||||
import module java.base;
|
||||
import aaa.AAA;
|
||||
import aaa.BBB;
|
||||
import aaa.CCC;
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
x();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package aaa;
|
||||
|
||||
import module java.base;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
new DDD();
|
||||
new EEE();
|
||||
List a = null;
|
||||
Date da =new Date();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package aaa;
|
||||
|
||||
import module java.base;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
new DDD();
|
||||
new EEE();
|
||||
List a = null;
|
||||
Date da =new Date();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package main;
|
||||
|
||||
import module java.base;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import aaa.AAA;
|
||||
import aaa.CCC;
|
||||
import aaa.BBB;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
List<String> a = new ArrayList<>();
|
||||
a.add("a");
|
||||
Date da =new Date();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package main;
|
||||
|
||||
import module java.base;
|
||||
import aaa.AAA;
|
||||
import aaa.BBB;
|
||||
import aaa.CCC;
|
||||
|
||||
public class Main {
|
||||
void usage() {
|
||||
new ArrayList<>();
|
||||
new AAA();
|
||||
new BBB();
|
||||
new CCC();
|
||||
List<String> a = new ArrayList<>();
|
||||
a.add("a");
|
||||
Date da =new Date();
|
||||
}
|
||||
}
|
||||
@@ -1121,7 +1121,6 @@ public class AddImportActionTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
myFixture.checkResult("""
|
||||
import a.*;
|
||||
import module java.base;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class Test{
|
||||
|
||||
@@ -17,10 +17,12 @@ import com.intellij.lang.LanguageImportStatements;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.lang.java.JavaImportOptimizer;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
@@ -56,6 +58,18 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase {
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
boolean preserveModuleImports = javaSettings.isPreserveModuleImports();
|
||||
boolean moduleImportFirst = javaSettings.isModuleImportFirst();
|
||||
boolean spaceBetweenModuleAndOtherImports = javaSettings.isSpaceBetweenModuleAndOtherImports();
|
||||
Disposer.register(getTestRootDisposable(), new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
javaSettings.setPreserveModuleImports(preserveModuleImports);
|
||||
javaSettings.setModuleImportFirst(moduleImportFirst);
|
||||
javaSettings.setSpaceBetweenModuleAndOtherImports(spaceBetweenModuleAndOtherImports);
|
||||
}
|
||||
});
|
||||
myFixture.enableInspections(new UnusedDeclarationInspection());
|
||||
}
|
||||
|
||||
@@ -526,6 +540,116 @@ public class OptimizeImportsTest extends OptimizeImportsTestCase {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void testImportModuleFirstWithoutSpace() {
|
||||
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.setPreserveModuleImports(true);
|
||||
javaSettings.setModuleImportFirst(true);
|
||||
javaSettings.setSpaceBetweenModuleAndOtherImports(false);
|
||||
doTest();
|
||||
});
|
||||
}
|
||||
|
||||
public void testImportModuleFirstWithSpace() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
myFixture.addClass("package aaa; public class AAA {}");
|
||||
myFixture.addClass("package aaa; public class BBB {}");
|
||||
myFixture.addClass("package aaa; public class CCC {}");
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
javaSettings.setPreserveModuleImports(true);
|
||||
javaSettings.setModuleImportFirst(true);
|
||||
javaSettings.setSpaceBetweenModuleAndOtherImports(true);
|
||||
doTest();
|
||||
});
|
||||
}
|
||||
|
||||
public void testImportModuleOverOtherImports() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
myFixture.addClass("package aaa; public class AAA {}");
|
||||
myFixture.addClass("package aaa; public class BBB {}");
|
||||
myFixture.addClass("package aaa; public class CCC {}");
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
javaSettings.setPreserveModuleImports(true);
|
||||
doTest();
|
||||
});
|
||||
}
|
||||
|
||||
public void testImportModuleConflictWithPackage() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
myFixture.addClass("package aaa; public class AAA {}");
|
||||
myFixture.addClass("package aaa; public class BBB {}");
|
||||
myFixture.addClass("package aaa; public class CCC {}");
|
||||
myFixture.addClass("package aaa; public class DDD {}");
|
||||
myFixture.addClass("package aaa; public class EEE {}");
|
||||
myFixture.addClass("package aaa; public class List {}");
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
javaSettings.setPreserveModuleImports(true);
|
||||
doTest();
|
||||
});
|
||||
}
|
||||
|
||||
public void testImportModuleConflictWithSamePackage() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
myFixture.addClass("package aaa; public class AAA {}");
|
||||
myFixture.addClass("package aaa; public class BBB {}");
|
||||
myFixture.addClass("package aaa; public class CCC {}");
|
||||
myFixture.addClass("package aaa; public class DDD {}");
|
||||
myFixture.addClass("package aaa; public class EEE {}");
|
||||
myFixture.addClass("package aaa; public class List {}");
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
javaSettings.setPreserveModuleImports(true);
|
||||
doTest();
|
||||
});
|
||||
}
|
||||
|
||||
public void testImportModuleOnDemandConflictWithSamePackage() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), () -> {
|
||||
myFixture.addClass("package aaa; public class AAA {}");
|
||||
myFixture.addClass("package aaa; public class BBB {}");
|
||||
myFixture.addClass("package aaa; public class CCC {}");
|
||||
myFixture.addClass("package aaa; public class DDD {}");
|
||||
myFixture.addClass("package aaa; public class EEE {}");
|
||||
myFixture.addClass("package aaa; public class List {}");
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
javaSettings.setPreserveModuleImports(true);
|
||||
doTest();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void testDoNotInsertImportForClassVisibleByInheritanceWithModuleConflict() {
|
||||
myFixture.addClass("""
|
||||
package one;
|
||||
public interface Super {
|
||||
class List {}
|
||||
|
||||
List x();
|
||||
}
|
||||
""");
|
||||
myFixture.addClass("""
|
||||
package two;
|
||||
public class List {}
|
||||
public class One {}
|
||||
public class Two {}
|
||||
public class Three {}
|
||||
public class Four {}
|
||||
public class Five {}
|
||||
""");
|
||||
myFixture.addClass("""
|
||||
package three;
|
||||
public class List {}
|
||||
public class Six {}
|
||||
public class Seven {}
|
||||
public class Eight {}
|
||||
public class Nine {}
|
||||
public class Ten {}
|
||||
""");
|
||||
doTest();
|
||||
}
|
||||
private void doTest() {
|
||||
doTest(".java");
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ package com.intellij.java.psi.resolve;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.java.testFramework.fixtures.LightJava9ModulesCodeInsightFixtureTestCase;
|
||||
import com.intellij.java.testFramework.fixtures.MultiModuleJava9ProjectDescriptor.ModuleDescriptor;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.roots.DependencyScope;
|
||||
@@ -11,9 +12,12 @@ import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -319,6 +323,26 @@ public class ResolveModuleImportTest extends LightJava9ModulesCodeInsightFixture
|
||||
});
|
||||
}
|
||||
|
||||
public void testOptimizeImportWithModuleConflict() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), ()->{
|
||||
prepareAmbiguousModuleTests();
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||
String fileName = getTestName(false) + ".java";
|
||||
try {
|
||||
PsiFile file = myFixture.configureByFile(fileName);
|
||||
JavaCodeStyleManager.getInstance(getProject()).optimizeImports(file);
|
||||
PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
|
||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after" + ".java");
|
||||
PsiTestUtil.checkFileStructure(file);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void testModuleImportWithDefaultPackageImport() {
|
||||
IdeaTestUtil.withLevel(getModule(), JavaFeature.PACKAGE_IMPORTS_SHADOW_MODULE_IMPORTS.getMinimumLevel(), ()->{
|
||||
addCode("module-info.java", """
|
||||
@@ -367,6 +391,10 @@ public class ResolveModuleImportTest extends LightJava9ModulesCodeInsightFixture
|
||||
package my.source.moduleB;
|
||||
public class Imported {}
|
||||
""", M2);
|
||||
addCode("my/source/moduleB/B.java", """
|
||||
package my.source.moduleB;
|
||||
public class B {}
|
||||
""", M2);
|
||||
addCode("module-info.java", """
|
||||
module my.source.moduleA {
|
||||
exports my.source.moduleA;
|
||||
@@ -376,6 +404,10 @@ public class ResolveModuleImportTest extends LightJava9ModulesCodeInsightFixture
|
||||
package my.source.moduleA;
|
||||
public class Imported {}
|
||||
""", M4);
|
||||
addCode("my/source/moduleA/A.java", """
|
||||
package my.source.moduleA;
|
||||
public class A {}
|
||||
""", M4);
|
||||
addCode("Test.java", """
|
||||
""");
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ checkbox.suppress.with.suppresswarnings=Suppress with @SuppressWarnings
|
||||
checkbox.treat.get.k.null.the.same.as.containskey.k.may.change.semantics=Treat 'get(k) != null' the same as 'containsKey(k)' (may change semantics)
|
||||
checkbox.use.fully.qualified.class.names=Use fully qualified class names
|
||||
checkbox.use.single.class.import=Use single class import
|
||||
checkbox.preserve.module.import=Preserve module imports
|
||||
checkbox.use.throws.rather.than.exception=Use @throws rather than @exception
|
||||
checkbox.warn.if.only.foreach.replacement.is.available=Warn if only 'forEach' replacement is available
|
||||
checkbox.warn.if.the.loop.is.trivial=Warn if the loop is trivial
|
||||
@@ -365,6 +366,8 @@ 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
|
||||
@@ -1607,6 +1610,7 @@ import.layout.panel.up.button=Up
|
||||
import.layout.panel.down.button=Down
|
||||
import.layout.panel.blank.line.entry=<blank line>
|
||||
import.layout.panel.all.other.imports=all other imports
|
||||
import.layout.panel.module.imports=module imports
|
||||
edit.contract.dialog.hint=<html>Please specify the contract text<p>Example: <code>_, null -> false</code><br><small>See intention action description for more details</small></html>
|
||||
edit.contract.dialog.mutates.hint=Specify comma-separated elements that can be mutated<p>Example: <code>this,param1</code><p>Leave empty for unspecified side effects.
|
||||
edit.range.dialog.message=Leave empty if unrestricted
|
||||
|
||||
@@ -33,6 +33,8 @@ 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());
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public final class JavaFxImportsOptimizer implements ImportOptimizer {
|
||||
final JavaCodeStyleSettings settings = JavaCodeStyleSettings.getInstance(file);
|
||||
final @NotNull List<ImportHelper.Import> sortedNames = ImportHelper.sortItemsAccordingToSettings(names, settings);
|
||||
final Map<String, Boolean> onDemand = new HashMap<>();
|
||||
ImportHelper.collectOnDemandImports(sortedNames, settings, onDemand);
|
||||
ImportHelper.collectOnDemandImports(sortedNames, settings, onDemand, new HashMap<>());
|
||||
for (String s : demandedForNested) {
|
||||
onDemand.put(s, false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user