use of org.sonar.plugins.python.api.tree.Decorator in project sonar-python by SonarSource.
the class PythonTreeMaker method classDefStatement.
public ClassDef classDefStatement(AstNode astNode) {
AstNode decoratorsNode = astNode.getFirstChild(PythonGrammar.DECORATORS);
List<Decorator> decorators = Collections.emptyList();
if (decoratorsNode != null) {
decorators = decoratorsNode.getChildren(PythonGrammar.DECORATOR).stream().map(this::decorator).collect(Collectors.toList());
}
Name name = name(astNode.getFirstChild(PythonGrammar.CLASSNAME).getFirstChild(PythonGrammar.NAME));
ArgList args = null;
AstNode leftPar = astNode.getFirstChild(PythonPunctuator.LPARENTHESIS);
if (leftPar != null) {
args = argList(astNode.getFirstChild(PythonGrammar.ARGLIST));
}
AstNode suite = astNode.getFirstChild(PythonGrammar.SUITE);
StatementList body = getStatementListFromSuite(suite);
Token classToken = toPyToken(astNode.getFirstChild(PythonKeyword.CLASS).getToken());
AstNode rightPar = astNode.getFirstChild(PythonPunctuator.RPARENTHESIS);
Token colon = toPyToken(astNode.getFirstChild(PythonPunctuator.COLON).getToken());
return new ClassDefImpl(decorators, classToken, name, leftPar != null ? toPyToken(leftPar.getToken()) : null, args, rightPar != null ? toPyToken(rightPar.getToken()) : null, colon, suiteNewLine(suite), suiteIndent(suite), body, suiteDedent(suite), DocstringExtractor.extractDocstring(body));
}
use of org.sonar.plugins.python.api.tree.Decorator in project sonar-python by SonarSource.
the class PythonTreeMaker method funcDefStatement.
public FunctionDef funcDefStatement(AstNode astNode) {
AstNode decoratorsNode = astNode.getFirstChild(PythonGrammar.DECORATORS);
List<Decorator> decorators = Collections.emptyList();
if (decoratorsNode != null) {
decorators = decoratorsNode.getChildren(PythonGrammar.DECORATOR).stream().map(this::decorator).collect(Collectors.toList());
}
Name name = name(astNode.getFirstChild(PythonGrammar.FUNCNAME).getFirstChild(PythonGrammar.NAME));
ParameterList parameterList = null;
AstNode typedArgListNode = astNode.getFirstChild(PythonGrammar.TYPEDARGSLIST);
if (typedArgListNode != null) {
List<AnyParameter> arguments = typedArgListNode.getChildren(PythonGrammar.TFPDEF, PythonPunctuator.MUL, PythonPunctuator.DIV).stream().map(this::parameter).filter(Objects::nonNull).collect(Collectors.toList());
List<Token> commas = punctuators(typedArgListNode, PythonPunctuator.COMMA);
parameterList = new ParameterListImpl(arguments, commas);
}
AstNode suite = astNode.getFirstChild(PythonGrammar.SUITE);
StatementList body = getStatementListFromSuite(suite);
AstNode defNode = astNode.getFirstChild(PythonKeyword.DEF);
Token asyncToken = null;
AstNode defPreviousSibling = defNode.getPreviousSibling();
if (defPreviousSibling != null && defPreviousSibling.getToken().getValue().equals("async")) {
asyncToken = toPyToken(defPreviousSibling.getToken());
}
Token lPar = toPyToken(astNode.getFirstChild(PythonPunctuator.LPARENTHESIS).getToken());
Token rPar = toPyToken(astNode.getFirstChild(PythonPunctuator.RPARENTHESIS).getToken());
TypeAnnotation returnType = null;
AstNode returnTypeNode = astNode.getFirstChild(PythonGrammar.FUN_RETURN_ANNOTATION);
if (returnTypeNode != null) {
List<AstNode> children = returnTypeNode.getChildren();
returnType = new TypeAnnotationImpl(toPyToken(children.get(0).getToken()), toPyToken(children.get(1).getToken()), expression(children.get(2)));
}
Token colon = toPyToken(astNode.getFirstChild(PythonPunctuator.COLON).getToken());
return new FunctionDefImpl(decorators, asyncToken, toPyToken(defNode.getToken()), name, lPar, parameterList, rPar, returnType, colon, suiteNewLine(suite), suiteIndent(suite), body, suiteDedent(suite), isMethodDefinition(astNode), DocstringExtractor.extractDocstring(body));
}
use of org.sonar.plugins.python.api.tree.Decorator in project sonar-python by SonarSource.
the class PythonTreeMakerTest method funcdef_statement.
@Test
public void funcdef_statement() {
setRootRule(PythonGrammar.FUNCDEF);
AstNode astNode = p.parse("def func(): pass");
FunctionDef functionDef = treeMaker.funcDefStatement(astNode);
assertThat(functionDef.name()).isNotNull();
assertThat(functionDef.name().name()).isEqualTo("func");
assertThat(functionDef.body().statements()).hasSize(1);
assertThat(functionDef.body().statements().get(0).is(Tree.Kind.PASS_STMT)).isTrue();
assertThat(functionDef.children()).hasSize(6);
assertThat(functionDef.parameters()).isNull();
assertThat(functionDef.isMethodDefinition()).isFalse();
assertThat(functionDef.docstring()).isNull();
assertThat(functionDef.decorators()).isEmpty();
assertThat(functionDef.asyncKeyword()).isNull();
assertThat(functionDef.returnTypeAnnotation()).isNull();
assertThat(functionDef.colon().value()).isEqualTo(":");
assertThat(functionDef.defKeyword().value()).isEqualTo("def");
assertThat(functionDef.leftPar().value()).isEqualTo("(");
assertThat(functionDef.rightPar().value()).isEqualTo(")");
functionDef = parse("def func(x): pass", treeMaker::funcDefStatement);
assertThat(functionDef.parameters().all()).hasSize(1);
functionDef = parse("async def func(x): pass", treeMaker::funcDefStatement);
assertThat(functionDef.asyncKeyword().value()).isEqualTo("async");
functionDef = parse("def func(x) -> string : pass", treeMaker::funcDefStatement);
TypeAnnotation returnType = functionDef.returnTypeAnnotation();
assertThat(returnType.getKind()).isEqualTo(Tree.Kind.RETURN_TYPE_ANNOTATION);
assertThat(returnType.expression().getKind()).isEqualTo(Tree.Kind.NAME);
functionDef = parse("@foo\ndef func(x): pass", treeMaker::funcDefStatement);
assertThat(functionDef.decorators()).hasSize(1);
Decorator decoratorTree = functionDef.decorators().get(0);
assertThat(decoratorTree.getKind()).isEqualTo(Tree.Kind.DECORATOR);
assertThat(decoratorTree.atToken().value()).isEqualTo("@");
assertThat(decoratorTree.name().names().get(0).name()).isEqualTo("foo");
assertThat(decoratorTree.leftPar()).isNull();
assertThat(decoratorTree.arguments()).isNull();
assertThat(decoratorTree.rightPar()).isNull();
functionDef = parse("@foo()\n@bar(1)\ndef func(x): pass", treeMaker::funcDefStatement);
assertThat(functionDef.decorators()).hasSize(2);
Decorator decoratorTree1 = functionDef.decorators().get(0);
assertThat(decoratorTree1.leftPar().value()).isEqualTo("(");
assertThat(decoratorTree1.arguments()).isNull();
assertThat(decoratorTree1.rightPar().value()).isEqualTo(")");
Decorator decoratorTree2 = functionDef.decorators().get(1);
assertThat(decoratorTree2.arguments().arguments()).extracting(arg -> ((RegularArgument) arg).expression().getKind()).containsExactly(Tree.Kind.NUMERIC_LITERAL);
functionDef = parse("def func(x, y): pass", treeMaker::funcDefStatement);
assertThat(functionDef.parameters().all()).hasSize(2);
functionDef = parse("def func(x = 'foo', y): pass", treeMaker::funcDefStatement);
assertThat(functionDef.parameters().all()).isEqualTo(functionDef.parameters().nonTuple());
List<Parameter> parameters = functionDef.parameters().nonTuple();
assertThat(parameters).hasSize(2);
Parameter parameter1 = parameters.get(0);
assertThat(parameter1.name().name()).isEqualTo("x");
assertThat(parameter1.equalToken().value()).isEqualTo("=");
assertThat(parameter1.defaultValue().is(Tree.Kind.STRING_LITERAL)).isTrue();
assertThat(parameter1.children()).doesNotContainNull();
Parameter parameter2 = parameters.get(1);
assertThat(parameter2.equalToken()).isNull();
assertThat(parameter2.defaultValue()).isNull();
assertThat(parameter2.children()).doesNotContainNull();
functionDef = parse("def func(p1, *p2, **p3): pass", treeMaker::funcDefStatement);
parameters = functionDef.parameters().nonTuple();
assertThat(parameters).extracting(p -> p.name().name()).containsExactly("p1", "p2", "p3");
assertThat(parameters).extracting(p -> p.starToken() == null ? null : p.starToken().value()).containsExactly(null, "*", "**");
Parameter parameter = parameters.get(2);
assertThat(parameter.children()).containsExactly(parameter.starToken(), parameter.name());
assertThat(parameter.firstToken()).isSameAs(parameter.starToken());
assertThat(parameter.lastToken()).isSameAs(parameter.name().lastToken());
functionDef = parse("def func(x : int, y): pass", treeMaker::funcDefStatement);
parameters = functionDef.parameters().nonTuple();
assertThat(parameters).hasSize(2);
TypeAnnotation annotation = parameters.get(0).typeAnnotation();
assertThat(annotation.getKind()).isEqualTo(Tree.Kind.PARAMETER_TYPE_ANNOTATION);
assertThat(((Name) annotation.expression()).name()).isEqualTo("int");
assertThat(annotation.children()).hasSize(2);
assertThat(parameters.get(1).typeAnnotation()).isNull();
functionDef = parse("def func(a, ((b, c), d)): pass", treeMaker::funcDefStatement);
assertThat(functionDef.parameters().all()).hasSize(2);
assertThat(functionDef.parameters().all()).extracting(Tree::getKind).containsExactly(Tree.Kind.PARAMETER, Tree.Kind.TUPLE_PARAMETER);
TupleParameter tupleParam = (TupleParameter) functionDef.parameters().all().get(1);
assertThat(tupleParam.openingParenthesis().value()).isEqualTo("(");
assertThat(tupleParam.closingParenthesis().value()).isEqualTo(")");
assertThat(tupleParam.parameters()).extracting(Tree::getKind).containsExactly(Tree.Kind.TUPLE_PARAMETER, Tree.Kind.PARAMETER);
assertThat(tupleParam.commas()).extracting(Token::value).containsExactly(",");
assertThat(tupleParam.children()).hasSize(5);
functionDef = parse("def func(x : int, y):\n \"\"\"\n" + "This is a function docstring\n" + "\"\"\"\n pass", treeMaker::funcDefStatement);
assertThat(functionDef.docstring().stringElements().get(0).value()).isEqualTo("\"\"\"\n" + "This is a function docstring\n" + "\"\"\"");
assertThat(functionDef.children()).hasSize(10);
functionDef = parse("def __call__(self, *, manager):\n pass", treeMaker::funcDefStatement);
assertThat(functionDef.parameters().all()).hasSize(3);
functionDef = parse("def __call__(*):\n pass", treeMaker::funcDefStatement);
assertThat(functionDef.parameters().all()).extracting(Tree::getKind).containsExactly(Kind.PARAMETER);
functionDef = parse("def f(a, /): pass", treeMaker::funcDefStatement);
assertThat(functionDef.parameters().all()).extracting(Tree::getKind).containsExactly(Kind.PARAMETER, Kind.PARAMETER);
assertThat(((Parameter) functionDef.parameters().all().get(1)).starToken().value()).isEqualTo("/");
assertThat(funcDef("def func(): ...").parameters()).isNull();
assertThat(funcDef("def func(a): ...").parameters().all()).hasSize(1);
assertThat(funcDef("def func(a, b): ...").parameters().all()).hasSize(2);
assertThat(funcDef("def func(a, *args): ...").parameters().all()).hasSize(2);
assertThat(funcDef("def func(a, **kwargs): ...").parameters().all()).hasSize(2);
assertThat(funcDef("def func(a, *args, **kwargs): ...").parameters().all()).hasSize(3);
assertThat(funcDef("def func(*args): ...").parameters().all()).hasSize(1);
assertThat(funcDef("def func(**kwargs): ...").parameters().all()).hasSize(1);
assertThat(funcDef("def func(*args, **kwargs): ...").parameters().all()).hasSize(2);
assertThat(funcDef("def func(*args, a, **kwargs): ...").parameters().all()).hasSize(3);
assertThat(funcDef("def func(*): ...").parameters().all()).hasSize(1);
assertThat(funcDef("def func(*, a): ...").parameters().all()).hasSize(2);
assertThat(funcDef("def func(a, b, *, c): ...").parameters().all()).hasSize(4);
assertThat(funcDef("def func(a, b, /): ...").parameters().all()).hasSize(3);
assertThat(funcDef("def func(a, b, /, c): ...").parameters().all()).hasSize(4);
assertThat(funcDef("def func(a, b, /, c, *args): ...").parameters().all()).hasSize(5);
assertThat(funcDef("def func(a, b, /, c, **kwargs): ...").parameters().all()).hasSize(5);
assertThat(funcDef("def func(a, b, /, *args): ...").parameters().all()).hasSize(4);
assertThat(funcDef("def func(a, b, /, **kwargs): ...").parameters().all()).hasSize(4);
}
use of org.sonar.plugins.python.api.tree.Decorator in project sonar-python by SonarSource.
the class PythonTreeMakerTest method decorators.
@Test
public void decorators() {
FunctionDef functionDef = funcDef("@foo()\n@bar(1)\ndef func(x): pass");
List<Decorator> decorators = functionDef.decorators();
assertThat(decorators).hasSize(2);
Decorator decorator = decorators.get(0);
assertThat(decorator.name().names().get(0).name()).isEqualTo("foo");
assertThat(TreeUtils.decoratorNameFromExpression(decorator.expression())).isEqualTo("foo");
assertThat(decorator.expression().is(Kind.CALL_EXPR)).isTrue();
functionDef = funcDef("@foo.bar(1)\ndef func(x): pass");
decorators = functionDef.decorators();
assertThat(decorators).hasSize(1);
decorator = decorators.get(0);
assertThat(decorator.name().names().get(0).name()).isEqualTo("foo");
assertThat(decorator.name().names().get(1).name()).isEqualTo("bar");
assertThat(TreeUtils.decoratorNameFromExpression(decorator.expression())).isEqualTo("foo.bar");
assertThat(decorator.expression().is(Kind.CALL_EXPR)).isTrue();
functionDef = funcDef("@buttons[\"hello\"].clicked.connect\ndef func(x): pass");
decorators = functionDef.decorators();
assertThat(decorators).hasSize(1);
decorator = decorators.get(0);
assertThat(decorator.name().names()).isEmpty();
assertThat(TreeUtils.decoratorNameFromExpression(decorator.expression())).isNull();
assertThat(decorator.expression().is(Kind.QUALIFIED_EXPR)).isTrue();
functionDef = funcDef("@hello() or bye()\ndef func(x): pass");
decorators = functionDef.decorators();
assertThat(decorators).hasSize(1);
decorator = decorators.get(0);
assertThat(decorator.expression().getKind()).isEqualTo(Kind.OR);
BinaryExpression binaryExpression = (BinaryExpression) decorator.expression();
assertThat(binaryExpression.leftOperand().getKind()).isEqualTo(Kind.CALL_EXPR);
assertThat(binaryExpression.rightOperand().getKind()).isEqualTo(Kind.CALL_EXPR);
functionDef = funcDef("@b:=some_decorator\ndef func(x): pass");
decorators = functionDef.decorators();
assertThat(decorators).hasSize(1);
decorator = decorators.get(0);
assertThat(decorator.expression().getKind()).isEqualTo(Kind.ASSIGNMENT_EXPRESSION);
}
use of org.sonar.plugins.python.api.tree.Decorator in project sonar-python by SonarSource.
the class PythonTreeMakerTest method classdef_statement.
@Test
public void classdef_statement() {
setRootRule(PythonGrammar.CLASSDEF);
AstNode astNode = p.parse("class clazz(Parent): pass");
ClassDef classDef = treeMaker.classDefStatement(astNode);
assertThat(classDef.name()).isNotNull();
assertThat(classDef.docstring()).isNull();
assertThat(classDef.classKeyword().value()).isEqualTo("class");
assertThat(classDef.leftPar().value()).isEqualTo("(");
assertThat(classDef.rightPar().value()).isEqualTo(")");
assertThat(classDef.colon().value()).isEqualTo(":");
assertThat(classDef.name().name()).isEqualTo("clazz");
assertThat(classDef.body().statements()).hasSize(1);
assertThat(classDef.body().statements().get(0).is(Tree.Kind.PASS_STMT)).isTrue();
assertThat(classDef.args().is(Tree.Kind.ARG_LIST)).isTrue();
assertThat(classDef.args().children()).hasSize(1);
assertThat(classDef.args().arguments().get(0).is(Tree.Kind.REGULAR_ARGUMENT)).isTrue();
assertThat(classDef.decorators()).isEmpty();
classDef = parse("class clazz: pass", treeMaker::classDefStatement);
assertThat(classDef.leftPar()).isNull();
assertThat(classDef.rightPar()).isNull();
assertThat(classDef.args()).isNull();
classDef = parse("class clazz(): pass", treeMaker::classDefStatement);
assertThat(classDef.leftPar().value()).isEqualTo("(");
assertThat(classDef.rightPar().value()).isEqualTo(")");
assertThat(classDef.args()).isNull();
astNode = p.parse("@foo.bar\nclass clazz: pass");
classDef = treeMaker.classDefStatement(astNode);
assertThat(classDef.decorators()).hasSize(1);
Decorator decorator = classDef.decorators().get(0);
assertThat(decorator.name().names()).extracting(Name::name).containsExactly("foo", "bar");
astNode = p.parse("class clazz:\n def foo(): pass");
classDef = treeMaker.classDefStatement(astNode);
FunctionDef funcDef = (FunctionDef) classDef.body().statements().get(0);
assertThat(funcDef.isMethodDefinition()).isTrue();
astNode = p.parse("class clazz:\n if True:\n def foo(): pass");
classDef = treeMaker.classDefStatement(astNode);
funcDef = (FunctionDef) ((IfStatement) classDef.body().statements().get(0)).body().statements().get(0);
assertThat(funcDef.isMethodDefinition()).isTrue();
astNode = p.parse("class ClassWithDocstring:\n" + "\t\"\"\"This is a docstring\"\"\"\n" + "\tpass");
classDef = treeMaker.classDefStatement(astNode);
assertThat(classDef.docstring().stringElements()).hasSize(1);
assertThat(classDef.docstring().stringElements().get(0).value()).isEqualTo("\"\"\"This is a docstring\"\"\"");
assertThat(classDef.children()).hasSize(7);
}
Aggregations