Skip to content

Commit 728093e

Browse files
committed
Merge branch 'eugene-auduchinok-optimize_imports'
2 parents d6f9633 + 854c1a3 commit 728093e

13 files changed

+666
-43
lines changed

src/META-INF/plugin.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373
bundle="do.not.touch.this.attribute"/>
7474

7575
<projectService serviceImplementation="com.goide.project.GoBuildTargetSettings"/>
76+
<projectService serviceImplementation="com.goide.project.GoExcludedPathsSettings"/>
77+
<applicationService serviceImplementation="com.goide.codeInsight.imports.GoCodeInsightSettings" />
7678

7779
<defaultLiveTemplatesProvider implementation="com.goide.template.GoLiveTemplatesProvider"/>
7880
<liveTemplateContext implementation="com.goide.template.GoEverywhereContextType"/>
@@ -88,6 +90,7 @@
8890
<annotator language="go" implementationClass="com.goide.GoAnnotator"/>
8991

9092
<lang.importOptimizer language="go" implementationClass="com.goide.codeInsight.imports.GoImportOptimizer"/>
93+
<referenceImporter implementation="com.goide.psi.impl.imports.GoReferenceImporter"/>
9194
<psi.fileReferenceHelper implementation="com.goide.psi.impl.imports.GoImportReferenceHelper"/>
9295
<fileContextProvider implementation="com.goide.psi.impl.imports.GoFileContextProvider"/>
9396

@@ -108,6 +111,7 @@
108111
<completion.contributor language="go" order="last" implementationClass="com.goide.completion.GoAutoImportCompletionContributor"/>
109112
<completion.confidence language="go" order="last" implementationClass="com.goide.completion.GoCompletionConfidence"/>
110113
<lookup.charFilter implementation="com.goide.completion.GoCharFilter"/>
114+
<lookup.actionProvider implementation="com.goide.codeInsight.imports.GoExcludePathLookupActionProvider"/>
111115

