mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 11:53:49 +07:00
Java: add "Layout on-demand import from the same package first" option (IDEA-204441)
enabled by default for consistency with other tools (cherry picked from commit df5a4b65c5f31b195bd091a91d16ea0bc7bcc36c) GitOrigin-RevId: 3b669ce15e9ad037bcff9c1e2638e2b823424ef7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f4cdf03f94
commit
2ec44412eb
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// 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.psi.codeStyle;
|
||||
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
@@ -57,7 +57,7 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
|
||||
public boolean GENERATE_FINAL_PARAMETERS;
|
||||
|
||||
@PsiModifier.ModifierConstant
|
||||
public String VISIBILITY = "public";
|
||||
public String VISIBILITY = PsiModifier.PUBLIC;
|
||||
|
||||
public boolean USE_EXTERNAL_ANNOTATIONS;
|
||||
public boolean GENERATE_USE_TYPE_ANNOTATION_BEFORE_TYPE = true;
|
||||
@@ -170,6 +170,7 @@ 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 USE_FQ_CLASS_NAMES;
|
||||
public boolean USE_SINGLE_CLASS_IMPORTS = true;
|
||||
public boolean INSERT_INNER_CLASS_IMPORTS;
|
||||
@@ -288,7 +289,16 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings implements Im
|
||||
@Override
|
||||
public void setLayoutStaticImportsSeparately(boolean value) {
|
||||
LAYOUT_STATIC_IMPORTS_SEPARATELY = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLayoutOnDemandImportFromSamePackageFirst() {
|
||||
return LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutOnDemandImportFromSamePackageFirst(boolean value) {
|
||||
this.LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -63,6 +63,7 @@ public abstract class CodeStyleImportsPanelBase extends JPanel {
|
||||
myPackageList.copyFrom(settings.getPackagesToUseImportOnDemand());
|
||||
|
||||
myImportLayoutPanel.getCbLayoutStaticImportsSeparately().setSelected(settings.isLayoutStaticImportsSeparately());
|
||||
myImportLayoutPanel.getCbLayoutOnDemandImportsFromSamePackageFirst().setSelected(settings.isLayoutOnDemandImportFromSamePackageFirst());
|
||||
|
||||
final JBTable importLayoutTable = myImportLayoutPanel.getImportLayoutTable();
|
||||
AbstractTableModel model = (AbstractTableModel)importLayoutTable.getModel();
|
||||
@@ -83,6 +84,7 @@ public abstract class CodeStyleImportsPanelBase extends JPanel {
|
||||
stopTableEditing();
|
||||
|
||||
settings.setLayoutStaticImportsSeparately(myImportLayoutPanel.areStaticImportsEnabled());
|
||||
settings.setLayoutOnDemandImportFromSamePackageFirst(myImportLayoutPanel.isLayoutOnDemandImportsFromSamePackageFirst());
|
||||
kotlinUI.apply(settings);
|
||||
PackageEntryTable list = myImportLayoutPanel.getImportLayoutList();
|
||||
settings.getImportLayoutTable().copyFrom(getCopyWithoutEmptyPackages(list));
|
||||
@@ -91,6 +93,7 @@ public abstract class CodeStyleImportsPanelBase extends JPanel {
|
||||
|
||||
public boolean isModifiedLayoutSettings(ImportsLayoutSettings settings) {
|
||||
boolean isModified = isModified(myImportLayoutPanel.getCbLayoutStaticImportsSeparately(), settings.isLayoutStaticImportsSeparately());
|
||||
isModified |= isModified(myImportLayoutPanel.getCbLayoutOnDemandImportsFromSamePackageFirst(), settings.isLayoutOnDemandImportFromSamePackageFirst());
|
||||
isModified |= kotlinUI.isModified(settings);
|
||||
|
||||
PackageEntryTable list = myImportLayoutPanel.getImportLayoutList();
|
||||
|
||||
@@ -37,6 +37,8 @@ import java.awt.*;
|
||||
public abstract class ImportLayoutPanel extends JPanel {
|
||||
private final JBCheckBox myCbLayoutStaticImportsSeparately =
|
||||
new JBCheckBox(JavaBundle.message("import.layout.static.imports.separately"));
|
||||
private final JBCheckBox myCbLayoutOnDemandImportsFromSamePackageFirst =
|
||||
new JBCheckBox(JavaBundle.message("import.layout.on.demand.import.from.same.package.first"));
|
||||
private final JBTable myImportLayoutTable;
|
||||
|
||||
private final PackageEntryTable myImportLayoutList = new PackageEntryTable();
|
||||
@@ -53,6 +55,10 @@ public abstract class ImportLayoutPanel extends JPanel {
|
||||
return myCbLayoutStaticImportsSeparately;
|
||||
}
|
||||
|
||||
public JBCheckBox getCbLayoutOnDemandImportsFromSamePackageFirst() {
|
||||
return myCbLayoutOnDemandImportsFromSamePackageFirst;
|
||||
}
|
||||
|
||||
public ImportLayoutPanel() {
|
||||
super(new BorderLayout());
|
||||
|
||||
@@ -108,7 +114,9 @@ public abstract class ImportLayoutPanel extends JPanel {
|
||||
.setPreferredSize(new Dimension(-1, JBUI.scale(180)))
|
||||
.createPanel();
|
||||
|
||||
final ImportLayoutPanelUI UI = new ImportLayoutPanelUI(myCbLayoutStaticImportsSeparately, importLayoutPanel);
|
||||
final ImportLayoutPanelUI UI = new ImportLayoutPanelUI(myCbLayoutStaticImportsSeparately,
|
||||
myCbLayoutOnDemandImportsFromSamePackageFirst,
|
||||
importLayoutPanel);
|
||||
add(UI.getPanel(), BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
@@ -215,6 +223,10 @@ public abstract class ImportLayoutPanel extends JPanel {
|
||||
return myCbLayoutStaticImportsSeparately.isSelected();
|
||||
}
|
||||
|
||||
public boolean isLayoutOnDemandImportsFromSamePackageFirst() {
|
||||
return myCbLayoutOnDemandImportsFromSamePackageFirst.isSelected();
|
||||
}
|
||||
|
||||
public static JBTable createTableForPackageEntries(final PackageEntryTable packageTable, final ImportLayoutPanel panel) {
|
||||
final String[] names = {
|
||||
JavaBundle.message("listbox.import.package"),
|
||||
|
||||
@@ -7,9 +7,10 @@ import com.intellij.ui.dsl.builder.Align
|
||||
import com.intellij.ui.dsl.builder.panel
|
||||
import javax.swing.JPanel
|
||||
|
||||
internal class ImportLayoutPanelUI(staticImportsCb: JBCheckBox, importLayoutPanel: JPanel) {
|
||||
internal class ImportLayoutPanelUI(staticImportsCb: JBCheckBox, onDemandBeforeSingleClassCb: JBCheckBox, importLayoutPanel: JPanel) {
|
||||
val panel = panel {
|
||||
group(JavaBundle.message("title.import.layout")) {
|
||||
row { cell(onDemandBeforeSingleClassCb) }
|
||||
row { cell(staticImportsCb) }
|
||||
row { cell(importLayoutPanel).align(Align.FILL) }.resizableRow()
|
||||
}.resizableRow()
|
||||
|
||||
@@ -51,7 +51,7 @@ import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class ImportHelper{
|
||||
public final class ImportHelper {
|
||||
private static final Logger LOG = Logger.getInstance(ImportHelper.class);
|
||||
|
||||
private final JavaCodeStyleSettings mySettings;
|
||||
@@ -124,7 +124,9 @@ public final class ImportHelper{
|
||||
classesToUseSingle.addAll(toReimport);
|
||||
|
||||
try {
|
||||
StringBuilder text = buildImportListText(resultList, classesOrPackagesToImportOnDemand.keySet(), classesToUseSingle, checker);
|
||||
boolean onDemandFirst = mySettings.isLayoutOnDemandImportFromSamePackageFirst();
|
||||
StringBuilder text =
|
||||
buildImportListText(resultList, classesOrPackagesToImportOnDemand.keySet(), classesToUseSingle, checker, onDemandFirst);
|
||||
for (PsiElement nonImport : nonImports) {
|
||||
text.append("\n").append(nonImport.getText());
|
||||
}
|
||||
@@ -378,43 +380,40 @@ public final class ImportHelper{
|
||||
private static @NotNull StringBuilder buildImportListText(@NotNull List<Import> imports,
|
||||
@NotNull Set<String> packagesOrClassesToImportOnDemand,
|
||||
@NotNull Set<String> namesToUseSingle,
|
||||
@NotNull ImportUtils.ImplicitImportChecker implicitImportContext) {
|
||||
Set<Import> importedPackagesOrClasses = new HashSet<>();
|
||||
@NotNull ImportUtils.ImplicitImportChecker implicitImportContext,
|
||||
boolean onDemandImportsFirst) {
|
||||
Set<String> importedPackagesOrClasses = new HashSet<>();
|
||||
@NonNls StringBuilder buffer = new StringBuilder();
|
||||
for (Import importedName : imports) {
|
||||
String name = importedName.name();
|
||||
boolean isStatic = importedName.isStatic();
|
||||
String packageOrClassName = StringUtil.getPackageName(name);
|
||||
boolean implicitlyImported = implicitImportContext.isImplicitlyImported(name, isStatic);
|
||||
boolean useOnDemand = implicitlyImported || packagesOrClassesToImportOnDemand.contains(packageOrClassName);
|
||||
Import current = new Import(packageOrClassName, isStatic);
|
||||
if (namesToUseSingle.remove(name)) {
|
||||
if (useOnDemand && importedPackagesOrClasses.contains(current)) {
|
||||
if (!implicitlyImported && packagesOrClassesToImportOnDemand.remove(packageOrClassName)) {
|
||||
appendImportStatement(packageOrClassName + ".*", isStatic, buffer);
|
||||
importedPackagesOrClasses.add(packageOrClassName);
|
||||
}
|
||||
if (namesToUseSingle.contains(name)) {
|
||||
if (!implicitlyImported && !onDemandImportsFirst && importedPackagesOrClasses.contains(packageOrClassName)) {
|
||||
buffer.insert(buffer.lastIndexOf("import "), "import " + (isStatic ? "static " : "") + name + ";\n");
|
||||
continue;
|
||||
}
|
||||
useOnDemand = false;
|
||||
else {
|
||||
appendImportStatement(name, isStatic, buffer);
|
||||
}
|
||||
}
|
||||
if (useOnDemand && (importedPackagesOrClasses.contains(current) || implicitlyImported)) continue;
|
||||
buffer.append("import ");
|
||||
if (isStatic) buffer.append("static ");
|
||||
if (useOnDemand) {
|
||||
importedPackagesOrClasses.add(current);
|
||||
buffer.append(packageOrClassName).append(".*");
|
||||
else if (!implicitlyImported && !importedPackagesOrClasses.contains(packageOrClassName)) {
|
||||
appendImportStatement(name, isStatic, buffer);
|
||||
}
|
||||
else {
|
||||
buffer.append(name);
|
||||
}
|
||||
buffer.append(";\n");
|
||||
}
|
||||
|
||||
for (String remainingSingle : namesToUseSingle) {
|
||||
buffer.append("import ").append(remainingSingle).append(";\n");
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static void appendImportStatement(String name, boolean isStatic, StringBuilder buffer) {
|
||||
buffer.append("import ");
|
||||
if (isStatic) buffer.append("static ");
|
||||
buffer.append(name).append(";\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds import if it is needed.
|
||||
* @return false when the FQN has to be used in code (e.g. when conflicting imports already exist)
|
||||
|
||||
@@ -135,6 +135,7 @@
|
||||
"label_indent_absolute": false,
|
||||
"label_indent_size": 0,
|
||||
"lambda_brace_style": "end_of_line",
|
||||
"layout_on_demand_import_from_same_package_first": true,
|
||||
"layout_static_imports_separately": true,
|
||||
"line_comment_add_space": false,
|
||||
"line_comment_add_space_on_reformat": false,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package p2;
|
||||
|
||||
import p1.List;
|
||||
import p1.*;
|
||||
import p1.List;
|
||||
|
||||
|
||||
A1 a1;
|
||||
|
||||
@@ -13,6 +13,46 @@ import org.intellij.lang.annotations.Language;
|
||||
@SuppressWarnings("ALL")
|
||||
public class LightOptimizeImportsTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
|
||||
public void testLayoutOnDemandImportsFromTheSamePackageFirst() {
|
||||
myFixture.addClass("package a.a; public class A {}");
|
||||
myFixture.addClass("package a.b; public class A {}");
|
||||
myFixture.addClass("package a.b; public class B {}");
|
||||
myFixture.addClass("package a.b; public class Boolean {}");
|
||||
@Language("JAVA") String code = """
|
||||
package a;
|
||||
|
||||
import a.a.A;
|
||||
import a.b.B;
|
||||
import a.b.Boolean;
|
||||
|
||||
class Main {
|
||||
A a;
|
||||
B b;
|
||||
Boolean bool;
|
||||
}""";
|
||||
myFixture.configureByText(JavaFileType.INSTANCE, code);
|
||||
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
javaSettings.LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST = true;
|
||||
javaSettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND = 1;
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> JavaCodeStyleManager.getInstance(getProject()).optimizeImports(getFile()));
|
||||
|
||||
@Language("JAVA") String result = """
|
||||
package a;
|
||||
|
||||
import a.a.*;
|
||||
import a.a.A;
|
||||
import a.b.*;
|
||||
import a.b.Boolean;
|
||||
|
||||
class Main {
|
||||
A a;
|
||||
B b;
|
||||
Boolean bool;
|
||||
}""";
|
||||
myFixture.checkResult(result);
|
||||
}
|
||||
|
||||
public void testImportLayoutStaticAndNonStaticImportsTogether() {
|
||||
myFixture.addClass("package aaa; public class AAA {}");
|
||||
myFixture.addClass("package aaa; public class BBB {" +
|
||||
@@ -223,6 +263,7 @@ public class LightOptimizeImportsTest extends LightJavaCodeInsightFixtureTestCas
|
||||
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
javaSettings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND = 1;
|
||||
javaSettings.LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST = false;
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> JavaCodeStyleManager.getInstance(getProject()).optimizeImports(getFile()));
|
||||
|
||||
@Language("JAVA")
|
||||
@@ -246,7 +287,7 @@ public class LightOptimizeImportsTest extends LightJavaCodeInsightFixtureTestCas
|
||||
public void testConflictInPackageWithImportInName() {
|
||||
myFixture.addClass("package a.importb; public class A {}");
|
||||
myFixture.addClass("package a.importb; public class B {}");
|
||||
myFixture.addClass("package a.importb; public class Boolean {}"); // conflict with java.lang.Process
|
||||
myFixture.addClass("package a.importb; public class Boolean {}"); // conflict with java.lang.Boolean
|
||||
|
||||
@Language("JAVA")
|
||||
String text = """
|
||||
@@ -267,6 +308,7 @@ public class LightOptimizeImportsTest extends LightJavaCodeInsightFixtureTestCas
|
||||
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
javaSettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND = 1;
|
||||
javaSettings.LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST = false;
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> JavaCodeStyleManager.getInstance(getProject()).optimizeImports(getFile()));
|
||||
|
||||
@Language("JAVA")
|
||||
@@ -362,6 +404,7 @@ public class LightOptimizeImportsTest extends LightJavaCodeInsightFixtureTestCas
|
||||
|
||||
JavaCodeStyleSettings javaSettings = JavaCodeStyleSettings.getInstance(getProject());
|
||||
javaSettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.addEntry(new PackageEntry(false, "p", true));
|
||||
javaSettings.LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST = false;
|
||||
WriteCommandAction.runWriteCommandAction(getProject(), () -> JavaCodeStyleManager.getInstance(getProject()).optimizeImports(getFile()));
|
||||
|
||||
@Language("JAVA") String result = """
|
||||
|
||||
@@ -364,6 +364,7 @@ icon.preview=Icon preview
|
||||
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.statically=Import statically
|
||||
include.accessors=&Include Accessors
|
||||
infer.nullity.progress=Post-processing results\u2026
|
||||
|
||||
@@ -974,11 +974,13 @@ com.intellij.psi.codeStyle.ImportsLayoutSettings
|
||||
- a:getNamesCountToUseImportOnDemand():I
|
||||
- a:getPackagesToUseImportOnDemand():com.intellij.psi.codeStyle.PackageEntryTable
|
||||
- a:isInsertInnerClassImports():Z
|
||||
- isLayoutOnDemandImportFromSamePackageFirst():Z
|
||||
- a:isLayoutStaticImportsSeparately():Z
|
||||
- a:isUseFqClassNames():Z
|
||||
- a:isUseSingleClassImports():Z
|
||||
- a:setClassCountToUseImportOnDemand(I):V
|
||||
- a:setInsertInnerClassImports(Z):V
|
||||
- setLayoutOnDemandImportFromSamePackageFirst(Z):V
|
||||
- a:setLayoutStaticImportsSeparately(Z):V
|
||||
- a:setNamesCountToUseImportOnDemand(I):V
|
||||
- a:setUseFqClassNames(Z):V
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// 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.psi.codeStyle;
|
||||
|
||||
public interface ImportsLayoutSettings {
|
||||
boolean isLayoutStaticImportsSeparately();
|
||||
void setLayoutStaticImportsSeparately(boolean value);
|
||||
default boolean isLayoutOnDemandImportFromSamePackageFirst() { return false; }
|
||||
default void setLayoutOnDemandImportFromSamePackageFirst(boolean value) {}
|
||||
int getNamesCountToUseImportOnDemand();
|
||||
void setNamesCountToUseImportOnDemand(int value);
|
||||
int getClassCountToUseImportOnDemand();
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.eclipse.importer;
|
||||
|
||||
import com.intellij.openapi.options.SchemeImportException;
|
||||
@@ -34,6 +32,7 @@ public class EclipseCodeStylePropertiesImporter implements EclipseFormatterOptio
|
||||
importOrderOfImports(uiPreferences, javaSettings);
|
||||
importStarImportThresholds(uiPreferences, javaSettings);
|
||||
javaSettings.LAYOUT_STATIC_IMPORTS_SEPARATELY = true;
|
||||
javaSettings.LAYOUT_ON_DEMAND_IMPORT_FROM_SAME_PACKAGE_FIRST = true;
|
||||
javaSettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND.copyFrom(new PackageEntryTable());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user