From 382c67ad25c78bfdf4fbbc22f3a2c41865a073a1 Mon Sep 17 00:00:00 2001 From: Fabio Zadrozny Date: Sat, 28 Sep 2024 07:47:26 -0300 Subject: [PATCH] Fix issue where local import would be added in the middle of the arguments. --- .../AddTokenAndImportStatement.java | 79 +++++++++++-------- .../ast/codecompletion/PyCodeCompletion.java | 10 +-- .../PyStringCodeCompletion.java | 6 +- .../core/docstrings/AssistDocString.java | 10 +-- .../pydev/core/docutils/PySelection.java | 44 +++++++---- .../pydev/editor/actions/PySelectionTest.java | 46 +++++------ .../AddTokenAndImportStatementTest.java | 70 +++++++++++----- 7 files changed, 160 insertions(+), 105 deletions(-) diff --git a/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/refactoring/quick_fixes/AddTokenAndImportStatement.java b/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/refactoring/quick_fixes/AddTokenAndImportStatement.java index c4295a81e1..13d2b64bb5 100644 --- a/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/refactoring/quick_fixes/AddTokenAndImportStatement.java +++ b/plugins/com.python.pydev.analysis/src/com/python/pydev/analysis/refactoring/quick_fixes/AddTokenAndImportStatement.java @@ -15,6 +15,7 @@ import org.python.pydev.core.docutils.PyDocIterator; import org.python.pydev.core.docutils.PyImportsHandling; import org.python.pydev.core.docutils.PySelection; +import org.python.pydev.core.docutils.PySelection.InsideParenthesisInfo; import org.python.pydev.core.docutils.PySelection.LineStartingScope; import org.python.pydev.core.docutils.SyntaxErrorException; import org.python.pydev.shared_core.log.Log; @@ -115,11 +116,41 @@ public LineStartingScope getPreviousLineThatStartsScope() { public void createTextEdit(ComputedInfo computedInfo) { try { + String delimiter = this.getDelimiter(); + + computedInfo.appliedWithTrigger = trigger == '.' || trigger == '('; + String appendForTrigger = ""; + if (computedInfo.appliedWithTrigger) { + if (trigger == '(') { + appendForTrigger = "()"; + + } else if (trigger == '.') { + appendForTrigger = "."; + } + } + + //if the trigger is ')', just let it apply regularly -- so, ')' will only be added if it's already in the completion. + + //first do the completion + if (computedInfo.fReplacementString.length() > 0) { + int dif = offset - computedInfo.fReplacementOffset; + computedInfo.replace(offset - dif, dif + computedInfo.fLen, + computedInfo.fReplacementString + appendForTrigger); + } + if (addLocalImport && computedInfo.realImportRep.length() > 0) { + if (addAsLocalImport(previousLineThatStartsScope, ps, delimiter, computedInfo, + addLocalImportsOnTopOfMethod)) { + // Ok, local import added + return; + } + // Otherwise, keep on going, this turned out to be a global import. + } + int lineToAddImport = -1; ImportHandleInfo groupInto = null; ImportHandleInfo realImportHandleInfo = null; - if (computedInfo.realImportRep.length() > 0 && !addLocalImport) { + if (computedInfo.realImportRep.length() > 0) { //Workaround for: https://sourceforge.net/tracker/?func=detail&aid=2697165&group_id=85796&atid=577329 //when importing from __future__ import with_statement, we actually want to add a 'with' token, not @@ -166,33 +197,6 @@ public void createTextEdit(ComputedInfo computedInfo) { } else { lineToAddImport = -1; } - String delimiter = this.getDelimiter(); - - computedInfo.appliedWithTrigger = trigger == '.' || trigger == '('; - String appendForTrigger = ""; - if (computedInfo.appliedWithTrigger) { - if (trigger == '(') { - appendForTrigger = "()"; - - } else if (trigger == '.') { - appendForTrigger = "."; - } - } - - //if the trigger is ')', just let it apply regularly -- so, ')' will only be added if it's already in the completion. - - //first do the completion - if (computedInfo.fReplacementString.length() > 0) { - int dif = offset - computedInfo.fReplacementOffset; - computedInfo.replace(offset - dif, dif + computedInfo.fLen, - computedInfo.fReplacementString + appendForTrigger); - } - if (addLocalImport && computedInfo.realImportRep.length() > 0) { - if (addAsLocalImport(previousLineThatStartsScope, ps, delimiter, computedInfo, - addLocalImportsOnTopOfMethod)) { - return; - } - } if (groupInto != null && realImportHandleInfo != null) { //let's try to group it @@ -333,6 +337,11 @@ private boolean addAsLocalImport(LineStartingScope previousLineThatStartsScope, localImportsLocation = computeLocalImportsLocation(ps, previousLineThatStartsScope, addLocalImportsOnTopOfMethod); } + if (localImportsLocation == null) { + // If we couldn't compute it, it's likely we're in the arguments, as such we need to add + // it as a global import. + return false; + } String indent = localImportsLocation.o1; int iLine = localImportsLocation.o2; String strToAdd = indent + computedInfo.realImportRep + delimiter; @@ -351,17 +360,21 @@ private boolean addAsLocalImport(LineStartingScope previousLineThatStartsScope, } private static Tuple computeLocalImportsLocation(PySelection ps, - LineStartingScope previousLineThatStartsScope, - boolean addLocalImportsOnTopOfMethod) throws SyntaxErrorException { + LineStartingScope previousLineThatStartsScope, boolean addLocalImportsOnTopOfMethod) + throws SyntaxErrorException { int iLineStartingScope; iLineStartingScope = previousLineThatStartsScope.iLineStartingScope; // Ok, we have the line where the scope starts... now, we have to check where that declaration // is finished (i.e.: def my( \n\n\n ): <- only after the ): - Tuple, Integer> tuple = new PySelection(ps.getDoc(), iLineStartingScope, 0) + InsideParenthesisInfo insideParenthesisInfo = new PySelection(ps.getDoc(), iLineStartingScope, 0) .getInsideParentesisToks(false); - if (tuple != null) { - iLineStartingScope = ps.getLineOfOffset(tuple.o2); + if (insideParenthesisInfo != null) { + int cursorOffset = ps.getAbsoluteCursorOffset(); + if (cursorOffset < insideParenthesisInfo.closeParenthesisOffset) { + return null; + } + iLineStartingScope = ps.getLineOfOffset(insideParenthesisInfo.closeParenthesisOffset); } //Go to a non-empty line from the line we have and the line we're currently in. diff --git a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/codecompletion/PyCodeCompletion.java b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/codecompletion/PyCodeCompletion.java index 02f11d2d57..6b8f768581 100644 --- a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/codecompletion/PyCodeCompletion.java +++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/codecompletion/PyCodeCompletion.java @@ -60,6 +60,7 @@ import org.python.pydev.core.autoedit.DefaultIndentPrefs; import org.python.pydev.core.docutils.ParsingUtils; import org.python.pydev.core.docutils.PySelection; +import org.python.pydev.core.docutils.PySelection.InsideParenthesisInfo; import org.python.pydev.core.docutils.PySelection.LineStartingScope; import org.python.pydev.core.log.Log; import org.python.pydev.core.logging.DebugSettings; @@ -88,7 +89,6 @@ import org.python.pydev.shared_core.structure.FastStack; import org.python.pydev.shared_core.structure.ImmutableTuple; import org.python.pydev.shared_core.structure.OrderedMap; -import org.python.pydev.shared_core.structure.Tuple; /** * @author Dmoore @@ -397,10 +397,10 @@ private void createSuperCodeCompletions(CompletionRequest request, TokensOrPropo if (scopeStart != null) { className = PySelection.getClassNameInLine(scopeStart.lineStartingScope); if (className != null && className.length() > 0) { - Tuple, Integer> insideParensBaseClasses = ps.getInsideParentesisToks(true, + InsideParenthesisInfo insideParensBaseClasses = ps.getInsideParentesisToks(true, scopeStart.iLineStartingScope); if (insideParensBaseClasses != null) { - for (String baseClass : insideParensBaseClasses.o1) { + for (String baseClass : insideParensBaseClasses.contents) { ICompletionState state = new CompletionState(-1, -1, null, request.nature, baseClass); String actTok = request.activationToken.replace("super()", baseClass); @@ -449,14 +449,14 @@ private void createOverrideCodeCompletions(CompletionRequest request, if (scopeStart != null) { className = PySelection.getClassNameInLine(scopeStart.lineStartingScope); if (className != null && className.length() > 0) { - Tuple, Integer> insideParensBaseClasses = ps.getInsideParentesisToks(true, + InsideParenthesisInfo insideParensBaseClasses = ps.getInsideParentesisToks(true, scopeStart.iLineStartingScope); if (insideParensBaseClasses != null) { //representation -> token and base class OrderedMap> map = new OrderedMap>(); - for (String baseClass : insideParensBaseClasses.o1) { + for (String baseClass : insideParensBaseClasses.contents) { try { ICompletionState state = new CompletionState(-1, -1, null, request.nature, baseClass); diff --git a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/codecompletion/PyStringCodeCompletion.java b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/codecompletion/PyStringCodeCompletion.java index ffaf5390af..f2f685a3ca 100644 --- a/plugins/org.python.pydev.ast/src/org/python/pydev/ast/codecompletion/PyStringCodeCompletion.java +++ b/plugins/org.python.pydev.ast/src/org/python/pydev/ast/codecompletion/PyStringCodeCompletion.java @@ -28,6 +28,7 @@ import org.python.pydev.core.PythonNatureWithoutProjectException; import org.python.pydev.core.TokensOrProposalsList; import org.python.pydev.core.docutils.PySelection; +import org.python.pydev.core.docutils.PySelection.InsideParenthesisInfo; import org.python.pydev.core.log.Log; import org.python.pydev.core.partition.PyPartitionScanner; import org.python.pydev.core.proposals.CompletionProposalFactory; @@ -41,7 +42,6 @@ import org.python.pydev.shared_core.partitioner.FastPartitioner; import org.python.pydev.shared_core.string.DocIterator; import org.python.pydev.shared_core.string.TextSelectionUtils; -import org.python.pydev.shared_core.structure.Tuple; /** * The code-completion engine that should be used inside strings @@ -288,8 +288,8 @@ private void fillWithParams(CompletionRequest request, List, Integer> insideParentesisToks = selection.getInsideParentesisToks(false); - for (String str : insideParentesisToks.o1) { + InsideParenthesisInfo insideParentesisToks = selection.getInsideParentesisToks(false); + for (String str : insideParentesisToks.contents) { if (str.startsWith(initial)) { ret.add(CompletionProposalFactory.get().createPyLinkedModeCompletionProposal(str, request.documentOffset - request.qlen, request.qlen, str.length(), diff --git a/plugins/org.python.pydev.core/src/org/python/pydev/core/docstrings/AssistDocString.java b/plugins/org.python.pydev.core/src/org/python/pydev/core/docstrings/AssistDocString.java index 68a5289d36..95a2dff085 100644 --- a/plugins/org.python.pydev.core/src/org/python/pydev/core/docstrings/AssistDocString.java +++ b/plugins/org.python.pydev.core/src/org/python/pydev/core/docstrings/AssistDocString.java @@ -30,6 +30,7 @@ import org.python.pydev.core.autoedit.DefaultIndentPrefs; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.core.docutils.PySelection.DocstringInfo; +import org.python.pydev.core.docutils.PySelection.InsideParenthesisInfo; import org.python.pydev.core.proposals.CompletionProposalFactory; import org.python.pydev.shared_core.code_completion.ICompletionProposalHandle; import org.python.pydev.shared_core.code_completion.IPyCompletionProposal; @@ -38,7 +39,6 @@ import org.python.pydev.shared_core.image.UIConstants; import org.python.pydev.shared_core.string.FastStringBuffer; import org.python.pydev.shared_core.string.StringUtils; -import org.python.pydev.shared_core.structure.Tuple; public class AssistDocString implements IAssistProps { @@ -65,16 +65,16 @@ public List getProps(PySelection ps, IImageCache imag IPyEdit edit, int offset) throws BadLocationException { ArrayList l = new ArrayList<>(); - Tuple, Integer> tuple = ps.getInsideParentesisToks(false); + InsideParenthesisInfo tuple = ps.getInsideParentesisToks(false); if (tuple == null) { if (ps.isInClassLine()) { - tuple = new Tuple, Integer>(new ArrayList(), offset); + tuple = new InsideParenthesisInfo(offset, offset, new ArrayList()); } else { return l; } } - List params = tuple.o1; - int lineOfOffset = ps.getLineOfOffset(tuple.o2); + List params = tuple.contents; + int lineOfOffset = ps.getLineOfOffset(tuple.closeParenthesisOffset); // Calculate only the initial part of the docstring here (everything else should be lazily computed on apply). String initial = PySelection.getIndentationFromLine(ps.getCursorLineContents()); diff --git a/plugins/org.python.pydev.core/src/org/python/pydev/core/docutils/PySelection.java b/plugins/org.python.pydev.core/src/org/python/pydev/core/docutils/PySelection.java index 90adbbaa7f..6eafbd8c7f 100644 --- a/plugins/org.python.pydev.core/src/org/python/pydev/core/docutils/PySelection.java +++ b/plugins/org.python.pydev.core/src/org/python/pydev/core/docutils/PySelection.java @@ -443,7 +443,19 @@ public String getLineContentsToCursor(boolean removeComments, boolean removeLite return buffer.toString(); } - public Tuple, Integer> getInsideParentesisToks(boolean addSelf) { + public static class InsideParenthesisInfo { + public final int openParenthesisOffset; + public final int closeParenthesisOffset; + public final List contents; + + public InsideParenthesisInfo(int openParenthesisOffset, int closeParenthesisOffset, List contents) { + this.openParenthesisOffset = openParenthesisOffset; + this.closeParenthesisOffset = closeParenthesisOffset; + this.contents = contents; + } + } + + public InsideParenthesisInfo getInsideParentesisToks(boolean addSelf) { String line = getLine(); int openParIndex = line.indexOf('('); if (openParIndex <= -1) { // we are in a line that does not have a parenthesis @@ -457,14 +469,14 @@ public Tuple, Integer> getInsideParentesisToks(boolean addSelf) { } public String getFirstInsideParentesisTok(int line) { - List insideParentesisToks = getInsideParentesisToks(true, line).o1; + List insideParentesisToks = getInsideParentesisToks(true, line).contents; if (insideParentesisToks != null && insideParentesisToks.size() > 0) { return insideParentesisToks.get(0); } return null; } - public Tuple, Integer> getInsideParentesisToks(boolean addSelf, int iLine) { + public InsideParenthesisInfo getInsideParentesisToks(boolean addSelf, int iLine) { String line = getLine(iLine); int openParIndex = line.indexOf('('); if (openParIndex <= -1) { // we are in a line that does not have a parenthesis @@ -497,14 +509,15 @@ public Tuple, Integer> getInsideParentesisToks(boolean addSelf, int * @return a Tuple so that the first param is the list and the second the offset of the end of the parenthesis. * It may return null if no starting parenthesis was found at the current line */ - public Tuple, Integer> getInsideParentesisToks(boolean addSelf, int offset, boolean isCall) { + public InsideParenthesisInfo getInsideParentesisToks(boolean addSelf, final int openParenthesisOffset, + boolean isCall) { List params = new ArrayList(); String docContents = doc.get(); - int j; + int closeParenthesisOffset; try { - j = ParsingUtils.create(docContents).eatPar(offset, null); + closeParenthesisOffset = ParsingUtils.create(docContents).eatPar(openParenthesisOffset, null); - final String insideParentesisTok = docContents.substring(offset + 1, j); + final String insideParentesisTok = docContents.substring(openParenthesisOffset + 1, closeParenthesisOffset); final ParsingUtils insideParensParsingUtils = ParsingUtils.create(insideParentesisTok); final int len = insideParentesisTok.length(); final FastStringBuffer buf = new FastStringBuffer(len); @@ -519,17 +532,17 @@ public Tuple, Integer> getInsideParentesisToks(boolean addSelf, int switch (c) { case '\'': case '"': - j = insideParensParsingUtils.eatLiterals(null, i); - buf.append(insideParentesisTok.substring(i, j + 1)); - i = j; + closeParenthesisOffset = insideParensParsingUtils.eatLiterals(null, i); + buf.append(insideParentesisTok.substring(i, closeParenthesisOffset + 1)); + i = closeParenthesisOffset; break; case '{': case '(': case '[': - j = insideParensParsingUtils.eatPar(i, null, c); - buf.append(insideParentesisTok.substring(i, j + 1)); - i = j; + closeParenthesisOffset = insideParensParsingUtils.eatPar(i, null, c); + buf.append(insideParentesisTok.substring(i, closeParenthesisOffset + 1)); + i = closeParenthesisOffset; break; default: @@ -576,7 +589,7 @@ public Tuple, Integer> getInsideParentesisToks(boolean addSelf, int throw new RuntimeException(e); } - return new Tuple, Integer>(params, j); + return new InsideParenthesisInfo(openParenthesisOffset, closeParenthesisOffset, params); } private static final void addTrimmedBufToList(FastStringBuffer buf, List list, boolean addSelf) { @@ -1283,8 +1296,7 @@ public List getParametersAfterCall(int currentOffset) { } while (Character.isWhitespace(c)); if (c == '(') { - Tuple, Integer> insideParentesisToks = getInsideParentesisToks(true, currentOffset, true); - return insideParentesisToks.o1; + return getInsideParentesisToks(true, currentOffset, true).contents; } } catch (Exception e) { diff --git a/plugins/org.python.pydev/tests/org/python/pydev/editor/actions/PySelectionTest.java b/plugins/org.python.pydev/tests/org/python/pydev/editor/actions/PySelectionTest.java index eea1571af2..0fe76dcd29 100644 --- a/plugins/org.python.pydev/tests/org/python/pydev/editor/actions/PySelectionTest.java +++ b/plugins/org.python.pydev/tests/org/python/pydev/editor/actions/PySelectionTest.java @@ -312,7 +312,7 @@ public void testGetInsideParentesis() throws Exception { String s = "def m1(self, a, b)"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(2, insideParentesisToks.size()); assertEquals("a", insideParentesisToks.get(0)); assertEquals("b", insideParentesisToks.get(1)); @@ -320,7 +320,7 @@ public void testGetInsideParentesis() throws Exception { s = "def m1(self, a, b, )"; doc = new Document(s); ps = new PySelection(doc, 0); - insideParentesisToks = ps.getInsideParentesisToks(false).o1; + insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(2, insideParentesisToks.size()); assertEquals("a", insideParentesisToks.get(0)); assertEquals("b", insideParentesisToks.get(1)); @@ -328,7 +328,7 @@ public void testGetInsideParentesis() throws Exception { s = "def m1(self, a, b=None)"; doc = new Document(s); ps = new PySelection(doc, 0); - insideParentesisToks = ps.getInsideParentesisToks(true).o1; + insideParentesisToks = ps.getInsideParentesisToks(true).contents; assertEquals(3, insideParentesisToks.size()); assertEquals("self", insideParentesisToks.get(0)); assertEquals("a", insideParentesisToks.get(1)); @@ -337,7 +337,7 @@ public void testGetInsideParentesis() throws Exception { s = "def m1(self, a, b=None)"; doc = new Document(s); ps = new PySelection(doc, 0); - insideParentesisToks = ps.getInsideParentesisToks(false).o1; + insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(2, insideParentesisToks.size()); assertEquals("a", insideParentesisToks.get(0)); assertEquals("b", insideParentesisToks.get(1)); @@ -346,14 +346,14 @@ public void testGetInsideParentesis() throws Exception { s = "def m1(self, a, (b,c) )"; doc = new Document(s); ps = new PySelection(doc, 0); - insideParentesisToks = ps.getInsideParentesisToks(false).o1; + insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("a", insideParentesisToks.get(0)); s = "def m1(self, a, b, \nc,\nd )"; doc = new Document(s); ps = new PySelection(doc, 0); - insideParentesisToks = ps.getInsideParentesisToks(false).o1; + insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(4, insideParentesisToks.size()); assertEquals("a", insideParentesisToks.get(0)); assertEquals("b", insideParentesisToks.get(1)); @@ -363,7 +363,7 @@ public void testGetInsideParentesis() throws Exception { s = "def m1(self, a=(1,2))"; doc = new Document(s); ps = new PySelection(doc, 0); - insideParentesisToks = ps.getInsideParentesisToks(false).o1; + insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("a", insideParentesisToks.get(0)); @@ -373,7 +373,7 @@ public void testGetInsideParentesis2() throws Exception { String s = "def __init__(self, env: Dict[str, str]):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("env", insideParentesisToks.get(0)); } @@ -382,7 +382,7 @@ public void testGetInsideParentesis3() throws Exception { String s = "def __init__(self, complex_var: Dict[str, Node[str]()]):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("complex_var", insideParentesisToks.get(0)); } @@ -391,7 +391,7 @@ public void testGetInsideParentesis4() throws Exception { String s = "def __init__(self, complex_var: Dict[str, Node('')]):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("complex_var", insideParentesisToks.get(0)); } @@ -400,7 +400,7 @@ public void testGetInsideParentesis5() throws Exception { String s = "def __init__(self, complex_var: Dict[str, Node(0)]):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("complex_var", insideParentesisToks.get(0)); } @@ -409,7 +409,7 @@ public void testGetInsideParentesis6() throws Exception { String s = "def __init__(self, complex_var: DefaultDict[int, bytes]()):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("complex_var", insideParentesisToks.get(0)); } @@ -418,7 +418,7 @@ public void testGetInsideParentesis7() throws Exception { String s = "def __init__(self, complex_var: collections.defaultdict()):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("complex_var", insideParentesisToks.get(0)); } @@ -427,7 +427,7 @@ public void testGetInsideParentesis8() throws Exception { String s = "def __init__(self, complex_var: str):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("complex_var", insideParentesisToks.get(0)); } @@ -436,7 +436,7 @@ public void testGetInsideParentesis9() throws Exception { String s = "def __init__(self, left: 'Tree', right: 'Tree'):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(2, insideParentesisToks.size()); assertEquals("left", insideParentesisToks.get(0)); assertEquals("right", insideParentesisToks.get(1)); @@ -446,7 +446,7 @@ public void testGetInsideParentesis10() throws Exception { String s = "def __init__(self, complex_var: Union[int, None, Empty]):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("complex_var", insideParentesisToks.get(0)); } @@ -455,7 +455,7 @@ public void testGetInsideParentesis11() throws Exception { String s = "def __init__(self, x: str): -> int"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("x", insideParentesisToks.get(0)); } @@ -464,7 +464,7 @@ public void testGetInsideParentesis12() throws Exception { String s = "def __init__(self, x: Union[int, None, Empty]): -> Union[str, None, int]"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("x", insideParentesisToks.get(0)); } @@ -473,7 +473,7 @@ public void testGetInsideParentesis13() throws Exception { String s = "def __init__(self, x: Union[Dict[str, str], None, Empty]):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(1, insideParentesisToks.size()); assertEquals("x", insideParentesisToks.get(0)); } @@ -482,7 +482,7 @@ public void testGetInsideParentesis14() throws Exception { String s = "def __init__(self, x: Union[Dict[str, str], None, Empty], y: str, z: Dict[int, int]):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(3, insideParentesisToks.size()); assertEquals("x", insideParentesisToks.get(0)); assertEquals("y", insideParentesisToks.get(1)); @@ -493,7 +493,7 @@ public void testGetInsideParentesis15() throws Exception { String s = "def __init__(self, x: Dict[str, str], y: Dict[str, str], z: Dict[int, int]):"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(3, insideParentesisToks.size()); assertEquals("x", insideParentesisToks.get(0)); assertEquals("y", insideParentesisToks.get(1)); @@ -504,7 +504,7 @@ public void testGetInsideParentesis16() throws Exception { String s = "def __init__(self, x: Dict[str, str], y: Dict[str, str], z: Dict[int, int]): -> Dict[str, int]"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(3, insideParentesisToks.size()); assertEquals("x", insideParentesisToks.get(0)); assertEquals("y", insideParentesisToks.get(1)); @@ -515,7 +515,7 @@ public void testGetInsideParentesis17() throws Exception { String s = "def __init__(self, x: Dict[str, str], \ny: Dict[str, str], \nz: Dict[int, int]): -> Dict[str, int]"; doc = new Document(s); ps = new PySelection(doc, 0); - List insideParentesisToks = ps.getInsideParentesisToks(false).o1; + List insideParentesisToks = ps.getInsideParentesisToks(false).contents; assertEquals(3, insideParentesisToks.size()); assertEquals("x", insideParentesisToks.get(0)); assertEquals("y", insideParentesisToks.get(1)); diff --git a/plugins/org.python.pydev/tests_analysis/com/python/pydev/analysis/refactoring/quick_fixes/AddTokenAndImportStatementTest.java b/plugins/org.python.pydev/tests_analysis/com/python/pydev/analysis/refactoring/quick_fixes/AddTokenAndImportStatementTest.java index ac51266a1a..89b4880fdb 100644 --- a/plugins/org.python.pydev/tests_analysis/com/python/pydev/analysis/refactoring/quick_fixes/AddTokenAndImportStatementTest.java +++ b/plugins/org.python.pydev/tests_analysis/com/python/pydev/analysis/refactoring/quick_fixes/AddTokenAndImportStatementTest.java @@ -50,11 +50,16 @@ public void checkImport(String baseDoc, String importToAdd, String expectedDoc, public void checkLocalImport(String baseDoc, String importToAdd, String expectedDoc, boolean addLocalImportsOnTopOfMethod) throws Exception { + int offset = baseDoc.length(); + checkLocalImport(baseDoc, importToAdd, expectedDoc, addLocalImportsOnTopOfMethod, offset); + } + + public void checkLocalImport(String baseDoc, String importToAdd, String expectedDoc, + boolean addLocalImportsOnTopOfMethod, int offset) throws Exception { Document document = new Document(baseDoc); char trigger = '\n'; - int offset = baseDoc.length(); boolean addLocalImport = true; boolean groupImports = true; @@ -634,29 +639,54 @@ public void testGroupImport12() throws Exception { } public void testLocalImport() throws Exception { - String baseDoc = "def method():\r\n" + - " pass\r\n" + - "\r\n" + - "\r\n" + - "def method2():\r\n" + - " x = \"\"\"\r\n" + - "some string\r\n" + - "\"\"\"\r\n" + - " sys"; - String expectedDoc = "def method():\r\n" + - " pass\r\n" + - "\r\n" + - "\r\n" + - "def method2():\r\n" + - " import sys\r\n" + - " x = \"\"\"\r\n" + - "some string\r\n" + - "\"\"\"\r\n" + - " sys"; + String baseDoc = """ + def method(): + pass + + + def method2(): + x = \""" + some string + \""" + sys"""; + String expectedDoc = """ + def method(): + pass + + + def method2(): + import sys + x = \""" + some string + \""" + sys"""; checkLocalImport(baseDoc, "import sys", expectedDoc, true); } + public void testLocalImportInsideMethod() throws Exception { + String baseDoc = """ + + def method( + b: int, + a: List, + ): + pass + """; + String expectedDoc = """ + from typing import List + + def method( + b: int, + a: List, + ): + pass + """; + + int i = baseDoc.indexOf("List"); + checkLocalImport(baseDoc, "from typing import List", expectedDoc, true, i); + } + public void testLocalImport2() throws Exception { String baseDoc = "def method():\r\n" + " pass\r\n" +