Browse Source

Refactor PythonAstWalker.

pull/2/head
mrward 15 years ago
parent
commit
4efdaf8edd
  1. 9
      src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj
  2. 203
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs
  3. 91
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonClass.cs
  4. 18
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCompilationUnit.cs
  5. 17
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConstructor.cs
  6. 98
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethod.cs
  7. 33
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethodDefinition.cs
  8. 39
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethodOrClassBodyRegion.cs
  9. 17
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModule.cs
  10. 26
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonProperty.cs
  11. 38
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonPropertyAssignment.cs
  12. 18
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonUsingScope.cs
  13. 56
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/PythonParserParsePropertyTests.cs

9
src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj

@ -93,22 +93,30 @@ @@ -93,22 +93,30 @@
<Compile Include="Src\IPythonResolver.cs" />
<Compile Include="Src\MemberName.cs" />
<Compile Include="Src\PythonBuiltInModuleMemberName.cs" />
<Compile Include="Src\PythonClass.cs" />
<Compile Include="Src\PythonClassResolver.cs" />
<Compile Include="Src\PythonCodeCompletionItemProvider.cs" />
<Compile Include="Src\PythonCompilationUnit.cs" />
<Compile Include="Src\PythonCompletionItemList.cs" />
<Compile Include="Src\PythonConsoleApplication.cs" />
<Compile Include="Src\PythonConstructor.cs" />
<Compile Include="Src\PythonDotNetMethodResolver.cs" />
<Compile Include="Src\PythonFromImport.cs" />
<Compile Include="Src\PythonImport.cs" />
<Compile Include="Src\PythonLanguageBinding.cs" />
<Compile Include="Src\PythonLocalVariableResolver.cs" />
<Compile Include="Src\PythonMemberResolver.cs" />
<Compile Include="Src\PythonMethod.cs" />
<Compile Include="Src\PythonMethodDefinition.cs" />
<Compile Include="Src\PythonMethodGroupResolveResult.cs" />
<Compile Include="Src\PythonMethodOrClassBodyRegion.cs" />
<Compile Include="Src\PythonMethodResolver.cs" />
<Compile Include="Src\PythonModule.cs" />
<Compile Include="Src\PythonModuleCompletionItems.cs" />
<Compile Include="Src\PythonModuleCompletionItemsFactory.cs" />
<Compile Include="Src\PythonImportResolver.cs" />
<Compile Include="Src\PythonNamespaceResolver.cs" />
<Compile Include="Src\PythonProperty.cs" />
<Compile Include="Src\PythonPropertyAssignment.cs" />
<Compile Include="Src\PythonResolverContext.cs" />
<Compile Include="Src\PythonSelfResolver.cs" />
@ -125,6 +133,7 @@ @@ -125,6 +133,7 @@
<Compile Include="Src\PythonTestRunnerApplication.cs" />
<Compile Include="Src\PythonTestRunnerContext.cs" />
<Compile Include="Src\PythonTestRunnerResponseFile.cs" />
<Compile Include="Src\PythonUsingScope.cs" />
<Compile Include="Src\PythonWorkbench.cs" />
<Compile Include="Src\SendLineToPythonConsoleCommand.cs" />
<Compile Include="Src\SendSelectedTextToPythonConsoleCommand.cs" />

203
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs

