Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
KDevelop
KDevelop Python Support
Commits
185978bf
Commit
185978bf
authored
Oct 26, 2022
by
frmdstryr
Committed by
Sven Brauch
Nov 05, 2022
Browse files
Add kw_default support
parent
8c105262
Changes
5
Hide whitespace changes
Inline
Side-by-side
duchain/declarationbuilder.cpp
View file @
185978bf
...
...
@@ -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
;
...
...
duchain/tests/pyduchaintest.cpp
View file @
185978bf
...
...
@@ -883,6 +883,11 @@ void PyDUChainTest::testTypes_data()
QTest
::
newRow
(
"arg_after_vararg"
)
<<
"def func(x, y, *, z:int): return z
\n
checkme = func()"
<<
"int"
;
QTest
::
newRow
(
"arg_after_vararg_with_default"
)
<<
"def func(x=5, y=3, *, z:int): return z
\n
checkme = func()"
<<
"int"
;
QTest
::
newRow
(
"arg_default"
)
<<
"def func(x=5, z='foo'): return z
\n
checkme = func()"
<<
"str"
;
QTest
::
newRow
(
"arg_kw_no_default"
)
<<
"def func(x=5, *, a, z='foo'): return a
\n
checkme = func()"
<<
"mixed"
;
QTest
::
newRow
(
"arg_kw_default_after_no_default"
)
<<
"def func(x=5, *, a, z='foo'): return z
\n
checkme = func()"
<<
"str"
;
QTest
::
newRow
(
"arg_kw_default"
)
<<
"def func(x=5, *, z='foo'): return z
\n
checkme = func()"
<<
"str"
;
QTest
::
newRow
(
"arg_kw_default_after_default"
)
<<
"def func(x=5, *, y='foo', z=True): return z
\n
checkme = func()"
<<
"bool"
;
QTest
::
newRow
(
"class_scope_end_inside"
)
<<
"a = str()
\n
class M:
\n
"
" a = 2
\n
foo = a
\n
"
...
...
parser/ast.cpp
View file @
185978bf
...
...
@@ -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
)
...
...
parser/ast.h
View file @
185978bf
...
...
@@ -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
;
...
...
parser/asttransformer.cpp
View file @
185978bf
...
...
@@ -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
))
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment