Skip to content

Commit

Permalink
Fix issue where local import would be added in the middle of the argu…
Browse files Browse the repository at this point in the history
…ments.
  • Loading branch information
fabioz committed Sep 28, 2024
1 parent 5b70f0c commit 382c67a
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -351,17 +360,21 @@ private boolean addAsLocalImport(LineStartingScope previousLineThatStartsScope,
}

private static Tuple<String, Integer> 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<List<String>, 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<List<String>, 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);
Expand Down Expand Up @@ -449,14 +449,14 @@ private void createOverrideCodeCompletions(CompletionRequest request,
if (scopeStart != null) {
className = PySelection.getClassNameInLine(scopeStart.lineStartingScope);
if (className != null && className.length() > 0) {
Tuple<List<String>, Integer> insideParensBaseClasses = ps.getInsideParentesisToks(true,
InsideParenthesisInfo insideParensBaseClasses = ps.getInsideParentesisToks(true,
scopeStart.iLineStartingScope);
if (insideParensBaseClasses != null) {

//representation -> token and base class
OrderedMap<String, ImmutableTuple<IToken, String>> map = new OrderedMap<String, ImmutableTuple<IToken, String>>();

for (String baseClass : insideParensBaseClasses.o1) {
for (String baseClass : insideParensBaseClasses.contents) {
try {
ICompletionState state = new CompletionState(-1, -1, null, request.nature,
baseClass);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -288,8 +288,8 @@ private void fillWithParams(CompletionRequest request, List<ICompletionProposalH
int currentLine = iterator.getCurrentLine() + 1;
PySelection selection = new PySelection(request.doc, currentLine, 0);
if (selection.isInFunctionLine(true)) {
Tuple<List<String>, 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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {

Expand All @@ -65,16 +65,16 @@ public List<ICompletionProposalHandle> getProps(PySelection ps, IImageCache imag
IPyEdit edit, int offset) throws BadLocationException {
ArrayList<ICompletionProposalHandle> l = new ArrayList<>();

Tuple<List<String>, Integer> tuple = ps.getInsideParentesisToks(false);
InsideParenthesisInfo tuple = ps.getInsideParentesisToks(false);
if (tuple == null) {
if (ps.isInClassLine()) {
tuple = new Tuple<List<String>, Integer>(new ArrayList<String>(), offset);
tuple = new InsideParenthesisInfo(offset, offset, new ArrayList<String>());
} else {
return l;
}
}
List<String> params = tuple.o1;
int lineOfOffset = ps.getLineOfOffset(tuple.o2);
List<String> 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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,19 @@ public String getLineContentsToCursor(boolean removeComments, boolean removeLite
return buffer.toString();
}

public Tuple<List<String>, Integer> getInsideParentesisToks(boolean addSelf) {
public static class InsideParenthesisInfo {
public final int openParenthesisOffset;
public final int closeParenthesisOffset;
public final List<String> contents;

public InsideParenthesisInfo(int openParenthesisOffset, int closeParenthesisOffset, List<String> 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
Expand All @@ -457,14 +469,14 @@ public Tuple<List<String>, Integer> getInsideParentesisToks(boolean addSelf) {
}

public String getFirstInsideParentesisTok(int line) {
List<String> insideParentesisToks = getInsideParentesisToks(true, line).o1;
List<String> insideParentesisToks = getInsideParentesisToks(true, line).contents;
if (insideParentesisToks != null && insideParentesisToks.size() > 0) {
return insideParentesisToks.get(0);
}
return null;
}

public Tuple<List<String>, 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
Expand Down Expand Up @@ -497,14 +509,15 @@ public Tuple<List<String>, 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<List<String>, Integer> getInsideParentesisToks(boolean addSelf, int offset, boolean isCall) {
public InsideParenthesisInfo getInsideParentesisToks(boolean addSelf, final int openParenthesisOffset,
boolean isCall) {
List<String> params = new ArrayList<String>();
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);
Expand All @@ -519,17 +532,17 @@ public Tuple<List<String>, 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:
Expand Down Expand Up @@ -576,7 +589,7 @@ public Tuple<List<String>, Integer> getInsideParentesisToks(boolean addSelf, int
throw new RuntimeException(e);

}
return new Tuple<List<String>, Integer>(params, j);
return new InsideParenthesisInfo(openParenthesisOffset, closeParenthesisOffset, params);
}

private static final void addTrimmedBufToList(FastStringBuffer buf, List<String> list, boolean addSelf) {
Expand Down Expand Up @@ -1283,8 +1296,7 @@ public List<String> getParametersAfterCall(int currentOffset) {
} while (Character.isWhitespace(c));

if (c == '(') {
Tuple<List<String>, Integer> insideParentesisToks = getInsideParentesisToks(true, currentOffset, true);
return insideParentesisToks.o1;
return getInsideParentesisToks(true, currentOffset, true).contents;
}

} catch (Exception e) {
Expand Down
Loading

0 comments on commit 382c67a

Please sign in to comment.