diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj index 12fd3f4a92..6085bbc5cf 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj @@ -109,6 +109,7 @@ + diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs index 9ff937dc2b..e9024e3266 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs @@ -223,7 +223,6 @@ namespace ICSharpCode.PythonBinding return convertedParameters.ToArray(); } - /// /// Adds the namespace to the class name taken from the class definition. /// @@ -242,5 +241,22 @@ namespace ICSharpCode.PythonBinding compilationUnit.Classes.Add(globalClass); } } + + public override bool Walk(AssignmentStatement node) + { + if (currentClass != null) { + WalkPropertyAssignment(node); + return false; + } + return base.Walk(node); + } + + void WalkPropertyAssignment(AssignmentStatement node) + { + PythonPropertyAssignment propertyAssignment = new PythonPropertyAssignment(node); + if (propertyAssignment.IsProperty()) { + propertyAssignment.AddPropertyToClass(currentClass); + } + } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonPropertyAssignment.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonPropertyAssignment.cs new file mode 100644 index 0000000000..2dba9e1534 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonPropertyAssignment.cs @@ -0,0 +1,54 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.SharpDevelop.Dom; +using IronPython.Compiler.Ast; + +namespace ICSharpCode.PythonBinding +{ + public class PythonPropertyAssignment + { + AssignmentStatement assignmentStatement; + + public PythonPropertyAssignment(AssignmentStatement assignmentStatement) + { + this.assignmentStatement = assignmentStatement; + } + + public bool IsProperty() + { + CallExpression rhs = assignmentStatement.Right as CallExpression; + if (rhs != null) { + NameExpression nameExpression = rhs.Target as NameExpression; + if (nameExpression != null) { + return nameExpression.Name == "property"; + } + } + return false; + } + + public void AddPropertyToClass(IClass c) + { + NameExpression nameExpression = assignmentStatement.Left[0] as NameExpression; + if (nameExpression != null) { + string propertyName = nameExpression.Name; + AddPropertyToClass(c, propertyName); + } + } + + void AddPropertyToClass(IClass c, string propertyName) + { + DefaultProperty property = new DefaultProperty(c, propertyName); + property.Region = GetPropertyRegion(); + c.Properties.Add(property); + } + + DomRegion GetPropertyRegion() + { + int line = assignmentStatement.Start.Line; + int column = assignmentStatement.Start.Column; + return new DomRegion(line, column, line, column); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/PythonParserParsePropertyTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/PythonParserParsePropertyTests.cs new file mode 100644 index 0000000000..7586707476 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/PythonParserParsePropertyTests.cs @@ -0,0 +1,63 @@ +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Parsing +{ + [TestFixture] + public class PythonParserParsePropertyTests + { + IProperty property; + + void ParseClassWithProperty() + { + string code = + "class MyClass:\r\n" + + " def __init__(self):\r\n" + + " self._count = 0\r\n" + + "\r\n" + + " def get_Count(self):\r\n" + + " return self._count\r\n" + + "\r\n" + + " def _set_Count(self, value):\r\n" + + " self._count = value\r\n" + + "\r\n" + + " Count = property(fget=get_Count, fset=set_Count)\r\n"; + + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + property = parseInfo.CompilationUnit.Classes[0].Properties[0]; + } + + [Test] + public void Parse_ClassHasPropertyCalledCount_ReturnParseInfoWithClassWithPropertyCalledCount() + { + ParseClassWithProperty(); + string name = property.Name; + + string expectedName = "Count"; + + Assert.AreEqual(expectedName, name); + } + + /// + /// Dom regions are one based. + /// + [Test] + public void Parse_ClassHasPropertyCalledCount_PropertyRegion() + { + ParseClassWithProperty(); + DomRegion region = property.Region; + + DomRegion expectedRegion = new DomRegion( + beginLine: 11, + beginColumn: 5, + endLine: 11, + endColumn: 5 + ); + + Assert.AreEqual(expectedRegion, region); + } + } +} \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj index afe6b830dd..e7e27dad6b 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj @@ -341,6 +341,7 @@ +