@ -18,32 +18,16 @@ namespace ICSharpCode.PythonBinding @@ -18,32 +18,16 @@ namespace ICSharpCode.PythonBinding
/// </summary>
public class PythonAstWalker : PythonWalker
{
DefaultCompilationUnit compilationUnit;
PythonCompilationUnit compilationUnit;
IClass currentClass;
IClass globalClass;
PythonModule module;
/// <summary>
/// All classes in a file take the namespace of the filename.
/// </summary>
public PythonAstWalker(IProjectContent projectContent, string fileName)
{
CreateCompilationUnit(projectContent, fileName);
}
void CreateCompilationUnit(IProjectContent projectContent, string fileName)
{
compilationUnit = new DefaultCompilationUnit(projectContent);
compilationUnit.FileName = fileName;
CreateUsingScopeForCompilationUnit(fileName);
}
void CreateUsingScopeForCompilationUnit(string fileName)
{
DefaultUsingScope usingScope = new DefaultUsingScope();
usingScope.NamespaceName = Path.GetFileNameWithoutExtension(fileName);
usingScope.Parent = new DefaultUsingScope();
compilationUnit.UsingScope = usingScope;
compilationUnit = new PythonCompilationUnit(projectContent, fileName);
}
/// <summary>
@ -62,184 +46,73 @@ namespace ICSharpCode.PythonBinding @@ -62,184 +46,73 @@ namespace ICSharpCode.PythonBinding
statement.Walk(this);
}
/// <summary>
/// Walks a class definition.
/// </summary>
public override bool Walk(ClassDefinition node)
public override bool Walk(ClassDefinition classDefinition)
{
DefaultClass c = new DefaultClass(compilationUnit, GetFullyQualifiedClassName(node));
c.Region = GetRegion(node);
c.BodyRegion = GetBodyRegion(node.Body, node.Header);
AddBaseTypes(c, node.Bases);
// Save the class.
compilationUnit.Classes.Add(c);
PythonClass c = new PythonClass(compilationUnit, classDefinition);
WalkClassBody(c, classDefinition.Body);
return false;
}
// Walk through all the class items.
void WalkClassBody(IClass c, Statement classBody)
{
currentClass = c;
node.Body.Walk(this);
classBody.Walk(this);
currentClass = null;
return false;
}
/// <summary>
/// Walks a function definition.
/// </summary>
public override bool Walk(FunctionDefinition node)
{
if (node.Body == null) {
return false;
}
bool ignoreFirstMethodParameter = true;
IClass c = currentClass;
if (currentClass == null) {
// Walking a global method.
CreateGlobalClass();
c = globalClass;
ignoreFirstMethodParameter = false;
}
IClass c = GetClassBeingWalked();
// Create method.
string methodName = node.Name;
DomRegion bodyRegion = GetBodyRegion(node.Body, node.Header);
DomRegion region = GetMethodRegion(node);
DefaultMethod method;
if (methodName == "__init__") {
method = new Constructor(ModifierEnum.Public, region, bodyRegion, c);
} else {
method = new DefaultMethod(methodName, new DefaultReturnType(c), ModifierEnum.Public, region, bodyRegion, c);
}
foreach (IParameter parameter in ConvertParameters(node.Parameters, ignoreFirstMethodParameter)) {
method.Parameters.Add(parameter);
}
c.Methods.Add(method);
return false;
}
/// <summary>
/// Walks an import statement and adds it to the compilation unit's
/// Usings.
/// </summary>
public override bool Walk(ImportStatement node)
{
PythonImport import = new PythonImport(compilationUnit.ProjectContent, node);
compilationUnit.UsingScope.Usings.Add(import);
return false;
}
public override bool Walk(FromImportStatement node)
{
PythonFromImport import = new PythonFromImport(compilationUnit.ProjectContent, node);
compilationUnit.UsingScope.Usings.Add(import);
PythonMethodDefinition methodDefinition = new PythonMethodDefinition(node);
methodDefinition.CreateMethod(c);
return false;
}
/// <summary>
/// Gets the body region for a class or a method.
/// </summary>
/// <remarks>
/// Note that SharpDevelop line numbers are zero based but the
/// DomRegion values are one based. IronPython columns and lines are one based.
/// </remarks>
/// <param name="body">The body statement.</param>
/// <param name="header">The location of the header. This gives the end location for the
/// method or class definition up to the colon.</param>
DomRegion GetBodyRegion(Statement body, SourceLocation header)
{
int columnAfterColonCharacter = header.Column + 1;
return new DomRegion(header.Line, header.Column + 1, body.End.Line, body.End.Column);
}
/// <summary>
/// Gets the region of the scope statement (typically a ClassDefinition).
/// </summary>
/// <remarks>
/// A class region includes the body.
/// </remarks>
DomRegion GetRegion(ScopeStatement statement)
{
return new DomRegion(statement.Start.Line, statement.Start.Column, statement.End.Line, statement.End.Column);
}
/// <summary>
/// Gets the region of a method. This does not include the body.
/// </summary>
DomRegion GetMethodRegion(FunctionDefinition node)
{
return new DomRegion(node.Start.Line, node.Start.Column, node.Header.Line, node.Header.Column + 1);
}
/// <summary>
/// Looks for any base types for the class defined in the
/// list of expressions and adds them to the class.
/// </summary>
void AddBaseTypes(IClass c, IList<Expression> baseTypes)
{
foreach (Expression expression in baseTypes) {
NameExpression nameExpression = expression as NameExpression;
MemberExpression memberExpression = expression as MemberExpression;
if (nameExpression != null) {
AddBaseType(c, nameExpression.Name);
} else if (memberExpression != null) {
AddBaseType(c, PythonControlFieldExpression.GetMemberName(memberExpression));
}
}
}
/// <summary>
/// Adds the named base type to the class.
/// If the current class is null then create a module so a method outside of a class can be
/// parsed.
/// </summary>
void AddBaseType(IClass c, string name)
IClass GetClassBeingWalked()
{
c.BaseTypes.Add(CreateSearchClassReturnType(c, name));
if (currentClass == null) {
// Walking a method outside a class.
CreateModule();
return module;
}
SearchClassReturnType CreateSearchClassReturnType(IClass c, string name)
{
return new SearchClassReturnType(c.ProjectContent, c, 0, 0, name, 0);
return currentClass;
}
/// <summary>
/// Converts from Python AST expressions to parameters.
/// Creates the module which will act as a class so it can hold any methods defined in the module.
/// </summary>
/// <remarks>If the parameters belong to a class method then the first
/// "self" parameter can be ignored.</remarks>
IParameter[] ConvertParameters(IList<Parameter> parameters, bool ignoreFirstParameter)
void CreateModule()
{
List<IParameter> convertedParameters = new List<IParameter>();
int startingIndex = 0;
if (ignoreFirstParameter) {
startingIndex = 1;
}
for (int i = startingIndex; i < parameters.Count; ++i) {
DefaultParameter parameter = new DefaultParameter(parameters[i].Name, null, new DomRegion());
convertedParameters.Add(parameter);
if (module == null) {
module = new PythonModule(compilationUnit);
}
return convertedParameters.ToArray();
}
/// <summary>
/// Adds the namespace to the class name taken from the class definition.
/// Walks an import statement and adds it to the compilation unit's
/// Usings.
/// </summary>
string GetFullyQualifiedClassName(ClassDefinition classDef)
public override bool Walk(ImportStatement node)
{
return String.Concat(compilationUnit.UsingScope.NamespaceName, ".", classDef.Name);
PythonImport import = new PythonImport(compilationUnit.ProjectContent, node);
compilationUnit.UsingScope.Usings.Add(import);
return false;
}
/// <summary>
/// Creates the dummy class that is used to hold global methods.
/// </summary>
void CreateGlobalClass()
public override bool Walk(FromImportStatement node)
{
if (globalClass == null) {
globalClass = new DefaultClass(compilationUnit, compilationUnit.UsingScope.NamespaceName);
compilationUnit.Classes.Add(globalClass);
}
PythonFromImport import = new PythonFromImport(compilationUnit.ProjectContent, node);
compilationUnit.UsingScope.Usings.Add(import);
return false;
}
public override bool Walk(AssignmentStatement node)
@ -254,9 +127,7 @@ namespace ICSharpCode.PythonBinding @@ -254,9 +127,7 @@ namespace ICSharpCode.PythonBinding
void WalkPropertyAssignment(AssignmentStatement node)
{
PythonPropertyAssignment propertyAssignment = new PythonPropertyAssignment(node);
if (propertyAssignment.IsProperty()) {
propertyAssignment.AddPropertyToClass(currentClass);
}
propertyAssignment.CreateProperty(currentClass);
}
}
}

