[java-formatter] IDEA-374207 Move PackageEntryTable to java module

GitOrigin-RevId: d97e192e615f88606b6d34a3e8c1e1061d09963e
This commit is contained in:
Mikhail Pyltsin
2025-11-03 12:02:03 +00:00
committed by intellij-monorepo-bot
parent 7a59af143c
commit 8ed129fde0
15 changed files with 436 additions and 108 deletions
@@ -85,5 +85,11 @@
<completion.frontendFriendlyInsertHandler handler="com.intellij.codeInsight.completion.method.MethodCallInstallerHandler"/>
<completion.frontendFriendlyInsertHandler handler="com.intellij.codeInsight.completion.method.NegationInsertHandler"/>
<registryKey key="code.style.package.entry.table.check.compatibility"
defaultValue="true"
description="Enable checks that the import layout is compatible"
restartRequired="true"/>
</extensions>
</idea-plugin>
@@ -4,7 +4,7 @@ package com.intellij.application.options
import com.intellij.java.frontback.impl.JavaFrontbackBundle
import com.intellij.openapi.application.ApplicationBundle
import com.intellij.openapi.ui.DialogPanel
import com.intellij.psi.codeStyle.ImportsLayoutSettings
import com.intellij.psi.codeStyle.JavaImportsLayoutSettings
import com.intellij.ui.dsl.builder.Align
import com.intellij.ui.dsl.builder.Panel
import com.intellij.ui.dsl.builder.columns
@@ -65,7 +65,7 @@ open class CodeStyleImportsBaseUI(private val packages: JComponent, private val
open fun Panel.fillCustomOptions() {}
open fun reset(settings: ImportsLayoutSettings) {
open fun reset(settings: JavaImportsLayoutSettings) {
cbUseFQClassNames.setSelected(settings.isUseFqClassNames())
cbUseSingleClassImports.setSelected(settings.isUseSingleClassImports())
cbInsertInnerClassImports.setSelected(settings.isInsertInnerClassImports())
@@ -73,7 +73,7 @@ open class CodeStyleImportsBaseUI(private val packages: JComponent, private val
namesCountField.text = settings.getNamesCountToUseImportOnDemand().toString()
}
fun apply(settings: ImportsLayoutSettings) {
fun apply(settings: JavaImportsLayoutSettings) {
settings.setUseFqClassNames(cbUseFQClassNames.isSelected)
settings.setUseSingleClassImports(cbUseSingleClassImports.isSelected)
settings.setInsertInnerClassImports(cbInsertInnerClassImports.isSelected)
@@ -87,7 +87,7 @@ open class CodeStyleImportsBaseUI(private val packages: JComponent, private val
}
}
fun isModified(settings: ImportsLayoutSettings): Boolean {
fun isModified(settings: JavaImportsLayoutSettings): Boolean {
return cbUseSingleClassImports.isSelected != settings.isUseSingleClassImports()
|| cbUseFQClassNames.isSelected != settings.isUseFqClassNames()
|| cbInsertInnerClassImports.isSelected != settings.isInsertInnerClassImports()
@@ -1,10 +1,7 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.application.options;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.ImportsLayoutSettings;
import com.intellij.psi.codeStyle.PackageEntry;
import com.intellij.psi.codeStyle.PackageEntryTable;
import com.intellij.psi.codeStyle.*;
import com.intellij.ui.TableUtil;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.ui.table.JBTable;
@@ -56,7 +53,7 @@ public abstract class CodeStyleImportsPanelBase extends JPanel {
ImportLayoutPanel.resizeColumns(packageTable, table, myImportLayoutPanel.areStaticImportsEnabled());
}
public void resetLayoutSettings(ImportsLayoutSettings settings) {
public void resetLayoutSettings(JavaImportsLayoutSettings settings) {
kotlinUI.reset(settings);
myImportLayoutPanel.getImportLayoutList().copyFrom(settings.getImportLayoutTable());
@@ -79,7 +76,7 @@ public abstract class CodeStyleImportsPanelBase extends JPanel {
}
}
public void applyLayoutSettings(ImportsLayoutSettings settings) {
public void applyLayoutSettings(JavaImportsLayoutSettings settings) {
stopTableEditing();
settings.setLayoutStaticImportsSeparately(myImportLayoutPanel.areStaticImportsEnabled());
@@ -89,7 +86,7 @@ public abstract class CodeStyleImportsPanelBase extends JPanel {
settings.getPackagesToUseImportOnDemand().copyFrom(getCopyWithoutEmptyPackages(myPackageList));
}
public boolean isModifiedLayoutSettings(ImportsLayoutSettings settings) {
public boolean isModifiedLayoutSettings(JavaImportsLayoutSettings settings) {
boolean isModified = isModified(myImportLayoutPanel.getCbLayoutStaticImportsSeparately(), settings.isLayoutStaticImportsSeparately());
isModified |= kotlinUI.isModified(settings);
@@ -3,6 +3,7 @@ package com.intellij.application.options
import com.intellij.application.options.JavaCodeStyleImportsPanel.InnerClassItem
import com.intellij.psi.codeStyle.ImportsLayoutSettings
import com.intellij.psi.codeStyle.JavaImportsLayoutSettings
import com.intellij.ui.AnActionButtonRunnable
import com.intellij.ui.TableUtil
import com.intellij.ui.ToolbarDecorator
@@ -60,7 +61,7 @@ internal class JavaCodeStyleImportsUI(packages: JComponent,
}
}
override fun reset(settings: ImportsLayoutSettings) {
override fun reset(settings: JavaImportsLayoutSettings) {
super.reset(settings)
doNotInsertInnerTable.setEnabled(cbInsertInnerClassImports.model.isSelected)
@@ -4,7 +4,9 @@ package com.intellij.psi.codeStyle;
import com.intellij.application.options.CodeStyle;
import com.intellij.configurationStore.Property;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.PsiFile;
@@ -20,8 +22,9 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements ImportsLayoutSettings {
public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements JavaImportsLayoutSettings {
private static final int CURRENT_VERSION = 1;
private static final @NotNull Logger LOG = Logger.getInstance(JavaCodeStyleSettings.class);
private int myVersion = CURRENT_VERSION;
private int myOldVersion = 0;
@@ -186,6 +189,7 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
public PackageEntryTable PACKAGES_TO_USE_IMPORT_ON_DEMAND = new PackageEntryTable();
@Property(externalName = "imports_layout")
public PackageEntryTable IMPORT_LAYOUT_TABLE = new PackageEntryTable();
private JavaLegacySettings legacySettings = new JavaLegacySettings();
private boolean updatedModuleImportLayout = false;
@@ -440,8 +444,8 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
INSERT_INNER_CLASS_IMPORTS = rootSettings.INSERT_INNER_CLASS_IMPORTS;
CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND = rootSettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND;
NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND = rootSettings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND;
PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(rootSettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND);
IMPORT_LAYOUT_TABLE.copyFrom(rootSettings.IMPORT_LAYOUT_TABLE);
PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(legacySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND);
IMPORT_LAYOUT_TABLE.copyFrom(legacySettings.IMPORT_LAYOUT_TABLE);
FIELD_NAME_PREFIX = rootSettings.FIELD_NAME_PREFIX;
STATIC_FIELD_NAME_PREFIX = rootSettings.STATIC_FIELD_NAME_PREFIX;
PARAMETER_NAME_PREFIX = rootSettings.PARAMETER_NAME_PREFIX;
@@ -469,6 +473,8 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
cloned.setRepeatAnnotations(getRepeatAnnotations());
cloned.PACKAGES_TO_USE_IMPORT_ON_DEMAND = new PackageEntryTable();
cloned.PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(PACKAGES_TO_USE_IMPORT_ON_DEMAND);
cloned.legacySettings = new JavaLegacySettings();
cloned.legacySettings.copyFrom(legacySettings);
cloned.IMPORT_LAYOUT_TABLE = new PackageEntryTable();
cloned.IMPORT_LAYOUT_TABLE.copyFrom(IMPORT_LAYOUT_TABLE);
cloned.myVersion = myVersion;
@@ -480,6 +486,7 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
@Override
public void readExternal(Element parentElement) throws InvalidDataException {
super.readExternal(parentElement);
legacySettings.readExternal(parentElement);
readExternalCollection(parentElement, myRepeatAnnotations, REPEAT_ANNOTATIONS, REPEAT_ANNOTATIONS_ITEM);
readExternalCollection(parentElement, myDoNotImportInner, DO_NOT_IMPORT_INNER, DO_NOT_IMPORT_INNER_ITEM);
myOldVersion = myVersion = CustomCodeStyleSettingsUtils.readVersion(parentElement.getChild(getTagName()));
@@ -681,4 +688,49 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
if (!myRepeatAnnotations.equals(otherSettings.getRepeatAnnotations())) return false;
return myDoNotImportInner.equals(otherSettings.getDoNotImportInner());
}
private static class JavaLegacySettings {
public final PackageEntryTable PACKAGES_TO_USE_IMPORT_ON_DEMAND = new PackageEntryTable();
public final PackageEntryTable IMPORT_LAYOUT_TABLE = new PackageEntryTable();
public boolean LAYOUT_STATIC_IMPORTS_SEPARATELY = true;
private JavaLegacySettings() {
this.PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false, "java.awt", false));
this.PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false,"javax.swing", false));
this.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_IMPORTS_ENTRY);
this.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
this.IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "javax", true));
this.IMPORT_LAYOUT_TABLE.addEntry(new PackageEntry(false, "java", true));
this.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
this.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
}
void readExternal(@NotNull Element parentElement) throws InvalidDataException {
DefaultJDOMExternalizer.readExternal(this, parentElement);
if (this.LAYOUT_STATIC_IMPORTS_SEPARATELY) {
// add <all other static imports> entry if there is none
boolean found = false;
for (PackageEntry entry : this.IMPORT_LAYOUT_TABLE.getEntries()) {
if (entry == PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY) {
found = true;
break;
}
}
if (!found) {
PackageEntry last =
this.IMPORT_LAYOUT_TABLE.getEntryCount() == 0 ? null : this.IMPORT_LAYOUT_TABLE.getEntryAt(this.IMPORT_LAYOUT_TABLE.getEntryCount() - 1);
if (last != PackageEntry.BLANK_LINE_ENTRY) {
this.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.BLANK_LINE_ENTRY);
}
this.IMPORT_LAYOUT_TABLE.addEntry(PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY);
}
}
}
void copyFrom(@NotNull JavaLegacySettings settings) {
this.IMPORT_LAYOUT_TABLE.copyFrom(settings.IMPORT_LAYOUT_TABLE);
this.PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(settings.PACKAGES_TO_USE_IMPORT_ON_DEMAND);
this.LAYOUT_STATIC_IMPORTS_SEPARATELY = settings.LAYOUT_STATIC_IMPORTS_SEPARATELY;
}
}
}
@@ -0,0 +1,31 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi.codeStyle;
public interface JavaImportsLayoutSettings extends ImportsLayoutSettings {
PackageEntryTable getImportLayoutTable();
PackageEntryTable getPackagesToUseImportOnDemand();
@Override
boolean isLayoutStaticImportsSeparately();
@Override
void setLayoutStaticImportsSeparately(boolean value);
@Override
int getNamesCountToUseImportOnDemand();
@Override
void setNamesCountToUseImportOnDemand(int value);
@Override
int getClassCountToUseImportOnDemand();
@Override
void setClassCountToUseImportOnDemand(int value);
@Override
boolean isInsertInnerClassImports();
@Override
void setInsertInnerClassImports(boolean value);
@Override
boolean isUseSingleClassImports();
@Override
void setUseSingleClassImports(boolean value);
@Override
boolean isUseFqClassNames();
@Override
void setUseFqClassNames(boolean value);
}
@@ -0,0 +1,188 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi.codeStyle;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class PackageEntryTable implements JDOMExternalizable, Cloneable {
private static final String NAME = "name";
private static final String STATIC = "static";
private static final String MODULE = "module";
private static final String SUBPACKAGES = "withSubpackages";
private static final Set<String> ALLOWED_ATTRIBUTES = Set.of(NAME, STATIC, MODULE, SUBPACKAGES);
private final List<PackageEntry> myEntries = new ArrayList<>();
@Override
public boolean equals(Object obj) {
if (!(obj instanceof PackageEntryTable other)) {
return false;
}
if (other.myEntries.size() != myEntries.size()) {
return false;
}
for (int i = 0; i < myEntries.size(); i++) {
PackageEntry entry = myEntries.get(i);
PackageEntry otherentry = other.myEntries.get(i);
if (!Comparing.equal(entry, otherentry)) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
if (!myEntries.isEmpty() && myEntries.get(0) != null) {
return myEntries.get(0).hashCode();
}
return 0;
}
@Override
public Object clone() throws CloneNotSupportedException {
PackageEntryTable clon = new PackageEntryTable();
clon.copyFrom(this);
return clon;
}
public void copyFrom(PackageEntryTable packageTable) {
myEntries.clear();
myEntries.addAll(packageTable.myEntries);
}
public PackageEntry[] getEntries() {
return myEntries.toArray(new PackageEntry[0]);
}
public void insertEntryAt(PackageEntry entry, int i) {
myEntries.add(i, entry);
}
public void removeEntryAt(int i) {
myEntries.remove(i);
}
public PackageEntry getEntryAt(int i) {
return myEntries.get(i);
}
public int getEntryCount() {
return myEntries.size();
}
public void setEntryAt(PackageEntry entry, int i) {
myEntries.set(i, entry);
}
public boolean contains(String packageName) {
for (PackageEntry entry : myEntries) {
if (packageName.startsWith(entry.getPackageName())) {
if (packageName.length() == entry.getPackageName().length()) return true;
if (entry.isWithSubpackages()) {
if (packageName.charAt(entry.getPackageName().length()) == '.') return true;
}
}
}
return false;
}
@Override
public void readExternal(Element element) throws InvalidDataException {
boolean checkCompatibilityEnabled = Registry.is("code.style.package.entry.table.check.compatibility", false);
myEntries.clear();
List<Element> children = element.getChildren();
for (final Element e : children) {
@NonNls String name = e.getName();
if ("package".equals(name)) {
if (checkCompatibilityEnabled && !isCompatible(e)) {
continue;
}
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(SUBPACKAGES));
if (packageName == null) {
throw new InvalidDataException();
}
PackageEntry entry;
if (packageName.isEmpty()) {
if (isModule) {
entry = PackageEntry.ALL_MODULE_IMPORTS;
}
else if (isStatic) {
entry = PackageEntry.ALL_OTHER_STATIC_IMPORTS_ENTRY;
}
else {
entry = PackageEntry.ALL_OTHER_IMPORTS_ENTRY;
}
}
else {
entry = new PackageEntry(isStatic, packageName, withSubpackages);
}
myEntries.add(entry);
}
else {
if ("emptyLine".equals(name)) {
myEntries.add(PackageEntry.BLANK_LINE_ENTRY);
}
}
}
}
private static boolean isCompatible(Element e) {
for (Attribute attribute : e.getAttributes()) {
if (!ALLOWED_ATTRIBUTES.contains(attribute.getName())) {
return false;
}
}
return true;
}
@Override
public void writeExternal(Element parentNode) throws WriteExternalException {
for (PackageEntry entry : myEntries) {
if (entry == PackageEntry.BLANK_LINE_ENTRY) {
@NonNls Element element = new Element("emptyLine");
parentNode.addContent(element);
}
else {
@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 ||
entry == PackageEntry.ALL_MODULE_IMPORTS ? "": packageName);
element.setAttribute(SUBPACKAGES, entry.isWithSubpackages() ? "true" : "false");
element.setAttribute(STATIC, entry.isStatic() ? "true" : "false");
if (entry == PackageEntry.ALL_MODULE_IMPORTS) {
element.setAttribute(MODULE, "true");
}
}
}
}
public void removeEmptyPackages() {
for(int i = myEntries.size()-1; i>=0; i--){
PackageEntry entry = myEntries.get(i);
if(StringUtil.isEmptyOrSpaces(entry.getPackageName())) {
removeEntryAt(i);
}
}
}
public void addEntry(PackageEntry entry) {
myEntries.add(entry);
}
}