From b24a863e68099fdf6e64f0544a566a57c7c41851 Mon Sep 17 00:00:00 2001 From: mrward Date: Mon, 4 Oct 2010 19:40:59 +0100 Subject: [PATCH] Add support for resolving properties, events and fields on local variables in IronPython. --- .../Project/PythonBinding.csproj | 1 + .../Project/Src/PythonClassMembers.cs | 38 ++++++++++ .../Project/Src/PythonCompletionItemList.cs | 2 - .../Project/Src/PythonMemberResolver.cs | 71 +++++++++++-------- .../Project/Src/PythonResolver.cs | 2 +- .../Resolver/ResolveClassPropertyTests.cs | 14 ++++ 6 files changed, 94 insertions(+), 34 deletions(-) create mode 100644 src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonClassMembers.cs diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj index 28cb8b0091..efc54d5625 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj @@ -94,6 +94,7 @@ + diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonClassMembers.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonClassMembers.cs new file mode 100644 index 0000000000..bf44d6e6e2 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonClassMembers.cs @@ -0,0 +1,38 @@ +// 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; + +namespace ICSharpCode.PythonBinding +{ + public class PythonClassMembers + { + List members; + + public PythonClassMembers(IClass declaringType) + { + members = GetMembers(declaringType); + } + + public IMember FindMember(string memberName) + { + foreach (IMember member in members) { + if (member.Name == memberName) { + return member; + } + } + return null; + } + + List GetMembers(IClass declaringType) + { + List members = new List(); + members.AddRange(declaringType.Events); + members.AddRange(declaringType.Fields); + members.AddRange(declaringType.Properties); + return members; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCompletionItemList.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCompletionItemList.cs index 833f150562..02322f4c57 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCompletionItemList.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCompletionItemList.cs @@ -12,8 +12,6 @@ namespace ICSharpCode.PythonBinding { if (IsNormalKey(key)) { return CompletionItemListKeyResult.NormalKey; - } else if (key == '(') { - return CompletionItemListKeyResult.NormalKey; } return base.ProcessInput(key); } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMemberResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMemberResolver.cs index 31dd610fe3..cab49606d7 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMemberResolver.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMemberResolver.cs @@ -13,83 +13,92 @@ namespace ICSharpCode.PythonBinding public class PythonMemberResolver : IPythonResolver { PythonClassResolver classResolver; + PythonLocalVariableResolver localVariableResolver; + PythonResolverContext resolverContext; - public PythonMemberResolver(PythonClassResolver classResolver) + public PythonMemberResolver(PythonClassResolver classResolver, PythonLocalVariableResolver localVariableResolver) { this.classResolver = classResolver; + this.localVariableResolver = localVariableResolver; } public ResolveResult Resolve(PythonResolverContext resolverContext) { - IMember member = FindMember(resolverContext); - if (member != null) { - return CreateMemberResolveResult(member); - } - return null; + this.resolverContext = resolverContext; + IMember member = FindMember(); + return CreateMemberResolveResult(member); } - IMember FindMember(PythonResolverContext resolverContext) + IMember FindMember() { - return FindMember(resolverContext, resolverContext.Expression); + return FindMember(resolverContext.Expression); } - IMember FindMember(PythonResolverContext resolverContext, string expression) + IMember FindMember(string expression) { MemberName memberName = new MemberName(expression); if (memberName.HasName) { - IClass c = FindClass(resolverContext, memberName.Type); + IClass c = FindClass(memberName.Type); if (c != null) { return FindMemberInClass(c, memberName.Name); } else { - return FindMember(resolverContext, memberName); + return FindMemberInParent(memberName); } } return null; } - IClass FindClass(PythonResolverContext resolverContext, string className) + IClass FindClass(string className) { - return classResolver.GetClass(resolverContext, className); + IClass c = FindClassFromClassResolver(className); + if (c != null) { + return c; + } + return FindClassFromLocalVariableResolver(className); } - MemberResolveResult CreateMemberResolveResult(IMember member) + IClass FindClassFromClassResolver(string className) { - return new MemberResolveResult(null, null, member); + return classResolver.GetClass(resolverContext, className); } - IMember FindMemberInClass(IClass matchingClass, string memberName) + IClass FindClassFromLocalVariableResolver(string localVariableName) { - List members = GetMembers(matchingClass); - foreach (IMember member in members) { - if (member.Name == memberName) { - return member; - } + MemberName memberName = new MemberName(localVariableName); + if (!memberName.HasName) { + string typeName = localVariableResolver.Resolve(localVariableName, resolverContext.FileContent); + return FindClassFromClassResolver(typeName); + } + return null; + } + + MemberResolveResult CreateMemberResolveResult(IMember member) + { + if (member != null) { + return new MemberResolveResult(null, null, member); } return null; } - List GetMembers(IClass c) + IMember FindMemberInClass(IClass matchingClass, string memberName) { - List members = new List(); - members.AddRange(c.Events); - members.AddRange(c.Fields); - members.AddRange(c.Properties); - return members; + PythonClassMembers classMembers = new PythonClassMembers(matchingClass); + return classMembers.FindMember(memberName); } - IMember FindMember(PythonResolverContext resolverContext, MemberName memberName) + IMember FindMemberInParent(MemberName memberName) { - IMember parentMember = FindMember(resolverContext, memberName.Type); + IMember parentMember = FindMember(memberName.Type); if (parentMember != null) { return FindMemberInParent(parentMember, memberName.Name); } return null; } - IMember FindMemberInParent(IMember parentMember, string propertyName) + IMember FindMemberInParent(IMember parentMember, string memberName) { IClass parentMemberClass = parentMember.ReturnType.GetUnderlyingClass(); - return FindMemberInClass(parentMemberClass, propertyName); + return FindMemberInClass(parentMemberClass, memberName); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs index 18bd70a044..4f4e4e86f8 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs @@ -27,8 +27,8 @@ namespace ICSharpCode.PythonBinding public PythonResolver() { methodResolver = new PythonMethodResolver(classResolver, standardModuleResolver); - memberResolver = new PythonMemberResolver(classResolver); localVariableResolver = new PythonLocalVariableResolver(classResolver); + memberResolver = new PythonMemberResolver(classResolver, localVariableResolver); resolvers.Add(importResolver); resolvers.Add(classResolver); diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveClassPropertyTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveClassPropertyTests.cs index 3efc9c7742..088af967cc 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveClassPropertyTests.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveClassPropertyTests.cs @@ -80,5 +80,19 @@ namespace PythonBinding.Tests.Resolver Assert.AreEqual(nestedClassProperty, resolvedMember); } + + [Test] + public void Resolve_ExpressionIsForPropertyOnLocalVariable_MemberResolveResultResolvedTypeIsMyClassProperty() + { + CreateClassWithOneProperty(); + string code = + "a = MyClass()\r\n" + + "a.MyProperty"; + + resolverHelper.Resolve("a.MyProperty", code); + IMember resolvedMember = resolverHelper.MemberResolveResult.ResolvedMember; + + Assert.AreEqual(myClassProperty, resolvedMember); + } } }