91
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonClass.cs

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
// 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 System.Collections.Generic;
using ICSharpCode.SharpDevelop.Dom;
using IronPython.Compiler.Ast;
namespace ICSharpCode.PythonBinding
{
public class PythonClass : DefaultClass
{
public PythonClass(ICompilationUnit compilationUnit, ClassDefinition classDefinition)
: base(compilationUnit, String.Empty)
{
GetFullyQualifiedName(classDefinition);
GetClassRegions(classDefinition);
AddBaseTypes(classDefinition.Bases);
compilationUnit.Classes.Add(this);
}
/// <summary>
/// Adds the namespace to the class name taken from the class definition.
/// </summary>
void GetFullyQualifiedName(ClassDefinition classDefinition)
{
string ns = CompilationUnit.UsingScope.NamespaceName;
FullyQualifiedName = String.Format("{0}.{1}", ns, classDefinition.Name);
}
void GetClassRegions(ClassDefinition classDefinition)
{
GetRegion(classDefinition);
BodyRegion = PythonMethodOrClassBodyRegion.GetBodyRegion(classDefinition);
}
/// <summary>
/// Gets the region of the scope statement (ClassDefinition).
/// </summary>
/// <remarks>
/// A class region includes the body.
/// </remarks>
void GetRegion(ScopeStatement statement)
{
Region = new DomRegion(statement.Start.Line, statement.Start.Column, statement.End.Line, statement.End.Column);
}
/// <summary>
/// Looks for any base types for the class defined in the
/// list of expressions and adds them to the class.
/// </summary>
void AddBaseTypes(IList<Expression> baseTypes)
{
foreach (Expression baseTypeExpression in baseTypes) {
AddBaseType(baseTypeExpression);
}
}
void AddBaseType(Expression baseTypeExpression)
{
NameExpression nameExpression = baseTypeExpression as NameExpression;
MemberExpression memberExpression = baseTypeExpression as MemberExpression;
if (nameExpression != null) {
AddBaseType(nameExpression.Name);
} else if (memberExpression != null) {
AddBaseType(memberExpression);
}
}
/// <summary>
/// Adds the named base type to the class.
/// </summary>
void AddBaseType(string name)
{
IReturnType returnType = CreateSearchClassReturnType(name);
BaseTypes.Add(returnType);
}
void AddBaseType(MemberExpression memberExpression)
{
string name = PythonControlFieldExpression.GetMemberName(memberExpression);
AddBaseType(name);
}
SearchClassReturnType CreateSearchClassReturnType(string name)
{
return new SearchClassReturnType(ProjectContent, this, 0, 0, name, 0);
}
}
}

