diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj index 70af68bbf6..f1235334c6 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj @@ -73,8 +73,16 @@ + + + + + + + + @@ -118,7 +126,7 @@ - + diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/MemberName.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/MemberName.cs new file mode 100644 index 0000000000..61f31468cd --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/MemberName.cs @@ -0,0 +1,79 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.PythonBinding +{ + /// + /// Split up an expression into a member name and a type name. + /// + /// + /// "myObject.Field" => "myObject" + "Field" + /// "System.Console.WriteLine" => "System.Console" + "Console.WriteLine" + /// + public class MemberName + { + string name = String.Empty; + string type = String.Empty; + + public MemberName(string expression) + { + Parse(expression); + } + + public MemberName(string typeName, string memberName) + { + this.type = typeName; + this.name = memberName; + } + + void Parse(string expression) + { + if (!String.IsNullOrEmpty(expression)) { + int index = expression.LastIndexOf('.'); + if (index > 0) { + type = expression.Substring(0, index); + name = expression.Substring(index + 1); + } else { + type = expression; + } + } + } + + public string Name { + get { return name; } + } + + public bool HasName { + get { return !String.IsNullOrEmpty(name); } + } + + public string Type { + get { return type; } + } + + public override string ToString() + { + return String.Format("Type: {0}, Member: {1}", type, name); + } + + public override bool Equals(object obj) + { + MemberName rhs = obj as MemberName; + if (rhs != null) { + return (name == rhs.name) && (type == rhs.type); + } + return false; + } + + public override int GetHashCode() + { + return name.GetHashCode() ^ type.GetHashCode(); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonClassResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonClassResolver.cs new file mode 100644 index 0000000000..aec031628d --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonClassResolver.cs @@ -0,0 +1,47 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonClassResolver + { + public PythonClassResolver() + { + } + + public ResolveResult Resolve(PythonResolverContext context, ExpressionResult expressionResult) + { + IClass matchingClass = GetClass(context, expressionResult.Expression); + if (matchingClass != null) { + return CreateTypeResolveResult(matchingClass); + } + return null; + } + + public IClass GetClass(PythonResolverContext context, string name) + { + if (String.IsNullOrEmpty(name)) { + return null; + } + + IClass matchedClass = context.GetClass(name); + if (matchedClass != null) { + return matchedClass; + } + + return context.GetImportedClass(name); + } + + TypeResolveResult CreateTypeResolveResult(IClass c) + { + return new TypeResolveResult(null, null, c); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpressionFinder.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpressionFinder.cs index de59660718..d51c54afaa 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpressionFinder.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpressionFinder.cs @@ -53,13 +53,8 @@ namespace ICSharpCode.PythonBinding /// public string RemoveLastPart(string expression) { - if (!String.IsNullOrEmpty(expression)) { - int index = expression.LastIndexOf('.'); - if (index > 0) { - return expression.Substring(0, index); - } - } - return String.Empty; + MemberName memberName = new MemberName(expression); + return memberName.Type; } /// diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportCompletion.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportCompletion.cs index ccad769a09..fac7340dea 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportCompletion.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportCompletion.cs @@ -17,7 +17,7 @@ namespace ICSharpCode.PythonBinding public class PythonImportCompletion { IProjectContent projectContent; - static readonly StandardPythonModules standardPythonModules = new StandardPythonModules(); + static readonly PythonStandardModules standardPythonModules = new PythonStandardModules(); public PythonImportCompletion(IProjectContent projectContent) { @@ -46,14 +46,14 @@ namespace ICSharpCode.PythonBinding public ArrayList GetCompletionItemsFromModule(string module) { - Type type = standardPythonModules.GetTypeForModule(module); + PythonStandardModuleType type = standardPythonModules.GetModuleType(module); if (type != null) { return GetCompletionItemsFromModule(type); } return projectContent.GetNamespaceContents(module); } - ArrayList GetCompletionItemsFromModule(Type type) + ArrayList GetCompletionItemsFromModule(PythonStandardModuleType type) { PythonModuleCompletionItems moduleItems = PythonModuleCompletionItemsFactory.Create(type); ArrayList items = new ArrayList(moduleItems); diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportExpression.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportExpression.cs index 4560daf8a6..07bcc5a915 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportExpression.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportExpression.cs @@ -123,7 +123,7 @@ namespace ICSharpCode.PythonBinding static bool ValidIsImportExpressionParameters(string text, int offset) { - if (String.IsNullOrEmpty(text) || (offset <= 0)) { + if (String.IsNullOrEmpty(text) || (offset <= 0) || (offset >= text.Length)) { return false; } return true; @@ -142,6 +142,9 @@ namespace ICSharpCode.PythonBinding while (offset > 0) { char ch = text[offset]; if (Char.IsWhiteSpace(ch)) { + if (IsNewLineOrCarriageReturn(ch)) { + return offset; + } if (!ignoreWhitespace) { return offset; } @@ -153,6 +156,11 @@ namespace ICSharpCode.PythonBinding return offset; } + static bool IsNewLineOrCarriageReturn(char ch) + { + return (ch == '\r') || (ch == '\n'); + } + static bool IsImportOrFromString(string text) { return IsImportString(text) || IsFromString(text); diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethodResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethodResolver.cs new file mode 100644 index 0000000000..96ed932c4c --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethodResolver.cs @@ -0,0 +1,83 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonMethodResolver + { + PythonClassResolver classResolver; + PythonStandardModuleResolver standardModuleResolver; + + public PythonMethodResolver(PythonClassResolver classResolver, PythonStandardModuleResolver standardModuleResolver) + { + this.classResolver = classResolver; + this.standardModuleResolver = standardModuleResolver; + } + + public ResolveResult Resolve(PythonResolverContext resolverContext, ExpressionResult expressionResult) + { + MemberName memberName = new MemberName(expressionResult.Expression); + MethodGroupResolveResult resolveResult = GetDotNetMethodResolveResult(resolverContext, memberName); + if (resolveResult != null) { + return resolveResult; + } + return GetStandardModuleMethodResolveResult(resolverContext, memberName); + } + + MethodGroupResolveResult GetDotNetMethodResolveResult(PythonResolverContext resolverContext, MemberName memberName) + { + IClass matchingClass = classResolver.GetClass(resolverContext, memberName.Type); + if (matchingClass != null) { + return CreateMethodGroupResolveResult(matchingClass, memberName.Name); + } + return null; + } + + MethodGroupResolveResult GetStandardModuleMethodResolveResult(PythonResolverContext resolverContext, MemberName memberName) + { + if (!memberName.HasName) { + memberName = CreateBuiltinModuleMemberName(memberName.Type); + } + PythonStandardModuleType type = standardModuleResolver.GetStandardModuleType(resolverContext, memberName.Type); + if (type != null) { + return GetStandardModuleMethodResolveResult(type, memberName.Name); + } + return null; + } + + MemberName CreateBuiltinModuleMemberName(string memberName) + { + return new MemberName(PythonStandardModuleResolver.PythonBuiltInModuleName, memberName); + } + + MethodGroupResolveResult GetStandardModuleMethodResolveResult(PythonStandardModuleType type, string methodName) + { + PythonModuleCompletionItems completionItems = PythonModuleCompletionItemsFactory.Create(type); + MethodGroup methods = completionItems.GetMethods(methodName); + if (methods.Count > 0) { + return CreateMethodGroupResolveResult(methods); + } + return null; + } + + MethodGroupResolveResult CreateMethodGroupResolveResult(IClass c, string methodName) + { + return new MethodGroupResolveResult(null, null, c.DefaultReturnType, methodName); + } + + MethodGroupResolveResult CreateMethodGroupResolveResult(MethodGroup methods) + { + MethodGroup[] methodGroups = new MethodGroup[] { methods }; + IMethod method = methods[0]; + IReturnType returnType = new DefaultReturnType(method.DeclaringType); + return new MethodGroupResolveResult(null, null, returnType, method.Name, methodGroups); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItems.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItems.cs index bcedddff9b..67657f79ac 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItems.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItems.cs @@ -7,10 +7,13 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Reflection; using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Dom.ReflectionLayer; using IronPython.Modules; using IronPython.Runtime; +using Microsoft.Scripting.Runtime; namespace ICSharpCode.PythonBinding { @@ -19,16 +22,16 @@ namespace ICSharpCode.PythonBinding DefaultCompilationUnit compilationUnit; DefaultClass moduleClass; DefaultProjectContent projectContent; - + static readonly BindingFlags PublicAndStaticBindingFlags = BindingFlags.Public | BindingFlags.Static; - - public PythonModuleCompletionItems(Type type) + + public PythonModuleCompletionItems(PythonStandardModuleType moduleType) { projectContent = new DefaultProjectContent(); compilationUnit = new DefaultCompilationUnit(projectContent); - moduleClass = new DefaultClass(compilationUnit, String.Empty); + moduleClass = new DefaultClass(compilationUnit, moduleType.Name); - AddCompletionItemsForType(type); + AddCompletionItemsForType(moduleType.Type); AddStandardCompletionItems(); } @@ -81,7 +84,52 @@ namespace ICSharpCode.PythonBinding IMethod CreateMethodFromMethodInfo(MethodInfo methodInfo, IClass c) { - return new DefaultMethod(c, methodInfo.Name); + DefaultMethod method = new DefaultMethod(c, methodInfo.Name); + method.Documentation = GetDocumentation(methodInfo); + method.ReturnType = CreateMethodReturnType(methodInfo); + method.Modifiers = ModifierEnum.Public; + + foreach (ParameterInfo paramInfo in methodInfo.GetParameters()) { + if (!IsCodeContextParameter(paramInfo)) { + IParameter parameter = ConvertParameter(paramInfo, method); + method.Parameters.Add(parameter); + } + } + + c.Methods.Add(method); + + return method; + } + + string GetDocumentation(MemberInfo memberInfo) + { + foreach (DocumentationAttribute documentation in GetDocumentationAttributes(memberInfo)) { + return documentation.Documentation; + } + return null; + } + + object[] GetDocumentationAttributes(MemberInfo memberInfo) + { + return memberInfo.GetCustomAttributes(typeof(DocumentationAttribute), false); + } + + IReturnType CreateMethodReturnType(MethodInfo methodInfo) + { + DefaultClass declaringType = new DefaultClass(compilationUnit, methodInfo.ReturnType.FullName); + return new DefaultReturnType(declaringType); + } + + bool IsCodeContextParameter(ParameterInfo paramInfo) + { + return paramInfo.ParameterType == typeof(CodeContext); + } + + IParameter ConvertParameter(ParameterInfo paramInfo, IMethod method) + { + DefaultClass c = new DefaultClass(compilationUnit, paramInfo.ParameterType.FullName); + DefaultReturnType returnType = new DefaultReturnType(c); + return new DefaultParameter(paramInfo.Name, returnType, DomRegion.Empty); } IField CreateFieldFromFieldInfo(FieldInfo fieldInfo, IClass c) @@ -93,6 +141,20 @@ namespace ICSharpCode.PythonBinding { DefaultCompilationUnit unit = new DefaultCompilationUnit(projectContent); return new DefaultClass(unit, type.Name); - } + } + + public MethodGroup GetMethods(string name) + { + List methods = new List(); + foreach (object member in InnerList) { + IMethod method = member as IMethod; + if (method != null) { + if (method.Name == name) { + methods.Add(method); + } + } + } + return new MethodGroup(methods); + } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItemsFactory.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItemsFactory.cs index 18bc1303d5..2d55a47748 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItemsFactory.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItemsFactory.cs @@ -12,12 +12,12 @@ namespace ICSharpCode.PythonBinding { public static class PythonModuleCompletionItemsFactory { - public static PythonModuleCompletionItems Create(Type type) + public static PythonModuleCompletionItems Create(PythonStandardModuleType moduleType) { - if (IsSysModule(type)) { - return new SysModuleCompletionItems(type); + if (IsSysModule(moduleType.Type)) { + return new SysModuleCompletionItems(moduleType); } - return new PythonModuleCompletionItems(type); + return new PythonModuleCompletionItems(moduleType); } static bool IsSysModule(Type type) diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonNamespaceResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonNamespaceResolver.cs new file mode 100644 index 0000000000..fe0f00cec2 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonNamespaceResolver.cs @@ -0,0 +1,36 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonNamespaceResolver + { + public PythonNamespaceResolver() + { + } + + public ResolveResult Resolve(ExpressionResult expressionResult) + { + if (IsNamespace(expressionResult)) { + PythonImportExpression importExpression = new PythonImportExpression(expressionResult.Expression); + PythonImportExpressionContext context = expressionResult.Context as PythonImportExpressionContext; + context.HasFromAndImport = importExpression.HasFromAndImport; + + return new PythonImportModuleResolveResult(importExpression); + } + return null; + } + + bool IsNamespace(ExpressionResult expressionResult) + { + return expressionResult.Context is PythonImportExpressionContext; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs index 095fcfcbc4..f43cf26c57 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs @@ -13,44 +13,46 @@ using ICSharpCode.SharpDevelop.Dom; namespace ICSharpCode.PythonBinding { - /// - /// Python Resolver. - /// public class PythonResolver : IResolver { - IProjectContent projectContent; - IClass callingClass; - ICompilationUnit compilationUnit; + PythonResolverContext resolverContext; + PythonNamespaceResolver namespaceResolver = new PythonNamespaceResolver(); + PythonClassResolver classResolver = new PythonClassResolver(); + PythonStandardModuleResolver standardModuleResolver = new PythonStandardModuleResolver(); + PythonMethodResolver methodResolver; public PythonResolver() { + methodResolver = new PythonMethodResolver(classResolver, standardModuleResolver); } public ResolveResult Resolve(ExpressionResult expressionResult, ParseInformation parseInfo, string fileContent) { - Console.WriteLine("Resolve: " + expressionResult.Expression); - - if (IsNamespace(expressionResult)) { - return ResolveImport(expressionResult); - } - if (String.IsNullOrEmpty(fileContent)) { return null; } - // Get the calling class and member. - if (!GetCallingMember(parseInfo, expressionResult.Region)) { + resolverContext = new PythonResolverContext(parseInfo); + if (!resolverContext.GetCallingMember(expressionResult.Region)) { return null; } - // Search for a type. - IClass matchingClass = GetClass(expressionResult.Expression); - if (matchingClass != null) { - return new TypeResolveResult(null, null, matchingClass); + ResolveResult resolveResult = namespaceResolver.Resolve(expressionResult); + if (resolveResult != null) { + return resolveResult; + } + + resolveResult = classResolver.Resolve(resolverContext, expressionResult); + if (resolveResult != null) { + return resolveResult; } - // Search for a method. - MethodGroupResolveResult resolveResult = GetMethodResolveResult(expressionResult.Expression); + resolveResult = standardModuleResolver.Resolve(resolverContext, expressionResult); + if (resolveResult != null) { + return resolveResult; + } + + resolveResult = methodResolver.Resolve(resolverContext, expressionResult); if (resolveResult != null) { return resolveResult; } @@ -62,198 +64,29 @@ namespace ICSharpCode.PythonBinding } // Search for a namespace. - if (projectContent.NamespaceExists(expressionResult.Expression)) { + if (resolverContext.NamespaceExists(expressionResult.Expression)) { return new NamespaceResolveResult(null, null, expressionResult.Expression); } return null; } - bool IsNamespace(ExpressionResult expressionResult) - { - return expressionResult.Context is PythonImportExpressionContext; - } - - ResolveResult ResolveImport(ExpressionResult expressionResult) - { - PythonImportExpression importExpression = new PythonImportExpression(expressionResult.Expression); - PythonImportExpressionContext context = expressionResult.Context as PythonImportExpressionContext; - context.HasFromAndImport = importExpression.HasFromAndImport; - - return new PythonImportModuleResolveResult(importExpression); - } - /// /// Called when Ctrl+Space is entered by the user. /// public ArrayList CtrlSpace(int caretLine, int caretColumn, ParseInformation parseInfo, string fileContent, ExpressionContext context) { - ICompilationUnit compilationUnit = GetCompilationUnit(parseInfo, true); - if (CompletionUnitHasProjectContent(compilationUnit)) { + resolverContext = new PythonResolverContext(parseInfo); + if (resolverContext.HasProjectContent) { if (context == ExpressionContext.Namespace) { - PythonImportCompletion importCompletion = new PythonImportCompletion(compilationUnit.ProjectContent); + PythonImportCompletion importCompletion = new PythonImportCompletion(resolverContext.ProjectContent); return importCompletion.GetCompletionItems(); } else { - ArrayList results = new ArrayList(); - CtrlSpaceResolveHelper.AddImportedNamespaceContents(results, compilationUnit, null); - return results; + return resolverContext.GetImportedTypes(); } } return new ArrayList(); } - bool CompletionUnitHasProjectContent(ICompilationUnit compilationUnit) - { - return (compilationUnit != null) && (compilationUnit.ProjectContent != null); - } - - /// - /// Gets the compilation unit for the specified parse information. - /// - ICompilationUnit GetCompilationUnit(ParseInformation parseInfo, bool mostRecent) - { - if (parseInfo != null) { - if (mostRecent) { - return parseInfo.MostRecentCompilationUnit; - } - return parseInfo.BestCompilationUnit; - } - return null; - } - - /// - /// Determines the class and member at the specified - /// line and column in the specified file. - /// - bool GetCallingMember(ParseInformation parseInfo, DomRegion region) - { - compilationUnit = GetCompilationUnit(parseInfo, true); - if (compilationUnit == null) { - return false; - } - - projectContent = compilationUnit.ProjectContent; - if (projectContent != null) { - ICompilationUnit bestCompilationUnit = GetCompilationUnit(parseInfo, false); - callingClass = GetCallingClass(compilationUnit, bestCompilationUnit, region); - return true; - } - return false; - } - - /// - /// Gets the calling class at the specified. - /// - IClass GetCallingClass(ICompilationUnit mostRecentCompilationUnit, ICompilationUnit bestCompilationUnit, DomRegion region) - { - // Try the most recent compilation unit first - IClass c = GetCallingClass(mostRecentCompilationUnit, region); - if (c != null) { - return c; - } - - // Try the best compilation unit. - if (bestCompilationUnit != null && bestCompilationUnit.ProjectContent != null) { - IClass oldClass = GetCallingClass(bestCompilationUnit, region); - if (oldClass != null) { - return oldClass; - } - } - return null; - } - - /// - /// Gets the calling class at the specified line and column. - /// - IClass GetCallingClass(ICompilationUnit compilationUnit, DomRegion region) - { - if (compilationUnit.Classes.Count > 0) { - return compilationUnit.Classes[0]; - } - return null; - } - - /// - /// Finds the specified class. - /// - IClass GetClass(string name) - { - // Try the project content first. This will - // match if the name is a fully qualified class name. - IClass matchedClass = projectContent.GetClass(name, 0); - if (matchedClass != null) { - return matchedClass; - } - - // Try the imported classes now. This will - // match on a partial name (i.e. without the namespace - // prefix). - return GetImportedClass(name); - } - - /// - /// Looks in the imported namespaces for a class that - /// matches the class name. The class name searched for is not fully - /// qualified. - /// - /// The unqualified class name. - IClass GetImportedClass(string name) - { - foreach (Object o in GetImportedTypes()) { - IClass c = o as IClass; - if (c != null && IsSameClassName(name, c.Name)) { - return c; - } - } - return null; - } - - /// - /// Determines whether the two type names are the same. - /// - static bool IsSameClassName(string name1, string name2) - { - return name1 == name2; - } - - /// - /// Returns an array of the types that are imported by the - /// current compilation unit. - /// - ArrayList GetImportedTypes() - { - ArrayList types = new ArrayList(); - CtrlSpaceResolveHelper.AddImportedNamespaceContents(types, this.compilationUnit, this.callingClass); - return types; - } - - /// - /// Tries to resolve a method in the expression. - /// - MethodGroupResolveResult GetMethodResolveResult(string expression) - { - // Remove last part of the expression and try to - // find this class. - PythonExpressionFinder expressionFinder = new PythonExpressionFinder(); - string className = expressionFinder.RemoveLastPart(expression); - if (!String.IsNullOrEmpty(className)) { - IClass matchingClass = GetClass(className); - if (matchingClass != null) { - string methodName = GetMethodName(expression); - return new MethodGroupResolveResult(null, null, matchingClass.DefaultReturnType, methodName); - } - } - return null; - } - - /// - /// Gets the method name from the expression. - /// - static string GetMethodName(string expression) - { - int index = expression.LastIndexOf('.'); - return expression.Substring(index + 1); - } - /// /// Tries to find the type that matches the local variable name. /// diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolverContext.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolverContext.cs new file mode 100644 index 0000000000..e5b456be76 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolverContext.cs @@ -0,0 +1,177 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonResolverContext + { + ICompilationUnit mostRecentCompilationUnit; + ICompilationUnit bestCompilationUnit; + IProjectContent projectContent; + IClass callingClass; + + public PythonResolverContext(ParseInformation parseInfo) + { + GetCompilationUnits(parseInfo); + GetProjectContent(); + } + + void GetCompilationUnits(ParseInformation parseInfo) + { + mostRecentCompilationUnit = GetCompilationUnit(parseInfo, true); + bestCompilationUnit = GetCompilationUnit(parseInfo, false); + } + + void GetProjectContent() + { + if (mostRecentCompilationUnit != null) { + projectContent = mostRecentCompilationUnit.ProjectContent; + } + } + + public ICompilationUnit MostRecentCompilationUnit { + get { return mostRecentCompilationUnit; } + } + + public IProjectContent ProjectContent { + get { return projectContent; } + } + + public bool HasProjectContent { + get { return projectContent != null; } + } + + public IClass CallingClass { + get { return callingClass; } + } + + public bool NamespaceExists(string name) + { + return projectContent.NamespaceExists(name); + } + + /// + /// Determines the class and member at the specified + /// line and column in the specified file. + /// + public bool GetCallingMember(DomRegion region) + { + if (mostRecentCompilationUnit == null) { + return false; + } + + if (projectContent != null) { + callingClass = GetCallingClass(mostRecentCompilationUnit, bestCompilationUnit, region); + return true; + } + return false; + } + + /// + /// Gets the compilation unit for the specified parse information. + /// + public ICompilationUnit GetCompilationUnit(ParseInformation parseInfo, bool mostRecent) + { + if (parseInfo != null) { + if (mostRecent) { + return parseInfo.MostRecentCompilationUnit; + } + return parseInfo.BestCompilationUnit; + } + return null; + } + + /// + /// Gets the calling class at the specified. + /// + IClass GetCallingClass(ICompilationUnit mostRecentCompilationUnit, ICompilationUnit bestCompilationUnit, DomRegion region) + { + // Try the most recent compilation unit first + IClass c = GetCallingClass(mostRecentCompilationUnit, region); + if (c != null) { + return c; + } + + // Try the best compilation unit. + if (bestCompilationUnit != null && bestCompilationUnit.ProjectContent != null) { + IClass oldClass = GetCallingClass(bestCompilationUnit, region); + if (oldClass != null) { + return oldClass; + } + } + return null; + } + + /// + /// Gets the calling class at the specified line and column. + /// + IClass GetCallingClass(ICompilationUnit compilationUnit, DomRegion region) + { + if (compilationUnit.Classes.Count > 0) { + return compilationUnit.Classes[0]; + } + return null; + } + + public IClass GetClass(string fullyQualifiedName) + { + return projectContent.GetClass(fullyQualifiedName, 0); + } + + /// + /// Returns an array of the types that are imported by the + /// current compilation unit. + /// + public ArrayList GetImportedTypes() + { + ArrayList types = new ArrayList(); + CtrlSpaceResolveHelper.AddImportedNamespaceContents(types, mostRecentCompilationUnit, callingClass); + return types; + } + + public bool HasImport(string name) + { + foreach (IUsing u in mostRecentCompilationUnit.UsingScope.Usings) { + foreach (string ns in u.Usings) { + if (name == ns) { + return true; + } + } + } + return false; + } + + /// + /// Looks in the imported namespaces for a class that + /// matches the class name. The class name searched for is not fully + /// qualified. + /// + /// The unqualified class name. + public IClass GetImportedClass(string name) + { + foreach (Object obj in GetImportedTypes()) { + IClass c = obj as IClass; + if ((c != null) && IsSameClassName(name, c.Name)) { + return c; + } + } + return null; + } + + /// + /// Determines whether the two type names are the same. + /// + static bool IsSameClassName(string name1, string name2) + { + return name1 == name2; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleResolveResult.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleResolveResult.cs new file mode 100644 index 0000000000..593e2c02f2 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleResolveResult.cs @@ -0,0 +1,31 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonStandardModuleResolveResult : ResolveResult + { + PythonStandardModuleType standardModuleType; + + public PythonStandardModuleResolveResult(PythonStandardModuleType standardModuleType) + : base(null, null, null) + { + this.standardModuleType = standardModuleType; + } + + public override ArrayList GetCompletionData(IProjectContent projectContent) + { + PythonModuleCompletionItems completionItems = PythonModuleCompletionItemsFactory.Create(standardModuleType); + ArrayList items = new ArrayList(completionItems); + return items; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleResolver.cs new file mode 100644 index 0000000000..362496915a --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleResolver.cs @@ -0,0 +1,44 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonStandardModuleResolver + { + public const string PythonBuiltInModuleName = "__builtin__"; + PythonStandardModules standardPythonModules = new PythonStandardModules(); + + public PythonStandardModuleResolver() + { + } + + public ResolveResult Resolve(PythonResolverContext resolverContext, ExpressionResult expressionResult) + { + PythonStandardModuleType type = GetStandardModuleType(resolverContext, expressionResult.Expression); + if (type != null) { + return new PythonStandardModuleResolveResult(type); + } + return null; + } + + public PythonStandardModuleType GetStandardModuleType(PythonResolverContext resolverContext, string name) + { + if (resolverContext.HasImport(name) || IsBuiltInModule(name)) { + return standardPythonModules.GetModuleType(name); + } + return null; + } + + bool IsBuiltInModule(string name) + { + return name == PythonBuiltInModuleName; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleType.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleType.cs new file mode 100644 index 0000000000..99b5047e9d --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleType.cs @@ -0,0 +1,31 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.PythonBinding +{ + public class PythonStandardModuleType + { + Type type; + string name; + + public PythonStandardModuleType(Type type, string name) + { + this.type = type; + this.name = name; + } + + public Type Type { + get { return type; } + } + + public string Name { + get { return name; } + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/StandardPythonModules.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModules.cs similarity index 77% rename from src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/StandardPythonModules.cs rename to src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModules.cs index ff1b9364d1..9f2a993ddd 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/StandardPythonModules.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModules.cs @@ -18,18 +18,18 @@ namespace ICSharpCode.PythonBinding /// Represents the standard library modules that are implemented in /// IronPython. /// - public class StandardPythonModules : ReadOnlyCollectionBase + public class PythonStandardModules : ReadOnlyCollectionBase { List moduleNames = new List(); Dictionary moduleTypes = new Dictionary(); - public StandardPythonModules() + public PythonStandardModules() { - GetStandardPythonModuleNames(); + GetPythonStandardModuleNames(); InnerList.AddRange(GetNames()); } - void GetStandardPythonModuleNames() + void GetPythonStandardModuleNames() { GetPythonModuleNamesFromAssembly(typeof(Builtin).Assembly); GetPythonModuleNamesFromAssembly(typeof(ModuleOps).Assembly); @@ -52,7 +52,16 @@ namespace ICSharpCode.PythonBinding } } - public Type GetTypeForModule(string moduleName) + public PythonStandardModuleType GetModuleType(string moduleName) + { + Type type = GetTypeForModule(moduleName); + if (type != null) { + return new PythonStandardModuleType(type, moduleName); + } + return null; + } + + Type GetTypeForModule(string moduleName) { Type type; if (moduleTypes.TryGetValue(moduleName, out type)) { diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/SysModuleCompletionItems.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/SysModuleCompletionItems.cs index 5469eb6f1a..93e8bb84b4 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/SysModuleCompletionItems.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/SysModuleCompletionItems.cs @@ -12,10 +12,10 @@ using ICSharpCode.SharpDevelop.Dom; namespace ICSharpCode.PythonBinding { public class SysModuleCompletionItems : PythonModuleCompletionItems - { - public SysModuleCompletionItems(Type type) - : base(type) - { + { + public SysModuleCompletionItems(PythonStandardModuleType moduleType) + : base(moduleType) + { AddCompletionItems(); } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromDateTimeImportCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromDateTimeImportCompletionTestFixture.cs index d6287d01bb..502e70030e 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromDateTimeImportCompletionTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromDateTimeImportCompletionTestFixture.cs @@ -35,7 +35,7 @@ namespace PythonBinding.Tests.Completion public void CompletionItemsContainsDateClass() { ArrayList items = resolveResult.GetCompletionData(projectContent); - IClass c = PythonCompletionItemsHelper.FindClassFromArray("datetime", items); + IClass c = PythonCompletionItemsHelper.FindClassFromCollection("datetime", items); Assert.IsNotNull(c); } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromImportPythonModuleCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromImportPythonModuleCompletionTestFixture.cs index 23eb748246..82dd8860bf 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromImportPythonModuleCompletionTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromImportPythonModuleCompletionTestFixture.cs @@ -39,7 +39,7 @@ namespace PythonBinding.Tests.Completion public void FromMathLibraryGetCompletionItemsReturnsPiField() { ArrayList items = completion.GetCompletionItemsFromModule("math"); - IField field = PythonCompletionItemsHelper.FindFieldFromArray("pi", items); + IField field = PythonCompletionItemsHelper.FindFieldFromCollection("pi", items); Assert.IsNotNull(field); } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromMathLibraryImportCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromMathLibraryImportCompletionTestFixture.cs index 42c81f109d..4aac7ed567 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromMathLibraryImportCompletionTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromMathLibraryImportCompletionTestFixture.cs @@ -36,35 +36,35 @@ namespace PythonBinding.Tests.Completion [Test] public void CompletionItemsContainsCosMethodFromMathLibrary() { - IMethod method = PythonCompletionItemsHelper.FindMethodFromArray("cos", completionItems); + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("cos", completionItems); Assert.IsNotNull(method); } [Test] public void CompletionItemsContainsPiPropertyFromMathLibrary() { - IField field = PythonCompletionItemsHelper.FindFieldFromArray("pi", completionItems); + IField field = PythonCompletionItemsHelper.FindFieldFromCollection("pi", completionItems); Assert.IsNotNull(field); } [Test] public void CompletionItemsDoesNotContainNonStaticToStringMethod() { - IMethod method = PythonCompletionItemsHelper.FindMethodFromArray("ToString", completionItems); + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("ToString", completionItems); Assert.IsNull(method); } [Test] public void CompletionItemsContain__name__() { - IField field = PythonCompletionItemsHelper.FindFieldFromArray("__name__", completionItems); + IField field = PythonCompletionItemsHelper.FindFieldFromCollection("__name__", completionItems); Assert.IsNotNull(field); } [Test] public void CompletionItemsContain__package__() { - IField field = PythonCompletionItemsHelper.FindFieldFromArray("__package__", completionItems); + IField field = PythonCompletionItemsHelper.FindFieldFromCollection("__package__", completionItems); Assert.IsNotNull(field); } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromSysLibraryImportCompletionItemsTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromSysLibraryImportCompletionItemsTestFixture.cs index 1759cab2b4..5f2314485b 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromSysLibraryImportCompletionItemsTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromSysLibraryImportCompletionItemsTestFixture.cs @@ -33,7 +33,7 @@ namespace PythonBinding.Tests.Completion [Test] public void GetCompletionItemsDoesNotReturnPythonHiddenMethods() { - IMethod method = PythonCompletionItemsHelper.FindMethodFromArray("_getframeImpl", completionItems); + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("_getframeImpl", completionItems); Assert.IsNull(method); } @@ -51,7 +51,7 @@ namespace PythonBinding.Tests.Completion IField GetFieldFromCompletionItems(string name) { - return PythonCompletionItemsHelper.FindFieldFromArray(name, completionItems); + return PythonCompletionItemsHelper.FindFieldFromCollection(name, completionItems); } [Test] @@ -105,7 +105,7 @@ namespace PythonBinding.Tests.Completion [Test] public void GetCompletionItemsReturnsExitMethod() { - IMethod method = PythonCompletionItemsHelper.FindMethodFromArray("exit", completionItems); + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("exit", completionItems); Assert.IsNotNull(method); } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetMethodsFromSysLibraryTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetMethodsFromSysLibraryTestFixture.cs new file mode 100644 index 0000000000..f296ffa03c --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetMethodsFromSysLibraryTestFixture.cs @@ -0,0 +1,94 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using IronPython.Modules; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class GetMethodsFromSysLibraryTestFixture + { + SysModuleCompletionItems completionItems; + MethodGroup exitMethodGroup; + MethodGroup displayHookMethodGroup; + + [SetUp] + public void Init() + { + PythonStandardModuleType moduleType = new PythonStandardModuleType(typeof(SysModule), "sys"); + completionItems = new SysModuleCompletionItems(moduleType); + exitMethodGroup = completionItems.GetMethods("exit"); + displayHookMethodGroup = completionItems.GetMethods("displayhook"); + } + + [Test] + public void TwoExitMethodsReturnedFromGetMethods() + { + Assert.AreEqual(2, exitMethodGroup.Count); + } + + [Test] + public void FirstMethodNameIsExit() + { + Assert.AreEqual("exit", exitMethodGroup[0].Name); + } + + [Test] + public void SecondMethodNameIsExit() + { + Assert.AreEqual("exit", exitMethodGroup[1].Name); + } + + [Test] + public void FirstMethodHasReturnType() + { + Assert.IsNotNull(exitMethodGroup[0].ReturnType); + } + + [Test] + public void SecondMethodHasReturnType() + { + Assert.IsNotNull(exitMethodGroup[1].ReturnType); + } + + [Test] + public void ExitMethodReturnsVoid() + { + IMethod method = displayHookMethodGroup[0]; + Assert.AreEqual("Void", method.ReturnType.Name); + } + + [Test] + public void DisplayHookMethodDoesNotHaveCodeContextParameter() + { + IMethod method = displayHookMethodGroup[0]; + IParameter parameter = method.Parameters[0]; + Assert.AreEqual("value", parameter.Name); + } + + [Test] + public void DisplayHookMethodReturnsVoid() + { + IMethod method = displayHookMethodGroup[0]; + Assert.AreEqual("Void", method.ReturnType.Name); + } + + [Test] + public void GetDefaultEncodingMethodReturnsString() + { + MethodGroup methodGroup = completionItems.GetMethods("getdefaultencoding"); + IMethod method = methodGroup[0]; + Assert.AreEqual("String", method.ReturnType.Name); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetPythonModulesTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetPythonModulesTestFixture.cs index 2152863ad5..db8d96ea34 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetPythonModulesTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetPythonModulesTestFixture.cs @@ -24,7 +24,7 @@ namespace PythonBinding.Tests.Resolver [TestFixtureSetUp] public void SetUpFixture() { - StandardPythonModules modules = new StandardPythonModules(); + PythonStandardModules modules = new PythonStandardModules(); moduleNames = modules.GetNames(); } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetTypeForPythonModuleTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetTypeForPythonModuleTestFixture.cs index 4e0fa05ceb..90fc863076 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetTypeForPythonModuleTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetTypeForPythonModuleTestFixture.cs @@ -15,24 +15,38 @@ namespace PythonBinding.Tests.Completion [TestFixture] public class GetTypeForPythonModuleTestFixture { - StandardPythonModules modules; + PythonStandardModules modules; + PythonStandardModuleType sysModuleType; [SetUp] public void Init() { - modules = new StandardPythonModules(); + modules = new PythonStandardModules(); + sysModuleType = modules.GetModuleType("sys"); } [Test] public void GetTypeReturnsNullForUnknownModuleName() { - Assert.IsNull(modules.GetTypeForModule("unknown")); + Assert.IsNull(modules.GetModuleType("unknown")); } [Test] public void GetTypeReturnsSysModuleTypeForSysModuleName() { - Assert.AreEqual(typeof(SysModule), modules.GetTypeForModule("sys")); + Assert.AreEqual(typeof(SysModule), modules.GetModuleType("sys").Type); + } + + [Test] + public void GetModuleTypeReturnsSysModuleTypeForSysModuleName() + { + Assert.AreEqual(typeof(SysModule), sysModuleType.Type); + } + + [Test] + public void GetModuleTypeReturnsSysModuleNameForSysModuleName() + { + Assert.AreEqual("sys", sysModuleType.Name); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/PythonSocketLibraryDocumentationTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/PythonSocketLibraryDocumentationTestFixture.cs new file mode 100644 index 0000000000..4f5ae5c405 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/PythonSocketLibraryDocumentationTestFixture.cs @@ -0,0 +1,48 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using IronPython.Modules; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + /// + /// Tests that the documentation is taken from the Documentation attribute for the method/field in the + /// python module classes. + /// + [TestFixture] + public class PythonSocketLibraryDocumentationTestFixture + { + PythonModuleCompletionItems completionItems; + + [SetUp] + public void Init() + { + PythonStandardModuleType moduleType = new PythonStandardModuleType(typeof(PythonSocket), "socket"); + completionItems = PythonModuleCompletionItemsFactory.Create(moduleType); + } + + [Test] + public void DocumentationForCreateConnectionMethodTakenFromDocumentationAttribute() + { + string doc = + "Connect to *address* and return the socket object.\n" + + "\n" + + "Convenience function. Connect to *address* (a 2-tuple ``(host,\nport)``) and return the socket object. Passing the optional\n" + + "*timeout* parameter will set the timeout on the socket instance\nbefore attempting to connect. If no *timeout* is supplied, the\n" + + "global default timeout setting returned by :func:`getdefaulttimeout`\n" + + "is used.\n"; + + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("create_connection", completionItems); + Assert.AreEqual(doc, method.Documentation); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FindExpressionOnLineWithSingleSpaceTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FindExpressionOnLineWithSingleSpaceTestFixture.cs new file mode 100644 index 0000000000..bd29fe5322 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FindExpressionOnLineWithSingleSpaceTestFixture.cs @@ -0,0 +1,34 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class FindExpressionOnLineWithSingleSpaceTestFixture + { + ExpressionResult result; + + [SetUp] + public void Init() + { + string text = " "; + PythonExpressionFinder expressionFinder = new PythonExpressionFinder(); + result = expressionFinder.FindExpression(text, 1); + } + + [Test] + public void ExpressionResultExpressionIsEmptyString() + { + Assert.AreEqual(String.Empty, result.Expression); + } + } +} \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FindExpressionWithImportOnPreviousLineTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FindExpressionWithImportOnPreviousLineTestFixture.cs new file mode 100644 index 0000000000..b57aa80d0a --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FindExpressionWithImportOnPreviousLineTestFixture.cs @@ -0,0 +1,35 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class FindExpressionWithImportOnPreviousLineTestFixture + { + ExpressionResult result; + + [SetUp] + public void Init() + { + string text = "import\r\n"; + PythonExpressionFinder expressionFinder = new PythonExpressionFinder(); + int offset = 8; // Cursor is just after \r\n on second line. + result = expressionFinder.FindExpression(text, offset); + } + + [Test] + public void ExpressionResultExpressionIsEmptyString() + { + Assert.AreEqual(String.Empty, result.Expression); + } + } +} \ 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 01ffe597a8..bdcde2a28a 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj @@ -81,6 +81,7 @@ + @@ -90,6 +91,7 @@ + @@ -307,6 +309,8 @@ + + @@ -344,6 +348,8 @@ + + @@ -353,10 +359,14 @@ + + + + diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/MemberNameTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/MemberNameTests.cs new file mode 100644 index 0000000000..073de3d1d4 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/MemberNameTests.cs @@ -0,0 +1,120 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using NUnit.Framework; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class MemberNameTests + { + [Test] + public void MemberNameIsEqualReturnsTrueWhenNameAndTypeAreSame() + { + MemberName lhs = new MemberName("type", "member"); + MemberName rhs = new MemberName("type", "member"); + + Assert.IsTrue(lhs.Equals(rhs)); + } + + [Test] + public void MemberNameIsEqualsReturnsFalseWhenMemberNameIsNull() + { + MemberName lhs = new MemberName("type", "Member"); + Assert.IsFalse(lhs.Equals(null)); + } + + [Test] + public void MemberNamePropertyReturnsMemberName() + { + MemberName methodName = new MemberName("type", "method"); + Assert.AreEqual("method", methodName.Name); + } + + [Test] + public void MemberNameTypePropertyReturnsType() + { + MemberName methodName = new MemberName("type", "method"); + Assert.AreEqual("type", methodName.Type); + } + + [Test] + public void MemberNameIsEqualReturnsFalseWhenMemberNameIsDifferent() + { + MemberName lhs = new MemberName("type", "method1"); + MemberName rhs = new MemberName("type", "method2"); + + Assert.IsFalse(lhs.Equals(rhs)); + } + + [Test] + public void MemberNameIsEqualReturnsFalseWhenTypeNameIsDifferent() + { + MemberName lhs = new MemberName("type1", "method"); + MemberName rhs = new MemberName("type2", "method"); + + Assert.IsFalse(lhs.Equals(rhs)); + } + + [Test] + public void MemberNameToStringShowsTypeNameAndMemberName() + { + MemberName methodName = new MemberName("type", "method"); + string expectedText = "Type: type, Member: method"; + Assert.AreEqual(expectedText, methodName.ToString()); + } + + [Test] + public void CreateMemberNameWithNullStringReturnsMemberNameWithEmptyTypeAndMemberName() + { + MemberName methodName = new MemberName(null); + MemberName expectedMemberName = new MemberName(String.Empty, String.Empty); + Assert.AreEqual(expectedMemberName, methodName); + } + + [Test] + public void CreateMemberNameWithEmptyStringReturnsMemberNameWithEmptyTypeAndMemberName() + { + MemberName methodName = new MemberName(String.Empty); + MemberName expectedMemberName = new MemberName(String.Empty, String.Empty); + Assert.AreEqual(expectedMemberName, methodName); + } + + [Test] + public void CreateMemberNameWithSystemDotConsoleDotWriteLineReturnsMemberNameWriteLineAndTypeNameSystemDotConsole() + { + MemberName methodName = new MemberName("System.Console.WriteLine"); + MemberName expectedMemberName = new MemberName("System.Console", "WriteLine"); + + Assert.AreEqual(expectedMemberName, methodName); + } + + [Test] + public void CreateMemberNameWithExpressionWithoutDotCharReturnsMemberNameOfEmptyStringAndExpressionAsTypeName() + { + MemberName methodName = new MemberName("test"); + MemberName expectedMemberName = new MemberName("test", String.Empty); + Assert.AreEqual(expectedMemberName, methodName); + } + + [Test] + public void HasNameReturnsFalseForMemberNameWithEmptyStringForMemberName() + { + MemberName memberName = new MemberName("System", String.Empty); + Assert.IsFalse(memberName.HasName); + } + + [Test] + public void HasNameReturnsTrueForMemberNameWithNonEmptyStringForMemberName() + { + MemberName memberName = new MemberName("System", "Console"); + Assert.IsTrue(memberName.HasName); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveBuiltInRoundMethodTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveBuiltInRoundMethodTestFixture.cs new file mode 100644 index 0000000000..191e9fce0d --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveBuiltInRoundMethodTestFixture.cs @@ -0,0 +1,121 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Dom.CSharp; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ResolveBuiltInRoundMethodTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("round", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "round\r\n" + + "\r\n"; + } + + [Test] + public void ResolveResultIsMethodGroupResolveResult() + { + Assert.IsTrue(resolveResult is MethodGroupResolveResult); + } + + [Test] + public void ResolveResultMethodNameIsRound() + { + Assert.AreEqual("round", MethodResolveResult.Name); + } + + MethodGroupResolveResult MethodResolveResult { + get { return (MethodGroupResolveResult)resolveResult; } + } + + [Test] + public void ResolveResultContainingTypeHasTwoRoundMethods() + { + List exitMethods = GetRoundMethods(); + Assert.AreEqual(2, exitMethods.Count); + } + + List GetRoundMethods() + { + return GetRoundMethods(-1); + } + + List GetRoundMethods(int parameterCount) + { + List methods = MethodResolveResult.ContainingType.GetMethods(); + return PythonCompletionItemsHelper.FindAllMethodsFromCollection("round", parameterCount, methods.ToArray()); + } + + [Test] + public void BothRoundMethodsArePublic() + { + foreach (IMethod method in GetRoundMethods()) { + Assert.IsTrue(method.IsPublic); + } + } + + [Test] + public void BothRoundMethodsHaveClassWithNameOfSys() + { + foreach (IMethod method in GetRoundMethods()) { + Assert.AreEqual("__builtin__", method.DeclaringType.Name); + } + } + + [Test] + public void OneRoundMethodHasTwoParameters() + { + int parameterCount = 2; + Assert.AreEqual(1, GetRoundMethods(parameterCount).Count); + } + + [Test] + public void RoundMethodParameterNameIsNumber() + { + IParameter parameter = GetFirstRoundMethodParameter(); + Assert.AreEqual("number", parameter.Name); + } + + IParameter GetFirstRoundMethodParameter() + { + int parameterCount = 1; + List methods = GetRoundMethods(parameterCount); + IMethod method = methods[0]; + return method.Parameters[0]; + } + + [Test] + public void RoundMethodParameterReturnTypeIsDouble() + { + IParameter parameter = GetFirstRoundMethodParameter(); + Assert.AreEqual("Double", parameter.ReturnType.Name); + } + + [Test] + public void RoundMethodParameterConvertedToStringUsingAmbienceReturnsDoubleNumberString() + { + IAmbience ambience = new CSharpAmbience(); + string text = ambience.Convert(GetFirstRoundMethodParameter()); + Assert.AreEqual("double number", text); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveConsoleWriteLineTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveConsoleWriteLineTestFixture.cs index 8e9ffb2911..9cea39b099 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveConsoleWriteLineTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveConsoleWriteLineTestFixture.cs @@ -20,34 +20,23 @@ namespace PythonBinding.Tests.Resolver /// resolved. /// [TestFixture] - public class ResolveConsoleWriteLineTestFixture + public class ResolveConsoleWriteLineTestFixture : ResolveTestFixtureBase { - PythonResolver resolver; - MockProjectContent mockProjectContent; - ResolveResult resolveResult; - ICompilationUnit compilationUnit; MockClass systemConsoleClass; - MethodGroupResolveResult methodResolveResult; - [TestFixtureSetUp] - public void SetUpFixture() + protected override ExpressionResult GetExpressionResult() { - resolver = new PythonResolver(); - ParseInformation parseInfo = new ParseInformation(); - mockProjectContent = new MockProjectContent(); - - systemConsoleClass = new MockClass(mockProjectContent, "System.Console"); - mockProjectContent.ClassToReturnFromGetClass = systemConsoleClass; - mockProjectContent.ClassNameForGetClass = "Console"; - - compilationUnit = new DefaultCompilationUnit(mockProjectContent); - parseInfo.SetCompilationUnit(compilationUnit); - - string python = "import System\r\n" + - "Console.WriteLine\r\n"; - ExpressionResult expressionResult = new ExpressionResult("Console.WriteLine", new DomRegion(2, 2), null, null); - resolveResult = resolver.Resolve(expressionResult, parseInfo, python); - methodResolveResult = resolveResult as MethodGroupResolveResult; + systemConsoleClass = new MockClass(projectContent, "System.Console"); + projectContent.ClassToReturnFromGetClass = systemConsoleClass; + projectContent.ClassNameForGetClass = "Console"; + return new ExpressionResult("Console.WriteLine", new DomRegion(2, 2), null, null); + } + + protected override string GetPythonScript() + { + return + "import System\r\n" + + "Console.WriteLine\r\n"; } [Test] @@ -62,12 +51,13 @@ namespace PythonBinding.Tests.Resolver [Test] public void GetClassName() { - Assert.AreEqual("Console", mockProjectContent.GetClassName); + Assert.AreEqual("Console", projectContent.GetClassName); } [Test] public void MethodNameResolveIsWriteLine() { + MethodGroupResolveResult methodResolveResult = (MethodGroupResolveResult)resolveResult; Assert.AreEqual("WriteLine", methodResolveResult.Name); } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromMathImportedMathModuleCompletionItemsTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromMathImportedMathModuleCompletionItemsTestFixture.cs index 336e6903a9..04b07292b4 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromMathImportedMathModuleCompletionItemsTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromMathImportedMathModuleCompletionItemsTestFixture.cs @@ -16,32 +16,29 @@ using PythonBinding.Tests.Utils; namespace PythonBinding.Tests.Resolver { [TestFixture] - public class ResolveFromMathImportedMathModuleCompletionItemsTestFixture + public class ResolveFromMathImportedMathModuleCompletionItemsTestFixture : ResolveTestFixtureBase { - ResolveResult resolveResult; - ArrayList results; - PythonResolver resolver; - ExpressionResult result; + ArrayList GetCompletionResults() + { + return resolveResult.GetCompletionData(projectContent); + } - [TestFixtureSetUp] - public void SetUpFixture() + protected override ExpressionResult GetExpressionResult() { - resolver = new PythonResolver(); - ParseInformation parseInfo = new ParseInformation(); - MockProjectContent projectContent = new MockProjectContent(); - parseInfo.SetCompilationUnit(new DefaultCompilationUnit(projectContent)); - - string code = "from math import"; + string code = GetPythonScript(); PythonExpressionFinder finder = new PythonExpressionFinder(); - result = finder.FindExpression(code, code.Length); - resolveResult = resolver.Resolve(result, parseInfo, code); - results = resolveResult.GetCompletionData(projectContent); + return finder.FindExpression(code, code.Length); } - + + protected override string GetPythonScript() + { + return "from math import"; + } + [Test] public void CompletionResultsContainCosMethodFromMathModule() { - IMethod method = PythonCompletionItemsHelper.FindMethodFromArray("cos", results); + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("cos", GetCompletionResults()); Assert.IsNotNull(method); } @@ -53,7 +50,7 @@ namespace PythonBinding.Tests.Resolver DefaultClass c = new DefaultClass(unit, "MyClass"); DefaultMethod method = new DefaultMethod(c, "Test"); - Assert.IsTrue(result.Context.ShowEntry(method)); + Assert.IsTrue(expressionResult.Context.ShowEntry(method)); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleExitMethodTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleExitMethodTestFixture.cs new file mode 100644 index 0000000000..c3413b0cb1 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleExitMethodTestFixture.cs @@ -0,0 +1,140 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Dom.CSharp; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ResolveSysModuleExitMethodTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("sys.exit", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "import sys\r\n" + + "sys.exit\r\n" + + "\r\n"; + } + + [Test] + public void ResolveResultIsMethodGroupResolveResult() + { + Assert.IsTrue(resolveResult is MethodGroupResolveResult); + } + + [Test] + public void ResolveResultMethodNameIsExit() + { + Assert.AreEqual("exit", MethodResolveResult.Name); + } + + MethodGroupResolveResult MethodResolveResult { + get { return (MethodGroupResolveResult)resolveResult; } + } + + [Test] + public void ResolveResultContainingTypeHasTwoExitMethods() + { + List exitMethods = GetExitMethods(); + Assert.AreEqual(2, exitMethods.Count); + } + + List GetExitMethods() + { + return GetExitMethods(-1); + } + + List GetExitMethods(int parameterCount) + { + List methods = MethodResolveResult.ContainingType.GetMethods(); + return PythonCompletionItemsHelper.FindAllMethodsFromCollection("exit", parameterCount, methods.ToArray()); + } + + [Test] + public void BothExitMethodsArePublic() + { + foreach (IMethod method in GetExitMethods()) { + Assert.IsTrue(method.IsPublic); + } + } + + [Test] + public void BothExitMethodsHaveClassWithNameOfSys() + { + foreach (IMethod method in GetExitMethods()) { + Assert.AreEqual("sys", method.DeclaringType.Name); + } + } + + [Test] + public void OneExitMethodHasOneParameter() + { + int parameterCount = 1; + Assert.AreEqual(1, GetExitMethods(parameterCount).Count); + } + + [Test] + public void ExitMethodParameterNameIsCode() + { + IParameter parameter = GetFirstExitMethodParameter(); + Assert.AreEqual("code", parameter.Name); + } + + IParameter GetFirstExitMethodParameter() + { + int parameterCount = 1; + List methods = GetExitMethods(parameterCount); + IMethod method = methods[0]; + return method.Parameters[0]; + } + + [Test] + public void ExitMethodParameterReturnTypeIsObject() + { + IParameter parameter = GetFirstExitMethodParameter(); + Assert.AreEqual("Object", parameter.ReturnType.Name); + } + + [Test] + public void ExitMethodParameterConvertedToStringUsingAmbienceReturnsObjectCodeString() + { + IAmbience ambience = new CSharpAmbience(); + string text = ambience.Convert(GetFirstExitMethodParameter()); + Assert.AreEqual("object code", text); + } + + [Test] + public void ExitMethodReturnTypeConvertedToStringUsingAmbienceReturnsVoid() + { + IAmbience ambience = new CSharpAmbience(); + List methods = GetExitMethods(); + IReturnType returnType = methods[0].ReturnType; + string text = ambience.Convert(returnType); + Assert.AreEqual("void", text); + } + + [Test] + public void MethodGroupContainingTypeHasTwoExitMethods() + { + IReturnType returnType = MethodResolveResult.ContainingType; + List methods = PythonCompletionItemsHelper.FindAllMethodsFromCollection("exit", returnType.GetMethods()); + Assert.AreEqual(2, methods.Count); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleTestFixture.cs new file mode 100644 index 0000000000..13d226204f --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleTestFixture.cs @@ -0,0 +1,61 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ResolveSysModuleTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("sys", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "import sys\r\n" + + "sys\r\n" + + "\r\n"; + } + + [Test] + public void CompilationUnitHasSysModuleInUsingsCollection() + { + Assert.AreEqual("sys", compilationUnit.UsingScope.Usings[0].Usings[0]); + } + + [Test] + public void ResolveResultContainsExitMethod() + { + ArrayList items = GetCompletionItems(); + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("exit", items); + Assert.IsNotNull(method); + } + + ArrayList GetCompletionItems() + { + return resolveResult.GetCompletionData(projectContent); + } + + [Test] + public void MathModuleExpressionShouldNotHaveAnyCompletionItemsSinceMathModuleIsNotImported() + { + ExpressionResult result = new ExpressionResult("math", ExpressionContext.Default); + resolveResult = resolver.Resolve(result, parseInfo, GetPythonScript()); + + Assert.IsNull(resolveResult); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleUnknownMethodTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleUnknownMethodTestFixture.cs new file mode 100644 index 0000000000..522eac13e6 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleUnknownMethodTestFixture.cs @@ -0,0 +1,40 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ResolveSysModuleUnknownMethodTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("sys.unknown", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "import sys\r\n" + + "sys.unknown\r\n" + + "\r\n"; + } + + [Test] + public void ResolveResultIsNull() + { + Assert.IsNull(resolveResult); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemImportTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemImportTestFixture.cs index 6468c4b994..8f90040a95 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemImportTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemImportTestFixture.cs @@ -20,29 +20,18 @@ namespace PythonBinding.Tests.Resolver /// a namespace. /// [TestFixture] - public class ResolveSystemImportTestFixture + public class ResolveSystemImportTestFixture : ResolveTestFixtureBase { - PythonResolver resolver; - MockProjectContent mockProjectContent; - PythonImportModuleResolveResult resolveResult; - ExpressionResult expressionResult; - - [TestFixtureSetUp] - public void SetUpFixture() + protected override ExpressionResult GetExpressionResult() { - resolver = new PythonResolver(); - ParseInformation parseInfo = new ParseInformation(); - mockProjectContent = new MockProjectContent(); - mockProjectContent.SetNamespaceExistsReturnValue(true); - DefaultCompilationUnit cu = new DefaultCompilationUnit(mockProjectContent); - cu.ErrorsDuringCompile = true; - cu.FileName = @"C:\Projects\Test\test.py"; - parseInfo.SetCompilationUnit(cu); - - string code = "import System"; + string code = GetPythonScript(); PythonExpressionFinder finder = new PythonExpressionFinder(); - expressionResult = finder.FindExpression(code, code.Length); - resolveResult = resolver.Resolve(expressionResult, parseInfo, code) as PythonImportModuleResolveResult; + return finder.FindExpression(code, code.Length); + } + + protected override string GetPythonScript() + { + return "import System"; } [Test] @@ -54,7 +43,8 @@ namespace PythonBinding.Tests.Resolver [Test] public void NamespaceName() { - Assert.AreEqual("System", resolveResult.Name); + PythonImportModuleResolveResult importResolveResult = (PythonImportModuleResolveResult)resolveResult; + Assert.AreEqual("System", importResolveResult.Name); } [Test] diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveTestFixtureBase.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveTestFixtureBase.cs new file mode 100644 index 0000000000..605a65e055 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveTestFixtureBase.cs @@ -0,0 +1,44 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + public abstract class ResolveTestFixtureBase + { + protected ICompilationUnit compilationUnit; + protected MockProjectContent projectContent; + protected PythonResolver resolver; + protected ResolveResult resolveResult; + protected ParseInformation parseInfo; + protected ExpressionResult expressionResult; + + [SetUp] + public void InitBase() + { + projectContent = new MockProjectContent(); + PythonParser parser = new PythonParser(); + string fileName = @"C:\projects\test\test.py"; + compilationUnit = parser.Parse(projectContent, fileName, GetPythonScript()); + parseInfo = new ParseInformation(compilationUnit); + + resolver = new PythonResolver(); + + expressionResult = GetExpressionResult(); + resolveResult = resolver.Resolve(expressionResult, parseInfo, GetPythonScript()); + } + + protected abstract ExpressionResult GetExpressionResult(); + + protected abstract string GetPythonScript(); + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveUnknownNamespaceTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveUnknownNamespaceTestFixture.cs index 76806cead1..2565ac0a94 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveUnknownNamespaceTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveUnknownNamespaceTestFixture.cs @@ -20,31 +20,22 @@ namespace PythonBinding.Tests.Resolver /// an unknown namespace. /// [TestFixture] - public class ResolveUnknownNamespaceTestFixture + public class ResolveUnknownNamespaceTestFixture : ResolveTestFixtureBase { - PythonResolver resolver; - MockProjectContent mockProjectContent; - ResolveResult resolveResult; - - [TestFixtureSetUp] - public void SetUpFixture() + protected override ExpressionResult GetExpressionResult() { - resolver = new PythonResolver(); - ParseInformation parseInfo = new ParseInformation(); - mockProjectContent = new MockProjectContent(); - mockProjectContent.NamespacesToAdd.Add("Test"); - - DefaultCompilationUnit cu = new DefaultCompilationUnit(mockProjectContent); - cu.ErrorsDuringCompile = true; - cu.FileName = @"C:\Projects\Test\test.py"; - parseInfo.SetCompilationUnit(cu); + projectContent.NamespacesToAdd.Add("Test"); - string python = "import System\r\n" + - "class Test:\r\n" + - "\tdef __init__(self):\r\n" + - "\t\tUnknown\r\n"; - ExpressionResult expressionResult = new ExpressionResult("Unknown", new DomRegion(3, 2), null, null); - resolveResult = resolver.Resolve(expressionResult, parseInfo, python); + return new ExpressionResult("Unknown", new DomRegion(3, 2), null, null); + } + + protected override string GetPythonScript() + { + return + "import System\r\n" + + "class Test:\r\n" + + " def __init__(self):\r\n" + + " Unknown\r\n"; } [Test] @@ -56,7 +47,7 @@ namespace PythonBinding.Tests.Resolver [Test] public void NamespaceExistsCalled() { - Assert.IsTrue(mockProjectContent.NamespaceExistsCalled); + Assert.IsTrue(projectContent.NamespaceExistsCalled); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/PythonCompletionItemsHelper.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/PythonCompletionItemsHelper.cs index 4a31099944..ede65d23f3 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/PythonCompletionItemsHelper.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/PythonCompletionItemsHelper.cs @@ -7,49 +7,91 @@ using System; using System.Collections; +using System.Collections.Generic; using ICSharpCode.SharpDevelop.Dom; namespace PythonBinding.Tests.Utils { public class PythonCompletionItemsHelper { - public static IMethod FindMethodFromArray(string name, ArrayList items) + delegate bool IsMatch(object item, string name); + + public static IMethod FindMethodFromCollection(string name, ICollection items) + { + return Find(name, items, IsMethodMatch) as IMethod; + } + + static object Find(string name, ICollection items, IsMatch match) { foreach (object item in items) { - IMethod method = item as IMethod; - if (method != null) { - if (method.Name == name) { - return method; - } + if (match(item, name)) { + return item; } } return null; } - public static IField FindFieldFromArray(string name, ArrayList items) + static bool IsMethodMatch(object obj, string name) { - foreach (object item in items) { - IField field = item as IField; - if (field != null) { - if (field.Name == name) { - return field; + return IsMethodMatch(obj, name, -1); + } + + static bool IsMethodMatch(object obj, string name, int parameterCount) + { + IMethod method = obj as IMethod; + if (method != null) { + if (method.Name == name) { + if (parameterCount >= 0) { + return method.Parameters.Count == parameterCount; } + return true; } } - return null; + return false; } - public static IClass FindClassFromArray(string name, ArrayList items) + public static List FindAllMethodsFromCollection(string name, int parameterCount, ICollection items) { + List matchedMethods = new List(); foreach (object item in items) { - IClass c = item as IClass; - if (c != null) { - if (c.Name == name) { - return c; - } + if (IsMethodMatch(item, name, parameterCount)) { + matchedMethods.Add((IMethod)item); } } - return null; + return matchedMethods; + } + + public static List FindAllMethodsFromCollection(string name, ICollection items) + { + return FindAllMethodsFromCollection(name, -1, items); + } + + public static IField FindFieldFromCollection(string name, ICollection items) + { + return Find(name, items, IsFieldMatch) as IField; + } + + static bool IsFieldMatch(object obj, string name) + { + IField field = obj as IField; + if (field != null) { + return field.Name == name; + } + return false; + } + + public static IClass FindClassFromCollection(string name, ICollection items) + { + return Find(name, items, IsClassMatch) as IClass; + } + + static bool IsClassMatch(object obj, string name) + { + IClass c = obj as IClass; + if (c != null) { + return c.Name == name; + } + return false; } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/PythonCompletionItemsHelperTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/PythonCompletionItemsHelperTests.cs index d6eb378e17..3b768670dc 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/PythonCompletionItemsHelperTests.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/PythonCompletionItemsHelperTests.cs @@ -7,6 +7,7 @@ using System; using System.Collections; +using System.Collections.Generic; using ICSharpCode.SharpDevelop.Dom; using NUnit.Framework; using PythonBinding.Tests.Utils; @@ -19,13 +20,18 @@ namespace PythonBinding.Tests.Utils.Tests [Test] public void FindMethodFromArrayReturnsExpectedMethod() { - DefaultClass c = new DefaultClass(new DefaultCompilationUnit(new DefaultProjectContent()), "Test"); + DefaultClass c = CreateClass(); DefaultMethod method = new DefaultMethod(c, "abc"); ArrayList items = new ArrayList(); items.Add(method); - Assert.AreEqual(method, PythonCompletionItemsHelper.FindMethodFromArray("abc", items)); + Assert.AreEqual(method, PythonCompletionItemsHelper.FindMethodFromCollection("abc", items)); + } + + DefaultClass CreateClass() + { + return new DefaultClass(new DefaultCompilationUnit(new DefaultProjectContent()), "Test"); } [Test] @@ -37,54 +43,109 @@ namespace PythonBinding.Tests.Utils.Tests ArrayList items = new ArrayList(); items.Add(method); - Assert.IsNull(PythonCompletionItemsHelper.FindMethodFromArray("unknown", items)); + Assert.IsNull(PythonCompletionItemsHelper.FindMethodFromCollection("unknown", items)); } [Test] public void FindFieldFromArrayReturnsExpectedField() { - DefaultClass c = new DefaultClass(new DefaultCompilationUnit(new DefaultProjectContent()), "Test"); + DefaultClass c = CreateClass(); DefaultField field = new DefaultField(c, "field"); ArrayList items = new ArrayList(); items.Add(field); - Assert.AreEqual(field, PythonCompletionItemsHelper.FindFieldFromArray("field", items)); + Assert.AreEqual(field, PythonCompletionItemsHelper.FindFieldFromCollection("field", items)); } [Test] public void FindFieldFromArrayReturnsExpectedNullForUnknownField() { - DefaultClass c = new DefaultClass(new DefaultCompilationUnit(new DefaultProjectContent()), "Test"); + DefaultClass c = CreateClass(); DefaultField field = new DefaultField(c, "field"); ArrayList items = new ArrayList(); items.Add(field); - Assert.IsNull(PythonCompletionItemsHelper.FindFieldFromArray("unknown-field-name", items)); + Assert.IsNull(PythonCompletionItemsHelper.FindFieldFromCollection("unknown-field-name", items)); } [Test] public void FindClassFromArrayReturnsExpectedClass() { - DefaultClass c = new DefaultClass(new DefaultCompilationUnit(new DefaultProjectContent()), "Test"); + DefaultClass c = CreateClass(); ArrayList items = new ArrayList(); items.Add(c); - Assert.AreEqual(c, PythonCompletionItemsHelper.FindClassFromArray("Test", items)); + Assert.AreEqual(c, PythonCompletionItemsHelper.FindClassFromCollection("Test", items)); } [Test] public void FindClassFromArrayReturnsExpectedNullForUnknownClassName() { - DefaultClass c = new DefaultClass(new DefaultCompilationUnit(new DefaultProjectContent()), "Test"); + DefaultClass c = CreateClass(); ArrayList items = new ArrayList(); items.Add(c); - Assert.IsNull(PythonCompletionItemsHelper.FindClassFromArray("unknown-class-name", items)); + Assert.IsNull(PythonCompletionItemsHelper.FindClassFromCollection("unknown-class-name", items)); + } + + [Test] + public void FindAllMethodsFromArrayReturnsExpectedMethods() + { + DefaultClass c = CreateClass(); + DefaultMethod method1 = new DefaultMethod(c, "abc"); + DefaultMethod method2 = new DefaultMethod(c, "abc"); + DefaultMethod method3 = new DefaultMethod(c, "def"); + + ArrayList items = new ArrayList(); + items.Add(method1); + items.Add(method2); + items.Add(method3); + + List expectedMethods = new List(); + expectedMethods.Add(method1); + expectedMethods.Add(method2); + + List methods = PythonCompletionItemsHelper.FindAllMethodsFromCollection("abc", items); + Assert.AreEqual(expectedMethods, methods); + } + + [Test] + public void FindAllMethodsFromArrayWithParameterCountReturnsExpectedMethods() + { + DefaultClass c = CreateClass(); + DefaultMethod method1 = new DefaultMethod(c, "abc"); + method1.Parameters.Add(CreateParameter("a")); + + DefaultMethod method2 = new DefaultMethod(c, "abc"); + method2.Parameters.Add(CreateParameter("a")); + method2.Parameters.Add(CreateParameter("b")); + + DefaultMethod method3 = new DefaultMethod(c, "abc"); + method3.Parameters.Add(CreateParameter("c")); + + ArrayList items = new ArrayList(); + items.Add(method1); + items.Add(method2); + items.Add(method3); + + List expectedMethods = new List(); + expectedMethods.Add(method1); + expectedMethods.Add(method3); + + int parameterCount = 1; + List methods = PythonCompletionItemsHelper.FindAllMethodsFromCollection("abc", parameterCount, items); + Assert.AreEqual(expectedMethods, methods); + } + + DefaultParameter CreateParameter(string name) + { + DefaultReturnType returnType = new DefaultReturnType(CreateClass()); + DomRegion region = new DomRegion(1, 1); + return new DefaultParameter(name, returnType, region); } - } }