112116
<lang.refactoringSupport language="go" implementationClass="com.goide.refactor.GoRefactoringSupportProvider"/>
113117
<spellchecker.support language="go" implementationClass="com.goide.inspections.GoSpellcheckingStrategy"/>
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/*
2+
* Copyright 2013-2015 Sergey Ignatov, Alexander Zolotov, Mihai Toader, Florin Patan
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.goide.codeInsight.imports;
18+
19+
import com.goide.project.GoExcludedPathsSettings;
20+
import com.intellij.openapi.application.ApplicationBundle;
21+
import com.intellij.openapi.options.ConfigurationException;
22+
import com.intellij.openapi.options.SearchableConfigurable;
23+
import com.intellij.openapi.project.Project;
24+
import com.intellij.openapi.ui.Messages;
25+
import com.intellij.openapi.util.text.StringUtil;
26+
import com.intellij.ui.*;
27+
import com.intellij.ui.components.JBList;
28+
import com.intellij.util.ui.FormBuilder;
29+
import com.intellij.util.ui.UIUtil;
30+
import org.jetbrains.annotations.Nls;
31+
import org.jetbrains.annotations.NotNull;
32+
import org.jetbrains.annotations.Nullable;
33+
34+
import javax.swing.*;
35+
import java.awt.*;
36+
import java.util.Arrays;
37+
38+
public class GoAutoImportConfigurable implements SearchableConfigurable {
39+
private JCheckBox myCbShowImportPopup;
40+
private JCheckBox myCbAddUnambiguousImports;
41+
private JBList myExcludePackagesList;
42+
private DefaultListModel myExcludePackagesModel;
43+
44+
@NotNull private GoCodeInsightSettings myCodeInsightSettings;
45+
@NotNull private GoExcludedPathsSettings myExcludedSettings;
46+
private boolean myIsDefaultProject;
47+
48+
public GoAutoImportConfigurable(@NotNull Project project) {
49+
myCodeInsightSettings = GoCodeInsightSettings.getInstance();
50+
myExcludedSettings = GoExcludedPathsSettings.getInstance(project);
51+
myIsDefaultProject = project.isDefault();
52+
}
53+
54+
@Nullable
55+
@Override
56+
public JComponent createComponent() {
57+
FormBuilder builder = FormBuilder.createFormBuilder();
58+
myCbShowImportPopup = new JCheckBox(ApplicationBundle.message("checkbox.show.import.popup"));
59+
myCbAddUnambiguousImports = new JCheckBox(ApplicationBundle.message("checkbox.add.unambiguous.imports.on.the.fly"));
60+
builder.addComponent(myCbShowImportPopup);
61+
builder.addComponent(myCbAddUnambiguousImports);
62+
63+
myExcludePackagesList = new JBList();
64+
JComponent excludedPanel = new JPanel(new BorderLayout());
65+
excludedPanel.add(ToolbarDecorator.createDecorator(myExcludePackagesList)
66+
.setAddAction(new AddImportExclusionAction()).disableUpDownActions().createPanel(), BorderLayout.CENTER);
67+
excludedPanel.setBorder(IdeBorderFactory.createTitledBorder(ApplicationBundle.message("exclude.from.completion.group"), true));
68+
if (!myIsDefaultProject) {
69+
builder.addComponent(excludedPanel);
70+
}
71+
72+
JPanel result = new JPanel(new BorderLayout());
73+
result.add(builder.getPanel(), BorderLayout.NORTH);
74+
return result;
75+
}
76+
77+
public void focusList() {
78+
myExcludePackagesList.setSelectedIndex(0);
79+
myExcludePackagesList.requestFocus();
80+
}
81+
82+
private String[] getExcludedPackages() {
83+
String[] excludedPackages = new String[myExcludePackagesModel.size()];
84+
for (int i = 0; i < myExcludePackagesModel.size(); i++) {
85+
excludedPackages[i] = (String)myExcludePackagesModel.elementAt(i);
86+
}
87+
Arrays.sort(excludedPackages);
88+
return excludedPackages;
89+
}
90+
91+
@Override
92+
public boolean isModified() {
93+
return myCodeInsightSettings.isShowImportPopup() != myCbShowImportPopup.isSelected() ||
94+
myCodeInsightSettings.isAddUnambiguousImportsOnTheFly() != myCbAddUnambiguousImports.isSelected() ||
95+
!Arrays.equals(getExcludedPackages(), myExcludedSettings.getExcludedPackages());
96+
}
97+
98+
@Override
99+
public void apply() throws ConfigurationException {
100+
myCodeInsightSettings.setShowImportPopup(myCbShowImportPopup.isSelected());
101+
myCodeInsightSettings.setAddUnambiguousImportsOnTheFly(myCbAddUnambiguousImports.isSelected());
102+
myExcludedSettings.setExcludedPackages(getExcludedPackages());
103+
}
104+
105+
@Override
106+
public void reset() {
107+
myCbShowImportPopup.setSelected(myCodeInsightSettings.isShowImportPopup());
108+
myCbAddUnambiguousImports.setSelected(myCodeInsightSettings.isAddUnambiguousImportsOnTheFly());
109+
110+
myExcludePackagesModel = new DefaultListModel();
111+
for (String name : myExcludedSettings.getExcludedPackages()) {
112+
myExcludePackagesModel.add(myExcludePackagesModel.size(), name);
113+
}
114+
myExcludePackagesList.setModel(myExcludePackagesModel);
115+
}
116+
117+
@NotNull
118+
@Override
119+
public String getId() {
120+
return "go.autoimport";
121+
}
122+
123+
@Nullable
124+
@Override
125+
public Runnable enableSearch(String option) {
126+
return null;
127+
}
128+
129+
@Nls
130+
@Override
131+
public String getDisplayName() {
132+
return "Auto Import";
133+
}
134+
135+
@Nullable
136+
@Override
137+
public String getHelpTopic() {
138+
return null;
139+
}
140+
141+
@Override
142+
public void disposeUIResources() {
143+
UIUtil.dispose(myExcludePackagesList);
144+
myExcludePackagesList = null;
145+
myExcludePackagesModel = null;
146+
}
147+
148+
private class AddImportExclusionAction implements AnActionButtonRunnable {
149+
@Override
150+
public void run(AnActionButton button) {
151+
String packageName =
152+
Messages.showInputDialog("Enter the import path to exclude from auto-import and completion:",
153+
"Exclude Import Path",
154+
Messages.getWarningIcon());
155+
addExcludedPackage(packageName);
156+
}
157+
158+
private void addExcludedPackage(@Nullable String packageName) {
159+
if (StringUtil.isEmpty(packageName)) return;
160+
int index = -Arrays.binarySearch(myExcludePackagesModel.toArray(), packageName) - 1;
161+
if (index >= 0) {
162+
myExcludePackagesModel.add(index, packageName);
163+
ListScrollingUtil.ensureIndexIsVisible(myExcludePackagesList, index, 0);
164+
}
165+
myExcludePackagesList.clearSelection();
166+
myExcludePackagesList.setSelectedValue(packageName, true);
167+
myExcludePackagesList.requestFocus();
168+
}
169+
}
170+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2013-2015 Sergey Ignatov, Alexander Zolotov, Mihai Toader, Florin Patan
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.goide.codeInsight.imports;
18+
19+
import com.intellij.openapi.components.*;
20+
import com.intellij.util.xmlb.XmlSerializerUtil;
21+
import org.jetbrains.annotations.Nullable;
22+
23+
@State(
24+
name = "Go",
25+
storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/editor.codeinsight.xml")
26+
)
27+
public class GoCodeInsightSettings implements PersistentStateComponent<GoCodeInsightSettings> {
28+
private boolean myShowImportPopup = true;
29+
private boolean myAddUnambiguousImportsOnTheFly = false;
30+
31+
public static GoCodeInsightSettings getInstance() {
32+
return ServiceManager.getService(GoCodeInsightSettings.class);
33+
}
34+
35+
@Nullable
36+
@Override
37+
public GoCodeInsightSettings getState() {
38+
return this;
39+
}
40+
41+
@Override
42+
public void loadState(GoCodeInsightSettings state) {
43+
XmlSerializerUtil.copyBean(state, this);
44+
}
45+
46+
public boolean isShowImportPopup() {
47+
return myShowImportPopup;
48+
}
49+
50+
public void setShowImportPopup(boolean showImportPopup) {
51+
myShowImportPopup = showImportPopup;
52+
}
53+
54+
public boolean isAddUnambiguousImportsOnTheFly() {
55+
return myAddUnambiguousImportsOnTheFly;
56+
}
57+
58+
public void setAddUnambiguousImportsOnTheFly(boolean addUnambiguousImportsOnTheFly) {
59+
myAddUnambiguousImportsOnTheFly = addUnambiguousImportsOnTheFly;
60+
}
61+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright 2013-2015 Sergey Ignatov, Alexander Zolotov, Mihai Toader, Florin Patan
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.goide.codeInsight.imports;
18+
19+
import com.goide.project.GoExcludedPathsSettings;
20+
import com.goide.psi.GoFile;
21+
import com.intellij.codeInsight.lookup.Lookup;
22+
import com.intellij.codeInsight.lookup.LookupActionProvider;
23+
import com.intellij.codeInsight.lookup.LookupElement;
24+
import com.intellij.codeInsight.lookup.LookupElementAction;
25+
import com.intellij.icons.AllIcons;
26+
import com.intellij.openapi.application.ApplicationManager;
27+
import com.intellij.openapi.options.ShowSettingsUtil;
28+
import com.intellij.openapi.project.Project;
29+
import com.intellij.psi.PsiElement;
30+
import com.intellij.util.Consumer;
31+
import com.intellij.util.containers.ContainerUtil;
32+
import org.jetbrains.annotations.NotNull;
33+
34+
import java.util.List;
35+
36+
public class GoExcludePathLookupActionProvider implements LookupActionProvider {
37+
@Override
38+
public void fillActions(LookupElement element, final Lookup lookup, Consumer<LookupElementAction> consumer) {
39+
PsiElement psiElement = element.getPsiElement();
40+
if (psiElement == null) return;
41+
42+
String importPath = ((GoFile)psiElement.getContainingFile()).getImportPath();
43+
if (importPath != null) {
44+
Project project = psiElement.getProject();
45+
for (String path : getPaths(importPath)) {
46+
consumer.consume(new ExcludePathAction(project, path));
47+
}
48+
consumer.consume(new EditExcludedAction(project));
49+
}
50+
}
51+
52+
private static List<String> getPaths(String importPath) {
53+
List<String> result = ContainerUtil.newArrayList(importPath);
54+
int i;
55+
while ((i = importPath.lastIndexOf('/')) > 0) {
56+
importPath = importPath.substring(0, i);
57+
result.add(importPath);
58+
}
59+
return result;
60+
}
61+
62+
private static class EditExcludedAction extends LookupElementAction {
63+
@NotNull Project myProject;
64+
65+
protected EditExcludedAction(@NotNull Project project) {
66+
super(AllIcons.Actions.Edit, "Edit auto import settings");
67+
myProject = project;
68+
}
69+
70+
@Override
71+
public Result performLookupAction() {
72+
ApplicationManager.getApplication().invokeLater(new Runnable() {
73+
@Override
74+
public void run() {
75+
final GoAutoImportConfigurable configurable = new GoAutoImportConfigurable(myProject);
76+
ShowSettingsUtil.getInstance()
77+
.editConfigurable(myProject, configurable, new Runnable() {
78+
@Override
79+
public void run() {
80+
configurable.focusList();
81+
}
82+
});
83+
}
84+
});
85+
return Result.HIDE_LOOKUP;
86+
}
87+
}
88+
89+
private static class ExcludePathAction extends LookupElementAction {
90+
private Project myProject;
91+
private String myImportPath;
92+
93+
protected ExcludePathAction(@NotNull Project project, @NotNull String importPath) {
94+
super(AllIcons.Actions.Exclude, "Exclude '" + importPath + "'");
95+
myProject = project;
96+
myImportPath = importPath;
97+
}
98+
99+
@Override
100+
public Result performLookupAction() {
101+
GoExcludedPathsSettings.getInstance(myProject).excludePath(myImportPath);
102+
return Result.HIDE_LOOKUP;
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)