18
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCompilationUnit.cs

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
// 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;
namespace ICSharpCode.PythonBinding
{
public class PythonCompilationUnit : DefaultCompilationUnit
{
public PythonCompilationUnit(IProjectContent projectContent, string fileName)
: base(projectContent)
{
this.FileName = fileName;
this.UsingScope = new PythonUsingScope(fileName);
}
}
}

17
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConstructor.cs

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
// 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 PythonConstructor : PythonMethod
{
public PythonConstructor(IClass declaringType, FunctionDefinition methodDefinition)
: base(declaringType, methodDefinition, "#ctor")
{
}
}
}

98
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethod.cs

@ -0,0 +1,98 @@ @@ -0,0 +1,98 @@
// 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 System.Collections.Generic;
using ICSharpCode.SharpDevelop.Dom;
using IronPython.Compiler.Ast;
using Microsoft.Scripting;
namespace ICSharpCode.PythonBinding
{
public class PythonMethod : DefaultMethod
{
public PythonMethod(IClass declaringType, FunctionDefinition methodDefinition)
: this(declaringType, methodDefinition, methodDefinition.Name)
{
}
public PythonMethod(IClass declaringType, FunctionDefinition methodDefinition, string name)
: base(declaringType, name)
{
ReturnType = new DefaultReturnType(declaringType);
Modifiers = ModifierEnum.Public;
GetMethodRegions(methodDefinition);
AddParameters(methodDefinition);
declaringType.Methods.Add(this);
}
void GetMethodRegions(FunctionDefinition methodDefinition)
{
GetBodyRegion(methodDefinition);
GetMethodRegion(methodDefinition);
}
void GetBodyRegion(FunctionDefinition methodDefinition)
{
BodyRegion = PythonMethodOrClassBodyRegion.GetBodyRegion(methodDefinition);
}
/// <summary>
/// Gets the region of a method. This does not include the body.
/// </summary>
void GetMethodRegion(FunctionDefinition methodDefinition)
{
SourceLocation start = methodDefinition.Start;
SourceLocation end = methodDefinition.Header;
Region = new DomRegion(start.Line, start.Column, end.Line, end.Column + 1);
}
void AddParameters(FunctionDefinition methodDefinition)
{
bool ignoreFirstMethodParameter = !DeclaringTypeIsPythonModule;
AddParameters(methodDefinition, ignoreFirstMethodParameter);
}
bool DeclaringTypeIsPythonModule {
get { return DeclaringType is PythonModule; }
}
void AddParameters(FunctionDefinition methodDefinition, bool ignoreFirstMethodParameter)
{
foreach (IParameter parameter in ConvertParameters(methodDefinition.Parameters, ignoreFirstMethodParameter)) {
Parameters.Add(parameter);
}
}
/// <summary>
/// Converts from Python AST expressions to parameters.
/// </summary>
/// <remarks>If the parameters belong to a class method then the first
/// "self" parameter can be ignored.</remarks>
IParameter[] ConvertParameters(IList<Parameter> parameters, bool ignoreFirstParameter)
{
int startingIndex = GetStartingIndex(ignoreFirstParameter);
return ConvertParameters(parameters, startingIndex);
}
int GetStartingIndex(bool ignoreFirstParameter)
{
if (ignoreFirstParameter) {
return 1;
}
return 0;
}
IParameter[] ConvertParameters(IList<Parameter> parameters, int startingIndex)
{
List<IParameter> convertedParameters = new List<IParameter>();
for (int i = startingIndex; i < parameters.Count; ++i) {
DefaultParameter parameter = new DefaultParameter(parameters[i].Name, null, new DomRegion());
convertedParameters.Add(parameter);
}
return convertedParameters.ToArray();
}
}
}

