From f39d157c771879bbcb7850783961949b6a8f6853 Mon Sep 17 00:00:00 2001 From: Fabio Zadrozny Date: Thu, 9 May 2024 09:08:59 -0300 Subject: [PATCH] Refactor: separate core/ui for import sorting. --- .../org.python.pydev.ast/META-INF/MANIFEST.MF | 1 + .../ast/sort_imports}/ImportArranger.java | 64 ++--- .../ast/sort_imports}/Pep8ImportArranger.java | 28 +- .../pydev/ast/sort_imports/SortImports.java | 168 ++++++++++++ .../META-INF/MANIFEST.MF | 1 + .../pydev/core/imports/ImportPreferences.java | 198 ++++++++++++++ .../pydev/editor/actions/PyFormatAction.java | 1 - .../editor/actions/PyOrganizeImports.java | 191 +++----------- .../CtxInsensitiveImportComplProposal.java | 4 +- .../heuristics/AssistImport.java | 6 +- .../preferences/PydevPrefsInitializer.java | 20 +- .../container/PyOrganizeImportsAction.java | 4 +- .../importsconf/ImportsPreferencesPage.java | 247 +++--------------- .../editor/actions/PyOrganizeImportsTest.java | 109 ++++---- 14 files changed, 550 insertions(+), 492 deletions(-) rename plugins/{org.python.pydev/src/org/python/pydev/editor/actions/organize_imports => org.python.pydev.ast/src/org/python/pydev/ast/sort_imports}/ImportArranger.java (91%) rename plugins/{org.python.pydev/src/org/python/pydev/editor/actions/organize_imports => org.python.pydev.ast/src/org/python/pydev/ast/sort_imports}/Pep8ImportArranger.java (95%) create mode 100644 plugins/org.python.pydev.ast/src/org/python/pydev/ast/sort_imports/SortImports.java create mode 100644 plugins/org.python.pydev.core/src/org/python/pydev/core/imports/ImportPreferences.java diff --git a/plugins/org.python.pydev.ast/META-INF/MANIFEST.MF b/plugins/org.python.pydev.ast/META-INF/MANIFEST.MF index 02225f3a89..d8e0d03a15 100644 --- a/plugins/org.python.pydev.ast/META-INF/MANIFEST.MF +++ b/plugins/org.python.pydev.ast/META-INF/MANIFEST.MF @@ -32,6 +32,7 @@ Export-Package: org.python.pydev.ast, org.python.pydev.ast.refactoring, org.python.pydev.ast.runners, org.python.pydev.ast.simpleassist, + org.python.pydev.ast.sort_imports, org.python.pydev.core.pep8, org.python.pydev.core.templates, org.python.pydev.plugin, diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/actions/organize_imports/ImportArranger.java b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/sort_imports/ImportArranger.java similarity index 91% rename from plugins/org.python.pydev/src/org/python/pydev/editor/actions/organize_imports/ImportArranger.java rename to plugins/org.python.pydev.ast/src/org/python/pydev/ast/sort_imports/ImportArranger.java index edb11677c8..3360a64c2c 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/actions/organize_imports/ImportArranger.java +++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/sort_imports/ImportArranger.java @@ -4,8 +4,9 @@ * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ -package org.python.pydev.editor.actions.organize_imports; +package org.python.pydev.ast.sort_imports; +import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -15,25 +16,22 @@ import java.util.Set; import java.util.TreeMap; -import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; -import org.eclipse.jface.viewers.ISelectionProvider; -import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; +import org.python.pydev.ast.formatter.PyFormatter; import org.python.pydev.core.IPyFormatStdProvider; import org.python.pydev.core.docutils.ImportHandle; import org.python.pydev.core.docutils.ImportHandle.ImportHandleInfo; import org.python.pydev.core.docutils.PyImportsHandling; import org.python.pydev.core.docutils.PySelection; +import org.python.pydev.core.formatter.FormatStd; +import org.python.pydev.core.imports.ImportPreferences; import org.python.pydev.core.log.Log; -import org.python.pydev.editor.actions.PyFormatAction; -import org.python.pydev.plugin.PyDevUiPrefs; -import org.python.pydev.shared_core.SharedCorePlugin; +import org.python.pydev.shared_core.io.FileUtils; import org.python.pydev.shared_core.string.FastStringBuffer; import org.python.pydev.shared_core.string.StringUtils; import org.python.pydev.shared_core.structure.Tuple; import org.python.pydev.shared_core.structure.Tuple3; -import org.python.pydev.ui.importsconf.ImportsPreferencesPage; public class ImportArranger { @@ -181,32 +179,13 @@ public int compare(Tuple o1, Tuple o2) { } } - /** - * @return the maximum number of columns that may be available in a line. - */ - private static int getMaxCols(boolean multilineImports) { - final int maxCols; - if (multilineImports) { - if (SharedCorePlugin.inTestMode()) { - maxCols = 80; - } else { - IPreferenceStore chainedPrefStore = PyDevUiPrefs.getChainedPrefStore(); - maxCols = chainedPrefStore - .getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN); - } - } else { - maxCols = Integer.MAX_VALUE; - } - return maxCols; - } - /** * @return true if the imports should be split with parenthesis (instead of escaping) */ private static boolean getBreakImportsWithParenthesis(IPyFormatStdProvider edit) { - String breakIportMode = ImportsPreferencesPage.getBreakIportMode(edit); + String breakIportMode = ImportPreferences.getBreakImportMode(edit); boolean breakWithParenthesis = true; - if (!breakIportMode.equals(ImportsPreferencesPage.BREAK_IMPORTS_MODE_PARENTHESIS)) { + if (!breakIportMode.equals(ImportPreferences.BREAK_IMPORTS_MODE_PARENTHESIS)) { breakWithParenthesis = false; } return breakWithParenthesis; @@ -225,21 +204,20 @@ private static boolean getBreakImportsWithParenthesis(IPyFormatStdProvider edit) protected final IPyFormatStdProvider edit; public ImportArranger(IDocument doc, boolean removeUnusedImports, String endLineDelim, String indentStr, - boolean automatic, IPyFormatStdProvider edit) { + boolean automatic, IPyFormatStdProvider edit, int maxCols) { this.doc = doc; this.endLineDelim = endLineDelim; this.indentStr = indentStr; this.removeUnusedImports = removeUnusedImports; this.automatic = automatic; this.edit = edit; - multilineImports = ImportsPreferencesPage.getMultilineImports(edit); - sortNamesGrouped = ImportsPreferencesPage.getSortNamesGrouped(edit); + multilineImports = ImportPreferences.getMultilineImports(edit); + sortNamesGrouped = ImportPreferences.getSortNamesGrouped(edit); breakWithParenthesis = getBreakImportsWithParenthesis(edit); - maxCols = getMaxCols(multilineImports); } public void perform() { - perform(ImportsPreferencesPage.getGroupImports(edit), edit); + perform(ImportPreferences.getGroupImports(edit), edit); } protected void perform(boolean groupFromImports, IPyFormatStdProvider edit) { @@ -301,13 +279,19 @@ private void perform(boolean groupFromImports, boolean executeOnlyIfChanged, IPy } try { - PyFormatAction std = new PyFormatAction(); - boolean throwSyntaxError = false; - ISelectionProvider selectionProvider = null; - int[] regionsToFormat = null; + FormatStd formatStd = (FormatStd) edit.getFormatStd(); + File editorFile = edit.getEditorFile(); + String filepath = null; + if (editorFile != null) { + filepath = FileUtils.getFileAbsolutePath(editorFile); + } + IDocument psDoc = new Document(finalStr); - PySelection ps = new PySelection(psDoc); - std.applyFormatAction(edit, ps, regionsToFormat, throwSyntaxError, selectionProvider); + + boolean isOpenedFile = false; + boolean throwSyntaxError = false; + PyFormatter.formatAll(filepath, psDoc, edit, isOpenedFile, formatStd, throwSyntaxError, true); + finalStr = psDoc.get(); if (addNewLinesToImports) { // Leave 2 empty new lines separating imports from code diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/actions/organize_imports/Pep8ImportArranger.java b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/sort_imports/Pep8ImportArranger.java similarity index 95% rename from plugins/org.python.pydev/src/org/python/pydev/editor/actions/organize_imports/Pep8ImportArranger.java rename to plugins/org.python.pydev.ast/src/org/python/pydev/ast/sort_imports/Pep8ImportArranger.java index 7abfe0b1ec..966b9ede65 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/actions/organize_imports/Pep8ImportArranger.java +++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/sort_imports/Pep8ImportArranger.java @@ -4,7 +4,7 @@ * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ -package org.python.pydev.editor.actions.organize_imports; +package org.python.pydev.ast.sort_imports; import java.io.File; import java.util.Collections; @@ -13,7 +13,6 @@ import java.util.List; import java.util.Map; -import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; @@ -27,13 +26,12 @@ import org.python.pydev.core.MisconfigurationException; import org.python.pydev.core.PythonNatureWithoutProjectException; import org.python.pydev.core.docutils.ImportHandle; +import org.python.pydev.core.imports.ImportPreferences; import org.python.pydev.core.log.Log; -import org.python.pydev.plugin.nature.PythonNature; import org.python.pydev.shared_core.io.FileUtils; import org.python.pydev.shared_core.string.FastStringBuffer; import org.python.pydev.shared_core.string.StringUtils; import org.python.pydev.shared_core.structure.Tuple3; -import org.python.pydev.ui.importsconf.ImportsPreferencesPage; public class Pep8ImportArranger extends ImportArranger { @@ -103,8 +101,8 @@ static class PathImportClassifier extends ImportClassifier { private Map mapToClassification = new HashMap(); - PathImportClassifier(IProject project) throws MisconfigurationException, PythonNatureWithoutProjectException { - PythonNature nature = PythonNature.getPythonNature(project); + PathImportClassifier(IPythonNature nature) + throws MisconfigurationException, PythonNatureWithoutProjectException { if (nature != null) { try { String externalProjectSourcePath = nature.getPythonPathNature().getProjectExternalSourcePath(true); @@ -178,16 +176,16 @@ private int classifyInternal(String module) { final ImportClassifier classifier; - public Pep8ImportArranger(IDocument doc, boolean removeUnusedImports, String endLineDelim, IProject prj, - String indentStr, boolean automatic, IPyFormatStdProvider edit) { - super(doc, removeUnusedImports, endLineDelim, indentStr, automatic, edit); - classifier = getClassifier(prj); + public Pep8ImportArranger(IDocument doc, boolean removeUnusedImports, String endLineDelim, IPythonNature nature, + String indentStr, boolean automatic, IPyFormatStdProvider edit, int maxCols) { + super(doc, removeUnusedImports, endLineDelim, indentStr, automatic, edit, maxCols); + classifier = getClassifier(nature); } - private ImportClassifier getClassifier(IProject p) { - if (p != null) { + private ImportClassifier getClassifier(IPythonNature nature) { + if (nature != null) { try { - return new PathImportClassifier(p); + return new PathImportClassifier(nature); } catch (MisconfigurationException e) { } catch (PythonNatureWithoutProjectException e) { } @@ -218,7 +216,7 @@ public int compare(Tuple3 o1, Tuple3 knownThirdParty = new HashSet(); + // isort itself already has a reasonable stdLib, so, don't do our own. + + String importEngine = ImportPreferences.getImportEngine(projectAdaptable); + if (!ImportPreferences.IMPORT_ENGINE_ISORT.equals(importEngine)) { + if (pythonNature != null) { + IInterpreterInfo projectInterpreter = pythonNature.getProjectInterpreter(); + ISystemModulesManager modulesManager = projectInterpreter.getModulesManager(); + ModulesKey[] onlyDirectModules = modulesManager.getOnlyDirectModules(); + + Set stdLib = new HashSet<>(); + + for (ModulesKey modulesKey : onlyDirectModules) { + if (modulesKey.file == null) { + int i = modulesKey.name.indexOf('.'); + String name; + if (i < 0) { + name = modulesKey.name; + } else { + name = modulesKey.name.substring(0, i); + } + // Add all names to std lib + stdLib.add(name); + } + } + for (ModulesKey modulesKey : onlyDirectModules) { + int i = modulesKey.name.indexOf('.'); + String name; + if (i < 0) { + name = modulesKey.name; + } else { + name = modulesKey.name.substring(0, i); + } + + // Consider all in site-packages to be third party. + if (modulesKey.file != null && modulesKey.file.toString().contains("site-packages")) { + stdLib.remove(name); + knownThirdParty.add(name); + } + } + } + } + + switch (importEngine) { + case ImportPreferences.IMPORT_ENGINE_ISORT: + if (fileContents.length() > 0) { + String encoding = null; + try { + encoding = FileUtils.getPythonFileEncoding(doc, null); + } catch (PyUnsupportedEncodingException e) { + Log.log(e); + } + if (encoding == null) { + encoding = "utf-8"; + } + + Optional executableLocation = ImportPreferences + .getISortExecutable(projectAdaptable); + String[] args = ImportPreferences.getISortArguments(projectAdaptable); + + String isortResult = ISortRunner.formatWithISort(targetFile, pythonNature, + fileContents, encoding, targetFile.getParentFile(), args, knownThirdParty, + executableLocation); + + if (isortResult != null) { + String delimiter = PySelection.getDelimiter(doc); + if (!delimiter.equals(System.lineSeparator())) { + // Argh, isort seems to not keep line delimiters, so, hack around it. + isortResult = StringUtils.replaceAll(isortResult, System.lineSeparator(), delimiter); + } + try { + DocUtils.updateDocRangeWithContents(doc, fileContents, isortResult.toString()); + } catch (Exception e) { + Log.log( + StringUtils.format( + "Error trying to apply isort result. Curr doc:\n>>>%s\n<<<.\nNew doc:\\n>>>%s\\n<<<.", + fileContents, isortResult.toString()), + e); + } + } + } + break; + + case ImportPreferences.IMPORT_ENGINE_REGULAR_SORT: + performArrangeImports(doc, removeUnusedImports, endLineDelim, indentStr, automatic, edit, maxCols); + break; + + default: //case ImportsPreferencesPage.IMPORT_ENGINE_PEP_8: + pep8PerformArrangeImports(doc, removeUnusedImports, endLineDelim, pythonNature, indentStr, automatic, + edit, maxCols); + break; + } + } + + public static void performPep8ArrangeImports(Document doc, String endLineDelim, String indentStr, + boolean automatic, IPyFormatStdProvider edit, IPythonNature nature, int maxCols) { + pep8PerformArrangeImports(doc, false, endLineDelim, nature, indentStr, automatic, edit, maxCols); + } + + /** + * Used by legacy tests. + * @param doc + * @param endLineDelim + * @param indentStr + */ + public static void performArrangeImports(Document doc, String endLineDelim, String indentStr, + IPyFormatStdProvider edit, int maxCols) { + performArrangeImports(doc, false, endLineDelim, indentStr, false, edit, maxCols); + } + + /** + * Pep8 compliant version. Actually does the action in the document. + * + * @param doc + * @param removeUnusedImports + * @param endLineDelim + */ + public static void pep8PerformArrangeImports(IDocument doc, boolean removeUnusedImports, String endLineDelim, + IPythonNature nature, String indentStr, boolean automatic, IPyFormatStdProvider edit, int maxCols) { + new Pep8ImportArranger(doc, removeUnusedImports, endLineDelim, nature, indentStr, automatic, edit, maxCols) + .perform(); + } + + /** + * Actually does the action in the document. Public for testing. + * + * @param doc + * @param removeUnusedImports + * @param endLineDelim + */ + public static void performArrangeImports(IDocument doc, boolean removeUnusedImports, String endLineDelim, + String indentStr, boolean automatic, IPyFormatStdProvider edit, int maxCols) { + new ImportArranger(doc, removeUnusedImports, endLineDelim, indentStr, automatic, edit, maxCols).perform(); + } +} diff --git a/plugins/org.python.pydev.core/META-INF/MANIFEST.MF b/plugins/org.python.pydev.core/META-INF/MANIFEST.MF index a30f7b0b77..eee9d2c7ea 100644 --- a/plugins/org.python.pydev.core/META-INF/MANIFEST.MF +++ b/plugins/org.python.pydev.core/META-INF/MANIFEST.MF @@ -26,6 +26,7 @@ Export-Package: org.python.copiedfromeclipsesrc, org.python.pydev.core.docutils, org.python.pydev.core.editor, org.python.pydev.core.formatter, + org.python.pydev.core.imports, org.python.pydev.core.interactive_console, org.python.pydev.core.interpreters, org.python.pydev.core.log, diff --git a/plugins/org.python.pydev.core/src/org/python/pydev/core/imports/ImportPreferences.java b/plugins/org.python.pydev.core/src/org/python/pydev/core/imports/ImportPreferences.java new file mode 100644 index 0000000000..642654cfc8 --- /dev/null +++ b/plugins/org.python.pydev.core/src/org/python/pydev/core/imports/ImportPreferences.java @@ -0,0 +1,198 @@ +package org.python.pydev.core.imports; + +import java.util.Optional; + +import org.eclipse.core.runtime.IAdaptable; +import org.python.pydev.core.CorePlugin; +import org.python.pydev.core.preferences.PyScopedPreferences; +import org.python.pydev.shared_core.SharedCorePlugin; +import org.python.pydev.shared_core.process.ProcessUtils; + +public class ImportPreferences { + + public static final String IMPORT_ENGINE = "IMPORT_ENGINE"; + public static final String IMPORT_ENGINE_REGULAR_SORT = "IMPORT_ENGINE_REGULAR_SORT"; + public static final String IMPORT_ENGINE_PEP_8 = "IMPORT_ENGINE_PEP_8"; + public static final String IMPORT_ENGINE_ISORT = "IMPORT_ENGINE_ISORT"; + + public final static String DEFAULT_IMPORT_ENGINE = IMPORT_ENGINE_PEP_8; + public static final String GROUP_IMPORTS = "GROUP_IMPORTS"; + + public final static boolean DEFAULT_GROUP_IMPORTS = true; + public static final String MULTILINE_IMPORTS = "MULTILINE_IMPORTS"; + + public final static boolean DEFAULT_MULTILINE_IMPORTS = true; + public static final String FROM_IMPORTS_FIRST = "FROM_IMPORTS_FIRST"; + + public final static boolean DEFAULT_FROM_IMPORTS_FIRST = false; + public static final String SORT_NAMES_GROUPED = "SORT_NAMES_GROUPED"; + + public final static boolean DEFAULT_SORT_NAMES_GROUPED = false; + public static final String DELETE_UNUSED_IMPORTS = "DELETE_UNUSED_IMPORTS"; + + //Left default as false because it can be a destructive operation (i.e.: many imports + //may have a reason even without being used -- and in this case it must be marked as @UnusedImport, + //so, making it so that the user has to enable this option and know what he is doing). + public final static boolean DEFAULT_DELETE_UNUSED_IMPORTS = false; + + public static final String BREAK_IMPORTS_MODE = "BREAK_IMPORTS_MODE"; + public static final String BREAK_IMPORTS_MODE_ESCAPE = "ESCAPE"; + public static final String BREAK_IMPORTS_MODE_PARENTHESIS = "PARENTHESIS"; + + public final static String DEFAULT_BREAK_IMPORTS_MODE = BREAK_IMPORTS_MODE_PARENTHESIS; + + public static final String LOCATION_SEARCH = "LOCATION_SEARCH"; + public static final String LOCATION_SPECIFY = "LOCATION_SPECIFY"; + public static final String ISORT_LOCATION_OPTION = "ISORT_LOCATION_OPTION"; + + public static final String DEFAULT_ISORT_LOCATION_OPTION = LOCATION_SEARCH; + public static final String ISORT_FILE_LOCATION = "ISORT_FILE_LOCATION"; + public static final String ISORT_PARAMETERS = "ISORT_PARAMETERS"; + + /** + * May be changed for testing purposes. + */ + public static boolean pep8ImportsForTests = true; + + /** + * @return whether to format imports according to pep8 + */ + public static String getImportEngine(IAdaptable projectAdaptable) { + if (SharedCorePlugin.inTestMode()) { + if (pep8ImportsForTests) { + return IMPORT_ENGINE_PEP_8; + } else { + return IMPORT_ENGINE_REGULAR_SORT; + } + } + String importEngine = PyScopedPreferences.getString(IMPORT_ENGINE, projectAdaptable); + if (importEngine == null) { + importEngine = IMPORT_ENGINE_PEP_8; + } + switch (importEngine) { + case IMPORT_ENGINE_PEP_8: + case IMPORT_ENGINE_ISORT: + case IMPORT_ENGINE_REGULAR_SORT: + return importEngine; + + default: + // Wrong value: use PEP 8 engine. + return IMPORT_ENGINE_PEP_8; + } + } + + public static Optional getISortExecutable(IAdaptable projectAdaptable) { + String locationOption = PyScopedPreferences.getString(ISORT_LOCATION_OPTION, projectAdaptable); + if (LOCATION_SPECIFY.equals(locationOption)) { + String isortFileLocation = PyScopedPreferences.getString(ISORT_FILE_LOCATION, projectAdaptable); + if (isortFileLocation != null && isortFileLocation.length() > 0) { + return Optional.of(isortFileLocation); + } + } + return Optional.empty(); + } + + public static String[] getISortArguments(IAdaptable projectAdaptable) { + String parameters = PyScopedPreferences.getString(ISORT_PARAMETERS, projectAdaptable); + if (parameters != null && parameters.length() > 0) { + return ProcessUtils.parseArguments(parameters); + } + return new String[0]; + } + + /** + * May be changed for testing purposes. + */ + public static boolean deleteUnusedImportsForTests = true; + + /** + * @return whether to delete unused imports + */ + public static boolean getDeleteUnusedImports(IAdaptable projectAdaptable) { + if (SharedCorePlugin.inTestMode()) { + return deleteUnusedImportsForTests; + } + return PyScopedPreferences.getBoolean(DELETE_UNUSED_IMPORTS, projectAdaptable); + } + + /** + * May be changed for testing purposes. + */ + public static String breakImportModeForTests = BREAK_IMPORTS_MODE_PARENTHESIS; + + /** + * @return the way to break imports as the constants specified + * @see BREAK_IMPORTS_MODE_ESCAPE + * @see BREAK_IMPORTS_MODE_PARENTHESIS + */ + public static String getBreakImportMode(IAdaptable projectAdaptable) { + if (SharedCorePlugin.inTestMode()) { + return breakImportModeForTests; + } + return PyScopedPreferences.getString(BREAK_IMPORTS_MODE, projectAdaptable); + } + + /** + * May be changed for testing purposes. + */ + public static boolean sortNamesGroupedForTests = false; + + public static boolean getSortNamesGrouped(IAdaptable projectAdaptable) { + if (SharedCorePlugin.inTestMode()) { + return sortNamesGroupedForTests; + } + return PyScopedPreferences.getBoolean(SORT_NAMES_GROUPED, projectAdaptable); + } + + /** + * May be changed for testing purposes. + */ + public static boolean multilineImportsForTests = true; + + /** + * @return true if imports should be wrapped when they exceed the print margin. + */ + public static boolean getMultilineImports(IAdaptable projectAdaptable) { + if (SharedCorePlugin.inTestMode()) { + return multilineImportsForTests; + } + return PyScopedPreferences.getBoolean(MULTILINE_IMPORTS, projectAdaptable); + } + + /** + * May be changed for testing purposes. + */ + public static boolean sortFromImportsFirstForTests = true; + + /** + * @return true if 'from ... import ...' statements should be sorted before 'import ...' statements. + * E.g, a set of imports would be organized like the following: + * from a_module import b, c, d + * from c_module import e, f + * import b_module + * import d_module + */ + public static boolean getSortFromImportsFirst(IAdaptable projectAdaptable) { + if (CorePlugin.getDefault() == null) { + return sortFromImportsFirstForTests; + } + return PyScopedPreferences.getBoolean(FROM_IMPORTS_FIRST, projectAdaptable); + } + + /** + * May be changed for testing purposes. + */ + public static boolean groupImportsForTests = true; + + /** + * @return true if imports should be grouped when possible. E.g.: If from aaa import b and from aaa import c + * exist, they should be grouped as from aaa import b, c + */ + public static boolean getGroupImports(IAdaptable projectAdaptable) { + if (SharedCorePlugin.inTestMode()) { + return groupImportsForTests; + } + return PyScopedPreferences.getBoolean(GROUP_IMPORTS, projectAdaptable); + } + +} diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/actions/PyFormatAction.java b/plugins/org.python.pydev/src/org/python/pydev/editor/actions/PyFormatAction.java index b9f6f0237f..63799a08a9 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/actions/PyFormatAction.java +++ b/plugins/org.python.pydev/src/org/python/pydev/editor/actions/PyFormatAction.java @@ -166,7 +166,6 @@ public void formatAll(IDocument doc, IPyFormatStdProvider edit, IFile f, boolean filepath = path.toOSString(); } PyFormatter.formatAll(filepath, doc, edit, isOpenedFile, formatStd, throwSyntaxError, true); - } } diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/actions/PyOrganizeImports.java b/plugins/org.python.pydev/src/org/python/pydev/editor/actions/PyOrganizeImports.java index ff4e89d34e..834ad67a5c 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/actions/PyOrganizeImports.java +++ b/plugins/org.python.pydev/src/org/python/pydev/editor/actions/PyOrganizeImports.java @@ -13,43 +13,33 @@ package org.python.pydev.editor.actions; import java.io.File; -import java.util.HashSet; import java.util.List; -import java.util.Optional; -import java.util.Set; import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.action.IAction; -import org.eclipse.jface.text.Document; +import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.DocumentRewriteSession; import org.eclipse.jface.text.IDocument; +import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; +import org.python.pydev.ast.sort_imports.SortImports; import org.python.pydev.core.ExtensionHelper; -import org.python.pydev.core.IInterpreterInfo; import org.python.pydev.core.IPyFormatStdProvider; import org.python.pydev.core.IPythonNature; -import org.python.pydev.core.ISystemModulesManager; import org.python.pydev.core.MisconfigurationException; -import org.python.pydev.core.ModulesKey; import org.python.pydev.core.PythonNatureWithoutProjectException; import org.python.pydev.core.autoedit.DefaultIndentPrefs; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.docutils.SyntaxErrorException; +import org.python.pydev.core.imports.ImportPreferences; import org.python.pydev.core.log.Log; -import org.python.pydev.core.pep8.ISortRunner; import org.python.pydev.editor.PyEdit; import org.python.pydev.editor.PySelectionFromEditor; -import org.python.pydev.editor.actions.organize_imports.ImportArranger; -import org.python.pydev.editor.actions.organize_imports.Pep8ImportArranger; import org.python.pydev.parser.prettyprinterv2.IFormatter; -import org.python.pydev.shared_core.io.FileUtils; -import org.python.pydev.shared_core.io.PyUnsupportedEncodingException; -import org.python.pydev.shared_core.string.StringUtils; +import org.python.pydev.plugin.PyDevUiPrefs; +import org.python.pydev.shared_core.SharedCorePlugin; import org.python.pydev.shared_core.string.TextSelectionUtils; -import org.python.pydev.shared_core.utils.DocUtils; -import org.python.pydev.ui.importsconf.ImportsPreferencesPage; /** * @author Fabio Zadrozny, Jeremy J. Carroll @@ -99,7 +89,6 @@ public void run(IAction action) { @SuppressWarnings("unchecked") private void organizeImports(PyEdit edit, final IDocument doc, IFile f, PySelection ps) throws MisconfigurationException, PythonNatureWithoutProjectException { - DocumentRewriteSession session = null; String endLineDelim = ps.getEndLineDelim(); List participants = null; if (f == null && !automatic) { @@ -120,6 +109,8 @@ private void organizeImports(PyEdit edit, final IDocument doc, IFile f, PySelect IAdaptable projectAdaptable = edit != null ? edit : f; String indentStr = edit != null ? edit.getIndentPrefs().getIndentationString() : DefaultIndentPrefs.get(f).getIndentationString(); + + DocumentRewriteSession session = null; session = TextSelectionUtils.startWrite(doc); try { //Important: the remove and later update have to be done in the same session (since the remove @@ -129,117 +120,33 @@ private void organizeImports(PyEdit edit, final IDocument doc, IFile f, PySelect boolean removeUnusedImports = false; if (!automatic) { //Only go through the removal of unused imports if it's manually activated (not on automatic mode). - removeUnusedImports = ImportsPreferencesPage.getDeleteUnusedImports(projectAdaptable); + removeUnusedImports = ImportPreferences.getDeleteUnusedImports(projectAdaptable); if (removeUnusedImports) { new OrganizeImportsFixesUnused().beforePerformArrangeImports(ps, edit, f); } } - Set knownThirdParty = new HashSet(); - // isort itself already has a reasonable stdLib, so, don't do our own. - - String importEngine = ImportsPreferencesPage.getImportEngine(projectAdaptable); + IPythonNature pythonNature = null; if (edit != null) { - IPythonNature pythonNature = edit.getPythonNature(); - if (pythonNature != null) { - IInterpreterInfo projectInterpreter = pythonNature.getProjectInterpreter(); - ISystemModulesManager modulesManager = projectInterpreter.getModulesManager(); - ModulesKey[] onlyDirectModules = modulesManager.getOnlyDirectModules(); - - Set stdLib = new HashSet<>(); - - for (ModulesKey modulesKey : onlyDirectModules) { - if (modulesKey.file == null) { - int i = modulesKey.name.indexOf('.'); - String name; - if (i < 0) { - name = modulesKey.name; - } else { - name = modulesKey.name.substring(0, i); - } - // Add all names to std lib - stdLib.add(name); - } - } - for (ModulesKey modulesKey : onlyDirectModules) { - int i = modulesKey.name.indexOf('.'); - String name; - if (i < 0) { - name = modulesKey.name; - } else { - name = modulesKey.name.substring(0, i); - } + pythonNature = edit.getPythonNature(); + } - // Consider all in site-packages to be third party. - if (modulesKey.file != null && modulesKey.file.toString().contains("site-packages")) { - stdLib.remove(name); - knownThirdParty.add(name); - } + File targetFile = edit != null ? edit.getEditorFile() : null; + if (targetFile == null) { + if (f != null) { + IPath location = f.getLocation(); + if (location != null) { + targetFile = location.toFile(); } } } - switch (importEngine) { - case ImportsPreferencesPage.IMPORT_ENGINE_ISORT: - if (fileContents.length() > 0) { - File targetFile = edit != null ? edit.getEditorFile() : null; - if (targetFile == null) { - if (f != null) { - IPath location = f.getLocation(); - if (location != null) { - targetFile = location.toFile(); - } - } - } - String encoding = null; - try { - encoding = FileUtils.getPythonFileEncoding(doc, null); - } catch (PyUnsupportedEncodingException e) { - Log.log(e); - } - if (encoding == null) { - encoding = "utf-8"; - } - - Optional executableLocation = ImportsPreferencesPage - .getISortExecutable(projectAdaptable); - String[] args = ImportsPreferencesPage.getISortArguments(projectAdaptable); + SortImports sortImports = new SortImports(); + int maxCols = getMaxCols(ImportPreferences.getMultilineImports(edit)); - String isortResult = ISortRunner.formatWithISort(targetFile, edit.getPythonNature(), - fileContents, encoding, targetFile.getParentFile(), args, knownThirdParty, - executableLocation); - - if (isortResult != null) { - String delimiter = PySelection.getDelimiter(doc); - if (!delimiter.equals(System.lineSeparator())) { - // Argh, isort seems to not keep line delimiters, so, hack around it. - isortResult = StringUtils.replaceAll(isortResult, System.lineSeparator(), delimiter); - } - try { - DocUtils.updateDocRangeWithContents(doc, fileContents, isortResult.toString()); - } catch (Exception e) { - Log.log( - StringUtils.format( - "Error trying to apply isort result. Curr doc:\n>>>%s\n<<<.\nNew doc:\\n>>>%s\\n<<<.", - fileContents, isortResult.toString()), - e); - } - } - } - break; - - case ImportsPreferencesPage.IMPORT_ENGINE_REGULAR_SORT: - performArrangeImports(doc, removeUnusedImports, endLineDelim, indentStr, automatic, edit); - break; - - default: //case ImportsPreferencesPage.IMPORT_ENGINE_PEP_8: - if (f == null) { - f = edit.getIFile(); - } - IProject p = f != null ? f.getProject() : null; - pep8PerformArrangeImports(doc, removeUnusedImports, endLineDelim, p, indentStr, automatic, edit); - break; - } + sortImports.sortImports(pythonNature, projectAdaptable, targetFile, + fileContents, doc, removeUnusedImports, endLineDelim, + indentStr, automatic, edit, maxCols); if (participants != null) { for (IOrganizeImports organizeImports : participants) { @@ -252,44 +159,22 @@ private void organizeImports(PyEdit edit, final IDocument doc, IFile f, PySelect } /** - * Actually does the action in the document. Public for testing. - * - * @param doc - * @param removeUnusedImports - * @param endLineDelim - */ - public static void performArrangeImports(IDocument doc, boolean removeUnusedImports, String endLineDelim, - String indentStr, boolean automatic, IPyFormatStdProvider edit) { - new ImportArranger(doc, removeUnusedImports, endLineDelim, indentStr, automatic, edit).perform(); - } - - /** - * Pep8 compliant version. Actually does the action in the document. - * - * @param doc - * @param removeUnusedImports - * @param endLineDelim - */ - public static void pep8PerformArrangeImports(IDocument doc, boolean removeUnusedImports, String endLineDelim, - IProject prj, String indentStr, boolean automatic, IPyFormatStdProvider edit) { - new Pep8ImportArranger(doc, removeUnusedImports, endLineDelim, prj, indentStr, automatic, edit).perform(); - } - - /** - * Used by legacy tests. - * @param doc - * @param endLineDelim - * @param indentStr + * @return the maximum number of columns that may be available in a line. */ - public static void performArrangeImports(Document doc, String endLineDelim, String indentStr, - IPyFormatStdProvider edit) { - performArrangeImports(doc, false, endLineDelim, indentStr, false, edit); - } - - public static void performPep8ArrangeImports(Document doc, String endLineDelim, String indentStr, - boolean automatic, IPyFormatStdProvider edit) { - IProject project = null; - pep8PerformArrangeImports(doc, false, endLineDelim, project, indentStr, automatic, edit); + private static int getMaxCols(boolean multilineImports) { + final int maxCols; + if (multilineImports) { + if (SharedCorePlugin.inTestMode()) { + maxCols = 80; + } else { + IPreferenceStore chainedPrefStore = PyDevUiPrefs.getChainedPrefStore(); + maxCols = chainedPrefStore + .getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN); + } + } else { + maxCols = Integer.MAX_VALUE; + } + return maxCols; } @Override diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/codecompletion/proposals/CtxInsensitiveImportComplProposal.java b/plugins/org.python.pydev/src/org/python/pydev/editor/codecompletion/proposals/CtxInsensitiveImportComplProposal.java index ebc319ba56..3128e35e3c 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/codecompletion/proposals/CtxInsensitiveImportComplProposal.java +++ b/plugins/org.python.pydev/src/org/python/pydev/editor/codecompletion/proposals/CtxInsensitiveImportComplProposal.java @@ -26,13 +26,13 @@ import org.python.pydev.core.IPyEdit; import org.python.pydev.core.IPySourceViewer; import org.python.pydev.core.autoedit.DefaultIndentPrefs; +import org.python.pydev.core.imports.ImportPreferences; import org.python.pydev.core.log.Log; import org.python.pydev.plugin.PyDevUiPrefs; import org.python.pydev.shared_core.SharedCorePlugin; import org.python.pydev.shared_core.code_completion.ICompletionProposalHandle; import org.python.pydev.shared_core.code_completion.IPyCompletionProposal; import org.python.pydev.shared_ui.ImageCache; -import org.python.pydev.ui.importsconf.ImportsPreferencesPage; import com.python.pydev.analysis.refactoring.quick_fixes.AddTokenAndImportStatement; @@ -217,7 +217,7 @@ protected void apply(IDocument document, char trigger, int stateMask, int offset realImportRep, fReplacementOffset, fLen, indentString, fReplacementString, appliedWithTrigger, importLen, document); new AddTokenAndImportStatement(document, trigger, offset, addLocalImport, getAddLocalImportsOnTopOfMethod(), - ImportsPreferencesPage.getGroupImports(projectAdaptable), maxCols).createTextEdit(computedInfo); + ImportPreferences.getGroupImports(projectAdaptable), maxCols).createTextEdit(computedInfo); this.fReplacementString = computedInfo.fReplacementString; this.appliedWithTrigger = computedInfo.appliedWithTrigger; this.importLen = computedInfo.importLen; diff --git a/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/heuristics/AssistImport.java b/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/heuristics/AssistImport.java index f1909970e5..6a0c680fc0 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/heuristics/AssistImport.java +++ b/plugins/org.python.pydev/src/org/python/pydev/editor/correctionassist/heuristics/AssistImport.java @@ -19,6 +19,7 @@ import org.python.pydev.core.IPyEdit; import org.python.pydev.core.IPythonNature; import org.python.pydev.core.docutils.PySelection; +import org.python.pydev.core.imports.ImportPreferences; import org.python.pydev.core.proposals.CompletionProposalFactory; import org.python.pydev.editor.actions.PyAction; import org.python.pydev.editor.correctionassist.IAssistProps; @@ -26,7 +27,6 @@ import org.python.pydev.shared_core.code_completion.IPyCompletionProposal; import org.python.pydev.shared_core.image.IImageCache; import org.python.pydev.shared_core.image.UIConstants; -import org.python.pydev.ui.importsconf.ImportsPreferencesPage; /** * @author Fabio Zadrozny @@ -71,10 +71,10 @@ public List getProps(PySelection ps, IImageCache imag if (i >= 0) { String cursorLineContents = ps.getCursorLineContents(); - String importEngine = ImportsPreferencesPage.getImportEngine(edit); + String importEngine = ImportPreferences.getImportEngine(edit); String messageToIgnore = "@NoMove"; String caption = messageToIgnore.substring(1); - if (ImportsPreferencesPage.IMPORT_ENGINE_ISORT.equals(importEngine)) { + if (ImportPreferences.IMPORT_ENGINE_ISORT.equals(importEngine)) { caption = messageToIgnore = "isort:skip"; } if (!cursorLineContents.contains(messageToIgnore)) { diff --git a/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PydevPrefsInitializer.java b/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PydevPrefsInitializer.java index b6cdf74127..eb6d2ad7d3 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PydevPrefsInitializer.java +++ b/plugins/org.python.pydev/src/org/python/pydev/plugin/preferences/PydevPrefsInitializer.java @@ -14,6 +14,7 @@ import org.eclipse.jface.resource.StringConverter; import org.osgi.service.prefs.Preferences; import org.python.pydev.builder.todo.PyTodoPrefPage; +import org.python.pydev.core.imports.ImportPreferences; import org.python.pydev.editor.codefolding.PyDevCodeFoldingPrefPage; import org.python.pydev.editor.commentblocks.CommentBlocksPreferences; import org.python.pydev.editor.correctionassist.docstrings.DocstringsPrefPage; @@ -26,7 +27,6 @@ import org.python.pydev.shared_core.SharedCorePlugin; import org.python.pydev.shared_core.actions.LineCommentOption; import org.python.pydev.shared_ui.word_boundaries.SubWordPreferences; -import org.python.pydev.ui.importsconf.ImportsPreferencesPage; import org.python.pydev.ui.wizards.project.IWizardNewProjectNameAndLocationPage; public class PydevPrefsInitializer extends AbstractPreferenceInitializer { @@ -238,15 +238,15 @@ public void initializeDefaultPreferences() { PyTitlePreferencesPage.DEFAULT_TITLE_EDITOR_DJANGO_MODULES_HANDLING); //imports - node.putBoolean(ImportsPreferencesPage.GROUP_IMPORTS, ImportsPreferencesPage.DEFAULT_GROUP_IMPORTS); - node.putBoolean(ImportsPreferencesPage.MULTILINE_IMPORTS, ImportsPreferencesPage.DEFAULT_MULTILINE_IMPORTS); - node.put(ImportsPreferencesPage.ISORT_LOCATION_OPTION, ImportsPreferencesPage.DEFAULT_ISORT_LOCATION_OPTION); - node.put(ImportsPreferencesPage.BREAK_IMPORTS_MODE, ImportsPreferencesPage.DEFAULT_BREAK_IMPORTS_MODE); - node.put(ImportsPreferencesPage.IMPORT_ENGINE, ImportsPreferencesPage.DEFAULT_IMPORT_ENGINE); - node.putBoolean(ImportsPreferencesPage.DELETE_UNUSED_IMPORTS, - ImportsPreferencesPage.DEFAULT_DELETE_UNUSED_IMPORTS); - node.putBoolean(ImportsPreferencesPage.FROM_IMPORTS_FIRST, ImportsPreferencesPage.DEFAULT_FROM_IMPORTS_FIRST); - node.putBoolean(ImportsPreferencesPage.SORT_NAMES_GROUPED, ImportsPreferencesPage.DEFAULT_SORT_NAMES_GROUPED); + node.putBoolean(ImportPreferences.GROUP_IMPORTS, ImportPreferences.DEFAULT_GROUP_IMPORTS); + node.putBoolean(ImportPreferences.MULTILINE_IMPORTS, ImportPreferences.DEFAULT_MULTILINE_IMPORTS); + node.put(ImportPreferences.ISORT_LOCATION_OPTION, ImportPreferences.DEFAULT_ISORT_LOCATION_OPTION); + node.put(ImportPreferences.BREAK_IMPORTS_MODE, ImportPreferences.DEFAULT_BREAK_IMPORTS_MODE); + node.put(ImportPreferences.IMPORT_ENGINE, ImportPreferences.DEFAULT_IMPORT_ENGINE); + node.putBoolean(ImportPreferences.DELETE_UNUSED_IMPORTS, + ImportPreferences.DEFAULT_DELETE_UNUSED_IMPORTS); + node.putBoolean(ImportPreferences.FROM_IMPORTS_FIRST, ImportPreferences.DEFAULT_FROM_IMPORTS_FIRST); + node.putBoolean(ImportPreferences.SORT_NAMES_GROUPED, ImportPreferences.DEFAULT_SORT_NAMES_GROUPED); //hover node.putBoolean(PyHoverPreferencesPage.COMBINE_HOVER_INFO, diff --git a/plugins/org.python.pydev/src/org/python/pydev/ui/actions/container/PyOrganizeImportsAction.java b/plugins/org.python.pydev/src/org/python/pydev/ui/actions/container/PyOrganizeImportsAction.java index 114fdb6455..a1ad5f80ec 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/ui/actions/container/PyOrganizeImportsAction.java +++ b/plugins/org.python.pydev/src/org/python/pydev/ui/actions/container/PyOrganizeImportsAction.java @@ -8,8 +8,8 @@ package org.python.pydev.ui.actions.container; import org.eclipse.jface.dialogs.MessageDialog; +import org.python.pydev.core.imports.ImportPreferences; import org.python.pydev.editor.actions.PyOrganizeImports; -import org.python.pydev.ui.importsconf.ImportsPreferencesPage; /** * Action used to organize imports to all the available python files. @@ -33,7 +33,7 @@ protected boolean confirmRun() { super.confirmRun() //Note: ask for the platform, but preferences will follow settings in each project. - && ((!ImportsPreferencesPage.getDeleteUnusedImports(null)) + && ((!ImportPreferences.getDeleteUnusedImports(null)) || MessageDialog .openConfirm( diff --git a/plugins/org.python.pydev/src/org/python/pydev/ui/importsconf/ImportsPreferencesPage.java b/plugins/org.python.pydev/src/org/python/pydev/ui/importsconf/ImportsPreferencesPage.java index 3801e1e707..895e10415d 100644 --- a/plugins/org.python.pydev/src/org/python/pydev/ui/importsconf/ImportsPreferencesPage.java +++ b/plugins/org.python.pydev/src/org/python/pydev/ui/importsconf/ImportsPreferencesPage.java @@ -6,9 +6,6 @@ */ package org.python.pydev.ui.importsconf; -import java.util.Optional; - -import org.eclipse.core.runtime.IAdaptable; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; @@ -18,11 +15,10 @@ import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; -import org.python.pydev.core.preferences.PyScopedPreferences; +import org.python.pydev.core.imports.ImportPreferences; import org.python.pydev.plugin.PyDevUiPrefs; import org.python.pydev.plugin.PydevPlugin; import org.python.pydev.shared_core.SharedCorePlugin; -import org.python.pydev.shared_core.process.ProcessUtils; import org.python.pydev.shared_core.string.WrapAndCaseUtils; import org.python.pydev.shared_ui.field_editors.BooleanFieldEditorCustom; import org.python.pydev.shared_ui.field_editors.ComboFieldEditor; @@ -56,17 +52,9 @@ public class ImportsPreferencesPage extends ScopedFieldEditorPreferencePage impl private FileFieldEditorCustom isortFileField; private CustomStringFieldEditor isortParameters; - public static final String LOCATION_SEARCH = "LOCATION_SEARCH"; - public static final String LOCATION_SPECIFY = "LOCATION_SPECIFY"; - public static final String ISORT_LOCATION_OPTION = "ISORT_LOCATION_OPTION"; - public static final String DEFAULT_ISORT_LOCATION_OPTION = LOCATION_SEARCH; - - public static final String ISORT_FILE_LOCATION = "ISORT_FILE_LOCATION"; - public static final String ISORT_PARAMETERS = "ISORT_PARAMETERS"; - public static final String[][] SEARCH_FORMATTER_LOCATION_OPTIONS = new String[][] { - { "Search in interpreter", LOCATION_SEARCH }, - { "Specify Location", LOCATION_SPECIFY }, + { "Search in interpreter", ImportPreferences.LOCATION_SEARCH }, + { "Specify Location", ImportPreferences.LOCATION_SPECIFY }, }; public ImportsPreferencesPage() { @@ -75,35 +63,6 @@ public ImportsPreferencesPage() { setDescription("Imports Preferences"); } - public static final String GROUP_IMPORTS = "GROUP_IMPORTS"; - public final static boolean DEFAULT_GROUP_IMPORTS = true; - - public static final String MULTILINE_IMPORTS = "MULTILINE_IMPORTS"; - public final static boolean DEFAULT_MULTILINE_IMPORTS = true; - - public static final String BREAK_IMPORTS_MODE = "BREAK_IMPORTS_MODE"; - public static final String BREAK_IMPORTS_MODE_ESCAPE = "ESCAPE"; - public static final String BREAK_IMPORTS_MODE_PARENTHESIS = "PARENTHESIS"; - public final static String DEFAULT_BREAK_IMPORTS_MODE = BREAK_IMPORTS_MODE_ESCAPE; - - public static final String IMPORT_ENGINE = "IMPORT_ENGINE"; - public static final String IMPORT_ENGINE_REGULAR_SORT = "IMPORT_ENGINE_REGULAR_SORT"; - public static final String IMPORT_ENGINE_PEP_8 = "IMPORT_ENGINE_PEP_8"; - public static final String IMPORT_ENGINE_ISORT = "IMPORT_ENGINE_ISORT"; - public final static String DEFAULT_IMPORT_ENGINE = IMPORT_ENGINE_PEP_8; - - public static final String DELETE_UNUSED_IMPORTS = "DELETE_UNUSED_IMPORTS"; - //Left default as false because it can be a destructive operation (i.e.: many imports - //may have a reason even without being used -- and in this case it must be marked as @UnusedImport, - //so, making it so that the user has to enable this option and know what he is doing). - public final static boolean DEFAULT_DELETE_UNUSED_IMPORTS = false; - - public static final String FROM_IMPORTS_FIRST = "FROM_IMPORTS_FIRST"; - public final static boolean DEFAULT_FROM_IMPORTS_FIRST = false; - - public static final String SORT_NAMES_GROUPED = "SORT_NAMES_GROUPED"; - public final static boolean DEFAULT_SORT_NAMES_GROUPED = false; - @Override protected void createFieldEditors() { final Composite p = getFieldEditorParent(); @@ -111,16 +70,17 @@ protected void createFieldEditors() { addField(new LabelFieldEditor("Label_Info_File_Preferences1", WrapAndCaseUtils.wrap( "These setting are used whenever imports are managed in the application\n\n", 80), p)); - importEngineFieldEditor = new ComboFieldEditor(IMPORT_ENGINE, "Select import sort engine to be used", + importEngineFieldEditor = new ComboFieldEditor(ImportPreferences.IMPORT_ENGINE, + "Select import sort engine to be used", new String[][] { - new String[] { "Pep 8", IMPORT_ENGINE_PEP_8 }, - new String[] { "Regular sort", IMPORT_ENGINE_REGULAR_SORT }, - new String[] { "isort", IMPORT_ENGINE_ISORT }, + new String[] { "Pep 8", ImportPreferences.IMPORT_ENGINE_PEP_8 }, + new String[] { "Regular sort", ImportPreferences.IMPORT_ENGINE_REGULAR_SORT }, + new String[] { "isort", ImportPreferences.IMPORT_ENGINE_ISORT }, }, p); addFieldWithToolTip(importEngineFieldEditor, p, "Select which import engine should be used to sort the imports when such an operation is requested."); - isortFormatterLocation = new RadioGroupFieldEditor(ISORT_LOCATION_OPTION, + isortFormatterLocation = new RadioGroupFieldEditor(ImportPreferences.ISORT_LOCATION_OPTION, "isort executable", 2, SEARCH_FORMATTER_LOCATION_OPTIONS, p); for (Button b : isortFormatterLocation.getRadioButtons()) { @@ -133,43 +93,50 @@ public void widgetSelected(SelectionEvent e) { } addField(isortFormatterLocation); - isortFileField = new FileFieldEditorCustom(ISORT_FILE_LOCATION, + isortFileField = new FileFieldEditorCustom(ImportPreferences.ISORT_FILE_LOCATION, "Location of the isort executable:", p, 1); addField(isortFileField); - isortParameters = new CustomStringFieldEditor(ISORT_PARAMETERS, "Parameters for isort", p); + isortParameters = new CustomStringFieldEditor(ImportPreferences.ISORT_PARAMETERS, "Parameters for isort", p); addField(isortParameters); - deleteUnusedImportsField = new BooleanFieldEditorCustom(DELETE_UNUSED_IMPORTS, WrapAndCaseUtils.wrap( - "Delete unused imports?", 80), p); + deleteUnusedImportsField = new BooleanFieldEditorCustom(ImportPreferences.DELETE_UNUSED_IMPORTS, + WrapAndCaseUtils.wrap( + "Delete unused imports?", 80), + p); addFieldWithToolTip( deleteUnusedImportsField, p, "Simple unused imports as reported by the code analysis are deleted. This can be configured to ignore certain files, and individual warnings can be surpressed."); - groupImportsField = new BooleanFieldEditorCustom(GROUP_IMPORTS, "Combine 'from' imports when possible?", p); + groupImportsField = new BooleanFieldEditorCustom(ImportPreferences.GROUP_IMPORTS, + "Combine 'from' imports when possible?", p); addField(groupImportsField); - fromImportsFirstBooleanEditor = new BooleanFieldEditorCustom(FROM_IMPORTS_FIRST, + fromImportsFirstBooleanEditor = new BooleanFieldEditorCustom(ImportPreferences.FROM_IMPORTS_FIRST, "Sort 'from' imports before 'import' imports?", p); addField(fromImportsFirstBooleanEditor); - multilineImportsField = new BooleanFieldEditorCustom(MULTILINE_IMPORTS, WrapAndCaseUtils.wrap( - "Allow multiline imports when the import size would exceed the print margin?", 80), p); + multilineImportsField = new BooleanFieldEditorCustom(ImportPreferences.MULTILINE_IMPORTS, + WrapAndCaseUtils.wrap( + "Allow multiline imports when the import size would exceed the print margin?", 80), + p); addField(multilineImportsField); - sortIndiviualOnGroupedField = new BooleanFieldEditorCustom(SORT_NAMES_GROUPED, WrapAndCaseUtils.wrap( - "Sort individual names on grouped imports?", 80), p); + sortIndiviualOnGroupedField = new BooleanFieldEditorCustom(ImportPreferences.SORT_NAMES_GROUPED, + WrapAndCaseUtils.wrap( + "Sort individual names on grouped imports?", 80), + p); addField(sortIndiviualOnGroupedField); - breakImportsInMultilineMode = new RadioGroupFieldEditor(BREAK_IMPORTS_MODE, + breakImportsInMultilineMode = new RadioGroupFieldEditor(ImportPreferences.BREAK_IMPORTS_MODE, "How to break imports in multiline?", 1, - new String[][] { { "Use escape char", BREAK_IMPORTS_MODE_ESCAPE }, - { "Use parenthesis", BREAK_IMPORTS_MODE_PARENTHESIS } }, + new String[][] { { "Use escape char", ImportPreferences.BREAK_IMPORTS_MODE_ESCAPE }, + { "Use parenthesis", ImportPreferences.BREAK_IMPORTS_MODE_PARENTHESIS } }, p); addField(breakImportsInMultilineMode); - updateEnablement(p, PyDevUiPrefs.getPreferenceStore().getString(IMPORT_ENGINE)); + updateEnablement(p, PyDevUiPrefs.getPreferenceStore().getString(ImportPreferences.IMPORT_ENGINE)); Combo importEngineCombo = importEngineFieldEditor.getCombo(); importEngineCombo.addSelectionListener(new SelectionListener() { @@ -203,14 +170,14 @@ public void widgetDefaultSelected(SelectionEvent e) { } private void updateEnablement(Composite p, String importEngine) { - boolean isIsort = importEngine.equals(IMPORT_ENGINE_ISORT); + boolean isIsort = importEngine.equals(ImportPreferences.IMPORT_ENGINE_ISORT); isortParameters.setVisible(isIsort, p); isortFileField.setVisible(isIsort); isortFormatterLocation.setVisible(isIsort, p); switch (importEngine) { - case IMPORT_ENGINE_PEP_8: + case ImportPreferences.IMPORT_ENGINE_PEP_8: fromImportsFirstBooleanEditor.setVisible(true, p); // Setting only valid for PEP 8 engine. deleteUnusedImportsField.setVisible(true, p); @@ -220,7 +187,7 @@ private void updateEnablement(Composite p, String importEngine) { breakImportsInMultilineMode.setVisible(true, p); break; - case IMPORT_ENGINE_REGULAR_SORT: + case ImportPreferences.IMPORT_ENGINE_REGULAR_SORT: fromImportsFirstBooleanEditor.setVisible(false, p); deleteUnusedImportsField.setVisible(true, p); @@ -230,7 +197,7 @@ private void updateEnablement(Composite p, String importEngine) { breakImportsInMultilineMode.setVisible(true, p); break; - case IMPORT_ENGINE_ISORT: + case ImportPreferences.IMPORT_ENGINE_ISORT: fromImportsFirstBooleanEditor.setVisible(false, p); deleteUnusedImportsField.setVisible(false, p); groupImportsField.setVisible(false, p); @@ -257,150 +224,4 @@ public void init(IWorkbench workbench) { // pass } - /** - * @return true if imports should be grouped when possible. E.g.: If from aaa import b and from aaa import c - * exist, they should be grouped as from aaa import b, c - */ - public static boolean getGroupImports(IAdaptable projectAdaptable) { - if (SharedCorePlugin.inTestMode()) { - return groupImportsForTests; - } - return PyScopedPreferences.getBoolean(GROUP_IMPORTS, projectAdaptable); - } - - /** - * May be changed for testing purposes. - */ - public static boolean groupImportsForTests = true; - - /** - * @return true if 'from ... import ...' statements should be sorted before 'import ...' statements. - * E.g, a set of imports would be organized like the following: - * from a_module import b, c, d - * from c_module import e, f - * import b_module - * import d_module - */ - public static boolean getSortFromImportsFirst(IAdaptable projectAdaptable) { - if (PydevPlugin.getDefault() == null) { - return sortFromImportsFirstForTests; - } - return PyScopedPreferences.getBoolean(FROM_IMPORTS_FIRST, projectAdaptable); - } - - /** - * May be changed for testing purposes. - */ - public static boolean sortFromImportsFirstForTests = true; - - /** - * @return true if imports should be wrapped when they exceed the print margin. - */ - public static boolean getMultilineImports(IAdaptable projectAdaptable) { - if (SharedCorePlugin.inTestMode()) { - return multilineImportsForTests; - } - return PyScopedPreferences.getBoolean(MULTILINE_IMPORTS, projectAdaptable); - } - - /** - * May be changed for testing purposes. - */ - public static boolean multilineImportsForTests = true; - - public static boolean getSortNamesGrouped(IAdaptable projectAdaptable) { - if (SharedCorePlugin.inTestMode()) { - return sortNamesGroupedForTests; - } - return PyScopedPreferences.getBoolean(SORT_NAMES_GROUPED, projectAdaptable); - } - - /** - * May be changed for testing purposes. - */ - public static boolean sortNamesGroupedForTests = false; - - /** - * @return the way to break imports as the constants specified - * @see #BREAK_IMPORTS_MODE_ESCAPE - * @see #BREAK_IMPORTS_MODE_PARENTHESIS - */ - public static String getBreakIportMode(IAdaptable projectAdaptable) { - if (SharedCorePlugin.inTestMode()) { - return breakImportModeForTests; - } - return PyScopedPreferences.getString(BREAK_IMPORTS_MODE, projectAdaptable); - } - - /** - * May be changed for testing purposes. - */ - public static String breakImportModeForTests = BREAK_IMPORTS_MODE_PARENTHESIS; - - /** - * @return whether to format imports according to pep8 - */ - public static String getImportEngine(IAdaptable projectAdaptable) { - if (SharedCorePlugin.inTestMode()) { - if (pep8ImportsForTests) { - return IMPORT_ENGINE_PEP_8; - } else { - return IMPORT_ENGINE_REGULAR_SORT; - } - } - String importEngine = PyScopedPreferences.getString(IMPORT_ENGINE, projectAdaptable); - if (importEngine == null) { - importEngine = IMPORT_ENGINE_PEP_8; - } - switch (importEngine) { - case IMPORT_ENGINE_PEP_8: - case IMPORT_ENGINE_ISORT: - case IMPORT_ENGINE_REGULAR_SORT: - return importEngine; - - default: - // Wrong value: use PEP 8 engine. - return IMPORT_ENGINE_PEP_8; - } - } - - /** - * May be changed for testing purposes. - */ - public static boolean pep8ImportsForTests = true; - - /** - * @return whether to delete unused imports - */ - public static boolean getDeleteUnusedImports(IAdaptable projectAdaptable) { - if (SharedCorePlugin.inTestMode()) { - return deleteUnusedImportsForTests; - } - return PyScopedPreferences.getBoolean(DELETE_UNUSED_IMPORTS, projectAdaptable); - } - - /** - * May be changed for testing purposes. - */ - public static boolean deleteUnusedImportsForTests = true; - - public static Optional getISortExecutable(IAdaptable projectAdaptable) { - String locationOption = PyScopedPreferences.getString(ISORT_LOCATION_OPTION, projectAdaptable); - if (LOCATION_SPECIFY.equals(locationOption)) { - String isortFileLocation = PyScopedPreferences.getString(ISORT_FILE_LOCATION, projectAdaptable); - if (isortFileLocation != null && isortFileLocation.length() > 0) { - return Optional.of(isortFileLocation); - } - } - return Optional.empty(); - } - - public static String[] getISortArguments(IAdaptable projectAdaptable) { - String parameters = PyScopedPreferences.getString(ISORT_PARAMETERS, projectAdaptable); - if (parameters != null && parameters.length() > 0) { - return ProcessUtils.parseArguments(parameters); - } - return new String[0]; - } - } diff --git a/plugins/org.python.pydev/tests/org/python/pydev/editor/actions/PyOrganizeImportsTest.java b/plugins/org.python.pydev/tests/org/python/pydev/editor/actions/PyOrganizeImportsTest.java index aaad5e0c53..653aea5015 100644 --- a/plugins/org.python.pydev/tests/org/python/pydev/editor/actions/PyOrganizeImportsTest.java +++ b/plugins/org.python.pydev/tests/org/python/pydev/editor/actions/PyOrganizeImportsTest.java @@ -14,6 +14,7 @@ import java.io.File; import org.eclipse.jface.text.Document; +import org.python.pydev.ast.sort_imports.SortImports; import org.python.pydev.core.IGrammarVersionProvider; import org.python.pydev.core.IIndentPrefs; import org.python.pydev.core.IPyFormatStdProvider; @@ -21,7 +22,7 @@ import org.python.pydev.core.MisconfigurationException; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.formatter.FormatStd; -import org.python.pydev.ui.importsconf.ImportsPreferencesPage; +import org.python.pydev.core.imports.ImportPreferences; import junit.framework.TestCase; @@ -30,6 +31,8 @@ */ public class PyOrganizeImportsTest extends TestCase { + private static final int MAX_COLS = 80; + public static void main(String[] args) { try { PyOrganizeImportsTest test = new PyOrganizeImportsTest(); @@ -83,8 +86,8 @@ public File getEditorFile() { @Override protected void setUp() throws Exception { super.setUp(); - ImportsPreferencesPage.groupImportsForTests = false; - ImportsPreferencesPage.sortNamesGroupedForTests = false; //default + ImportPreferences.groupImportsForTests = false; + ImportPreferences.sortNamesGroupedForTests = false; //default formatStd.spaceAfterComma = true; formatStd.trimLines = true; } @@ -95,8 +98,8 @@ protected void setUp() throws Exception { @Override protected void tearDown() throws Exception { super.tearDown(); - ImportsPreferencesPage.groupImportsForTests = true; //default - ImportsPreferencesPage.sortNamesGroupedForTests = false; //default + ImportPreferences.groupImportsForTests = true; //default + ImportPreferences.sortNamesGroupedForTests = false; //default } public void testPerform() { @@ -104,7 +107,7 @@ public void testPerform() { + "from a import b"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from a import b\n" + "from a import c\n" + "from b import d\n" + "import a\n" + "import b\n" + "\n"; @@ -114,12 +117,12 @@ public void testPerform() { } public void testPerformWithGrouping() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "import b\n" + "import a\n" + "\n" + "from a import c\n" + "from b import d\n" + "from a import b"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from a import b, c\n" + "from b import d\n" + "import a\n" + "import b\n" + "\n"; @@ -128,13 +131,13 @@ public void testPerformWithGrouping() { } public void testPerformWithGroupingSorted() { - ImportsPreferencesPage.groupImportsForTests = true; - ImportsPreferencesPage.sortNamesGroupedForTests = true; + ImportPreferences.groupImportsForTests = true; + ImportPreferences.sortNamesGroupedForTests = true; String d = "" + "from a import b, c, a\n" + "\n" + ""; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from a import a, b, c\n" + "\n"; @@ -143,13 +146,13 @@ public void testPerformWithGroupingSorted() { } public void testPerformWithGroupingSorted2() { - ImportsPreferencesPage.groupImportsForTests = true; - ImportsPreferencesPage.sortNamesGroupedForTests = true; + ImportPreferences.groupImportsForTests = true; + ImportPreferences.sortNamesGroupedForTests = true; String d = "" + "from a import b, B, c, A, a\n" + "\n" + ""; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from a import A, B, a, b, c\n" + "\n"; @@ -158,12 +161,12 @@ public void testPerformWithGroupingSorted2() { } public void testPerformWithGroupingAndWild() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "import b\n" + "import a\n" + "\n" + "from a import *\n" + "from b import d\n" + "from a import b"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from a import *\n" + "from b import d\n" + "import a\n" + "import b\n" + "\n"; @@ -173,12 +176,12 @@ public void testPerformWithGroupingAndWild() { } public void testPerformWithGroupingAndComments() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "import b #comment\n" + "import a\n" + "\n" + "from a import c #comment\n" + "from a import f #comment2\n" + "from a import e\n" + "from b import d\n" + "from a import b"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from a import b, e, c #comment\n" + "from a import f #comment2\n" + "from b import d\n" + "import a\n" + "import b #comment\n" + "\n"; @@ -187,11 +190,11 @@ public void testPerformWithGroupingAndComments() { } public void testPerformWithGroupingWithAs() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from a import c as d\n" + "from a import f as g\n" + "import e as g\n"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from a import c as d, f as g\n" + "import e as g\n" + ""; @@ -200,14 +203,14 @@ public void testPerformWithGroupingWithAs() { } public void testPerformGroupingWithWraps() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from a import cccccccccccccccccccccccccccccccccccccccccccccccccc\n" + //50 * 'c' "from a import eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n" + "from a import ffffffffffffffffffffffffffffffffffffffffffffffffff"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from a import (cccccccccccccccccccccccccccccccccccccccccccccccccc,\n" + " eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee,\n" @@ -218,13 +221,13 @@ public void testPerformGroupingWithWraps() { } public void testPerformGroupingWithWrapsLong() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from cccccccccccccccccccccccccccccccccccccccccccccccccc import eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n" + "from cccccccccccccccccccccccccccccccccccccccccccccccccc import ffffffffffffffffffffffffffffffffffffffffffffffffff"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from cccccccccccccccccccccccccccccccccccccccccccccccccc import (\n" + " eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee,\n" @@ -235,7 +238,7 @@ public void testPerformGroupingWithWrapsLong() { } public void testPerformGroupingWithWraps3() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from a import cccccccccc\n" + //10 * 'c' @@ -244,7 +247,7 @@ public void testPerformGroupingWithWraps3() { + "from a import hhhhhhhhhh\n" + ""; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from a import (aaaaaaaaaa, bbbbbbbbbb, cccccccccc, dddddddddd, eeeeeeeeee,\n" + " ffffffffff, gggggggggg, hhhhhhhhhh)\n"; @@ -254,14 +257,14 @@ public void testPerformGroupingWithWraps3() { } public void testPerformGroupingWithWraps2() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from a import cccccccccccccccccccccccccccccccccccccccccccccccccc\n" + //50 * 'c' "from a import eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee #comment 1\n" + "from a import ffffffffffffffffffffffffffffffffffffffffffffffffff #comment 2"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from a import (cccccccccccccccccccccccccccccccccccccccccccccccccc,\n" + " eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee) #comment 1\n" @@ -272,12 +275,12 @@ public void testPerformGroupingWithWraps2() { } public void testPerformGroupingWithWraps4() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from cccccccccccccccccccccccccccccccccccccccccccccccccc import eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n"; //50 * 'c' Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from cccccccccccccccccccccccccccccccccccccccccccccccccc import (\n" + " eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee)\n"; @@ -287,12 +290,12 @@ public void testPerformGroupingWithWraps4() { } public void testPerformGroupingWithWraps5() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from cccccccccccccccccccccccccccccccccccccccccccccccccc \\\nimport eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n"; //50 * 'c' Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from cccccccccccccccccccccccccccccccccccccccccccccccccc import (\n" + " eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee)\n"; @@ -302,12 +305,12 @@ public void testPerformGroupingWithWraps5() { } public void testPerformGroupingWithWraps6() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa import (bbbbbbbbbbb, cccccccccc, dddddddddddddddddddd, eeeeeeeeeeeeeeeeeeeeeeee, ffffffffffffffffff)\n"; //50 * 'c' Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa import (bbbbbbbbbbb,\n" + " cccccccccc, dddddddddddddddddddd, eeeeeeeeeeeeeeeeeeeeeeee,\n" @@ -318,12 +321,12 @@ public void testPerformGroupingWithWraps6() { } public void testPerformGroupingWithWraps7() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa import (bbbbbbbbbbbb, cccccccccc, dddddddddddddddddddd, eeeeeeeeeeeeeeeeeeeeeeee, ffffffffffffffffff)\n"; //50 * 'c' Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa import (\n" + " bbbbbbbbbbbb, cccccccccc, dddddddddddddddddddd, eeeeeeeeeeeeeeeeeeeeeeee,\n" @@ -342,7 +345,7 @@ public void testPerform2() { + "from a import b"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + header + "from a import b\n" + "from a import c\n" + "from b import d\n" + "import a\n" + "import b\n" + "\n"; @@ -360,7 +363,7 @@ public void testPerform3() { + "from a import b"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + header + "from a import b\n" + "from a import c\n" + "from b import d\n" + "import a\n" + "import b\n" + "\n"; @@ -377,7 +380,7 @@ public void testPerform4() { + "from a import b"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + header + "from a import b\n" + "from a import c\n" + "from b import d\n" + "import a\n" + "import b\n" + "\n"; @@ -391,7 +394,7 @@ public void testPerform5() { String d = "" + "import sys\n" + "from os import (pipe,\n" + "path)\n" + "import time\n"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from os import (pipe,\n" + "path)\n" + "import sys\n" + "import time\n"; assertEquals(result, doc.get()); @@ -403,7 +406,7 @@ public void testPerform7() { String d = "" + "import sys\n" + "from ...os.path import pipe,\\\n" + "path\n" + "import time\n"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String result = "" + "from ...os.path import pipe, \\\n" + "path\n" + "import sys\n" + "import time\n"; assertEquals(result, doc.get()); @@ -415,7 +418,7 @@ public void testPerform6() { String d = "" + "import sys #comment1\n" + "import sys2 #comment2\n"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); assertEquals(d, doc.get()); } @@ -425,39 +428,39 @@ public void testPerform8() { "from __a import b\n"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); assertEquals(d, doc.get()); } public void testPerform9() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from __future__ import division\n" + //the __future__ imports must always come first "from .backends.common import NoSuchObject\n"; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); assertEquals(d, doc.get()); } public void testPerform10() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "from a import b\n" + "from a import c ;something\n" + "from a import c\n" + ""; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); String expected = "" + "from a import b, c\n" + "from a import c ;something\n" + ""; assertEquals(expected, doc.get()); } public void testPerform11() { - ImportsPreferencesPage.groupImportsForTests = true; + ImportPreferences.groupImportsForTests = true; String d = "" + "a = 10; from a import b\n" + "from a import c ;something\n" + ""; Document doc = new Document(d); - PyOrganizeImports.performArrangeImports(doc, "\n", " ", edit); + SortImports.performArrangeImports(doc, "\n", " ", edit, MAX_COLS); assertEquals(d, doc.get()); } @@ -511,7 +514,7 @@ public void testPep8ImportOrganizer() throws Exception { + "sys.path.insert(0, os.path.realpath(os.path.abspath('..')))\n\n" + ""; Document doc = new Document(s); - PyOrganizeImports.performPep8ArrangeImports(doc, "\n", " ", true, edit); + SortImports.performPep8ArrangeImports(doc, "\n", " ", true, edit, null, MAX_COLS); assertEquals(result, doc.get()); } @@ -537,7 +540,7 @@ public void testPep8ImportOrganizer2() throws Exception { + "sys.path.insert(0, os.path.realpath(os.path.abspath('..')))\n\n" + ""; Document doc = new Document(s); - PyOrganizeImports.performPep8ArrangeImports(doc, "\n", " ", true, edit); + SortImports.performPep8ArrangeImports(doc, "\n", " ", true, edit, null, MAX_COLS); assertEquals(result, doc.get()); } @@ -562,7 +565,7 @@ public void testPep8ImportOrganizer3() throws Exception { + "import unittest\n" + ""; Document doc = new Document(s); - PyOrganizeImports.performPep8ArrangeImports(doc, "\n", " ", true, edit); + SortImports.performPep8ArrangeImports(doc, "\n", " ", true, edit, null, MAX_COLS); assertEquals(result, doc.get()); } @@ -587,7 +590,7 @@ public void testPep8ImportOrganizer4() throws Exception { + "import unittest\n" + ""; Document doc = new Document(s); - PyOrganizeImports.performPep8ArrangeImports(doc, "\n", " ", true, edit); + SortImports.performPep8ArrangeImports(doc, "\n", " ", true, edit, null, MAX_COLS); assertEquals(result, doc.get()); }