diff --git a/src/META-INF/plugin.xml b/src/META-INF/plugin.xml index 350a0d85ec..e1e78292dd 100644 --- a/src/META-INF/plugin.xml +++ b/src/META-INF/plugin.xml @@ -52,6 +52,13 @@ + + + com.goide.codeInsight.imports.GoOptimizeImportsPassFactory + + + + diff --git a/src/com/goide/codeInsight/imports/GoAutoImportConfigurable.java b/src/com/goide/codeInsight/imports/GoAutoImportConfigurable.java index 92734d77fa..f938d27c44 100644 --- a/src/com/goide/codeInsight/imports/GoAutoImportConfigurable.java +++ b/src/com/goide/codeInsight/imports/GoAutoImportConfigurable.java @@ -37,6 +37,7 @@ public class GoAutoImportConfigurable implements SearchableConfigurable { private JCheckBox myCbShowImportPopup; + private JCheckBox myCbOptimizeImportsOnTheFly; private JCheckBox myCbAddUnambiguousImports; private JBList myExcludePackagesList; private DefaultListModel myExcludePackagesModel; @@ -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(); @@ -94,6 +97,7 @@ 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()); } @@ -101,6 +105,7 @@ public boolean isModified() { @Override public void apply() throws ConfigurationException { myCodeInsightSettings.setShowImportPopup(myCbShowImportPopup.isSelected()); + myCodeInsightSettings.setOptimizeImportsOnTheFly(myCbOptimizeImportsOnTheFly.isSelected()); myCodeInsightSettings.setAddUnambiguousImportsOnTheFly(myCbAddUnambiguousImports.isSelected()); myExcludedSettings.setExcludedPackages(getExcludedPackages()); } @@ -108,6 +113,7 @@ public void apply() throws ConfigurationException { @Override public void reset() { myCbShowImportPopup.setSelected(myCodeInsightSettings.isShowImportPopup()); + myCbOptimizeImportsOnTheFly.setSelected(myCodeInsightSettings.isOptimizeImportsOnTheFly()); myCbAddUnambiguousImports.setSelected(myCodeInsightSettings.isAddUnambiguousImportsOnTheFly()); myExcludePackagesModel = new DefaultListModel(); diff --git a/src/com/goide/codeInsight/imports/GoCodeInsightSettings.java b/src/com/goide/codeInsight/imports/GoCodeInsightSettings.java index e5ff2532be..96b3905607 100644 --- a/src/com/goide/codeInsight/imports/GoCodeInsightSettings.java +++ b/src/com/goide/codeInsight/imports/GoCodeInsightSettings.java @@ -26,6 +26,7 @@ ) public class GoCodeInsightSettings implements PersistentStateComponent { private boolean myShowImportPopup = true; + private boolean myOptimizeImportsOnTheFly = true; private boolean myAddUnambiguousImportsOnTheFly = true; public static GoCodeInsightSettings getInstance() { @@ -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; } diff --git a/src/com/goide/codeInsight/imports/GoOptimizeImportsPass.java b/src/com/goide/codeInsight/imports/GoOptimizeImportsPass.java new file mode 100644 index 0000000000..d7cbfd5653 --- /dev/null +++ b/src/com/goide/codeInsight/imports/GoOptimizeImportsPass.java @@ -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); + } +} diff --git a/src/com/goide/codeInsight/imports/GoOptimizeImportsPassFactory.java b/src/com/goide/codeInsight/imports/GoOptimizeImportsPassFactory.java new file mode 100644 index 0000000000..fc9fdd78a8 --- /dev/null +++ b/src/com/goide/codeInsight/imports/GoOptimizeImportsPassFactory.java @@ -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"; + } +} diff --git a/testData/imports/optimize/on-the-fly/redeclaredImport-after.go b/testData/imports/optimize/on-the-fly/redeclaredImport-after.go new file mode 100644 index 0000000000..7e9335a425 --- /dev/null +++ b/testData/imports/optimize/on-the-fly/redeclaredImport-after.go @@ -0,0 +1,10 @@ +package a +import ( + "fmt" + "http" +) + +func b() { + http.get("123") + fmt.Println() +} \ No newline at end of file diff --git a/testData/imports/optimize/on-the-fly/redeclaredImport.go b/testData/imports/optimize/on-the-fly/redeclaredImport.go new file mode 100644 index 0000000000..93d0327847 --- /dev/null +++ b/testData/imports/optimize/on-the-fly/redeclaredImport.go @@ -0,0 +1,11 @@ +package a +import ( + fmt "fmt" + "fmt" + "http" +) + +func b() { + http.get("123") + fmt.Println() +} \ No newline at end of file diff --git a/testData/imports/optimize/on-the-fly/redundantImport-after.go b/testData/imports/optimize/on-the-fly/redundantImport-after.go new file mode 100644 index 0000000000..7e9335a425 --- /dev/null +++ b/testData/imports/optimize/on-the-fly/redundantImport-after.go @@ -0,0 +1,10 @@ +package a +import ( + "fmt" + "http" +) + +func b() { + http.get("123") + fmt.Println() +} \ No newline at end of file diff --git a/testData/imports/optimize/on-the-fly/redundantImport.go b/testData/imports/optimize/on-the-fly/redundantImport.go new file mode 100644 index 0000000000..659443dad2 --- /dev/null +++ b/testData/imports/optimize/on-the-fly/redundantImport.go @@ -0,0 +1,10 @@ +package a +import ( + fmt "fmt" + "http" +) + +func b() { + http.get("123") + fmt.Println() +} \ No newline at end of file diff --git a/testData/imports/optimize/on-the-fly/unusedImport-after.go b/testData/imports/optimize/on-the-fly/unusedImport-after.go new file mode 100644 index 0000000000..ee8dcd3341 --- /dev/null +++ b/testData/imports/optimize/on-the-fly/unusedImport-after.go @@ -0,0 +1,4 @@ +package a + +func b() { +} \ No newline at end of file diff --git a/testData/imports/optimize/on-the-fly/unusedImport.go b/testData/imports/optimize/on-the-fly/unusedImport.go new file mode 100644 index 0000000000..11061ba799 --- /dev/null +++ b/testData/imports/optimize/on-the-fly/unusedImport.go @@ -0,0 +1,5 @@ +package a +import "fmt" + +func b() { +} \ No newline at end of file diff --git a/tests/com/goide/codeInsight/imports/GoOptimizeImportsOnTheFlyTest.java b/tests/com/goide/codeInsight/imports/GoOptimizeImportsOnTheFlyTest.java new file mode 100644 index 0000000000..11892a0496 --- /dev/null +++ b/tests/com/goide/codeInsight/imports/GoOptimizeImportsOnTheFlyTest.java @@ -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(); } +} diff --git a/tests/com/goide/inspections/GoHighlightingTest.java b/tests/com/goide/inspections/GoHighlightingTest.java index 8f76fa2b50..246b37034c 100644 --- a/tests/com/goide/inspections/GoHighlightingTest.java +++ b/tests/com/goide/inspections/GoHighlightingTest.java @@ -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; @@ -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() { diff --git a/tests/com/goide/inspections/GoTestSignaturesInspectionTest.java b/tests/com/goide/inspections/GoTestSignaturesInspectionTest.java index 0cd570d713..6b2b03f0a8 100644 --- a/tests/com/goide/inspections/GoTestSignaturesInspectionTest.java +++ b/tests/com/goide/inspections/GoTestSignaturesInspectionTest.java @@ -16,6 +16,7 @@ package com.goide.inspections; +import com.goide.codeInsight.imports.GoCodeInsightSettings; import com.goide.quickfix.GoQuickFixTestBase; import com.intellij.testFramework.LightProjectDescriptor; @@ -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