33
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethodDefinition.cs

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
// 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 System.Collections.Generic;
using ICSharpCode.SharpDevelop.Dom;
using IronPython.Compiler.Ast;
using Microsoft.Scripting;
namespace ICSharpCode.PythonBinding
{
public class PythonMethodDefinition
{
FunctionDefinition methodDefinition;
public PythonMethodDefinition(FunctionDefinition methodDefinition)
{
this.methodDefinition = methodDefinition;
}
public PythonMethod CreateMethod(IClass c)
{
if (IsConstructor) {
return new PythonConstructor(c, methodDefinition);
}
return new PythonMethod(c, methodDefinition);
}
bool IsConstructor {
get { return methodDefinition.Name == "__init__"; }
}
}
}

39
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethodOrClassBodyRegion.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
// 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;
using Microsoft.Scripting;
namespace ICSharpCode.PythonBinding
{
public static class PythonMethodOrClassBodyRegion
{
/// <summary>
/// Gets the body region for a class or a method.
/// </summary>
/// <remarks>
/// Note that SharpDevelop line numbers are zero based but the
/// DomRegion values are one based. IronPython columns and lines are one based.
/// </remarks>
/// <param name="body">The body statement.</param>
/// <param name="header">The location of the header. This gives the end location for the
/// method or class definition up to the colon.</param>
public static DomRegion GetBodyRegion(Statement body, SourceLocation header)
{
int columnAfterColonCharacter = header.Column + 1;
return new DomRegion(header.Line, header.Column + 1, body.End.Line, body.End.Column);
}
public static DomRegion GetBodyRegion(FunctionDefinition methodDefinition)
{
return GetBodyRegion(methodDefinition.Body, methodDefinition.Header);
}
public static DomRegion GetBodyRegion(ClassDefinition classDefinition)
{
return GetBodyRegion(classDefinition.Body, classDefinition.Header);
}
}
}

17
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModule.cs

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
// 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;
namespace ICSharpCode.PythonBinding
{
public class PythonModule : DefaultClass
{
public PythonModule(ICompilationUnit compilationUnit)
: base(compilationUnit, compilationUnit.UsingScope.NamespaceName)
{
compilationUnit.Classes.Add(this);
}
}
}

26
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonProperty.cs

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
// 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 Microsoft.Scripting;
namespace ICSharpCode.PythonBinding
{
public class PythonProperty : DefaultProperty
{
public PythonProperty(IClass declaringType, string name, SourceLocation location)
: base(declaringType, name)
{
GetPropertyRegion(location);
declaringType.Properties.Add(this);
}
void GetPropertyRegion(SourceLocation location)
{
int line = location.Line;
int column = location.Column;
Region = new DomRegion(line, column, line, column);
}
}
}

38
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonPropertyAssignment.cs

