Commit 185978bf authored by frmdstryr's avatar frmdstryr Committed by Sven Brauch
Browse files

Add kw_default support

parent 8c105262
......@@ -1740,6 +1740,12 @@ void DeclarationBuilder::visitArguments( ArgumentsAst* node )
int defaultParametersCount = node->defaultValues.length();
int parametersCount = node->arguments.length();
int firstDefaultParameterOffset = parametersCount - defaultParametersCount;
int defaultKwParametersCount = node->defaultKwValues.length();
int kwonlyCount = node->kwonlyargs.length();
int posonlyCount = node->posonlyargs.length();
int totalArgCount = parametersCount + posonlyCount + kwonlyCount;
int firstDefaultKwParameterOffset = totalArgCount - defaultKwParametersCount;
int currentIndex = 0;
foreach ( ArgAst* arg, node->posonlyargs + node->arguments + node->kwonlyargs ) {
// Iterate over all the function's arguments, create declarations, and add the arguments
......@@ -1792,6 +1798,18 @@ void DeclarationBuilder::visitArguments( ArgumentsAst* node )
// TODO add the real expression from the document here as default value
workingOnDeclaration->addDefaultParameter(IndexedString("..."));
}
else if ( currentIndex > firstDefaultKwParameterOffset && currentIndex <= totalArgCount ) {
// Handle kw only arguments with default values, like def foo(*, bar = 3): pass
// Find type of given default value, and assign it to the declaration
ExpressionVisitor v(currentContext());
v.visitNode(node->defaultKwValues.at(currentIndex - firstDefaultKwParameterOffset - 1));
if ( v.lastType() ) {
argumentType = v.lastType();
}
// TODO add the real expression from the document here as default value
workingOnDeclaration->addDefaultParameter(IndexedString("..."));
}
if ( isFirst && ! workingOnDeclaration->isStatic() && currentContext() && currentContext()->parentContext() ) {
DUChainReadLocker lock;
......
......@@ -883,6 +883,11 @@ void PyDUChainTest::testTypes_data()
QTest::newRow("arg_after_vararg") << "def func(x, y, *, z:int): return z\ncheckme = func()" << "int";
QTest::newRow("arg_after_vararg_with_default") << "def func(x=5, y=3, *, z:int): return z\ncheckme = func()" << "int";
QTest::newRow("arg_default") << "def func(x=5, z='foo'): return z\ncheckme = func()" << "str";
QTest::newRow("arg_kw_no_default") << "def func(x=5, *, a, z='foo'): return a\ncheckme = func()" << "mixed";
QTest::newRow("arg_kw_default_after_no_default") << "def func(x=5, *, a, z='foo'): return z\ncheckme = func()" << "str";
QTest::newRow("arg_kw_default") << "def func(x=5, *, z='foo'): return z\ncheckme = func()" << "str";
QTest::newRow("arg_kw_default_after_default") << "def func(x=5, *, y='foo', z=True): return z\ncheckme = func()" << "bool";
QTest::newRow("class_scope_end_inside") << "a = str()\nclass M:\n"
" a = 2\n foo = a\n"
......
......@@ -114,6 +114,7 @@ QString ArgumentsAst::dump() const
dumpList(r, ", args=", arguments);
dumpList(r, ", kwonlyargs=", kwonlyargs);
dumpList(r, ", defaults=", defaultValues);
dumpList(r, ", kw_defaults=", defaultKwValues);
if (vararg)
dumpNode(r, ", vararg=", vararg);
if (kwarg)
......
......@@ -774,6 +774,7 @@ public:
QList<ArgAst*> kwonlyargs;
QList<ArgAst*> posonlyargs;
QList<ExpressionAst*> defaultValues;
QList<ExpressionAst*> defaultKwValues;
ArgAst* vararg;
ArgAst* kwarg;
QString dump() const override;
......
......@@ -252,20 +252,17 @@ Ast* AstTransformer::visitArgumentsNode(PyObject* node, Ast* parent)
PyObjectRef posonlyargs = getattr<PyObjectRef>(node, "posonlyargs");
v->posonlyargs = visitNodeList<ArgAst>(posonlyargs, v);
}
// TODO: kw_defaults?
//{
// PyObject *kw_defaults = getattr<PyObjectRef>(node, "kw_defaults");
// v->kw_defaults = visitNodeList<ArgAst>(kw_defaults, v);
// Py_DECREF(kw_defaults);
//}
#endif
{
PyObjectRef kw_defaults = getattr<PyObjectRef>(node, "kw_defaults");
v->defaultKwValues = visitNodeList<ExpressionAst>(kw_defaults, v);
}
return v;
}
Ast* AstTransformer::visitComprehensionNode(PyObject* node, Ast* parent) {
if ( ! node || node == Py_None ) return nullptr; // TODO: Type check?
if ( ! node || node == Py_None ) return nullptr;
// qDebug() << "visit comp: " << PyUnicodeObjectToQString(PyObject_Str(node));
Q_ASSERT(PyObject_IsInstance(node, grammar.ast_comprehension));
ComprehensionAst* v = new ComprehensionAst(parent);
......@@ -505,7 +502,7 @@ Ast* AstTransformer::visitExprNode(PyObject* node, Ast* parent)
{
PyObject* ops = getattr<PyObject*>(node, "ops");
// TODO? Check list?
Q_ASSERT(PyList_Check(ops));
for ( int _i = 0; _i < PyList_Size(ops); _i++ ) {
PyObject* elt = PyList_GET_ITEM(ops, _i); // borrowed
ExpressionAst::ComparisonOperatorTypes cmp;
......@@ -1174,6 +1171,7 @@ Ast* AstTransformer::visitStmtNode(PyObject* node, Ast* parent)
GlobalAst* v = new GlobalAst(parent);
PyObject* names = getattr<PyObject*>(node, "names");
Q_ASSERT(PyList_Check(names));
for ( int _i = 0; _i < PyList_Size(names); _i++ ) {
Python::Identifier* id = new Python::Identifier(PyUnicodeObjectToQString(
static_cast<PyObject*>(PyList_GET_ITEM(names, _i))
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment