From c2067ff719b87f5b2cf378a7ff5d3e3095d6f45b Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Tue, 22 Apr 2014 23:13:13 +0400 Subject: [PATCH] PY-1194 Provide completion and navigation for url tag in django template PY-3591 Support {% url %} tag arguments completion Params to be supported --- .../jetbrains/python/FunctionParameter.java | 21 ++++++++++++++++ .../jetbrains/python/psi/PyArgumentList.java | 10 ++++++++ .../python/psi/impl/PyArgumentListImpl.java | 25 ++++++++++++++++--- 3 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 python/psi-api/src/com/jetbrains/python/FunctionParameter.java diff --git a/python/psi-api/src/com/jetbrains/python/FunctionParameter.java b/python/psi-api/src/com/jetbrains/python/FunctionParameter.java new file mode 100644 index 000000000000..bceba9efc24b --- /dev/null +++ b/python/psi-api/src/com/jetbrains/python/FunctionParameter.java @@ -0,0 +1,21 @@ +package com.jetbrains.python; + +import org.jetbrains.annotations.Nullable; + +/** + * This class (possibly enum) represents function parameter + * + * @author Ilya.Kazakevich + */ +public interface FunctionParameter { + /** + * @return parameter position + */ + int getPosition(); + + /** + * @return parameter name (if known) + */ + @Nullable + String getName(); +} diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java b/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java index f89f25fdf2d2..0a1a9c325f0a 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java @@ -16,6 +16,7 @@ package com.jetbrains.python.psi; import com.intellij.lang.ASTNode; +import com.jetbrains.python.FunctionParameter; import com.jetbrains.python.psi.resolve.PyResolveContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -78,4 +79,13 @@ public interface PyArgumentList extends PyElement { @Nullable ASTNode getClosingParen(); + + /** + * Searches parameter value and returns it if exists. + * + * @param parameter param to search + * @return function parameter value expression or null if does not exist + */ + @Nullable + PyExpression getValueExpressionForParam(@NotNull FunctionParameter parameter); } diff --git a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java index 2e6120a29303..d0c83cc65957 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java @@ -27,6 +27,7 @@ import com.jetbrains.NotNullPredicate; import com.jetbrains.python.PyElementTypes; import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.PythonDialectsTokenSetProvider; +import com.jetbrains.python.FunctionParameter; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.resolve.PyResolveContext; import org.jetbrains.annotations.NotNull; @@ -203,7 +204,6 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList catch (IncorrectOperationException e1) { throw new IllegalStateException(e1); } - } else { getNode().addChild(arg.getNode(), par); @@ -214,7 +214,7 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList public ASTNode getClosingParen() { ASTNode node = getNode(); final ASTNode[] children = node.getChildren(TokenSet.create(PyTokenTypes.RPAR)); - return children.length == 0 ? null : children[children.length-1]; + return children.length == 0 ? null : children[children.length - 1]; } private void addArgumentNode(PyExpression arg, ASTNode beforeThis, boolean commaFirst) { @@ -256,14 +256,12 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList // 1: Nothing, just add addArgumentNode(argument, node, true); break; - } else if (PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens().contains(type)) { // 2: After some argument followed by comma: after comma, add element, add comma // 3: After some argument not followed by comma: add comma, add element addArgumentNode(argument, node, true); break; - } else if (type == PyTokenTypes.COMMA) { ASTNode next = PyUtil.getNextNonWhitespace(node); @@ -333,4 +331,23 @@ public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList return (PsiTreeUtil.getParentOfType(input, PyKeywordArgument.class) == null) && !(input instanceof PyKeywordArgument); } } + + @Nullable + @Override + public PyExpression getValueExpressionForParam(@NotNull final FunctionParameter parameter) { + final String parameterName = parameter.getName(); + if (parameterName != null) { + final PyKeywordArgument kwarg = getKeywordArgument(parameterName); + if (kwarg != null) { + return kwarg.getValueExpression(); + } + } + + final PyExpression[] arguments = getArguments(); + if (arguments.length > parameter.getPosition()) { + return arguments[parameter.getPosition()]; + } + + return null; + } }