Skip to content

Optimize imports on the fly #1807

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@
</component>
</module-components>

<project-components>
<component>
<implementation-class>com.goide.codeInsight.imports.GoOptimizeImportsPassFactory</implementation-class>
<skipForDefaultProject/>
</component>
</project-components>

<extensions defaultExtensionNs="com.intellij">
<stubIndex implementation="com.goide.stubs.index.GoAllPublicNamesIndex"/>
<stubIndex implementation="com.goide.stubs.index.GoAllPrivateNamesIndex"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

public class GoAutoImportConfigurable implements SearchableConfigurable {
private JCheckBox myCbShowImportPopup;
private JCheckBox myCbOptimizeImportsOnTheFly;
private JCheckBox myCbAddUnambiguousImports;
private JBList myExcludePackagesList;
private DefaultListModel myExcludePackagesModel;
Expand All @@ -58,8 +59,10 @@ public GoAutoImportConfigurable(@NotNull Project project, boolean dialogMode) {
public JComponent createComponent() {
FormBuilder builder = FormBuilder.createFormBuilder();
myCbShowImportPopup = new JCheckBox(ApplicationBundle.message("checkbox.show.import.popup"));
myCbOptimizeImportsOnTheFly = new JCheckBox(ApplicationBundle.message("checkbox.optimize.imports.on.the.fly"));
myCbAddUnambiguousImports = new JCheckBox(ApplicationBundle.message("checkbox.add.unambiguous.imports.on.the.fly"));
builder.addComponent(myCbShowImportPopup);
builder.addComponent(myCbOptimizeImportsOnTheFly);
builder.addComponent(myCbAddUnambiguousImports);

myExcludePackagesList = new JBList();
Expand Down Expand Up @@ -94,20 +97,23 @@ private String[] getExcludedPackages() {
@Override
public boolean isModified() {
return myCodeInsightSettings.isShowImportPopup() != myCbShowImportPopup.isSelected() ||
myCodeInsightSettings.isOptimizeImportsOnTheFly() != myCbOptimizeImportsOnTheFly.isSelected() ||
myCodeInsightSettings.isAddUnambiguousImportsOnTheFly() != myCbAddUnambiguousImports.isSelected() ||
!Arrays.equals(getExcludedPackages(), myExcludedSettings.getExcludedPackages());
}

@Override
public void apply() throws ConfigurationException {
myCodeInsightSettings.setShowImportPopup(myCbShowImportPopup.isSelected());
myCodeInsightSettings.setOptimizeImportsOnTheFly(myCbOptimizeImportsOnTheFly.isSelected());
myCodeInsightSettings.setAddUnambiguousImportsOnTheFly(myCbAddUnambiguousImports.isSelected());
myExcludedSettings.setExcludedPackages(getExcludedPackages());
}

@Override
public void reset() {
myCbShowImportPopup.setSelected(myCodeInsightSettings.isShowImportPopup());
myCbOptimizeImportsOnTheFly.setSelected(myCodeInsightSettings.isOptimizeImportsOnTheFly());
myCbAddUnambiguousImports.setSelected(myCodeInsightSettings.isAddUnambiguousImportsOnTheFly());

myExcludePackagesModel = new DefaultListModel();
Expand Down
9 changes: 9 additions & 0 deletions src/com/goide/codeInsight/imports/GoCodeInsightSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
)
public class GoCodeInsightSettings implements PersistentStateComponent<GoCodeInsightSettings> {
private boolean myShowImportPopup = true;
private boolean myOptimizeImportsOnTheFly = true;
private boolean myAddUnambiguousImportsOnTheFly = true;

public static GoCodeInsightSettings getInstance() {
Expand All @@ -51,6 +52,14 @@ public void setShowImportPopup(boolean showImportPopup) {
myShowImportPopup = showImportPopup;
}

public boolean isOptimizeImportsOnTheFly() {
return myOptimizeImportsOnTheFly;
}

public void setOptimizeImportsOnTheFly(boolean optimizeImportsOnTheFly) {
myOptimizeImportsOnTheFly = optimizeImportsOnTheFly;
}

public boolean isAddUnambiguousImportsOnTheFly() {
return myAddUnambiguousImportsOnTheFly;
}
Expand Down
52 changes: 52 additions & 0 deletions src/com/goide/codeInsight/imports/GoOptimizeImportsPass.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2013-2015 Sergey Ignatov, Alexander Zolotov, Mihai Toader, Florin Patan
*
* 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.
*/

package com.goide.codeInsight.imports;

import com.intellij.codeInsight.daemon.impl.DefaultHighlightInfoProcessor;
import com.intellij.codeInsight.daemon.impl.ProgressableTextEditorHighlightingPass;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.util.DocumentUtil;
import org.jetbrains.annotations.NotNull;

public class GoOptimizeImportsPass extends ProgressableTextEditorHighlightingPass {
@NotNull private final PsiFile myFile;
private Runnable myRunnableFix;

public GoOptimizeImportsPass(@NotNull Project project, @NotNull PsiFile file, @NotNull Editor editor) {
super(project, editor.getDocument(), "Go Optimize Imports Pass", file, editor, file.getTextRange(), false,
new DefaultHighlightInfoProcessor());
myFile = file;
}

@Override
protected void collectInformationWithProgress(@NotNull ProgressIndicator progress) {
myRunnableFix = new GoImportOptimizer().processFile(myFile);
progress.checkCanceled();
}

@Override
protected void applyInformationWithProgress() {
final Project project = myFile.getProject();
UndoManager undoManager = UndoManager.getInstance(project);
if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return;
DocumentUtil.writeInRunUndoTransparentAction(myRunnableFix);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2013-2015 Sergey Ignatov, Alexander Zolotov, Mihai Toader, Florin Patan
*
* 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.
*/

package com.goide.codeInsight.imports;

import com.goide.psi.GoFile;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeHighlighting.TextEditorHighlightingPassFactory;
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
import com.intellij.codeInsight.daemon.impl.FileStatusMap;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class GoOptimizeImportsPassFactory extends AbstractProjectComponent implements TextEditorHighlightingPassFactory {
protected GoOptimizeImportsPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar) {
super(project);
highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL}, null, false, -1);
}

@Nullable
@Override
public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull Editor editor) {
TextRange range = FileStatusMap.getDirtyTextRange(editor, Pass.UPDATE_ALL);
if (range != null && file instanceof GoFile && GoCodeInsightSettings.getInstance().isOptimizeImportsOnTheFly()) {
return new GoOptimizeImportsPass(file.getProject(), file, editor);
}
return null;
}

@NotNull
@Override
public String getComponentName() {
return "OptimizeImportsPassFactory";
}
}
10 changes: 10 additions & 0 deletions testData/imports/optimize/on-the-fly/redeclaredImport-after.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package a
import (
"fmt"
"http"
)

func b() {
http.get("123")
fmt.Println()
}
11 changes: 11 additions & 0 deletions testData/imports/optimize/on-the-fly/redeclaredImport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package a
import (
fmt "fmt"
"fmt"
"http"
)

func b() {
http.get("123")
fmt.Println()
}
10 changes: 10 additions & 0 deletions testData/imports/optimize/on-the-fly/redundantImport-after.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package a
import (
"fmt"
"http"
)

func b() {
http.get("123")
fmt.Println()
}
10 changes: 10 additions & 0 deletions testData/imports/optimize/on-the-fly/redundantImport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package a
import (
fmt "fmt"
"http"
)

func b() {
http.get("123")
fmt.Println()
}
4 changes: 4 additions & 0 deletions testData/imports/optimize/on-the-fly/unusedImport-after.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package a

func b() {
}
5 changes: 5 additions & 0 deletions testData/imports/optimize/on-the-fly/unusedImport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package a
import "fmt"

func b() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2013-2015 Sergey Ignatov, Alexander Zolotov, Mihai Toader, Florin Patan
*
* 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.
*/

package com.goide.codeInsight.imports;

import com.goide.GoCodeInsightFixtureTestCase;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;

public class GoOptimizeImportsOnTheFlyTest extends GoCodeInsightFixtureTestCase {
@Override
public void setUp() throws Exception {
super.setUp();
setUpProjectSdk();
((CodeInsightTestFixtureImpl)myFixture).canChangeDocumentDuringHighlighting(true);
}

@Override
protected void tearDown() throws Exception {
super.tearDown();
}

@Override
protected String getBasePath() {
return "imports/optimize/on-the-fly";
}

@Override
protected LightProjectDescriptor getProjectDescriptor() {
return createMockProjectDescriptor();
}

@Override
protected boolean isWriteActionRequired() {
return false;
}

private void doTest() {
String testName = getTestName(true);
myFixture.configureByFile(testName + ".go");
myFixture.doHighlighting();
myFixture.checkResultByFile(testName + "-after.go");
}

public void testUnusedImport() { doTest(); }
public void testRedundantImport() { doTest(); }
public void testRedeclaredImport() { doTest(); }
}
8 changes: 8 additions & 0 deletions tests/com/goide/inspections/GoHighlightingTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.goide.inspections;

import com.goide.GoCodeInsightFixtureTestCase;
import com.goide.codeInsight.imports.GoCodeInsightSettings;
import com.goide.inspections.unresolved.*;
import com.goide.project.GoModuleLibrariesService;
import com.intellij.openapi.command.WriteCommandAction;
Expand Down Expand Up @@ -54,6 +55,13 @@ public void setUp() throws Exception {
GoTestSignaturesInspection.class,
GoAssignmentNilWithoutExplicitType.class
);
GoCodeInsightSettings.getInstance().setOptimizeImportsOnTheFly(false);
}

@Override
protected void tearDown() throws Exception {
GoCodeInsightSettings.getInstance().setOptimizeImportsOnTheFly(true);
super.tearDown();
}

private void doTest() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.goide.inspections;

import com.goide.codeInsight.imports.GoCodeInsightSettings;
import com.goide.quickfix.GoQuickFixTestBase;
import com.intellij.testFramework.LightProjectDescriptor;

Expand All @@ -25,6 +26,13 @@ protected void setUp() throws Exception {
super.setUp();
setUpProjectSdk();
myFixture.enableInspections(GoTestSignaturesInspection.class);
GoCodeInsightSettings.getInstance().setOptimizeImportsOnTheFly(false);
}

@Override
protected void tearDown() throws Exception {
GoCodeInsightSettings.getInstance().setOptimizeImportsOnTheFly(true);
super.tearDown();
}

@Override
Expand Down