@ -16,39 +16,39 @@ namespace ICSharpCode.PythonBinding @@ -16,39 +16,39 @@ namespace ICSharpCode.PythonBinding
this.assignmentStatement = assignmentStatement;
}
public bool IsProperty()
public PythonProperty CreateProperty(IClass c)
{
CallExpression rhs = assignmentStatement.Right as CallExpression;
if (rhs != null) {
NameExpression nameExpression = rhs.Target as NameExpression;
if (IsProperty()) {
NameExpression nameExpression = assignmentStatement.Left[0] as NameExpression;
if (nameExpression != null) {
return nameExpression.Name == "property";
string propertyName = nameExpression.Name;
return CreateProperty(c, propertyName);
}
}
return false;
return null;
}
public void AddPropertyToClass(IClass c)
bool IsProperty()
{
NameExpression nameExpression = assignmentStatement.Left[0] as NameExpression;
if (nameExpression != null) {
string propertyName = nameExpression.Name;
AddPropertyToClass(c, propertyName);
CallExpression callExpression = assignmentStatement.Right as CallExpression;
if (callExpression != null) {
return IsPropertyFunctionBeingCalled(callExpression);
}
return false;
}
void AddPropertyToClass(IClass c, string propertyName)
bool IsPropertyFunctionBeingCalled(CallExpression callExpression)
{
DefaultProperty property = new DefaultProperty(c, propertyName);
property.Region = GetPropertyRegion();
c.Properties.Add(property);
NameExpression nameExpression = callExpression.Target as NameExpression;
if (nameExpression != null) {
return nameExpression.Name == "property";
}
return false;
}
DomRegion GetPropertyRegion()
PythonProperty CreateProperty(IClass c, string propertyName)
{
int line = assignmentStatement.Start.Line;
int column = assignmentStatement.Start.Column;
return new DomRegion(line, column, line, column);
return new PythonProperty(c, propertyName, assignmentStatement.Start);
}
}
}

18
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonUsingScope.cs

@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
// 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 System.IO;
using ICSharpCode.SharpDevelop.Dom;
namespace ICSharpCode.PythonBinding
{
public class PythonUsingScope : DefaultUsingScope
{
public PythonUsingScope(string fileName)
{
NamespaceName = Path.GetFileNameWithoutExtension(fileName);
Parent = new DefaultUsingScope();
}
}
}

56
src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/PythonParserParsePropertyTests.cs

@ -59,5 +59,61 @@ namespace PythonBinding.Tests.Parsing @@ -59,5 +59,61 @@ namespace PythonBinding.Tests.Parsing
Assert.AreEqual(expectedRegion, region);
}
[Test]
public void Parse_ClassMethodHasNoPropertyButHasAssignmentStatementSetToValueFromFunctionCall_ParseInfoHasNoPropertyAdded()
{
string code =
"class MyClass:\r\n" +
" a = foo()\r\n" +
"\r\n";
ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code);
int count = parseInfo.CompilationUnit.Classes[0].Properties.Count;
Assert.AreEqual(0, count);
}
[Test]
public void Parse_ClassMethodHasNoPropertyButHasAssignmentStatementUsingMemberExpression_ParseInfoHasNoPropertyAddedAndNoExceptionThrown()
{
string code =
"class MyClass:\r\n" +
" a.b = foo()\r\n" +
"\r\n";
ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code);
int count = parseInfo.CompilationUnit.Classes[0].Properties.Count;
Assert.AreEqual(0, count);
}
[Test]
public void Parse_ClassMethodHasNoPropertyButHasAssignmentStatementSetToIntegerValue_ParseInfoHasNoPropertyAddedAndNoExceptionThrown()
{
string code =
"class MyClass:\r\n" +
" a = 1\r\n" +
"\r\n";
ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code);
int count = parseInfo.CompilationUnit.Classes[0].Properties.Count;
Assert.AreEqual(0, count);
}
[Test]
public void Parse_ClassMethodHasNoPropertyButHasAssignmentStatementSetToValueFromMemberExpressionCall_ParseInfoHasNoPropertyAddedAndNoExceptionThrown()
{
string code =
"class MyClass:\r\n" +
" a = foo.bar()\r\n" +
"\r\n";
ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code);
int count = parseInfo.CompilationUnit.Classes[0].Properties.Count;
Assert.AreEqual(0, count);
}
}
}
Loading…
Cancel
Save