mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-imports] IDEA-13817 Create "favorites" for static import and completion
GitOrigin-RevId: 786ff0d07a68ecb53f3c929600353bc28f483bf0
This commit is contained in:
committed by
intellij-monorepo-bot
parent
2afb61710c
commit
b1a1f903ba
@@ -415,6 +415,7 @@
|
||||
<projectService serviceImplementation="com.intellij.jarRepository.RemoteRepositoriesConfiguration"/>
|
||||
<projectService serviceImplementation="com.intellij.jarRepository.services.MavenRepositoryServicesManager"/>
|
||||
<projectService serviceImplementation="com.intellij.codeInsight.JavaProjectCodeInsightSettings"/>
|
||||
<applicationService serviceImplementation="com.intellij.codeInsight.JavaIdeCodeInsightSettings"/>
|
||||
<projectService serviceInterface="com.intellij.testIntegration.TestFailedLineManager"
|
||||
serviceImplementation="com.intellij.execution.codeInspection.TestFailedLineManagerImpl"/>
|
||||
<projectService serviceInterface="com.intellij.codeInspection.ex.EntryPointsManager"
|
||||
|
||||
@@ -1,232 +0,0 @@
|
||||
// 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.editor;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.JavaProjectCodeInsightSettings;
|
||||
import com.intellij.execution.util.ListTableWithButtons;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ComboBoxTableRenderer;
|
||||
import com.intellij.openapi.ui.ComponentValidator;
|
||||
import com.intellij.openapi.ui.ValidationInfo;
|
||||
import com.intellij.openapi.ui.cellvalidators.CellComponentProvider;
|
||||
import com.intellij.openapi.ui.cellvalidators.CellTooltipManager;
|
||||
import com.intellij.openapi.ui.cellvalidators.ValidatingTableCellRendererWrapper;
|
||||
import com.intellij.openapi.ui.cellvalidators.ValidationUtils;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.ScrollingUtil;
|
||||
import com.intellij.ui.components.fields.ExtendableTextField;
|
||||
import com.intellij.ui.scale.JBUIScale;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
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.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class ExcludeTable extends ListTableWithButtons<ExcludeTable.Item> {
|
||||
private static final Pattern ourPackagePattern = Pattern.compile("([\\w*]+\\.)*[\\w*]+");
|
||||
|
||||
private static final BiFunction<Object, JComponent, ValidationInfo> validationInfoProducer = (value, component) ->
|
||||
(value == null || StringUtil.isEmpty(value.toString()) || ourPackagePattern.matcher(value.toString()).matches()) ?
|
||||
null : new ValidationInfo(JavaBundle.message("illegal.name.validation.info", value.toString()), component);
|
||||
|
||||
private static final Disposable validatorsDisposable = Disposer.newDisposable();
|
||||
private static final ColumnInfo<Item, String> NAME_COLUMN = new ColumnInfo<>(JavaBundle.message("exclude.table.mask")) {
|
||||
|
||||
@Override
|
||||
public @Nullable String valueOf(Item pair) {
|
||||
return pair.exclude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCellEditor getEditor(Item pair) {
|
||||
ExtendableTextField cellEditor = new ExtendableTextField();
|
||||
cellEditor.putClientProperty(DarculaUIUtil.COMPACT_PROPERTY, Boolean.TRUE);
|
||||
|
||||
new ComponentValidator(validatorsDisposable).withValidator(() -> {
|
||||
String text = cellEditor.getText();
|
||||
boolean hasError = !StringUtil.isEmpty(text) && !ourPackagePattern.matcher(text).matches();
|
||||
ValidationUtils.setExtension(cellEditor, ValidationUtils.ERROR_EXTENSION, hasError);
|
||||
|
||||
return validationInfoProducer.apply(text, cellEditor);
|
||||
}).andRegisterOnDocumentListener(cellEditor).installOn(cellEditor);
|
||||
|
||||
return new DefaultCellEditor(cellEditor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCellRenderer getRenderer(Item pair) {
|
||||
JTextField cellEditor = new JTextField();
|
||||
cellEditor.putClientProperty(DarculaUIUtil.COMPACT_PROPERTY, Boolean.TRUE);
|
||||
|
||||
return new ValidatingTableCellRendererWrapper(new DefaultTableCellRenderer()).
|
||||
withCellValidator((value, row, column) -> validationInfoProducer.apply(value, null)).
|
||||
bindToEditorSize(cellEditor::getPreferredSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(Item pair) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Item item, String value) {
|
||||
item.exclude = value;
|
||||
}
|
||||
};
|
||||
|
||||
private static final ColumnInfo<Item, ExclusionScope> SCOPE_COLUMN = new ColumnInfo<>(JavaBundle.message(
|
||||
"exclude.table.scope.column")) {
|
||||
@Override
|
||||
public @Nullable ExclusionScope valueOf(Item pair) {
|
||||
return pair.scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCellRenderer getRenderer(Item pair) {
|
||||
return new ComboBoxTableRenderer<>(ExclusionScope.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCellEditor getEditor(Item pair) {
|
||||
return new ComboBoxTableRenderer<>(ExclusionScope.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(Item pair) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Item pair, ExclusionScope value) {
|
||||
pair.scope = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMaxStringValue() {
|
||||
return "Project";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAdditionalWidth() {
|
||||
return JBUIScale.scale(12) + AllIcons.General.ArrowDown.getIconWidth();
|
||||
}
|
||||
};
|
||||
private final Project myProject;
|
||||
|
||||
ExcludeTable(@NotNull Project project) {
|
||||
myProject = project;
|
||||
|
||||
JBTable table = getTableView();
|
||||
table.getEmptyText().clear();
|
||||
table.getEmptyText().appendLine(JavaBundle.message("exclude.from.imports.no.exclusions"));
|
||||
table.getEmptyText().appendLine(JavaBundle.message("exclude.from.imports.no.exclusions.2"));
|
||||
table.setStriped(false);
|
||||
new CellTooltipManager(myProject).withCellComponentProvider(CellComponentProvider.forTable(table)).installOn(table);
|
||||
|
||||
Disposer.register(project, validatorsDisposable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListTableModel<Item> createListModel() {
|
||||
return new ListTableModel<>(NAME_COLUMN, SCOPE_COLUMN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item createElement() {
|
||||
return new Item("", ExclusionScope.IDE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEmpty(Item element) {
|
||||
return element.exclude.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item cloneElement(Item variable) {
|
||||
return new Item(variable.exclude, variable.scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canDeleteElement(Item selection) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void addExcludePackage(@NotNull String packageName) {
|
||||
int index = 0;
|
||||
while (index < getTableView().getListTableModel().getRowCount()) {
|
||||
if (getTableView().getListTableModel().getItem(index).exclude.compareTo(packageName) > 0) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
getTableView().getListTableModel().insertRow(index, new Item(packageName, ExclusionScope.IDE));
|
||||
getTableView().clearSelection();
|
||||
getTableView().addRowSelectionInterval(index, index);
|
||||
ScrollingUtil.ensureIndexIsVisible(getTableView(), index, 0);
|
||||
IdeFocusManager.getGlobalInstance().requestFocus(getTableView(), false);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
List<Item> rows = new ArrayList<>();
|
||||
for (String s : CodeInsightSettings.getInstance().EXCLUDED_PACKAGES) {
|
||||
rows.add(new Item(s, ExclusionScope.IDE));
|
||||
}
|
||||
for (String s : JavaProjectCodeInsightSettings.getSettings(myProject).excludedNames) {
|
||||
rows.add(new Item(s, ExclusionScope.Project));
|
||||
}
|
||||
rows.sort(Comparator.comparing(o -> o.exclude));
|
||||
|
||||
setValues(rows);
|
||||
}
|
||||
|
||||
void apply() {
|
||||
CodeInsightSettings.getInstance().EXCLUDED_PACKAGES = ArrayUtilRt.toStringArray(getExcludedPackages(ExclusionScope.IDE));
|
||||
JavaProjectCodeInsightSettings.getSettings(myProject).excludedNames = getExcludedPackages(ExclusionScope.Project);
|
||||
}
|
||||
|
||||
private List<String> getExcludedPackages(ExclusionScope scope) {
|
||||
List<String> result = new ArrayList<>();
|
||||
for (Item pair : getTableView().getListTableModel().getItems()) {
|
||||
if (scope == pair.scope) {
|
||||
result.add(pair.exclude);
|
||||
}
|
||||
}
|
||||
Collections.sort(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean isModified() {
|
||||
return !getExcludedPackages(ExclusionScope.IDE).equals(Arrays.asList(CodeInsightSettings.getInstance().EXCLUDED_PACKAGES))
|
||||
||
|
||||
!getExcludedPackages(ExclusionScope.Project).equals(JavaProjectCodeInsightSettings.getSettings(myProject).excludedNames);
|
||||
|
||||
}
|
||||
|
||||
private enum ExclusionScope {Project, IDE}
|
||||
|
||||
static class Item {
|
||||
String exclude;
|
||||
ExclusionScope scope;
|
||||
|
||||
Item(@NotNull String exclude, ExclusionScope scope) {
|
||||
this.exclude = exclude;
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
// 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.application.options.editor;
|
||||
|
||||
import com.intellij.execution.util.ListTableWithButtons;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.ui.ComboBoxTableRenderer;
|
||||
import com.intellij.openapi.ui.ComponentValidator;
|
||||
import com.intellij.openapi.ui.ValidationInfo;
|
||||
import com.intellij.openapi.ui.cellvalidators.CellComponentProvider;
|
||||
import com.intellij.openapi.ui.cellvalidators.CellTooltipManager;
|
||||
import com.intellij.openapi.ui.cellvalidators.ValidatingTableCellRendererWrapper;
|
||||
import com.intellij.openapi.ui.cellvalidators.ValidationUtils;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.ScrollingUtil;
|
||||
import com.intellij.ui.components.fields.ExtendableTextField;
|
||||
import com.intellij.ui.scale.JBUIScale;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.ui.ColumnInfo;
|
||||
import com.intellij.util.ui.ListTableModel;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellEditor;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
abstract class ImportTable extends ListTableWithButtons<ImportTable.Item> implements Disposable.Default {
|
||||
private static final Pattern ourPackagePattern = Pattern.compile("([\\w*]+\\.)*[\\w*]+");
|
||||
|
||||
private static final BiFunction<Object, JComponent, ValidationInfo> validationInfoProducer = (value, component) ->
|
||||
(value == null || StringUtil.isEmpty(value.toString()) || ourPackagePattern.matcher(value.toString()).matches()) ?
|
||||
null : new ValidationInfo(JavaBundle.message("illegal.name.validation.info", value.toString()), component);
|
||||
|
||||
private static final Disposable validatorsDisposable = Disposer.newDisposable();
|
||||
|
||||
private final @NotNull @Nls String myNameColumn;
|
||||
private final @NotNull @Nls String myScopeColumn;
|
||||
|
||||
|
||||
ImportTable(@NotNull Disposable parentDisposable,
|
||||
@NlsSafe @NotNull String firstMessageLine,
|
||||
@NlsSafe @NotNull String secondMessageLine,
|
||||
@NotNull @Nls String nameColumn,
|
||||
@NotNull @Nls String scopeColumn) {
|
||||
myNameColumn = nameColumn;
|
||||
myScopeColumn = scopeColumn;
|
||||
JBTable table = getTableView();
|
||||
table.getEmptyText().clear();
|
||||
table.getEmptyText().appendLine(firstMessageLine);
|
||||
table.getEmptyText().appendLine(secondMessageLine);
|
||||
table.setStriped(false);
|
||||
new CellTooltipManager(parentDisposable).withCellComponentProvider(CellComponentProvider.forTable(table)).installOn(table);
|
||||
Disposer.register(parentDisposable, validatorsDisposable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListTableModel<Item> createListModel() {
|
||||
return new ListTableModel<>(createNameColumn(), createScopeColumn());
|
||||
}
|
||||
|
||||
private ColumnInfo<Item, Scope> createScopeColumn() {
|
||||
return new ColumnInfo<>(myScopeColumn) {
|
||||
@Override
|
||||
public @Nullable ImportTable.Scope valueOf(Item pair) {
|
||||
return pair.scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCellRenderer getRenderer(Item pair) {
|
||||
return new ComboBoxTableRenderer<>(Scope.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCellEditor getEditor(Item pair) {
|
||||
return new ComboBoxTableRenderer<>(Scope.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(Item pair) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Item pair, Scope value) {
|
||||
pair.scope = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMaxStringValue() {
|
||||
return "Project";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAdditionalWidth() {
|
||||
return JBUIScale.scale(12) + AllIcons.General.ArrowDown.getIconWidth();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private ColumnInfo<Item, String> createNameColumn() {
|
||||
return new ColumnInfo<>(myNameColumn) {
|
||||
|
||||
@Override
|
||||
public @Nullable String valueOf(Item pair) {
|
||||
return pair.row;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCellEditor getEditor(Item pair) {
|
||||
ExtendableTextField cellEditor = new ExtendableTextField();
|
||||
cellEditor.putClientProperty(DarculaUIUtil.COMPACT_PROPERTY, Boolean.TRUE);
|
||||
|
||||
new ComponentValidator(validatorsDisposable).withValidator(() -> {
|
||||
String text = cellEditor.getText();
|
||||
boolean hasError = !StringUtil.isEmpty(text) && !ourPackagePattern.matcher(text).matches();
|
||||
ValidationUtils.setExtension(cellEditor, ValidationUtils.ERROR_EXTENSION, hasError);
|
||||
|
||||
return validationInfoProducer.apply(text, cellEditor);
|
||||
}).andRegisterOnDocumentListener(cellEditor).installOn(cellEditor);
|
||||
|
||||
return new DefaultCellEditor(cellEditor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableCellRenderer getRenderer(Item pair) {
|
||||
JTextField cellEditor = new JTextField();
|
||||
cellEditor.putClientProperty(DarculaUIUtil.COMPACT_PROPERTY, Boolean.TRUE);
|
||||
|
||||
return new ValidatingTableCellRendererWrapper(new DefaultTableCellRenderer()).
|
||||
withCellValidator((value, row, column) -> validationInfoProducer.apply(value, null)).
|
||||
bindToEditorSize(cellEditor::getPreferredSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(Item pair) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Item item, String value) {
|
||||
item.row = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item createElement() {
|
||||
return new Item("", Scope.IDE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEmpty(Item element) {
|
||||
return element.row.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item cloneElement(Item variable) {
|
||||
return new Item(variable.row, variable.scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canDeleteElement(Item selection) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void addRow(@NotNull String row) {
|
||||
int index = 0;
|
||||
while (index < getTableView().getListTableModel().getRowCount()) {
|
||||
if (getTableView().getListTableModel().getItem(index).row.compareTo(row) > 0) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
getTableView().getListTableModel().insertRow(index, new Item(row, Scope.IDE));
|
||||
getTableView().clearSelection();
|
||||
getTableView().addRowSelectionInterval(index, index);
|
||||
ScrollingUtil.ensureIndexIsVisible(getTableView(), index, 0);
|
||||
IdeFocusManager.getGlobalInstance().requestFocus(getTableView(), false);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
List<Item> rows = new ArrayList<>();
|
||||
for (String s : getIdeRows()) {
|
||||
rows.add(new Item(s, Scope.IDE));
|
||||
}
|
||||
for (String s : getProjectRows()) {
|
||||
rows.add(new Item(s, Scope.Project));
|
||||
}
|
||||
rows.sort(Comparator.comparing(o -> o.row));
|
||||
|
||||
setValues(rows);
|
||||
}
|
||||
|
||||
void apply() {
|
||||
setIdeRows(ArrayUtilRt.toStringArray(getRows(Scope.IDE)));
|
||||
setProjectRows(getRows(Scope.Project).toArray(ArrayUtilRt.EMPTY_STRING_ARRAY));
|
||||
}
|
||||
|
||||
protected abstract @NotNull String @NotNull [] getIdeRows();
|
||||
|
||||
protected abstract @NotNull String @NotNull [] getProjectRows();
|
||||
|
||||
protected abstract void setIdeRows(@NotNull String @NotNull [] rows);
|
||||
|
||||
protected abstract void setProjectRows(@NotNull String @NotNull [] rows);
|
||||
|
||||
private List<String> getRows(Scope scope) {
|
||||
List<String> result = new ArrayList<>();
|
||||
for (Item pair : getTableView().getListTableModel().getItems()) {
|
||||
if (scope == pair.scope) {
|
||||
result.add(pair.row);
|
||||
}
|
||||
}
|
||||
Collections.sort(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean isModified() {
|
||||
return !Arrays.equals(ArrayUtilRt.toStringArray(getRows(Scope.IDE)), getIdeRows())
|
||||
||
|
||||
!Arrays.equals(ArrayUtilRt.toStringArray(getRows(Scope.Project)), getProjectRows());
|
||||
}
|
||||
|
||||
private enum Scope {Project, IDE}
|
||||
|
||||
static class Item {
|
||||
String row;
|
||||
Scope scope;
|
||||
|
||||
Item(@NotNull String row, Scope scope) {
|
||||
this.row = row;
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
+80
-2
@@ -4,17 +4,24 @@ package com.intellij.application.options.editor
|
||||
import com.intellij.application.options.CodeStyleConfigurableWrapper
|
||||
import com.intellij.codeInsight.CodeInsightSettings
|
||||
import com.intellij.codeInsight.CodeInsightWorkspaceSettings
|
||||
import com.intellij.codeInsight.JavaIdeCodeInsightSettings
|
||||
import com.intellij.codeInsight.JavaProjectCodeInsightSettings
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.DataManager
|
||||
import com.intellij.ide.util.TreeClassChooserFactory
|
||||
import com.intellij.java.JavaBundle
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.application.ApplicationBundle
|
||||
import com.intellij.openapi.options.UiDslUnnamedConfigurable
|
||||
import com.intellij.openapi.options.ex.Settings
|
||||
import com.intellij.openapi.project.DumbService.Companion.isDumb
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.ProjectManager
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.ui.AnActionButtonRunnable
|
||||
import com.intellij.ui.ContextHelpLabel
|
||||
import com.intellij.ui.IdeUICustomization
|
||||
import com.intellij.ui.dsl.builder.*
|
||||
@@ -22,10 +29,70 @@ import com.intellij.ui.dsl.listCellRenderer.textListCellRenderer
|
||||
import javax.swing.JComponent
|
||||
|
||||
class JavaAutoImportOptions(val project: Project) : UiDslUnnamedConfigurable.Simple(), AutoImportOptionsProvider {
|
||||
private val excludeTable = ExcludeTable(project)
|
||||
private val excludeTable = object : ImportTable(project,
|
||||
JavaBundle.message("exclude.from.imports.no.exclusions"),
|
||||
JavaBundle.message("exclude.from.imports.no.exclusions.2"),
|
||||
JavaBundle.message("exclude.table.mask"),
|
||||
JavaBundle.message("exclude.table.scope.column")) {
|
||||
override fun getIdeRows(): Array<out String> {
|
||||
return CodeInsightSettings.getInstance().EXCLUDED_PACKAGES
|
||||
}
|
||||
|
||||
override fun getProjectRows(): Array<out String> {
|
||||
return JavaProjectCodeInsightSettings.getSettings(project).excludedNames.toTypedArray()
|
||||
}
|
||||
|
||||
override fun setIdeRows(rows: Array<out String>) {
|
||||
CodeInsightSettings.getInstance().EXCLUDED_PACKAGES = rows
|
||||
}
|
||||
|
||||
override fun setProjectRows(rows: Array<out String>) {
|
||||
JavaProjectCodeInsightSettings.getSettings(project).excludedNames = rows.toList()
|
||||
}
|
||||
}
|
||||
|
||||
private val autoStaticImportTable = object : ImportTable(project,
|
||||
JavaBundle.message("auto.static.import.comment"),
|
||||
JavaBundle.message("auto.static.import.comment.2"),
|
||||
JavaBundle.message("auto.static.import.class"),
|
||||
JavaBundle.message("auto.static.import.scope")) {
|
||||
override fun createAddAction(): AnActionButtonRunnable? {
|
||||
return AnActionButtonRunnable { button ->
|
||||
val element = createElement()
|
||||
|
||||
if (!project.isDefault && !isDumb(project)) {
|
||||
val chooser = TreeClassChooserFactory.getInstance(project)
|
||||
.createWithInnerClassesScopeChooser(JavaBundle.message("dialog.title.choose.class"), GlobalSearchScope.allScope(project), null, null)
|
||||
chooser.showDialog()
|
||||
val selected = chooser.getSelected()
|
||||
element.row = selected?.qualifiedName ?: ""
|
||||
}
|
||||
|
||||
addNewElement(element)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getIdeRows(): Array<out String> {
|
||||
return JavaIdeCodeInsightSettings.getInstance().includedAutoStaticNames.toTypedArray()
|
||||
}
|
||||
|
||||
override fun getProjectRows(): Array<out String> {
|
||||
return JavaProjectCodeInsightSettings.getSettings(project).includedAutoStaticNames.toTypedArray()
|
||||
}
|
||||
|
||||
override fun setIdeRows(rows: Array<out String>) {
|
||||
JavaIdeCodeInsightSettings.getInstance().includedAutoStaticNames = rows.toList()
|
||||
}
|
||||
|
||||
override fun setProjectRows(rows: Array<out String>) {
|
||||
JavaProjectCodeInsightSettings.getSettings(project).includedAutoStaticNames = rows.toList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun Panel.createContent() {
|
||||
excludeTable.tableView.setShowGrid(false)
|
||||
autoStaticImportTable.tableView.setShowGrid(false)
|
||||
|
||||
val dcaSettings = DaemonCodeAnalyzerSettings.getInstance()
|
||||
val ciSettings = CodeInsightSettings.getInstance()
|
||||
val ciWorkspaceSettings = CodeInsightWorkspaceSettings.getInstance(project)
|
||||
@@ -73,6 +140,14 @@ class JavaAutoImportOptions(val project: Project) : UiDslUnnamedConfigurable.Sim
|
||||
toolTipText = IdeUICustomization.getInstance().projectMessage("configurable.current.project.tooltip")
|
||||
}
|
||||
}
|
||||
row {
|
||||
cell(autoStaticImportTable.component)
|
||||
.align(AlignX.FILL)
|
||||
.label(JavaBundle.message("auto.static.import.completion.group"), LabelPosition.TOP)
|
||||
.onApply { autoStaticImportTable.apply() }
|
||||
.onReset { autoStaticImportTable.reset() }
|
||||
.onIsModified { autoStaticImportTable.isModified }
|
||||
}
|
||||
row {
|
||||
cell(excludeTable.component)
|
||||
.align(AlignX.FILL)
|
||||
@@ -81,6 +156,9 @@ class JavaAutoImportOptions(val project: Project) : UiDslUnnamedConfigurable.Sim
|
||||
.onApply { excludeTable.apply() }
|
||||
.onReset { excludeTable.reset() }
|
||||
.onIsModified { excludeTable.isModified }
|
||||
.applyToComponent {
|
||||
disposable?.let { Disposer.register(it, excludeTable) }
|
||||
}
|
||||
}
|
||||
}
|
||||
onApply {
|
||||
@@ -101,6 +179,6 @@ class JavaAutoImportOptions(val project: Project) : UiDslUnnamedConfigurable.Sim
|
||||
}
|
||||
|
||||
fun addExcludePackage(packageName: String) {
|
||||
excludeTable.addExcludePackage(packageName)
|
||||
excludeTable.addRow(packageName)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// 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.codeInsight;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.SettingsCategory;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import com.intellij.util.xmlb.annotations.XCollection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@State(name = "JavaIdeCodeInsightSettings", storages = @Storage("codeInsightSettings.xml"), category = SettingsCategory.CODE, perClient = true)
|
||||
public class JavaIdeCodeInsightSettings implements PersistentStateComponent<JavaIdeCodeInsightSettings> {
|
||||
|
||||
@XCollection(propertyElementName = "included-static-names", elementName = "name", valueAttributeName = "")
|
||||
public List<String> includedAutoStaticNames = new ArrayList<>();
|
||||
|
||||
public static JavaIdeCodeInsightSettings getInstance() {
|
||||
return ApplicationManager.getApplication().getService(JavaIdeCodeInsightSettings.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable JavaIdeCodeInsightSettings getState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(@NotNull JavaIdeCodeInsightSettings state) {
|
||||
XmlSerializerUtil.copyBean(state, this);
|
||||
}
|
||||
}
|
||||
@@ -28,11 +28,25 @@ public class JavaProjectCodeInsightSettings implements PersistentStateComponent<
|
||||
|
||||
@XCollection(propertyElementName = "excluded-names", elementName = "name", valueAttributeName = "")
|
||||
public List<String> excludedNames = new ArrayList<>();
|
||||
@XCollection(propertyElementName = "included-static-names", elementName = "name", valueAttributeName = "")
|
||||
public List<String> includedAutoStaticNames = new ArrayList<>();
|
||||
|
||||
public static JavaProjectCodeInsightSettings getSettings(@NotNull Project project) {
|
||||
return project.getService(JavaProjectCodeInsightSettings.class);
|
||||
}
|
||||
|
||||
public List<String> getAllIncludedAutoStaticNames() {
|
||||
List<String> names = new ArrayList<>(includedAutoStaticNames);
|
||||
names.addAll(JavaIdeCodeInsightSettings.getInstance().includedAutoStaticNames);
|
||||
return names;
|
||||
}
|
||||
|
||||
public boolean isStaticAutoImportClass(@Nullable String name) {
|
||||
if (name == null) return false;
|
||||
return includedAutoStaticNames.contains(name) ||
|
||||
JavaIdeCodeInsightSettings.getInstance().includedAutoStaticNames.contains(name);
|
||||
}
|
||||
|
||||
public boolean isExcluded(@NotNull String name) {
|
||||
for (String excluded : excludedNames) {
|
||||
if (nameMatches(name, excluded)) {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
// 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.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.JavaProjectCodeInsightSettings;
|
||||
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.VariableLookupItem;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
@@ -32,6 +35,16 @@ public class JavaStaticMemberProcessor extends StaticMemberProcessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
Project project = parameters.getPosition().getProject();
|
||||
JavaProjectCodeInsightSettings codeInsightSettings = JavaProjectCodeInsightSettings.getSettings(project);
|
||||
JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project);
|
||||
GlobalSearchScope resolveScope = parameters.getOriginalFile().getResolveScope();
|
||||
for (String classNames : codeInsightSettings.getAllIncludedAutoStaticNames()) {
|
||||
PsiClass aClass = javaPsiFacade.findClass(classNames, resolveScope);
|
||||
if (aClass != null) {
|
||||
importMembersOf(aClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,12 +28,13 @@ public abstract class StaticMemberProcessor {
|
||||
private final PsiResolveHelper myResolveHelper;
|
||||
private boolean myHintShown;
|
||||
private final boolean myPackagedContext;
|
||||
|
||||
private final JavaProjectCodeInsightSettings codeInsightSettings;
|
||||
protected StaticMemberProcessor(@NotNull PsiElement position) {
|
||||
myPosition = position;
|
||||
myProject = myPosition.getProject();
|
||||
myResolveHelper = JavaPsiFacade.getInstance(myProject).getResolveHelper();
|
||||
myPackagedContext = JavaCompletionUtil.inSomePackage(position);
|
||||
codeInsightSettings = JavaProjectCodeInsightSettings.getSettings(position.getProject());
|
||||
}
|
||||
|
||||
public void importMembersOf(@NotNull PsiClass psiClass) {
|
||||
@@ -60,7 +61,12 @@ public abstract class StaticMemberProcessor {
|
||||
if (member instanceof PsiMethod && !classesToSkip.add(containingClass)) return;
|
||||
if(!additionalFilter(member)) return;
|
||||
boolean shouldImport = myStaticImportedClasses.contains(containingClass);
|
||||
showHint(shouldImport);
|
||||
if (!shouldImport && codeInsightSettings.isStaticAutoImportClass(containingClass.getQualifiedName())) {
|
||||
shouldImport = true;
|
||||
}
|
||||
else {
|
||||
showHint(shouldImport);
|
||||
}
|
||||
LookupElement item = member instanceof PsiMethod ? createItemWithOverloads((PsiMethod)member, containingClass, shouldImport) :
|
||||
member instanceof PsiField ? createLookupElement(member, containingClass, shouldImport) :
|
||||
null;
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.intellij.psi.impl.source.codeStyle;
|
||||
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
import com.intellij.codeInsight.ImportFilter;
|
||||
import com.intellij.codeInsight.JavaProjectCodeInsightSettings;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.jsp.JspSpiUtil;
|
||||
@@ -103,7 +104,8 @@ public final class ImportHelper {
|
||||
Map<String, Boolean> classesOrPackagesToImportOnDemand = new HashMap<>();
|
||||
List<PsiImportModuleStatement> previousModuleStatements = collectModuleImports(file, mySettings);
|
||||
Map<String, PsiImportModuleStatement> moduleStatementMap = collectNamesImportedByModules(file, previousModuleStatements, resultList);
|
||||
collectOnDemandImports(resultList, mySettings, classesOrPackagesToImportOnDemand, moduleStatementMap);
|
||||
JavaProjectCodeInsightSettings javaProjectCodeInsightSettings = JavaProjectCodeInsightSettings.getSettings(file.getProject());
|
||||
collectOnDemandImports(resultList, mySettings, javaProjectCodeInsightSettings, classesOrPackagesToImportOnDemand, moduleStatementMap);
|
||||
|
||||
MultiMap<String, String> conflictingMemberNames = new MultiMap<>();
|
||||
for (Import anImport : resultList) {
|
||||
@@ -211,7 +213,8 @@ public final class ImportHelper {
|
||||
}
|
||||
|
||||
public static void collectOnDemandImports(@NotNull List<Import> resultList,
|
||||
@NotNull JavaCodeStyleSettings settings,
|
||||
@NotNull JavaCodeStyleSettings javaCodeStyleSettings,
|
||||
@NotNull JavaProjectCodeInsightSettings javaProjectCodeInsightSettings,
|
||||
@NotNull Map<String, Boolean> outClassesOrPackagesToImportOnDemand,
|
||||
@NotNull Map<String, PsiImportModuleStatement> moduleStatementMap) {
|
||||
Object2IntMap<String> packageToCountMap = new Object2IntOpenHashMap<>();
|
||||
@@ -225,12 +228,13 @@ public final class ImportHelper {
|
||||
}
|
||||
|
||||
classToCountMap.forEach((className, count) -> {
|
||||
if (isToUseImportOnDemand(className, count, true, settings)) {
|
||||
if (isToUseImportOnDemand(className, count, true, javaCodeStyleSettings) ||
|
||||
javaProjectCodeInsightSettings.isStaticAutoImportClass(className)) {
|
||||
outClassesOrPackagesToImportOnDemand.put(className, true);
|
||||
}
|
||||
});
|
||||
packageToCountMap.forEach((packageName, count) -> {
|
||||
if (isToUseImportOnDemand(packageName, count, false, settings)) {
|
||||
if (isToUseImportOnDemand(packageName, count, false, javaCodeStyleSettings)) {
|
||||
outClassesOrPackagesToImportOnDemand.put(packageName, false);
|
||||
}
|
||||
});
|
||||
@@ -930,7 +934,7 @@ public final class ImportHelper {
|
||||
return maxSpace;
|
||||
}
|
||||
|
||||
private static boolean isToUseImportOnDemand(@NotNull String packageName,
|
||||
private static boolean isToUseImportOnDemand(@NotNull String packageOrClassName,
|
||||
int classCount,
|
||||
boolean isStaticImportNeeded,
|
||||
@NotNull JavaCodeStyleSettings settings) {
|
||||
@@ -938,9 +942,9 @@ public final class ImportHelper {
|
||||
int limitCount = isStaticImportNeeded ? settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND :
|
||||
settings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND;
|
||||
if (classCount >= limitCount) return true;
|
||||
if (packageName.isEmpty()) return false;
|
||||
if (packageOrClassName.isEmpty()) return false;
|
||||
PackageEntryTable table = settings.PACKAGES_TO_USE_IMPORT_ON_DEMAND;
|
||||
return table.contains(packageName);
|
||||
return table.contains(packageOrClassName);
|
||||
}
|
||||
|
||||
private static int findEntryIndex(@NotNull String packageName, boolean isStatic, boolean isModule, PackageEntry @NotNull [] entries) {
|
||||
|
||||
+8
@@ -2,6 +2,7 @@
|
||||
package com.intellij.psi.impl.source.codeStyle;
|
||||
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
import com.intellij.codeInsight.JavaProjectCodeInsightSettings;
|
||||
import com.intellij.codeInspection.dataFlow.ContractReturnValue;
|
||||
import com.intellij.codeInspection.dataFlow.JavaMethodContractUtil;
|
||||
import com.intellij.codeInspection.dataFlow.MethodContract;
|
||||
@@ -133,6 +134,13 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager {
|
||||
return ImportHelper.hasConflictingOnStaticDemandImport(file, psiClass, referenceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStaticAutoImportClass(@Nullable String fqn) {
|
||||
if (fqn == null) return false;
|
||||
JavaProjectCodeInsightSettings settings = JavaProjectCodeInsightSettings.getSettings(myProject);
|
||||
return settings.isStaticAutoImportClass(fqn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addImport(@NotNull PsiJavaFile file, @NotNull PsiClass refClass) {
|
||||
return new ImportHelper(JavaCodeStyleSettings.getInstance(file)).addImport(file, refClass);
|
||||
|
||||
@@ -4,10 +4,12 @@ package com.intellij.psi.impl.source.codeStyle;
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
import com.intellij.codeInsight.AnnotationTargetUtil;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
|
||||
import com.intellij.codeInsight.intention.impl.AddOnDemandStaticImportAction;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.ReferenceAdjuster;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
@@ -15,10 +17,12 @@ import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl;
|
||||
import com.intellij.psi.impl.source.SourceJavaCodeReference;
|
||||
import com.intellij.psi.impl.source.jsp.jspJava.JspClass;
|
||||
import com.intellij.psi.impl.source.tree.*;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
|
||||
import com.intellij.psi.jsp.JspFile;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import com.siyeh.ig.psiutils.ImportUtils;
|
||||
import one.util.streamex.StreamEx;
|
||||
@@ -40,6 +44,10 @@ public final class JavaReferenceAdjuster implements ReferenceAdjuster {
|
||||
deQualifyImpl((PsiQualifiedReferenceElement)element);
|
||||
return element;
|
||||
}
|
||||
if (tryAutoStaticallyImport(ref)) {
|
||||
deQualifyImpl((PsiQualifiedReferenceElement)element);
|
||||
return element;
|
||||
}
|
||||
}
|
||||
if (elementType == JavaElementType.JAVA_CODE_REFERENCE || incompleteCode ||
|
||||
parentType == JavaElementType.REFERENCE_EXPRESSION || parentType == JavaElementType.METHOD_REF_EXPRESSION) {
|
||||
@@ -130,6 +138,31 @@ public final class JavaReferenceAdjuster implements ReferenceAdjuster {
|
||||
return element;
|
||||
}
|
||||
|
||||
private static boolean tryAutoStaticallyImport(@NotNull PsiReferenceExpression reference) {
|
||||
JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(reference.getProject());
|
||||
PsiFile file = reference.getContainingFile();
|
||||
if (!(file instanceof PsiJavaFile javaFile)) return false;
|
||||
if (reference instanceof PsiMethodReferenceExpression) return false;
|
||||
String memberName = reference.getReferenceName();
|
||||
if (memberName == null) return false;
|
||||
PsiJavaCodeReferenceElement qualifier = ObjectUtils.tryCast(reference.getQualifier(), PsiJavaCodeReferenceElement.class);
|
||||
if (qualifier == null) return false;
|
||||
if (GenericsUtil.isGenericReference(reference, qualifier)) return false;
|
||||
if (PsiTreeUtil.getParentOfType(reference, PsiImportStatementBase.class) != null) return false;
|
||||
if (!(qualifier.resolve() instanceof PsiClass psiClass)) return false;
|
||||
String classQualifiedName = psiClass.getQualifiedName();
|
||||
if (!javaCodeStyleManager.isStaticAutoImportClass(classQualifiedName)) return false;
|
||||
PsiElement referenceNameElement = qualifier.getReferenceNameElement();
|
||||
if (referenceNameElement == null) return false;
|
||||
PsiClass anImport = AddOnDemandStaticImportAction.getClassToPerformStaticImport(referenceNameElement);
|
||||
if (anImport == null) return false;
|
||||
if (javaCodeStyleManager.hasConflictingOnDemandImport(javaFile, anImport, memberName)) return false;
|
||||
PsiImportList importList = javaFile.getImportList();
|
||||
if (importList == null) return false;
|
||||
PsiReferenceExpressionImpl.bindToElementViaStaticImport(anImport, memberName, importList);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ASTNode process(@NotNull ASTNode element, boolean addImports, boolean incompleteCode, Project project) {
|
||||
final CodeStyleSettings settings = CodeStyle.getSettings(element.getPsi().getContainingFile());
|
||||
|
||||
@@ -24,6 +24,15 @@ public abstract class JavaCodeStyleManager {
|
||||
public static final int DO_NOT_ADD_IMPORTS = 0x1000;
|
||||
public static final int INCOMPLETE_CODE = 0x2000;
|
||||
|
||||
/**
|
||||
* Determines whether the specified fully qualified name (FQN) represents
|
||||
* a class that should be statically auto-imported in the context.
|
||||
*
|
||||
* @param fqn the fully qualified name of the target class, must not be null
|
||||
* @return true if the class is configured to be statically auto-imported, false otherwise
|
||||
*/
|
||||
public abstract boolean isStaticAutoImportClass(@Nullable String fqn);
|
||||
|
||||
public abstract boolean addImport(@NotNull PsiJavaFile file, @NotNull PsiClass refClass);
|
||||
public abstract @NotNull PsiElement shortenClassReferences(@NotNull PsiElement element,
|
||||
@MagicConstant(flags = {DO_NOT_ADD_IMPORTS, INCOMPLETE_CODE}) int flags) throws IncorrectOperationException;
|
||||
|
||||
@@ -22,6 +22,11 @@ import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class CoreJavaCodeStyleManager extends JavaCodeStyleManager {
|
||||
@Override
|
||||
public boolean isStaticAutoImportClass(@Nullable String fqn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addImport(@NotNull PsiJavaFile file, @NotNull PsiClass refClass) {
|
||||
return false;
|
||||
|
||||
+5
-2
@@ -105,8 +105,11 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements
|
||||
String qualifiedName = qualifierClass.getQualifiedName();
|
||||
List<PsiJavaCodeReferenceElement> refs = getImportsFromClass(importList, qualifiedName);
|
||||
JavaFileCodeStyleFacade javaCodeStyleSettingsFacade = JavaFileCodeStyleFacade.forContext(importList.getContainingFile());
|
||||
if (!javaCodeStyleSettingsFacade.isToImportOnDemand(qualifiedName) && refs.size() + 1 < javaCodeStyleSettingsFacade.getNamesCountToUseImportOnDemand() ||
|
||||
JavaCodeStyleManager.getInstance(qualifierClass.getProject()).hasConflictingOnDemandImport((PsiJavaFile)importList.getContainingFile(), qualifierClass, staticName)) {
|
||||
JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(qualifierClass.getProject());
|
||||
if ((!javaCodeStyleSettingsFacade.isToImportOnDemand(qualifiedName) &&
|
||||
!javaCodeStyleManager.isStaticAutoImportClass(qualifiedName) &&
|
||||
refs.size() + 1 < javaCodeStyleSettingsFacade.getNamesCountToUseImportOnDemand()) ||
|
||||
javaCodeStyleManager.hasConflictingOnDemandImport((PsiJavaFile)importList.getContainingFile(), qualifierClass, staticName)) {
|
||||
importList.add(JavaPsiFacade.getElementFactory(qualifierClass.getProject()).createImportStaticStatement(qualifierClass, staticName));
|
||||
} else {
|
||||
for (PsiJavaCodeReferenceElement ref : refs) {
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import java.util.*;
|
||||
|
||||
class Foo {
|
||||
void m() {
|
||||
List<CharSequence> l = Arrays.asList("a", "b").stream().toli<caret>
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.util.*;
|
||||
|
||||
import static org.example.AAA.*;
|
||||
|
||||
class Foo {
|
||||
void m() {
|
||||
List<CharSequence> l = Arrays.asList("a", "b").stream().toli<caret>
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.example.AAA.*;
|
||||
|
||||
class Foo {
|
||||
void m() {
|
||||
List<CharSequence> l = Arrays.asList("a", "b").stream().collect(Collectors.toList());<caret>
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.stream.Collectors.*;
|
||||
|
||||
class Foo {
|
||||
void m() {
|
||||
List<CharSequence> l = Arrays.asList("a", "b").stream().collect(toList());<caret>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import java.util.List;
|
||||
|
||||
|
||||
class Foo {
|
||||
void test(List<String> baz) {
|
||||
so<caret>
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import java.util.List;
|
||||
|
||||
|
||||
class Foo {
|
||||
void test(List<String> baz) {
|
||||
so<caret>
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
class Foo {
|
||||
void test(List<String> baz) {
|
||||
Arrays.sort(<caret>);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import java.util.List;
|
||||
|
||||
|
||||
class Foo {
|
||||
void test(List<String> baz) {
|
||||
so<caret>
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
|
||||
class Foo {
|
||||
void test(List<String> baz) {
|
||||
so<caret>
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
|
||||
class Foo {
|
||||
void test(List<String> baz) {
|
||||
sort(<caret>);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.util.List;
|
||||
|
||||
import static org.example.AAA.*;
|
||||
|
||||
class Foo {
|
||||
void test(List<String> baz) {
|
||||
so<caret>
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.example.AAA.*;
|
||||
|
||||
class Foo {
|
||||
void test(List<String> baz) {
|
||||
Arrays.sort(<caret>);
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Arrays.*;
|
||||
|
||||
|
||||
class Foo {
|
||||
void test(List<String> baz) {
|
||||
sort(<caret>);
|
||||
}
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
// 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.java.codeInsight.completion;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.JavaProjectCodeInsightSettings;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.NeedsIndex;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@NeedsIndex.ForStandardLibrary
|
||||
public class AutoStaticImportCompletionTest extends NormalCompletionTestCase {
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
try {
|
||||
JavaProjectCodeInsightSettings.getSettings(getProject()).includedAutoStaticNames.clear();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
addSuppressedException(e);
|
||||
}
|
||||
finally {
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LightProjectDescriptor getProjectDescriptor() {
|
||||
return JAVA_21;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getBasePath() {
|
||||
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/completion/autoStaticImport/";
|
||||
}
|
||||
|
||||
public void testSimpleStaticAutoImport() {
|
||||
addStaticAutoImport("java.util.Arrays");
|
||||
configure();
|
||||
type("r");
|
||||
LookupElement[] elements = myFixture.getLookupElements();
|
||||
LookupElement element = ContainerUtil.find(elements, e ->
|
||||
e.getLookupString().equals("sort") &&
|
||||
e.getPsiElement() instanceof PsiMethod method &&
|
||||
method.getContainingClass().getQualifiedName().equals("java.util.Arrays"));
|
||||
assertNotNull(element);
|
||||
selectItem(element);
|
||||
checkResult();
|
||||
}
|
||||
|
||||
@NeedsIndex.Full
|
||||
public void testSimpleStaticAutoImportWithConflict() {
|
||||
addStaticAutoImport("java.util.Arrays");
|
||||
myFixture.addClass("""
|
||||
package org.example;
|
||||
public final class AAA {
|
||||
public static <T> List<T> sort(T[] args){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
""");
|
||||
configure();
|
||||
type("r");
|
||||
LookupElement[] elements = myFixture.getLookupElements();
|
||||
LookupElement element = ContainerUtil.find(elements, e ->
|
||||
e.getLookupString().equals("sort") &&
|
||||
e.getPsiElement() instanceof PsiMethod method &&
|
||||
method.getContainingClass().getQualifiedName().equals("java.util.Arrays"));
|
||||
assertNotNull(element);
|
||||
selectItem(element);
|
||||
checkResult();
|
||||
}
|
||||
|
||||
public void testSimpleStaticAutoImportWithAlreadyImported() {
|
||||
addStaticAutoImport("java.util.Arrays");
|
||||
configure();
|
||||
type("r");
|
||||
LookupElement[] elements = myFixture.getLookupElements();
|
||||
LookupElement element = ContainerUtil.find(elements, e ->
|
||||
e.getLookupString().equals("sort") &&
|
||||
e.getPsiElement() instanceof PsiMethod method &&
|
||||
method.getContainingClass().getQualifiedName().equals("java.util.Arrays"));
|
||||
assertNotNull(element);
|
||||
selectItem(element);
|
||||
checkResult();
|
||||
}
|
||||
|
||||
public void testNoAutoImport() {
|
||||
configure();
|
||||
type("r");
|
||||
LookupElement[] elements = myFixture.getLookupElements();
|
||||
LookupElement element = ContainerUtil.find(elements, e ->
|
||||
e.getLookupString().equals("sort") &&
|
||||
e.getPsiElement() instanceof PsiMethod method &&
|
||||
method.getContainingClass().getQualifiedName().equals("java.util.Arrays"));
|
||||
assertNull(element);
|
||||
}
|
||||
|
||||
@NeedsIndex.Full
|
||||
public void testChainedAutoStaticImport() {
|
||||
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_1_8, () -> {
|
||||
addStaticAutoImport("java.util.stream.Collectors");
|
||||
configureByTestName();
|
||||
selectItem(ContainerUtil.find(myItems, it -> it.getLookupString().contains("toList")));
|
||||
checkResult();
|
||||
});
|
||||
}
|
||||
|
||||
@NeedsIndex.Full
|
||||
public void testChainedAutoStaticImportWithConflict() {
|
||||
IdeaTestUtil.withLevel(getModule(), LanguageLevel.JDK_1_8, () -> {
|
||||
addStaticAutoImport("java.util.stream.Collectors");
|
||||
myFixture.addClass("""
|
||||
package org.example;
|
||||
public final class AAA {
|
||||
public static <T> List<T> toList(){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
""");
|
||||
configureByTestName();
|
||||
selectItem(ContainerUtil.find(myItems, it -> it.getLookupString().contains("toList")));
|
||||
checkResult();
|
||||
});
|
||||
}
|
||||
|
||||
public void testNoSimpleStaticAutoImport() {
|
||||
configure();
|
||||
LookupElement[] elements = myFixture.completeBasic();
|
||||
LookupElement element = ContainerUtil.find(elements, e ->
|
||||
e.getLookupString().equals("sort") &&
|
||||
e.getPsiElement() instanceof PsiMethod method &&
|
||||
method.getContainingClass().getQualifiedName().equals("java.util.Arrays"));
|
||||
assertNotNull(element);
|
||||
selectItem(element);
|
||||
checkResult();
|
||||
}
|
||||
|
||||
private void addStaticAutoImport(@NotNull String name) {
|
||||
JavaProjectCodeInsightSettings.getSettings(getProject()).includedAutoStaticNames.add(name);
|
||||
}
|
||||
}
|
||||
@@ -236,9 +236,14 @@ error.text.this.is.not.a.valid.java.class.name=This is not a valid Java class na
|
||||
exclude.0.from.completion=Exclude ''{0}'' from completion
|
||||
exclude.accessors=&Exclude Accessors
|
||||
exclude.from.completion.group=Exclude from auto-import and completion:
|
||||
auto.static.import.completion.group=Include auto-import of static members in completion:
|
||||
auto.static.import.comment=Add a class to include its static members
|
||||
auto.static.import.comment.2=in auto-import and completion
|
||||
auto.static.import.class=Class
|
||||
auto.static.import.scope=Scope
|
||||
exclude.from.imports.no.exclusions=Add a class, package, or member
|
||||
exclude.from.imports.no.exclusions.2=to exclude from auto-import and completion
|
||||
exclude.table.mask=Class, package, or member
|
||||
exclude.table.mask=Class, Package, or Member
|
||||
exclude.table.scope.column=Scope
|
||||
export.to.html.generate.hyperlinks.checkbox=Generate &hyperlinks to classes
|
||||
external.annotation.prompt=External Annotation Prompt
|
||||
|
||||
+3
-1
@@ -1,6 +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 org.jetbrains.plugins.javaFX.fxml.codeInsight;
|
||||
|
||||
import com.intellij.codeInsight.JavaProjectCodeInsightSettings;
|
||||
import com.intellij.ide.highlighter.XmlFileType;
|
||||
import com.intellij.injected.editor.VirtualFileWindow;
|
||||
import com.intellij.lang.ASTNode;
|
||||
@@ -47,9 +48,10 @@ public final class JavaFxImportsOptimizer implements ImportOptimizer {
|
||||
collectNamesToImport(names, demandedForNested, (XmlFile)file);
|
||||
names.sort((o1, o2) -> StringUtil.compare(o1.name(), o2.name(), true));
|
||||
final JavaCodeStyleSettings settings = JavaCodeStyleSettings.getInstance(file);
|
||||
JavaProjectCodeInsightSettings javaProjectCodeInsightSettings = JavaProjectCodeInsightSettings.getSettings(file.getProject());
|
||||
final @NotNull List<ImportHelper.Import> sortedNames = ImportHelper.sortItemsAccordingToSettings(names, settings);
|
||||
final Map<String, Boolean> onDemand = new HashMap<>();
|
||||
ImportHelper.collectOnDemandImports(sortedNames, settings, onDemand, new HashMap<>());
|
||||
ImportHelper.collectOnDemandImports(sortedNames, settings, javaProjectCodeInsightSettings, onDemand, new HashMap<>());
|
||||
for (String s : demandedForNested) {
|
||||
onDemand.put(s, false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user