diff --git a/src/AddIns/BackendBindings/Python/Python.Build.Tasks/Project/Src/PythonCompiler.cs b/src/AddIns/BackendBindings/Python/Python.Build.Tasks/Project/Src/PythonCompiler.cs index f75aec175d..c75550d014 100644 --- a/src/AddIns/BackendBindings/Python/Python.Build.Tasks/Project/Src/PythonCompiler.cs +++ b/src/AddIns/BackendBindings/Python/Python.Build.Tasks/Project/Src/PythonCompiler.cs @@ -133,7 +133,7 @@ namespace ICSharpCode.Python.Build.Tasks /// Generates an executable from the already compiled dll. /// void GenerateExecutable(string outputAssemblyDll) - { + { string outputAssemblyFileNameWithoutExtension = Path.GetFileNameWithoutExtension(outputAssembly); AssemblyName assemblyName = new AssemblyName(outputAssemblyFileNameWithoutExtension); AssemblyBuilder assemblyBuilder = PythonOps.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); @@ -141,14 +141,45 @@ namespace ICSharpCode.Python.Build.Tasks TypeBuilder typeBuilder = moduleBuilder.DefineType("PythonMain", TypeAttributes.Public); MethodBuilder mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[0]); - // Mark main method as STA. - mainMethod.SetCustomAttribute(typeof(STAThreadAttribute).GetConstructor(Type.EmptyTypes), new byte[0]); + MarkMainMethodAsSTA(mainMethod); + GenerateMainMethodBody(mainMethod, outputAssemblyDll); + + // Add resources. + AddResources(moduleBuilder); + // Create executable. + typeBuilder.CreateType(); + assemblyBuilder.SetEntryPoint(mainMethod, targetKind); + assemblyBuilder.Save(assemblyName.Name + ".exe", executableKind, machine); + } + + void MarkMainMethodAsSTA(MethodBuilder mainMethod) + { + mainMethod.SetCustomAttribute(typeof(STAThreadAttribute).GetConstructor(Type.EmptyTypes), new byte[0]); + } + + void GenerateMainMethodBody(MethodBuilder mainMethod, string outputAssemblyDll) + { ILGenerator generator = mainMethod.GetILGenerator(); + LocalBuilder exeAssemblyLocalVariable = generator.DeclareLocal(typeof(Assembly)); + LocalBuilder directoryLocalVariable = generator.DeclareLocal(typeof(string)); + LocalBuilder fileNameLocalVariable = generator.DeclareLocal(typeof(string)); + + generator.EmitCall(OpCodes.Call, typeof(Assembly).GetMethod("GetExecutingAssembly", new Type[0], new ParameterModifier[0]), null); + generator.Emit(OpCodes.Stloc_0); + + generator.Emit(OpCodes.Ldloc_0); + generator.EmitCall(OpCodes.Callvirt, typeof(Assembly).GetMethod("get_Location"), null); + generator.EmitCall(OpCodes.Call, typeof(Path).GetMethod("GetDirectoryName", new Type[] {typeof(String)}, new ParameterModifier[0]), null); + generator.Emit(OpCodes.Stloc_1); + + generator.Emit(OpCodes.Ldloc_1); generator.Emit(OpCodes.Ldstr, Path.GetFileName(outputAssemblyDll)); - generator.EmitCall(OpCodes.Call, typeof(Path).GetMethod("GetFullPath", new Type[] {typeof(String)}, new ParameterModifier[0]), null); - generator.EmitCall(OpCodes.Call, typeof(Assembly).GetMethod("LoadFile", new Type[] {typeof(String)}, new ParameterModifier[0]), null); + generator.EmitCall(OpCodes.Call, typeof(Path).GetMethod("Combine", new Type[] {typeof(String), typeof(String)}, new ParameterModifier[0]), null); + generator.Emit(OpCodes.Stloc_2); + generator.Emit(OpCodes.Ldloc_2); + generator.EmitCall(OpCodes.Call, typeof(Assembly).GetMethod("LoadFile", new Type[] {typeof(String)}, new ParameterModifier[0]), null); generator.Emit(OpCodes.Ldstr, Path.GetFileNameWithoutExtension(mainFile)); // Add referenced assemblies. @@ -156,14 +187,6 @@ namespace ICSharpCode.Python.Build.Tasks generator.EmitCall(OpCodes.Call, typeof(PythonOps).GetMethod("InitializeModule"), new Type[0]); generator.Emit(OpCodes.Ret); - - // Add resources. - AddResources(moduleBuilder); - - // Create executable. - typeBuilder.CreateType(); - assemblyBuilder.SetEntryPoint(mainMethod, targetKind); - assemblyBuilder.Save(assemblyName.Name + ".exe", executableKind, machine); } /// diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj index acc67e636b..eec429f367 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/PythonBinding.csproj @@ -44,6 +44,9 @@ ..\..\RequiredLibraries\IronPython.dll + + ..\..\RequiredLibraries\IronPython.Modules.dll + ..\..\RequiredLibraries\Microsoft.Dynamic.dll @@ -71,6 +74,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -92,13 +115,18 @@ + + - + + + + @@ -108,8 +136,9 @@ - + + Always diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/IPythonResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/IPythonResolver.cs new file mode 100644 index 0000000000..5610daefd4 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/IPythonResolver.cs @@ -0,0 +1,17 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public interface IPythonResolver + { + ResolveResult Resolve(PythonResolverContext resolverContext, ExpressionResult expressionResult); + } +} 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/PythonAstWalker.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs index bce3cef11c..3c276ddd91 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs @@ -25,7 +25,7 @@ namespace ICSharpCode.PythonBinding DefaultCompilationUnit compilationUnit; DefaultClass currentClass; DefaultClass globalClass; - string ns; + string currentNamespace; /// /// All classes in a file take the namespace of the filename. @@ -34,7 +34,7 @@ namespace ICSharpCode.PythonBinding { compilationUnit = new DefaultCompilationUnit(projectContent); compilationUnit.FileName = fileName; - ns = Path.GetFileNameWithoutExtension(fileName); + currentNamespace = Path.GetFileNameWithoutExtension(fileName); } /// @@ -116,13 +116,15 @@ namespace ICSharpCode.PythonBinding /// public override bool Walk(ImportStatement node) { - Console.WriteLine("Walk.Import"); - DefaultUsing newUsing = new DefaultUsing(compilationUnit.ProjectContent); - foreach (DottedName name in node.Names) { - Console.WriteLine("Name: " + name.MakeString()); - newUsing.Usings.Add(name.MakeString()); - } - compilationUnit.UsingScope.Usings.Add(newUsing); + 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); return false; } @@ -138,7 +140,7 @@ namespace ICSharpCode.PythonBinding /// method or class definition up to the colon. DomRegion GetBodyRegion(Statement body, SourceLocation header) { - // Add one so the region starts from just after the colon. + int columnAfterColonCharacter = header.Column + 1; return new DomRegion(header.Line, header.Column + 1, body.End.Line, body.End.Column); } @@ -213,7 +215,7 @@ namespace ICSharpCode.PythonBinding /// string GetFullyQualifiedClassName(ClassDefinition classDef) { - return String.Concat(ns, ".", classDef.Name); + return String.Concat(currentNamespace, ".", classDef.Name); } /// @@ -222,7 +224,7 @@ namespace ICSharpCode.PythonBinding void CreateGlobalClass() { if (globalClass == null) { - globalClass = new DefaultClass(compilationUnit, ns); + globalClass = new DefaultClass(compilationUnit, currentNamespace); compilationUnit.Classes.Add(globalClass); } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonBuiltInModuleMemberName.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonBuiltInModuleMemberName.cs new file mode 100644 index 0000000000..e0386e0b6e --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonBuiltInModuleMemberName.cs @@ -0,0 +1,26 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.PythonBinding +{ + public class PythonBuiltInModuleMemberName : MemberName + { + public const string PythonBuiltInModuleName = "__builtin__"; + + public PythonBuiltInModuleMemberName(string memberName) + : base(PythonBuiltInModuleName, memberName) + { + } + + public static bool IsBuiltInModule(string name) + { + return name == PythonBuiltInModuleName; + } + } +} 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..89ce150a66 --- /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 : IPythonResolver + { + 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/PythonCodeCompletionBinding.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCodeCompletionBinding.cs index ca07b74f0c..e31def2822 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCodeCompletionBinding.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonCodeCompletionBinding.cs @@ -34,7 +34,7 @@ namespace ICSharpCode.PythonBinding switch (word.ToLowerInvariant()) { case "import": case "from": - CtrlSpaceCompletionItemProvider dataProvider = CreateCtrlSpaceCompletionDataProvider(ExpressionContext.Importable); + AbstractCompletionItemProvider dataProvider = CreateCompletionDataProvider(); ShowCodeCompletionWindow(editor, dataProvider, ' '); return true; } @@ -42,18 +42,9 @@ namespace ICSharpCode.PythonBinding return false; } - public override bool CtrlSpace(ICSharpCode.SharpDevelop.Editor.ITextEditor editor) + protected virtual AbstractCompletionItemProvider CreateCompletionDataProvider() { - CreateCtrlSpaceCompletionDataProvider(null).ShowCompletion(editor); - return true; - } - - /// - /// Creates a CtrlSpaceCompletionItemProvider. - /// - protected virtual CtrlSpaceCompletionItemProvider CreateCtrlSpaceCompletionDataProvider(ExpressionContext expressionContext) - { - return new PythonCtrlSpaceCompletionItemProvider(expressionContext); + return new CodeCompletionItemProvider(); } /// @@ -63,23 +54,5 @@ namespace ICSharpCode.PythonBinding { completionItemProvider.ShowCompletion(editor); } - - class PythonCtrlSpaceCompletionItemProvider : CtrlSpaceCompletionItemProvider - { - public PythonCtrlSpaceCompletionItemProvider(ExpressionContext context) - : base(context) - { - } - - protected override List CtrlSpace(ICSharpCode.SharpDevelop.Editor.ITextEditor editor, ExpressionContext context) - { - return new PythonResolver().CtrlSpace( - editor.Caret.Line, - editor.Caret.Column, - ParserService.GetParseInformation(editor.FileName), - editor.Document.Text, - context); - } - } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs index 838f993d96..13cbb95f63 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonControlFieldExpression.cs @@ -275,9 +275,13 @@ namespace ICSharpCode.PythonBinding if (property != null) { string name = nameExpression.Name; if (property.PropertyType != typeof(bool)) { - object instance = componentCreator.GetInstance(name); - if (instance != null) { - return SetPropertyValue(component, memberName, instance); + if ("self" == name) { + return SetPropertyValue(component, memberName, componentCreator.RootComponent); + } else { + object instance = componentCreator.GetInstance(name); + if (instance != null) { + return SetPropertyValue(component, memberName, instance); + } } } return SetPropertyValue(component, memberName, name); diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerGenerator.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerGenerator.cs index e11fa27c4f..8262adcfcc 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerGenerator.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerGenerator.cs @@ -13,11 +13,14 @@ using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; +using System.Drawing; +using System.Reflection; using System.Text; using System.Windows.Forms; using ICSharpCode.FormsDesigner; using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Project; diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDotNetMethodResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDotNetMethodResolver.cs new file mode 100644 index 0000000000..8aac5b07cd --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDotNetMethodResolver.cs @@ -0,0 +1,32 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonDotNetMethodResolver + { + PythonClassResolver classResolver; + + public PythonDotNetMethodResolver(PythonClassResolver classResolver) + { + this.classResolver = classResolver; + } + + public ResolveResult Resolve(PythonResolverContext resolverContext, ExpressionResult expressionResult) + { + MemberName memberName = new MemberName(expressionResult.Expression); + IClass matchingClass = classResolver.GetClass(resolverContext, memberName.Type); + if (matchingClass != null) { + return new PythonMethodGroupResolveResult(matchingClass, memberName.Name); + } + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpression.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpression.cs new file mode 100644 index 0000000000..613a2fbc8a --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpression.cs @@ -0,0 +1,80 @@ +// +// +// +// +// $Revision$ +// + +using System; +using Microsoft.Scripting; +using Microsoft.Scripting.Hosting; +using Microsoft.Scripting.Hosting.Providers; +using Microsoft.Scripting.Runtime; +using IronPython.Compiler; +using IronPython.Runtime; + +namespace ICSharpCode.PythonBinding +{ + public class PythonExpression + { + Tokenizer tokenizer; + Token currentToken; + + public PythonExpression(ScriptEngine engine, string expression) + { + Init(engine, expression); + } + + void Init(ScriptEngine engine, string expression) + { + PythonContext context = HostingHelpers.GetLanguageContext(engine) as PythonContext; + SourceUnit source = CreateSourceUnit(context, expression); + CreateTokenizer(source); + } + + SourceUnit CreateSourceUnit(PythonContext context, string expression) + { + StringTextContentProvider textProvider = new StringTextContentProvider(expression); + return context.CreateSourceUnit(textProvider, String.Empty, SourceCodeKind.SingleStatement); + } + + void CreateTokenizer(SourceUnit source) + { + PythonCompilerSink sink = new PythonCompilerSink(); + PythonCompilerOptions options = new PythonCompilerOptions(); + + tokenizer = new Tokenizer(sink, options); + tokenizer.Initialize(source); + } + + public Token GetNextToken() + { + currentToken = tokenizer.GetNextToken(); + return currentToken; + } + + public Token CurrentToken { + get { return currentToken; } + } + + public bool IsImportToken(Token token) + { + return token.Kind == IronPython.Compiler.TokenKind.KeywordImport; + } + + public bool IsFromToken(Token token) + { + return token.Kind == IronPython.Compiler.TokenKind.KeywordFrom; + } + + public bool IsDotToken(Token token) + { + return token.Kind == IronPython.Compiler.TokenKind.Dot; + } + + public bool IsNameToken(Token token) + { + return token.Kind == IronPython.Compiler.TokenKind.Name; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpressionFinder.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpressionFinder.cs index de9ff715ee..ae5a64ba72 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpressionFinder.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonExpressionFinder.cs @@ -15,57 +15,20 @@ namespace ICSharpCode.PythonBinding /// public class PythonExpressionFinder : IExpressionFinder { - static readonly string ImportStatement = "import"; - - public PythonExpressionFinder() + class ExpressionRange { + public int Start; + public int End; + + public int Length { + get { return End - Start + 1; } + } } - /// - /// Finds an expression before the current offset. - /// - /// - /// The expression is found before the specified offset. The - /// offset is just before the current cursor position. For example, - /// if the user presses the dot character then the offset - /// will be just before the dot. All characters before the offset and - /// at the offset are considered when looking for - /// the expression. All characters afterwards are ignored. - /// - public ExpressionResult FindExpression(string text, int offset) + ExpressionRange expressionRange = new ExpressionRange(); + + public PythonExpressionFinder() { - if (text != null && IsValidOffset(text, offset)) { - bool found = false; - ExpressionContext expressionContext = ExpressionContext.Default; - int currentOffset = offset - 1; - while (!found && currentOffset >= 0) { - char currentChar = text[currentOffset]; - switch (currentChar) { - case '\n': - case '\r': - case '\t': - found = true; - break; - case ' ': - if (IsImportStatement(text, currentOffset - 1)) { - // Make sure entire line is taken. - currentOffset = FindLineStartOffset(text, currentOffset); - currentOffset--; - expressionContext = ExpressionContext.Importable; - } - found = true; - break; - default: - currentOffset--; - break; - } - } - - // Create expression result. - string expression = Substring(text, currentOffset + 1, offset - 1); - return new ExpressionResult(expression, expressionContext); - } - return new ExpressionResult(null); } /// @@ -90,26 +53,42 @@ 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; } - + /// - /// Gets the substring starting from the specified index and - /// finishing at the specified end index. The character at the - /// end index is included in the string. + /// Finds an expression before the current offset. /// - static string Substring(string text, int startIndex, int endIndex) + /// + /// The expression is found before the specified offset. The + /// offset is just before the current cursor position. For example, + /// if the user presses the dot character then the offset + /// will be just before the dot. All characters before the offset and + /// at the offset are considered when looking for + /// the expression. All characters afterwards are ignored. + /// + public ExpressionResult FindExpression(string text, int offset) { - int length = endIndex - startIndex + 1; - return text.Substring(startIndex, length); + if (!IsValidFindExpressionParameters(text, offset)) { + return new ExpressionResult(null); + } + + expressionRange.End = offset - 1; + expressionRange.Start = FindExpressionStart(text, expressionRange.End); + + if (IsImportExpression(text)) { + ExtendRangeToStartOfLine(text); + return CreatePythonImportExpressionResult(text, expressionRange); + } + return CreateDefaultExpressionResult(text, expressionRange); } + bool IsValidFindExpressionParameters(string text, int offset) + { + return (text != null) && IsValidOffset(text, offset); + } + /// /// This checks that the offset passed to the FindExpression method is valid. Usually the offset is /// just after the last character in the text. @@ -120,77 +99,99 @@ namespace ICSharpCode.PythonBinding /// 2) Be inside the string. /// 3) Be just after the end of the text. /// - static bool IsValidOffset(string text, int offset) + bool IsValidOffset(string text, int offset) { return (offset > 0) && (offset <= text.Length); } - /// - /// Checks that the preceding text is an import statement. - /// The offset points to the last character of the import statement - /// (i.e. the 't') if it exists. - /// - static bool IsImportStatement(string text, int offset) - { - // Trim any whitespace from the end. - while (StringLongerThanImportStatement(offset)) { - if (text[offset] == ' ') { - --offset; - } else { - break; + int FindExpressionStart(string text, int offset) + { + while (offset >= 0) { + char currentChar = text[offset]; + switch (currentChar) { + case '\n': + case '\r': + case '\t': + case ' ': + return offset + 1; } + offset--; + } + return 0; + } + + bool IsImportExpression(string text) + { + if (PythonImportExpression.IsImportExpression(text, expressionRange.End)) { + return true; } - // Look for import statement. - if (StringLongerThanImportStatement(offset)) { - int i; - for (i = ImportStatement.Length - 1; i >= 0; --i) { - char currentChar = text[offset]; - if (currentChar != ImportStatement[i]) { - return false; - } - --offset; - } - - // Complete match? - if (i == -1) { + if (IsSpaceCharacterBeforeExpression(text, expressionRange)) { + if (PythonImportExpression.IsImportExpression(text, expressionRange.Start)) { return true; } } return false; } - /// - /// Tests that the string is long enough to contain the - /// import statement. This tests that: - /// - /// (offset + 1) >= ImportStatement.Length - /// - /// The offset points to the last character in the string - /// which could be part of the import statement. - /// - static bool StringLongerThanImportStatement(int offset) + bool IsSpaceCharacterBeforeExpression(string text, ExpressionRange range) + { + int characterBeforeExpressionOffset = range.Start - 1; + if (characterBeforeExpressionOffset >= 0) { + return text[characterBeforeExpressionOffset] == ' '; + } + return false; + } + + void ExtendRangeToStartOfLine(string text) { - return (offset + 1) >= ImportStatement.Length; + if (expressionRange.Start > expressionRange.End) { + expressionRange.Start = expressionRange.End; + } + expressionRange.Start = FindLineStart(text, expressionRange.Start); } /// /// Finds the start of the line in the text starting from the /// offset and working backwards. /// - static int FindLineStartOffset(string text, int offset) + int FindLineStart(string text, int offset) { while (offset >= 0) { char currentChar = text[offset]; switch (currentChar) { case '\n': return offset + 1; - default: - --offset; - break; } + --offset; } return 0; } + + ExpressionResult CreatePythonImportExpressionResult(string text, ExpressionRange range) + { + return CreateExpressionResult(text, range, new PythonImportExpressionContext()); + } + + ExpressionResult CreateDefaultExpressionResult(string text, ExpressionRange range) + { + return CreateExpressionResult(text, range, ExpressionContext.Default); + } + + ExpressionResult CreateExpressionResult(string text, ExpressionRange range, ExpressionContext context) + { + string expression = Substring(text, range); + return new ExpressionResult(expression, context); + } + + /// + /// Gets the substring starting from the specified index and + /// finishing at the specified end index. The character at the + /// end index is included in the string. + /// + string Substring(string text, ExpressionRange range) + { + return text.Substring(range.Start, range.Length); + } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormsDesignerDisplayBinding.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormsDesignerDisplayBinding.cs index 114adcd627..d0b1a194c9 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormsDesignerDisplayBinding.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormsDesignerDisplayBinding.cs @@ -8,6 +8,7 @@ using ICSharpCode.SharpDevelop.Editor; using System; using System.IO; + using ICSharpCode.FormsDesigner; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFromImport.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFromImport.cs new file mode 100644 index 0000000000..31ec0dae18 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFromImport.cs @@ -0,0 +1,73 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using IronPython.Compiler.Ast; + +namespace ICSharpCode.PythonBinding +{ + public class PythonFromImport : DefaultUsing + { + FromImportStatement fromImport; + + public PythonFromImport(IProjectContent projectContent, FromImportStatement fromImport) + : base(projectContent) + { + this.fromImport = fromImport; + } + + public bool IsImportedName(string name) + { + if (String.IsNullOrEmpty(name)) { + return false; + } + + for (int i = 0; i < fromImport.Names.Count; ++i) { + string importedName = GetImportedAsNameIfExists(i); + if (importedName == name) { + return true; + } + } + return false; + } + + string GetImportedAsNameIfExists(int index) + { + if (fromImport.AsNames != null) { + string importedAsName = fromImport.AsNames[index]; + if (importedAsName != null) { + return importedAsName; + } + } + return fromImport.Names[index]; + } + + public string Module { + get { return fromImport.Root.MakeString(); } + } + + public string GetOriginalNameForAlias(string alias) + { + if (fromImport.AsNames == null) { + return null; + } + + int index = fromImport.AsNames.IndexOf(alias); + if (index >= 0) { + return fromImport.Names[index]; + } + return null; + } + + public bool ImportsEverything { + get { + return fromImport.Names[0] == "*"; + } + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImport.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImport.cs new file mode 100644 index 0000000000..8671bbf156 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImport.cs @@ -0,0 +1,55 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using IronPython.Compiler.Ast; + +namespace ICSharpCode.PythonBinding +{ + public class PythonImport : DefaultUsing + { + ImportStatement importStatement; + + public PythonImport(IProjectContent projectContent, ImportStatement importStatement) + : base(projectContent) + { + this.importStatement = importStatement; + AddUsings(); + } + + void AddUsings() + { + for (int i = 0; i < importStatement.Names.Count; ++i) { + string name = GetImportedAsNameIfExists(i); + Usings.Add(name); + } + } + + string GetImportedAsNameIfExists(int index) + { + string name = importStatement.AsNames[index]; + if (name != null) { + return name; + } + return importStatement.Names[index].MakeString(); + } + + public string Module { + get { return importStatement.Names[0].MakeString(); } + } + + public string GetOriginalNameForAlias(string alias) + { + int index = importStatement.AsNames.IndexOf(alias); + if (index >= 0) { + return importStatement.Names[index].MakeString(); + } + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportCompletion.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportCompletion.cs new file mode 100644 index 0000000000..aa9ffe5098 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportCompletion.cs @@ -0,0 +1,63 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Reflection; +using ICSharpCode.SharpDevelop.Dom; +using IronPython.Modules; +using IronPython.Runtime; + +namespace ICSharpCode.PythonBinding +{ + public class PythonImportCompletion + { + IProjectContent projectContent; + static readonly PythonStandardModules standardPythonModules = new PythonStandardModules(); + + public PythonImportCompletion(IProjectContent projectContent) + { + this.projectContent = projectContent; + } + + public List GetCompletionItems() + { + return GetCompletionItems(String.Empty); + } + + public List GetCompletionItems(string subNamespace) + { + List items = projectContent.GetNamespaceContents(subNamespace); + + if (String.IsNullOrEmpty(subNamespace)) { + AddStandardPythonModules(items); + } + return items; + } + + void AddStandardPythonModules(List items) + { + items.AddRange(standardPythonModules); + } + + public List GetCompletionItemsFromModule(string module) + { + PythonStandardModuleType type = standardPythonModules.GetModuleType(module); + if (type != null) { + return GetCompletionItemsFromModule(type); + } + return projectContent.GetNamespaceContents(module); + } + + List GetCompletionItemsFromModule(PythonStandardModuleType type) + { + PythonModuleCompletionItems moduleItems = PythonModuleCompletionItemsFactory.Create(type); + List items = new List(moduleItems); + return items; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportExpression.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportExpression.cs new file mode 100644 index 0000000000..07bcc5a915 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportExpression.cs @@ -0,0 +1,179 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Text; +using IronPython.Compiler; +using IronPython.Hosting; +using Microsoft.Scripting.Hosting; + +namespace ICSharpCode.PythonBinding +{ + public class PythonImportExpression : PythonExpression + { + string module = String.Empty; + string identifier = String.Empty; + bool hasFromAndImport; + + public PythonImportExpression(string expression) + : this(Python.CreateEngine(), expression) + { + } + + public PythonImportExpression(ScriptEngine engine, string expression) + : base(engine, expression) + { + Parse(engine, expression); + } + + void Parse(ScriptEngine engine, string expression) + { + Token token = GetNextToken(); + if (IsImportToken(token)) { + ParseImportExpression(); + } else if (IsFromToken(token)) { + ParseFromExpression(); + } + } + + void ParseImportExpression() + { + GetModuleName(); + } + + void ParseFromExpression() + { + GetModuleName(); + + if (IsImportToken(CurrentToken)) { + hasFromAndImport = true; + GetIdentifierName(); + } + } + + void GetModuleName() + { + module = GetName(); + } + + string GetName() + { + StringBuilder name = new StringBuilder(); + Token token = GetNextToken(); + while (IsNameToken(token)) { + name.Append((string)token.Value); + token = GetNextToken(); + if (IsDotToken(token)) { + name.Append('.'); + token = GetNextToken(); + } + } + return name.ToString(); + } + + void GetIdentifierName() + { + identifier = GetName(); + } + + public bool HasFromAndImport { + get { return hasFromAndImport; } + } + + public string Module { + get { return module; } + } + + public string Identifier { + get { return identifier; } + } + + public bool HasIdentifier { + get { return !String.IsNullOrEmpty(identifier); } + } + + /// + /// Returns true if the expression is of the form: + /// + /// "import " + /// "from " + /// "import System" + /// "from System" + /// "from System import Console" + /// + public static bool IsImportExpression(string text, int offset) + { + if (!ValidIsImportExpressionParameters(text, offset)) { + return false; + } + + string previousWord = FindPreviousWord(text, offset); + if (IsImportOrFromString(previousWord)) { + return true; + } + + int previousWordOffset = offset - previousWord.Length + 1; + previousWord = FindPreviousWord(text, previousWordOffset); + return IsImportOrFromString(previousWord); + } + + static bool ValidIsImportExpressionParameters(string text, int offset) + { + if (String.IsNullOrEmpty(text) || (offset <= 0) || (offset >= text.Length)) { + return false; + } + return true; + } + + static string FindPreviousWord(string text, int offset) + { + int previousWordOffset = FindPreviousWordOffset(text, offset); + int length = offset - previousWordOffset + 1; + return text.Substring(previousWordOffset, length); + } + + static int FindPreviousWordOffset(string text, int offset) + { + bool ignoreWhitespace = true; + while (offset > 0) { + char ch = text[offset]; + if (Char.IsWhiteSpace(ch)) { + if (IsNewLineOrCarriageReturn(ch)) { + return offset; + } + if (!ignoreWhitespace) { + return offset; + } + } else { + ignoreWhitespace = false; + } + --offset; + } + return offset; + } + + static bool IsNewLineOrCarriageReturn(char ch) + { + return (ch == '\r') || (ch == '\n'); + } + + static bool IsImportOrFromString(string text) + { + return IsImportString(text) || IsFromString(text); + } + + static bool IsImportString(string text) + { + return text.Trim() == "import"; + } + + static bool IsFromString(string text) + { + return text.Trim() == "from"; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportExpressionContext.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportExpressionContext.cs new file mode 100644 index 0000000000..4232cde21d --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportExpressionContext.cs @@ -0,0 +1,42 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonImportExpressionContext : ExpressionContext + { + public bool HasFromAndImport { get; set; } + + public override bool ShowEntry(ICompletionEntry entry) + { + if (HasFromAndImport) { + return ShowEntryForImportIdentifier(entry); + } + return ShowEntryForImportModule(entry); + } + + bool ShowEntryForImportModule(ICompletionEntry entry) + { + return entry is NamespaceEntry; + } + + bool ShowEntryForImportIdentifier(ICompletionEntry entry) + { + if (entry is IMethod) { + return true; + } else if (entry is IField) { + return true; + } else if (entry is IClass) { + return true; + } + return false; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportModuleResolveResult.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportModuleResolveResult.cs new file mode 100644 index 0000000000..38e5e063b2 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportModuleResolveResult.cs @@ -0,0 +1,47 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonImportModuleResolveResult : ResolveResult + { + PythonImportExpression expression; + + public PythonImportModuleResolveResult(PythonImportExpression expression) + : base(null, null, null) + { + this.expression = expression; + } + + public string Name { + get { return expression.Module; } + } + + public override List GetCompletionData(IProjectContent projectContent) + { + PythonImportCompletion completion = new PythonImportCompletion(projectContent); + if (expression.HasFromAndImport) { + if (expression.HasIdentifier) { + return new List(); + } else { + return completion.GetCompletionItemsFromModule(expression.Module); + } + } + return completion.GetCompletionItems(expression.Module); + } + + public override ResolveResult Clone() + { + return new PythonImportModuleResolveResult(expression); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportResolver.cs new file mode 100644 index 0000000000..3d0b280876 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonImportResolver.cs @@ -0,0 +1,36 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonImportResolver : IPythonResolver + { + public PythonImportResolver() + { + } + + public ResolveResult Resolve(PythonResolverContext resolverContext, 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/PythonMethodGroupResolveResult.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethodGroupResolveResult.cs new file mode 100644 index 0000000000..da4df52284 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethodGroupResolveResult.cs @@ -0,0 +1,20 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonMethodGroupResolveResult : MethodGroupResolveResult + { + public PythonMethodGroupResolveResult(IClass containingClass, string methodName) + : base(null, null, containingClass.DefaultReturnType, methodName) + { + } + } +} 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..d56e50661d --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonMethodResolver.cs @@ -0,0 +1,33 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonMethodResolver : IPythonResolver + { + PythonDotNetMethodResolver dotNetMethodResolver; + PythonStandardModuleMethodResolver standardModuleMethodResolver; + + public PythonMethodResolver(PythonClassResolver classResolver, PythonStandardModuleResolver standardModuleResolver) + { + dotNetMethodResolver = new PythonDotNetMethodResolver(classResolver); + standardModuleMethodResolver = new PythonStandardModuleMethodResolver(standardModuleResolver); + } + + public ResolveResult Resolve(PythonResolverContext resolverContext, ExpressionResult expressionResult) + { + ResolveResult resolveResult = dotNetMethodResolver.Resolve(resolverContext, expressionResult); + if (resolveResult != null) { + return resolveResult; + } + return standardModuleMethodResolver.Resolve(resolverContext, expressionResult); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItems.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItems.cs new file mode 100644 index 0000000000..dbd73a744f --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItems.cs @@ -0,0 +1,160 @@ +// +// +// +// +// $Revision$ +// + +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 +{ + public class PythonModuleCompletionItems : List + { + DefaultCompilationUnit compilationUnit; + DefaultClass moduleClass; + DefaultProjectContent projectContent; + + static readonly BindingFlags PublicAndStaticBindingFlags = BindingFlags.Public | BindingFlags.Static; + + public PythonModuleCompletionItems(PythonStandardModuleType moduleType) + { + projectContent = new DefaultProjectContent(); + compilationUnit = new DefaultCompilationUnit(projectContent); + moduleClass = new DefaultClass(compilationUnit, moduleType.Name); + + AddCompletionItemsForType(moduleType.Type); + AddStandardCompletionItems(); + } + + void AddCompletionItemsForType(Type type) + { + foreach (MemberInfo member in type.GetMembers(PublicAndStaticBindingFlags)) { + if (!HasPythonHiddenAttribute(member)) { + ICompletionEntry item = CreateCompletionItem(member, moduleClass); + if (item != null) { + Add(item); + } + } + } + } + + void AddStandardCompletionItems() + { + AddField("__name__"); + AddField("__package__"); + } + + protected void AddField(string name) + { + DefaultField field = new DefaultField(moduleClass, name); + Add(field); + } + + bool HasPythonHiddenAttribute(MemberInfo memberInfo) + { + foreach (Attribute attribute in memberInfo.GetCustomAttributes(false)) { + Type type = attribute.GetType(); + if (type.Name == "PythonHiddenAttribute") { + return true; + } + } + return false; + } + + ICompletionEntry CreateCompletionItem(MemberInfo memberInfo, IClass c) + { + if (memberInfo is MethodInfo) { + return CreateMethodFromMethodInfo((MethodInfo)memberInfo, c); + } else if (memberInfo is FieldInfo) { + return CreateFieldFromFieldInfo((FieldInfo)memberInfo, c); + } else if (memberInfo is Type) { + return CreateClassFromType((Type)memberInfo); + } + return null; + } + + IMethod CreateMethodFromMethodInfo(MethodInfo methodInfo, IClass c) + { + 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) + { + return new DefaultField(c, fieldInfo.Name); + } + + IClass CreateClassFromType(Type type) + { + DefaultCompilationUnit unit = new DefaultCompilationUnit(projectContent); + return new DefaultClass(unit, type.Name); + } + + public MethodGroup GetMethods(string name) + { + List methods = new List(); + foreach (object member in this) { + 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 new file mode 100644 index 0000000000..2d55a47748 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonModuleCompletionItemsFactory.cs @@ -0,0 +1,28 @@ +// +// +// +// +// $Revision$ +// + +using System; +using IronPython.Modules; + +namespace ICSharpCode.PythonBinding +{ + public static class PythonModuleCompletionItemsFactory + { + public static PythonModuleCompletionItems Create(PythonStandardModuleType moduleType) + { + if (IsSysModule(moduleType.Type)) { + return new SysModuleCompletionItems(moduleType); + } + return new PythonModuleCompletionItems(moduleType); + } + + static bool IsSysModule(Type type) + { + return type == typeof(SysModule); + } + } +} 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..862ffc69c9 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonNamespaceResolver.cs @@ -0,0 +1,28 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonNamespaceResolver : IPythonResolver + { + public PythonNamespaceResolver() + { + } + + public ResolveResult Resolve(PythonResolverContext resolverContext, ExpressionResult expressionResult) + { + string actualNamespace = resolverContext.UnaliasImportedModuleName(expressionResult.Expression); + if (resolverContext.NamespaceExists(actualNamespace)) { + return new NamespaceResolveResult(null, null, actualNamespace); + } + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs index 701b56972e..c96053cd4e 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs @@ -14,264 +14,75 @@ using ICSharpCode.SharpDevelop.Dom; namespace ICSharpCode.PythonBinding { - /// - /// Python Resolver. - /// - public class PythonResolver : IResolver + public class PythonResolver : IResolver, IPythonResolver { - IProjectContent projectContent; - IClass callingClass; - ICompilationUnit compilationUnit; - static string[] standardModuleNames; + PythonResolverContext resolverContext; + PythonImportResolver importResolver = new PythonImportResolver(); + PythonNamespaceResolver namespaceResolver = new PythonNamespaceResolver(); + PythonClassResolver classResolver = new PythonClassResolver(); + PythonStandardModuleResolver standardModuleResolver = new PythonStandardModuleResolver(); + PythonMethodResolver methodResolver; + + List resolvers = new List(); public PythonResolver() { + methodResolver = new PythonMethodResolver(classResolver, standardModuleResolver); + + resolvers.Add(importResolver); + resolvers.Add(classResolver); + resolvers.Add(standardModuleResolver); + resolvers.Add(methodResolver); + resolvers.Add(namespaceResolver); } public ResolveResult Resolve(ExpressionResult expressionResult, ParseInformation parseInfo, string fileContent) { - Console.WriteLine("Resolve: " + expressionResult.Expression); - 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); - } - - // Search for a method. - MethodGroupResolveResult resolveResult = GetMethodResolveResult(expressionResult.Expression); - if (resolveResult != null) { - return resolveResult; - } - - // Search for a local variable. - LocalResolveResult localResolveResult = GetLocalVariable(expressionResult.Expression, parseInfo.CompilationUnit.FileName, fileContent); - if (localResolveResult != null) { - return localResolveResult; - } - - // Search for a namespace. - string namespaceExpression = GetNamespaceExpression(expressionResult.Expression); - if (projectContent.NamespaceExists(namespaceExpression)) { - return new NamespaceResolveResult(null, null, namespaceExpression); - } - return null; + return Resolve(resolverContext, expressionResult); } - - /// - /// Called when Ctrl+Space is entered by the user. - /// - public List CtrlSpace(int caretLine, int caretColumn, ParseInformation parseInfo, string fileContent, ExpressionContext context) - { - List results = new List(); - ICompilationUnit compilationUnit = GetCompilationUnit(parseInfo, true); - if (compilationUnit != null && compilationUnit.ProjectContent != null) { - if (context == ExpressionContext.Importable) { - // Add namespace contents for import code completion. - compilationUnit.ProjectContent.AddNamespaceContents(results, String.Empty, compilationUnit.ProjectContent.Language, true); - - // Add built-in module names. - results.AddRange(GetStandardPythonModuleNames().Select(name => new NamespaceEntry(name))); - } else { - // Add namespace contents. - CtrlSpaceResolveHelper.AddImportedNamespaceContents(results, compilationUnit, null); - } - } - return results; - } - - /// - /// Gets the compilation unit for the specified parse information. - /// - ICompilationUnit GetCompilationUnit(ParseInformation parseInfo, bool mostRecent) - { - if (parseInfo != null) { - return parseInfo.CompilationUnit; - } - 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) + public ResolveResult Resolve(PythonResolverContext resolverContext, ExpressionResult expressionResult) { - // 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; + foreach (IPythonResolver resolver in resolvers) { + ResolveResult resolveResult = resolver.Resolve(resolverContext, expressionResult); + if (resolveResult != null) { + return resolveResult; } } - 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; - } - - /// - /// Removes the "import " or "from " part of a namespace expression if it exists. - /// - static string GetNamespaceExpression(string expression) - { - string ns = GetNamespaceExpression("import ", expression); - if (ns == null) { - ns = GetNamespaceExpression("from ", expression); - } - if (ns != null) { - return ns; - } - return expression; - } - - /// - /// Removes the "import " or "from " part of a namespace expression if it exists. - /// - static string GetNamespaceExpression(string importString, string expression) - { - int index = expression.IndexOf(importString, StringComparison.OrdinalIgnoreCase); - if (index >= 0) { - return expression.Substring(index + importString.Length); - } - 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; - } +// // Search for a local variable. +// LocalResolveResult localResolveResult = GetLocalVariable(expressionResult.Expression, parseInfo.BestCompilationUnit.FileName, fileContent); +// if (localResolveResult != null) { +// return localResolveResult; +// } - // 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. - /// - List GetImportedTypes() - { - List types = new List(); - CtrlSpaceResolveHelper.AddImportedNamespaceContents(types, this.compilationUnit, this.callingClass); - return types; - } - - /// - /// Gets the standard python module names and caches the result. - /// - static string[] GetStandardPythonModuleNames() - { - if (standardModuleNames == null) { - StandardPythonModules modules = new StandardPythonModules(); - standardModuleNames = modules.GetNames(); - } - return standardModuleNames; - } - - /// - /// Tries to resolve a method in the expression. + /// Called when Ctrl+Space is entered by the user. /// - MethodGroupResolveResult GetMethodResolveResult(string expression) + public List CtrlSpace(int caretLine, int caretColumn, ParseInformation parseInfo, string fileContent, ExpressionContext context) { - // 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); + resolverContext = new PythonResolverContext(parseInfo); + if (resolverContext.HasProjectContent) { + if (context == ExpressionContext.Namespace) { + PythonImportCompletion importCompletion = new PythonImportCompletion(resolverContext.ProjectContent); + return importCompletion.GetCompletionItems(); + } else { + return resolverContext.GetImportedTypes(); } } - return null; - } - - /// - /// Gets the method name from the expression. - /// - static string GetMethodName(string expression) - { - int index = expression.LastIndexOf('.'); - return expression.Substring(index + 1); + return new List(); } /// 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..b6a9f6729c --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolverContext.cs @@ -0,0 +1,242 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +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 List GetImportedTypes() + { + List types = new List(); + 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; + } + + /// + /// Looks for the module name where the specified identifier is imported from. + /// + public string GetModuleForImportedName(string name) + { + foreach (IUsing u in mostRecentCompilationUnit.UsingScope.Usings) { + PythonFromImport pythonFromImport = u as PythonFromImport; + if (pythonFromImport != null) { + if (pythonFromImport.IsImportedName(name)) { + return pythonFromImport.Module; + } + } + } + return null; + } + + /// + /// Converts a name into the correct identifier name based on any from import as statements. + /// + public string UnaliasImportedName(string name) + { + foreach (IUsing u in mostRecentCompilationUnit.UsingScope.Usings) { + PythonFromImport pythonFromImport = u as PythonFromImport; + if (pythonFromImport != null) { + string actualName = pythonFromImport.GetOriginalNameForAlias(name); + if (actualName != null) { + return actualName; + } + } + } + return name; + } + + /// + /// Converts the module name to its original unaliased value if it exists. + /// + public string UnaliasImportedModuleName(string name) + { + foreach (IUsing u in mostRecentCompilationUnit.UsingScope.Usings) { + PythonImport pythonImport = u as PythonImport; + if (pythonImport != null) { + string actualName = pythonImport.GetOriginalNameForAlias(name); + if (actualName != null) { + return actualName; + } + } + } + return name; + } + + public string[] GetModulesThatImportEverything() + { + List modules = new List(); + foreach (IUsing u in mostRecentCompilationUnit.UsingScope.Usings) { + PythonFromImport pythonFromImport = u as PythonFromImport; + if (pythonFromImport != null) { + if (pythonFromImport.ImportsEverything) { + modules.Add(pythonFromImport.Module); + } + } + } + return modules.ToArray(); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleMethodResolveResult.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleMethodResolveResult.cs new file mode 100644 index 0000000000..6e35b298fe --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleMethodResolveResult.cs @@ -0,0 +1,38 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonStandardModuleMethodGroupResolveResult : MethodGroupResolveResult + { + public PythonStandardModuleMethodGroupResolveResult(IReturnType containingType, string methodName, MethodGroup[] methodGroups) + : base(null, null, containingType, methodName, methodGroups) + { + } + + public static PythonStandardModuleMethodGroupResolveResult Create(PythonStandardModuleType type, string methodName) + { + PythonModuleCompletionItems completionItems = PythonModuleCompletionItemsFactory.Create(type); + MethodGroup methods = completionItems.GetMethods(methodName); + if (methods.Count > 0) { + return Create(methods); + } + return null; + } + + static PythonStandardModuleMethodGroupResolveResult Create(MethodGroup methods) + { + MethodGroup[] methodGroups = new MethodGroup[] { methods }; + IMethod method = methods[0]; + IReturnType returnType = new DefaultReturnType(method.DeclaringType); + return new PythonStandardModuleMethodGroupResolveResult(returnType, method.Name, methodGroups); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleMethodResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleMethodResolver.cs new file mode 100644 index 0000000000..992be2b5f3 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleMethodResolver.cs @@ -0,0 +1,84 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class PythonStandardModuleMethodResolver + { + PythonStandardModuleResolver standardModuleResolver; + + public PythonStandardModuleMethodResolver(PythonStandardModuleResolver standardModuleResolver) + { + this.standardModuleResolver = standardModuleResolver; + } + + public ResolveResult Resolve(PythonResolverContext resolverContext, ExpressionResult expressionResult) + { + MemberName memberName = new MemberName(expressionResult.Expression); + MethodGroupResolveResult result = ResolveMethodFromImportedNames(resolverContext, memberName); + if (result != null) { + return result; + } + result = ResolveIfMethodIsImported(resolverContext, memberName); + if (result != null) { + return result; + } + return ResolveMethodFromModulesThatImportEverything(resolverContext, memberName); + } + + MethodGroupResolveResult ResolveMethodFromImportedNames(PythonResolverContext resolverContext, MemberName memberName) + { + if (!memberName.HasName) { + string name = memberName.Type; + string moduleName = resolverContext.GetModuleForImportedName(name); + if (moduleName != null) { + PythonStandardModuleType type = standardModuleResolver.GetStandardModuleType(moduleName); + if (type != null) { + name = resolverContext.UnaliasImportedName(name); + return PythonStandardModuleMethodGroupResolveResult.Create(type, name); + } + } + } + return null; + } + + MethodGroupResolveResult ResolveIfMethodIsImported(PythonResolverContext resolverContext, MemberName memberName) + { + if (!memberName.HasName) { + memberName = new PythonBuiltInModuleMemberName(memberName.Type); + } + + PythonStandardModuleType type = standardModuleResolver.GetStandardModuleTypeIfImported(resolverContext, memberName.Type); + if (type != null) { + return CreateResolveResult(type, memberName.Name); + } + return null; + } + + MethodGroupResolveResult ResolveMethodFromModulesThatImportEverything(PythonResolverContext resolverContext, MemberName memberName) + { + foreach (string module in resolverContext.GetModulesThatImportEverything()) { + PythonStandardModuleType type = standardModuleResolver.GetStandardModuleType(module); + if (type != null) { + MethodGroupResolveResult resolveResult = CreateResolveResult(type, memberName.Type); + if (resolveResult != null) { + return resolveResult; + } + } + } + return null; + } + + MethodGroupResolveResult CreateResolveResult(PythonStandardModuleType type, string name) + { + return PythonStandardModuleMethodGroupResolveResult.Create(type, name); + } + } +} 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..9d208a1ca3 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModuleResolveResult.cs @@ -0,0 +1,32 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +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 List GetCompletionData(IProjectContent projectContent) + { + PythonModuleCompletionItems completionItems = PythonModuleCompletionItemsFactory.Create(standardModuleType); + List items = new List(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..224f00b237 --- /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 : IPythonResolver + { + PythonStandardModules standardPythonModules = new PythonStandardModules(); + + public PythonStandardModuleResolver() + { + } + + public ResolveResult Resolve(PythonResolverContext resolverContext, ExpressionResult expressionResult) + { + PythonStandardModuleType type = GetStandardModuleTypeIfImported(resolverContext, expressionResult.Expression); + if (type != null) { + return new PythonStandardModuleResolveResult(type); + } + return null; + } + + public PythonStandardModuleType GetStandardModuleTypeIfImported(PythonResolverContext resolverContext, string moduleName) + { + if (resolverContext.HasImport(moduleName) || PythonBuiltInModuleMemberName.IsBuiltInModule(moduleName)) { + string actualModuleName = resolverContext.UnaliasImportedModuleName(moduleName); + return standardPythonModules.GetModuleType(actualModuleName); + } + return null; + } + + public PythonStandardModuleType GetStandardModuleType(string moduleName) + { + return standardPythonModules.GetModuleType(moduleName); + } + } +} 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/PythonStandardModules.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModules.cs new file mode 100644 index 0000000000..3866bbd8e6 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonStandardModules.cs @@ -0,0 +1,64 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using ICSharpCode.SharpDevelop.Dom; +using IronPython.Modules; +using IronPython.Runtime; + +namespace ICSharpCode.PythonBinding +{ + /// + /// Represents the standard library modules that are implemented in + /// IronPython. + /// + public class PythonStandardModules : List + { + Dictionary moduleTypes = new Dictionary(); + + public PythonStandardModules() + { + GetPythonStandardModuleNames(); + } + + void GetPythonStandardModuleNames() + { + GetPythonModuleNamesFromAssembly(typeof(Builtin).Assembly); + GetPythonModuleNamesFromAssembly(typeof(ModuleOps).Assembly); + } + + void GetPythonModuleNamesFromAssembly(Assembly assembly) + { + foreach (Attribute attribute in Attribute.GetCustomAttributes(assembly, typeof(PythonModuleAttribute))) { + PythonModuleAttribute pythonModuleAttribute = attribute as PythonModuleAttribute; + Add(new NamespaceEntry(pythonModuleAttribute.Name)); + moduleTypes.Add(pythonModuleAttribute.Name, pythonModuleAttribute.Type); + } + } + + 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)) { + return type; + } + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/StandardPythonModules.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/StandardPythonModules.cs deleted file mode 100644 index 7b308a39f1..0000000000 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/StandardPythonModules.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// -// -// -// $Revision$ -// - -using System; -using System.Collections.Generic; -using System.Reflection; -using IronPython.Modules; -using IronPython.Runtime; - -namespace ICSharpCode.PythonBinding -{ - /// - /// Represents the standard library modules that are implemented in - /// IronPython. - /// - public class StandardPythonModules - { - public StandardPythonModules() - { - } - - /// - /// Gets the names of the standard Python library modules. - /// - public string[] GetNames() - { - List names = new List(); - names.Add("sys"); - Assembly assembly = typeof(Builtin).Assembly; - foreach (Attribute customAttribute in Attribute.GetCustomAttributes(assembly, typeof(PythonModuleAttribute))) { - PythonModuleAttribute pythonModuleAttribute = customAttribute as PythonModuleAttribute; - names.Add(pythonModuleAttribute.Name); - } - return names.ToArray(); - } - } -} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/StringTextContentProvider.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/StringTextContentProvider.cs new file mode 100644 index 0000000000..5a48b3fdf8 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/StringTextContentProvider.cs @@ -0,0 +1,33 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.IO; +using System.Text; + +using Microsoft.Scripting; +using Microsoft.Scripting.Hosting; +using Microsoft.Scripting.Hosting.Providers; + +namespace ICSharpCode.PythonBinding +{ + public class StringTextContentProvider : TextContentProvider + { + string code; + + public StringTextContentProvider(string code) + { + this.code = code; + } + + public override SourceCodeReader GetReader() + { + StringReader stringReader = new StringReader(code); + return new SourceCodeReader(stringReader, Encoding.UTF8); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/SysModuleCompletionItems.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/SysModuleCompletionItems.cs new file mode 100644 index 0000000000..93e8bb84b4 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/SysModuleCompletionItems.cs @@ -0,0 +1,53 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.PythonBinding +{ + public class SysModuleCompletionItems : PythonModuleCompletionItems + { + public SysModuleCompletionItems(PythonStandardModuleType moduleType) + : base(moduleType) + { + AddCompletionItems(); + } + + void AddCompletionItems() + { + AddField("__stderr__"); + AddField("__stdin__"); + AddField("__stdout__"); + AddField("argv"); + AddField("builtin_module_names"); + AddField("dont_write_byte_code"); + AddField("executable"); + AddField("exec_prefix"); + AddField("flags"); + AddField("hexversion"); + AddField("last_type"); + AddField("last_value"); + AddField("last_traceback"); + AddField("meta_path"); + AddField("modules"); + AddField("path"); + AddField("path_hooks"); + AddField("path_importer_cache"); + AddField("ps1"); + AddField("ps2"); + AddField("py3kwarning"); + AddField("stderr"); + AddField("stdin"); + AddField("stdout"); + AddField("version"); + AddField("version_info"); + AddField("warnoptions"); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/FromImportCompletion.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/CodeCompletionBindingFromImportCompletionTestFixture.cs similarity index 71% rename from src/AddIns/BackendBindings/Python/PythonBinding/Test/FromImportCompletion.cs rename to src/AddIns/BackendBindings/Python/PythonBinding/Test/CodeCompletionBindingFromImportCompletionTestFixture.cs index a8d811f0cb..8d560b5fb5 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/FromImportCompletion.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/CodeCompletionBindingFromImportCompletionTestFixture.cs @@ -5,11 +5,10 @@ // $Revision$ // -using ICSharpCode.SharpDevelop; using System; using ICSharpCode.Core; using ICSharpCode.PythonBinding; -using ICSharpCode.SharpDevelop.Editor.AvalonEdit; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Dom; using NUnit.Framework; using PythonBinding.Tests.Utils; @@ -21,18 +20,21 @@ namespace PythonBinding.Tests /// importable code completion keyword. /// [TestFixture] - public class FromImportCompletion + public class FromImportCompletionTestFixture { DerivedPythonCodeCompletionBinding codeCompletionBinding; bool handlesImportKeyword; + SharpDevelopTextAreaControl textAreaControl; [TestFixtureSetUp] public void SetUpFixture() { - PropertyService.InitializeServiceForUnitTests(); + if (!PropertyService.Initialized) { + PropertyService.InitializeService(String.Empty, String.Empty, String.Empty); + } + textAreaControl = new SharpDevelopTextAreaControl(); codeCompletionBinding = new DerivedPythonCodeCompletionBinding(); - var editor = new AvalonEditTextEditorAdapter(new ICSharpCode.AvalonEdit.TextEditor()); - handlesImportKeyword = codeCompletionBinding.HandleKeyword(editor, "from"); + handlesImportKeyword = codeCompletionBinding.HandleKeyword(textAreaControl, "from"); } [Test] diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/CodeCompletionBindingFromImportCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/CodeCompletionBindingFromImportCompletionTestFixture.cs new file mode 100644 index 0000000000..33b7c30163 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/CodeCompletionBindingFromImportCompletionTestFixture.cs @@ -0,0 +1,46 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.Core; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Editor.AvalonEdit; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests +{ + /// + /// Tests that the From keyword is correctly identified as a + /// importable code completion keyword. + /// + [TestFixture] + public class FromImportCompletionTestFixture + { + DerivedPythonCodeCompletionBinding codeCompletionBinding; + bool handlesImportKeyword; + AvalonEditTextEditorAdapter textEditor; + + [TestFixtureSetUp] + public void SetUpFixture() + { + if (!PropertyService.Initialized) { + PropertyService.InitializeService(String.Empty, String.Empty, String.Empty); + } + textEditor = new AvalonEditTextEditorAdapter(new ICSharpCode.AvalonEdit.TextEditor()); + codeCompletionBinding = new DerivedPythonCodeCompletionBinding(); + handlesImportKeyword = codeCompletionBinding.HandleKeyword(textEditor, "from"); + } + + [Test] + public void HandlesImportKeyWord() + { + Assert.IsTrue(handlesImportKeyword); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/ImportCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/CodeCompletionBindingImportCompletionTestFixture.cs similarity index 72% rename from src/AddIns/BackendBindings/Python/PythonBinding/Test/ImportCompletionTestFixture.cs rename to src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/CodeCompletionBindingImportCompletionTestFixture.cs index fed05e0396..e50567742b 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/ImportCompletionTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/CodeCompletionBindingImportCompletionTestFixture.cs @@ -6,14 +6,10 @@ // using System; -using ICSharpCode.AvalonEdit; using ICSharpCode.Core; using ICSharpCode.PythonBinding; -using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Editor; -using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; -using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Editor.AvalonEdit; +using ICSharpCode.SharpDevelop.Dom; using NUnit.Framework; using PythonBinding.Tests.Utils; @@ -23,18 +19,20 @@ namespace PythonBinding.Tests /// Tests the code completion after an "import" statement. /// [TestFixture] - public class ImportCompletionTestFixture + public class CodeCompletionBindingImportCompletionTestFixture { - ICSharpCode.SharpDevelop.Editor.ITextEditor textEditor; DerivedPythonCodeCompletionBinding codeCompletionBinding; bool handlesImportKeyword; + AvalonEditTextEditorAdapter textEditor; [TestFixtureSetUp] public void SetUpFixture() { - PropertyService.InitializeServiceForUnitTests(); - codeCompletionBinding = new DerivedPythonCodeCompletionBinding(); + if (!PropertyService.Initialized) { + PropertyService.InitializeService(String.Empty, String.Empty, String.Empty); + } textEditor = new AvalonEditTextEditorAdapter(new ICSharpCode.AvalonEdit.TextEditor()); + codeCompletionBinding = new DerivedPythonCodeCompletionBinding(); handlesImportKeyword = codeCompletionBinding.HandleKeyword(textEditor, "import"); } @@ -63,9 +61,9 @@ namespace PythonBinding.Tests } [Test] - public void CtrlSpaceCompletionDataProviderCreated() + public void CompletionDataProviderCreated() { - Assert.IsTrue(codeCompletionBinding.IsCtrlSpaceCompletionDataProviderCreated); + Assert.IsTrue(codeCompletionBinding.IsCompletionDataProviderCreated); } [Test] @@ -83,7 +81,7 @@ namespace PythonBinding.Tests [Test] public void CompletionProviderUsedWhenDisplayingCodeCompletionWindow() { - Assert.AreSame(codeCompletionBinding.CtrlSpaceCompletionDataProvider, codeCompletionBinding.CompletionProviderUsedWhenDisplayingCodeCompletionWindow); + Assert.AreSame(codeCompletionBinding.CompletionDataProvider, codeCompletionBinding.CompletionProviderUsedWhenDisplayingCodeCompletionWindow); } [Test] @@ -91,11 +89,5 @@ namespace PythonBinding.Tests { Assert.AreEqual(' ', codeCompletionBinding.CompletionCharacter); } - - [Test] - public void ExpressionContextIsImportable() - { - Assert.AreEqual(ExpressionContext.Importable, codeCompletionBinding.ExpressionContext); - } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromDateTimeImportCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromDateTimeImportCompletionTestFixture.cs new file mode 100644 index 0000000000..0027bfe74d --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromDateTimeImportCompletionTestFixture.cs @@ -0,0 +1,43 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class FromDateTimeLibraryImportCompletionTestFixture + { + PythonImportExpression importExpression; + PythonImportModuleResolveResult resolveResult; + MockProjectContent projectContent; + + [SetUp] + public void Init() + { + string code = "from datetime import"; + importExpression = new PythonImportExpression(code); + resolveResult = new PythonImportModuleResolveResult(importExpression); + + projectContent = new MockProjectContent(); + } + + [Test] + public void CompletionItemsContainsDateClass() + { + List items = resolveResult.GetCompletionData(projectContent); + IClass c = PythonCompletionItemsHelper.FindClassFromCollection("datetime", items); + Assert.IsNotNull(c); + } + + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromImportDotNetNamespaceCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromImportDotNetNamespaceCompletionTestFixture.cs new file mode 100644 index 0000000000..5cbe4003ac --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromImportDotNetNamespaceCompletionTestFixture.cs @@ -0,0 +1,55 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.PythonBinding; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class FromImportDotNetNamespaceCompletionTestFixture + { + PythonImportCompletion completion; + MockProjectContent projectContent; + DefaultClass c; + + [SetUp] + public void Init() + { + projectContent = new MockProjectContent(); + completion = new PythonImportCompletion(projectContent); + + DefaultCompilationUnit unit = new DefaultCompilationUnit(projectContent); + ParseInformation parseInfo = new ParseInformation(unit); + c = new DefaultClass(unit, "Class"); + List namespaceItems = new List(); + namespaceItems.Add(c); + projectContent.AddExistingNamespaceContents("System", namespaceItems); + } + + [Test] + public void FromDotNetSystemLibraryGetCompletionItemsReturnsAllClassesFromSystemNamespace() + { + List items = completion.GetCompletionItemsFromModule("System"); + List expectedItems = new List(); + expectedItems.Add(c); + + Assert.AreEqual(expectedItems, items); + } + + [Test] + public void SystemNamespaceSearchedForWhenGetCompletionItemsMethodCalled() + { + completion.GetCompletionItemsFromModule("System"); + Assert.AreEqual("System", projectContent.NamespacePassedToGetNamespaceContentsMethod); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromImportPythonModuleCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromImportPythonModuleCompletionTestFixture.cs new file mode 100644 index 0000000000..07d5b4228c --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromImportPythonModuleCompletionTestFixture.cs @@ -0,0 +1,46 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.PythonBinding; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class FromImportPythonModuleCompletionTestFixture + { + PythonImportCompletion completion; + MockProjectContent projectContent; + + [SetUp] + public void Init() + { + projectContent = new MockProjectContent(); + ParseInformation parseInfo = new ParseInformation(new DefaultCompilationUnit(projectContent)); + completion = new PythonImportCompletion(projectContent); + } + + [Test] + public void FromUnknownLibraryNoCompletionItemsReturned() + { + List items = completion.GetCompletionItemsFromModule("unknown"); + Assert.AreEqual(0, items.Count); + } + + [Test] + public void FromMathLibraryGetCompletionItemsReturnsPiField() + { + List items = completion.GetCompletionItemsFromModule("math"); + 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 new file mode 100644 index 0000000000..94f79a2a5d --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromMathLibraryImportCompletionTestFixture.cs @@ -0,0 +1,71 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class FromMathLibraryImportCompletionTestFixture + { + PythonImportExpression importExpression; + PythonImportModuleResolveResult resolveResult; + MockProjectContent projectContent; + List completionItems; + + [SetUp] + public void Init() + { + string code = "from math import"; + importExpression = new PythonImportExpression(code); + resolveResult = new PythonImportModuleResolveResult(importExpression); + + projectContent = new MockProjectContent(); + completionItems = resolveResult.GetCompletionData(projectContent); + } + + [Test] + public void CompletionItemsContainsCosMethodFromMathLibrary() + { + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("cos", completionItems); + Assert.IsNotNull(method); + } + + [Test] + public void CompletionItemsContainsPiPropertyFromMathLibrary() + { + IField field = PythonCompletionItemsHelper.FindFieldFromCollection("pi", completionItems); + Assert.IsNotNull(field); + } + + [Test] + public void CompletionItemsDoesNotContainNonStaticToStringMethod() + { + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("ToString", completionItems); + Assert.IsNull(method); + } + + [Test] + public void CompletionItemsContain__name__() + { + IField field = PythonCompletionItemsHelper.FindFieldFromCollection("__name__", completionItems); + Assert.IsNotNull(field); + } + + [Test] + public void CompletionItemsContain__package__() + { + IField field = PythonCompletionItemsHelper.FindFieldFromCollection("__package__", completionItems); + Assert.IsNotNull(field); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromMathLibraryImportCosMethodCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromMathLibraryImportCosMethodCompletionTestFixture.cs new file mode 100644 index 0000000000..2f8e92fb6b --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromMathLibraryImportCosMethodCompletionTestFixture.cs @@ -0,0 +1,49 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + /// + /// With dot completion if the from import statement has an a identifier then no + /// completion items should be returned. + /// + /// For example pressing '.' after the following should not show any completion items: + /// + /// "from math import cos" + /// + [TestFixture] + public class FromMathLibraryImportCosMethodCompletionTestFixture + { + PythonImportExpression importExpression; + PythonImportModuleResolveResult resolveResult; + MockProjectContent projectContent; + + [SetUp] + public void Init() + { + string code = "from math import cos"; + importExpression = new PythonImportExpression(code); + resolveResult = new PythonImportModuleResolveResult(importExpression); + + projectContent = new MockProjectContent(); + } + + [Test] + public void NoCompletionItemsReturned() + { + List items = resolveResult.GetCompletionData(projectContent); + Assert.AreEqual(0, items.Count); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromSysLibraryImportCompletionItemsTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromSysLibraryImportCompletionItemsTestFixture.cs new file mode 100644 index 0000000000..c0da1dd851 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/FromSysLibraryImportCompletionItemsTestFixture.cs @@ -0,0 +1,232 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.PythonBinding; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class FromSysLibraryImportCompletionItemsTestFixture + { + PythonImportCompletion completion; + MockProjectContent projectContent; + List completionItems; + + [SetUp] + public void Init() + { + projectContent = new MockProjectContent(); + ParseInformation parseInfo = new ParseInformation(new DefaultCompilationUnit(projectContent)); + completion = new PythonImportCompletion(projectContent); + completionItems = completion.GetCompletionItemsFromModule("sys"); + } + + [Test] + public void GetCompletionItemsDoesNotReturnPythonHiddenMethods() + { + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("_getframeImpl", completionItems); + Assert.IsNull(method); + } + + [Test] + public void GetCompletionItemsReturns__name__() + { + AssertFieldExists("__name__"); + } + + void AssertFieldExists(string name) + { + IField field = GetFieldFromCompletionItems(name); + Assert.IsNotNull(field, String.Format("Field '{0}' not found in completion items.", name)); + } + + IField GetFieldFromCompletionItems(string name) + { + return PythonCompletionItemsHelper.FindFieldFromCollection(name, completionItems); + } + + [Test] + public void GetCompletionItemsReturns__package__() + { + AssertFieldExists("__package__"); + } + + [Test] + public void GetCompletionItemsReturns__stderr__() + { + AssertFieldExists("__stderr__"); + } + + [Test] + public void GetCompletionItemsReturns__stdin__() + { + AssertFieldExists("__stdin__"); + } + + [Test] + public void GetCompletionItemsReturns__stdout__() + { + AssertFieldExists("__stdout__"); + } + + [Test] + public void GetCompletionItemsReturnsArgv() + { + AssertFieldExists("argv"); + } + + [Test] + public void GetCompletionItemsReturnsBuiltInModuleNames() + { + AssertFieldExists("builtin_module_names"); + } + + [Test] + public void GetCompletionItemsReturnsExecutable() + { + AssertFieldExists("executable"); + } + + [Test] + public void GetCompletionItemsReturnsExecPrefix() + { + AssertFieldExists("exec_prefix"); + } + + [Test] + public void GetCompletionItemsReturnsExitMethod() + { + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("exit", completionItems); + Assert.IsNotNull(method); + } + + [Test] + public void GetCompletionItemsReturnsFlags() + { + AssertFieldExists("flags"); + } + + [Test] + public void GetCompletionItemsReturnsHexVersion() + { + AssertFieldExists("hexversion"); + } + + [Test] + public void GetCompletionItemsReturnsLastType() + { + AssertFieldExists("last_type"); + } + + [Test] + public void GetCompletionItemsReturnsLastValue() + { + AssertFieldExists("last_value"); + } + + [Test] + public void GetCompletionItemsReturnsLastTraceback() + { + AssertFieldExists("last_traceback"); + } + + [Test] + public void GetCompletionItemsReturnsMetaPath() + { + AssertFieldExists("meta_path"); + } + + [Test] + public void GetCompletionItemsReturnsModules() + { + AssertFieldExists("modules"); + } + + [Test] + public void GetCompletionItemsReturnsPath() + { + AssertFieldExists("path"); + } + + [Test] + public void GetCompletionItemsReturnsPathHooks() + { + AssertFieldExists("path_hooks"); + } + + [Test] + public void GetCompletionItemsReturnsPathImporterCache() + { + AssertFieldExists("path_importer_cache"); + } + + [Test] + public void GetCompletionItemsReturnsPs1() + { + AssertFieldExists("ps1"); + } + + [Test] + public void GetCompletionItemsReturnsPs2() + { + AssertFieldExists("ps2"); + } + + [Test] + public void GetCompletionItemsReturnsPy3kWarning() + { + AssertFieldExists("py3kwarning"); + } + + [Test] + public void GetCompletionItemsReturnsDontWriteByteCode() + { + AssertFieldExists("dont_write_byte_code"); + } + + [Test] + public void GetCompletionItemsReturnsStdErr() + { + AssertFieldExists("stderr"); + } + + [Test] + public void GetCompletionItemsReturnsStdIn() + { + AssertFieldExists("stdin"); + } + + [Test] + public void GetCompletionItemsReturnsStdOut() + { + AssertFieldExists("stdout"); + } + + [Test] + public void GetCompletionItemsReturnsVersion() + { + AssertFieldExists("version"); + } + + [Test] + public void GetCompletionItemsReturnsVersionInfo() + { + AssertFieldExists("version_info"); + } + + [Test] + public void GetCompletionItemsReturnsWarnOptions() + { + AssertFieldExists("warnoptions"); + } + } +} 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 new file mode 100644 index 0000000000..084aedcf38 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetPythonModulesTestFixture.cs @@ -0,0 +1,71 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Text; +using NUnit.Framework; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; + +namespace PythonBinding.Tests.Resolver +{ + /// + /// Tests the standard Python module names can be determined + /// for IronPython. + /// + [TestFixture] + public class GetPythonModulesTestFixture + { + List moduleNames; + + [TestFixtureSetUp] + public void SetUpFixture() + { + moduleNames = new PythonStandardModules(); + } + + [Test] + public void ContainsSysModuleName() + { + Assert.Contains(new NamespaceEntry("sys"), moduleNames); + } + + [Test] + public void SysModuleInListOfModulesOnlyOnce() + { + int countOccurrencesOfSysModuleName = 0; + foreach (ICompletionEntry entry in moduleNames) { + if (entry.Name == "sys") { + countOccurrencesOfSysModuleName++; + } + } + Assert.AreEqual(1, countOccurrencesOfSysModuleName); + } + + [Test] + public void ContainsBuiltInModule() + { + Assert.Contains(new NamespaceEntry("__builtin__"), moduleNames, "Module names: " + WriteList(moduleNames)); + } + + [Test] + public void ContainsMathModule() + { + Assert.Contains(new NamespaceEntry("math"), moduleNames); + } + + static string WriteList(List items) + { + StringBuilder text = new StringBuilder(); + foreach (ICompletionEntry item in items) { + text.AppendLine(item.Name); + } + return text.ToString(); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetTypeForPythonModuleTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetTypeForPythonModuleTestFixture.cs new file mode 100644 index 0000000000..90fc863076 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/GetTypeForPythonModuleTestFixture.cs @@ -0,0 +1,52 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using IronPython.Modules; +using NUnit.Framework; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class GetTypeForPythonModuleTestFixture + { + PythonStandardModules modules; + PythonStandardModuleType sysModuleType; + + [SetUp] + public void Init() + { + modules = new PythonStandardModules(); + sysModuleType = modules.GetModuleType("sys"); + } + + [Test] + public void GetTypeReturnsNullForUnknownModuleName() + { + Assert.IsNull(modules.GetModuleType("unknown")); + } + + [Test] + public void GetTypeReturnsSysModuleTypeForSysModuleName() + { + 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/ImportCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportCompletionTestFixture.cs new file mode 100644 index 0000000000..b6196f978b --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportCompletionTestFixture.cs @@ -0,0 +1,54 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.PythonBinding; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class ImportCompletionTestFixture + { + List completionItems; + MockProjectContent projectContent; + + [SetUp] + public void Init() + { + projectContent = new MockProjectContent(); + ParseInformation parseInfo = new ParseInformation(new DefaultCompilationUnit(projectContent)); + List namespaceItems = new List(); + namespaceItems.Add(new NamespaceEntry("Test")); + projectContent.AddExistingNamespaceContents(String.Empty, namespaceItems); + + PythonImportCompletion completion = new PythonImportCompletion(projectContent); + completionItems = completion.GetCompletionItems(); + } + + [Test] + public void TestNamespaceIsAddedToCompletionItems() + { + Assert.Contains(new NamespaceEntry("Test"), completionItems); + } + + [Test] + public void MathStandardPythonModuleIsAddedToCompletionItems() + { + Assert.Contains(new NamespaceEntry("math"), completionItems); + } + + [Test] + public void NamespacePassedToProjectContentGetNamespaceContentsIsEmptyString() + { + Assert.AreEqual(String.Empty, projectContent.NamespacePassedToGetNamespaceContentsMethod); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportEmptyNamespaceCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportEmptyNamespaceCompletionTestFixture.cs new file mode 100644 index 0000000000..69afc183c2 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportEmptyNamespaceCompletionTestFixture.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.PythonBinding; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class ImportEmptyNamespaceCompletionTestFixture + { + List completionItems; + MockProjectContent projectContent; + + [SetUp] + public void Init() + { + projectContent = new MockProjectContent(); + ParseInformation parseInfo = new ParseInformation(new DefaultCompilationUnit(projectContent)); + + PythonImportCompletion completion = new PythonImportCompletion(projectContent); + completionItems = completion.GetCompletionItems(String.Empty); + } + + [Test] + public void StandardMathPythonModuleIsAddedToCompletionItems() + { + Assert.Contains(new NamespaceEntry("math"), completionItems); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportResolveResultReturnsNoCompletionItemsIfExpressionHasIdentifierTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportResolveResultReturnsNoCompletionItemsIfExpressionHasIdentifierTestFixture.cs new file mode 100644 index 0000000000..228fb6f694 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportResolveResultReturnsNoCompletionItemsIfExpressionHasIdentifierTestFixture.cs @@ -0,0 +1,52 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class ImportResolveResultReturnsNoCompletionItemsIfExpressionHasIdentifierTestFixture + { + PythonImportExpression importExpression; + PythonImportModuleResolveResult resolveResult; + MockProjectContent projectContent; + + [SetUp] + public void Init() + { + string code = "from System import Console"; + importExpression = new PythonImportExpression(code); + resolveResult = new PythonImportModuleResolveResult(importExpression); + + projectContent = new MockProjectContent(); + DefaultCompilationUnit unit = new DefaultCompilationUnit(projectContent); + DefaultClass c = new DefaultClass(unit, "Test"); + List namespaceItems = new List(); + namespaceItems.Add(c); + projectContent.AddExistingNamespaceContents("System", namespaceItems); + } + + [Test] + public void ProjectContentGetNamespaceReturnsOneItem() + { + Assert.AreEqual(1, projectContent.GetNamespaceContents("System").Count); + } + + [Test] + public void NoCompletionItemsReturned() + { + List items = resolveResult.GetCompletionData(projectContent); + Assert.AreEqual(0, items.Count); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportSubNamespaceCompletionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportSubNamespaceCompletionTestFixture.cs new file mode 100644 index 0000000000..3e77ec497f --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/ImportSubNamespaceCompletionTestFixture.cs @@ -0,0 +1,49 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.PythonBinding; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class ImportSubNamespaceCompletionTestFixture + { + List completionItems; + MockProjectContent projectContent; + + [SetUp] + public void Init() + { + projectContent = new MockProjectContent(); + List namespaceItems = new List(); + namespaceItems.Add(new NamespaceEntry("ICSharpCode.PythonBinding.Test")); + projectContent.AddExistingNamespaceContents("ICSharpCode", namespaceItems); + + PythonImportCompletion completion = new PythonImportCompletion(projectContent); + completionItems = completion.GetCompletionItems("ICSharpCode"); + } + + [Test] + public void TestNamespaceIsAddedToCompletionItems() + { + List expectedItems = new List(); + expectedItems.Add(new NamespaceEntry("ICSharpCode.PythonBinding.Test")); + Assert.AreEqual(expectedItems, completionItems); + } + + [Test] + public void NamespacePassedToProjectContentGetNamespaceContentsIsSubNamespaceName() + { + Assert.AreEqual("ICSharpCode", projectContent.NamespacePassedToGetNamespaceContentsMethod); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/MathModuleMembersInPythonContextTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/MathModuleMembersInPythonContextTestFixture.cs new file mode 100644 index 0000000000..b5cfc386a2 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/MathModuleMembersInPythonContextTestFixture.cs @@ -0,0 +1,34 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using IronPython.Hosting; +using IronPython.Modules; +using IronPython.Runtime; +using Microsoft.Scripting.Hosting; +using Microsoft.Scripting.Hosting.Providers; +using Microsoft.Scripting.Runtime; +using NUnit.Framework; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class MathModuleMembersInPythonContextTestFixture + { + [Test] + public void UnableToGetMathModuleFromBuiltinModuleDictionary() + { + ScriptEngine engine = Python.CreateEngine(); + PythonContext context = HostingHelpers.GetLanguageContext(engine) as PythonContext; + + object mathModuleFromBuiltinModuleDictionaryObject = null; + context.BuiltinModuleDict.TryGetValue("math", out mathModuleFromBuiltinModuleDictionaryObject); + Assert.IsNull(mathModuleFromBuiltinModuleDictionaryObject); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/NamespaceContentsAddedToCtrlSpaceTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/NamespaceContentsAddedToCtrlSpaceTestFixture.cs similarity index 81% rename from src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/NamespaceContentsAddedToCtrlSpaceTestFixture.cs rename to src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/NamespaceContentsAddedToCtrlSpaceTestFixture.cs index 961a402383..258b9df69a 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/NamespaceContentsAddedToCtrlSpaceTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/NamespaceContentsAddedToCtrlSpaceTestFixture.cs @@ -35,17 +35,20 @@ namespace PythonBinding.Tests.Resolver mockProjectContent = new MockProjectContent(); mockProjectContent.NamespacesToAdd.Add("Test"); myTestClass = new MockClass(mockProjectContent, "MyTestClass"); - mockProjectContent.NamespaceContentsToReturn.Add(myTestClass); - + List namespaceItems = new List(); + namespaceItems.Add(myTestClass); + mockProjectContent.AddExistingNamespaceContents("MyNamespace", namespaceItems); + DefaultCompilationUnit cu = new DefaultCompilationUnit(mockProjectContent) { ErrorsDuringCompile = true }; // Add usings. DefaultUsing newUsing = new DefaultUsing(cu.ProjectContent); newUsing.Usings.Add("MyNamespace"); - cu.UsingScope.Usings.Add(newUsing); - + DefaultUsingScope usingScope = new DefaultUsingScope(); + usingScope.Usings.Add(newUsing); + cu.UsingScope = usingScope; ParseInformation parseInfo = new ParseInformation(cu); - + results = resolver.CtrlSpace(0, "".Length, parseInfo, "", ExpressionContext.Default); } @@ -58,7 +61,7 @@ namespace PythonBinding.Tests.Resolver [Test] public void NamespaceSearchedForContents() { - Assert.AreEqual("MyNamespace", mockProjectContent.NamespaceContentsSearched); + Assert.AreEqual("MyNamespace", mockProjectContent.NamespacePassedToGetNamespaceContentsMethod); } [Test] diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/PythonImportExpressionContextTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/PythonImportExpressionContextTestFixture.cs new file mode 100644 index 0000000000..a3ef492d4e --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/PythonImportExpressionContextTestFixture.cs @@ -0,0 +1,109 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class PythonImportExpressionContextTestFixture + { + [Test] + public void ShowEntryReturnsTrueForIMethod() + { + PythonImportExpressionContext context = new PythonImportExpressionContext(); + context.HasFromAndImport = true; + + IMethod method = CreateMethod(); + + Assert.IsTrue(context.ShowEntry(method)); + } + + IMethod CreateMethod() + { + IClass c = CreateClass(); + return new DefaultMethod(c, "Test"); + } + + IClass CreateClass() + { + DefaultCompilationUnit unit = new DefaultCompilationUnit(new MockProjectContent()); + return new DefaultClass(unit, "ICSharpCode.MyClass"); + } + + [Test] + public void ShowEntryReturnsFalseForNull() + { + PythonImportExpressionContext context = new PythonImportExpressionContext(); + context.HasFromAndImport = true; + Assert.IsFalse(context.ShowEntry(null)); + } + + [Test] + public void ShowEntryReturnsFalseForIMethodWhenHasFromAndImportIsFalse() + { + PythonImportExpressionContext context = new PythonImportExpressionContext(); + IMethod method = CreateMethod(); + Assert.IsFalse(context.ShowEntry(method)); + } + + [Test] + public void PythonImportExpressionContextHasFromAndImportIsFalseByDefault() + { + PythonImportExpressionContext context = new PythonImportExpressionContext(); + Assert.IsFalse(context.HasFromAndImport); + } + + [Test] + public void ShowEntryReturnsTrueForIField() + { + PythonImportExpressionContext context = new PythonImportExpressionContext(); + context.HasFromAndImport = true; + IField field = CreateField(); + + Assert.IsTrue(context.ShowEntry(field)); + } + + IField CreateField() + { + IClass c = CreateClass(); + return new DefaultField(c, "field"); + } + + [Test] + public void ShowEntryReturnsFalseForIFieldWhenHasFromAndImportIsFalse() + { + PythonImportExpressionContext context = new PythonImportExpressionContext(); + IField field = CreateField(); + + Assert.IsFalse(context.ShowEntry(field)); + } + + [Test] + public void ShowEntryReturnsTrueForIClass() + { + PythonImportExpressionContext context = new PythonImportExpressionContext(); + context.HasFromAndImport = true; + IClass c = CreateClass(); + + Assert.IsTrue(context.ShowEntry(c)); + } + + [Test] + public void ShowEntryReturnsFalseForIClassWhenHasFromAndImportIsFalse() + { + PythonImportExpressionContext context = new PythonImportExpressionContext(); + IClass c = CreateClass(); + + Assert.IsFalse(context.ShowEntry(c)); + } + } +} 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/Completion/SysModuleMembersInPythonContextTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/SysModuleMembersInPythonContextTestFixture.cs new file mode 100644 index 0000000000..d88593b78f --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Completion/SysModuleMembersInPythonContextTestFixture.cs @@ -0,0 +1,56 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using IronPython.Hosting; +using IronPython.Modules; +using IronPython.Runtime; +using Microsoft.Scripting.Hosting; +using Microsoft.Scripting.Hosting.Providers; +using Microsoft.Scripting.Runtime; +using NUnit.Framework; + +namespace PythonBinding.Tests.Completion +{ + [TestFixture] + public class SysModuleMembersInPythonContextTestFixture + { + IList membersFromSystemState; + object sysModuleFromBuiltinModuleDictionaryObject; + + [SetUp] + public void Init() + { + ScriptEngine engine = Python.CreateEngine(); + PythonContext context = HostingHelpers.GetLanguageContext(engine) as PythonContext; + + membersFromSystemState = context.GetMemberNames(context.SystemState); + + sysModuleFromBuiltinModuleDictionaryObject = null; + context.BuiltinModuleDict.TryGetValue("sys", out sysModuleFromBuiltinModuleDictionaryObject); + } + + [Test] + public void ExitMethodIsMemberOfSystemState() + { + Assert.IsTrue(membersFromSystemState.Contains("exit")); + } + + [Test] + public void SysModuleFromBuiltinModuleDictionary() + { + Assert.IsNull(sysModuleFromBuiltinModuleDictionaryObject); + } + + [Test] + public void PathIsMemberOfSystemState() + { + Assert.IsTrue(membersFromSystemState.Contains("path")); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/LoadFileSystemWatcherTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/LoadFileSystemWatcherTestFixture.cs new file mode 100644 index 0000000000..bd99ebb297 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/LoadFileSystemWatcherTestFixture.cs @@ -0,0 +1,78 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Windows.Forms; + +using ICSharpCode.PythonBinding; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Designer +{ + [TestFixture] + public class LoadFileSystemWatcherTestFixture : LoadFormTestFixtureBase + { + public override string PythonCode { + get { + return + "class MainForm(System.Windows.Forms.Form):\r\n" + + " def InitializeComponent(self):\r\n" + + " self._fileSystemWatcher1 = System.IO.FileSystemWatcher()\r\n" + + " self._fileSystemWatcher1.BeginInit()\r\n" + + " self.SuspendLayout()\r\n" + + " # \r\n" + + " # fileSystemWatcher1\r\n" + + " # \r\n" + + " self._fileSystemWatcher1.EnableRaisingEvents = True\r\n" + + " self._fileSystemWatcher1.SynchronizingObject = self\r\n" + + " # \r\n" + + " # MainForm\r\n" + + " # \r\n" + + " self.ClientSize = System.Drawing.Size(300, 400)\r\n" + + " self.Name = \"MainForm\"\r\n" + + " self._fileSystemWatcher1.EndInit()\r\n" + + " self.ResumeLayout(False)\r\n"; + } + } + + public CreatedInstance FileSystemWatcherInstance { + get { return ComponentCreator.CreatedInstances[0]; } + } + + public FileSystemWatcher FileSystemWatcher { + get { return FileSystemWatcherInstance.Object as FileSystemWatcher; } + } + + [Test] + public void ComponentName() + { + Assert.AreEqual("fileSystemWatcher1", FileSystemWatcherInstance.Name); + } + + [Test] + public void ComponentType() + { + Assert.AreEqual("System.IO.FileSystemWatcher", FileSystemWatcherInstance.InstanceType.FullName); + } + + [Test] + public void FileSystemWatcherEnableRaisingEventsIsTrue() + { + Assert.IsTrue(FileSystemWatcher.EnableRaisingEvents); + } + + [Test] + public void FileSystemWatcherSynchronisingObjectIsForm() + { + Assert.AreSame(Form, FileSystemWatcher.SynchronizingObject); + } + } +} 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/Expressions/FindImportExpressionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FindImportExpressionTestFixture.cs index f0a6c3fdcb..1d28b38e64 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FindImportExpressionTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FindImportExpressionTestFixture.cs @@ -34,6 +34,14 @@ namespace PythonBinding.Tests.Expressions Assert.AreEqual("import", result.Expression); } + [Test] + public void ExpressionContextIsNamespaceForImportExpression() + { + string text = "import"; + ExpressionResult result = expressionFinder.FindExpression(text, text.Length); + Assert.IsNotNull(result.Context as PythonImportExpressionContext); + } + /// /// Currently the expression finder returns the full import expression. /// It should probably just return the namespace. @@ -44,16 +52,18 @@ namespace PythonBinding.Tests.Expressions string text = "import System"; ExpressionResult result = expressionFinder.FindExpression(text, text.Length); Assert.AreEqual("import System", result.Expression); - Assert.AreEqual(ExpressionContext.Importable, result.Context); + Assert.IsNotNull(result.Context as PythonImportExpressionContext); } [Test] public void MultipleLinesWithImportAndNamespace() { - string text = "# Line to ignore\r\nimport System"; + string text = + "# Line to ignore\r\n" + + "import System"; ExpressionResult result = expressionFinder.FindExpression(text, text.Length); Assert.AreEqual("import System", result.Expression); - Assert.AreEqual(ExpressionContext.Importable, result.Context); + Assert.IsNotNull(result.Context as PythonImportExpressionContext); } [Test] @@ -62,7 +72,7 @@ namespace PythonBinding.Tests.Expressions string text = "import System"; ExpressionResult result = expressionFinder.FindExpression(text, text.Length); Assert.AreEqual(text, result.Expression); - Assert.AreEqual(ExpressionContext.Importable, result.Context); + Assert.IsNotNull(result.Context as PythonImportExpressionContext); } [Test] @@ -71,7 +81,7 @@ namespace PythonBinding.Tests.Expressions string text = "from System import Test"; ExpressionResult result = expressionFinder.FindExpression(text, text.Length); Assert.AreEqual(text, result.Expression); - Assert.AreEqual(ExpressionContext.Importable, result.Context); + Assert.IsNotNull(result.Context as PythonImportExpressionContext); } /// @@ -84,5 +94,14 @@ namespace PythonBinding.Tests.Expressions ExpressionResult result = expressionFinder.FindExpression(text, text.Length); Assert.AreEqual("Test", result.Expression); } + + [Test] + public void FromStatementWithoutAnyImportPart() + { + string text = "from System"; + ExpressionResult result = expressionFinder.FindExpression(text, text.Length); + Assert.AreEqual(text, result.Expression); + Assert.IsNotNull(result.Context as PythonImportExpressionContext); + } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FromImportNamespaceExpressionTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FromImportNamespaceExpressionTests.cs new file mode 100644 index 0000000000..03216566cc --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FromImportNamespaceExpressionTests.cs @@ -0,0 +1,58 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using IronPython.Hosting; +using Microsoft.Scripting.Hosting; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class FromImportNamespaceExpressionTests + { + ScriptEngine engine; + + [SetUp] + public void Init() + { + engine = Python.CreateEngine(); + } + + [Test] + public void FromModuleNameIsSystemForFromSystemExpression() + { + PythonImportExpression expression = new PythonImportExpression(engine, "from System"); + Assert.AreEqual("System", expression.Module); + Assert.IsFalse(expression.HasFromAndImport); + } + + [Test] + public void FromModuleNameIsEmptyWhenOnlyFromIsInExpression() + { + PythonImportExpression expression = new PythonImportExpression(engine, "from"); + Assert.AreEqual(String.Empty, expression.Module); + Assert.IsFalse(expression.HasFromAndImport); + } + + [Test] + public void FromModuleNameIsSystemForFromSystemExpressionWithWhitespaceBetweenImportAndSystem() + { + PythonImportExpression expression = new PythonImportExpression(engine, "from \t System"); + Assert.AreEqual("System", expression.Module); + Assert.IsFalse(expression.HasFromAndImport); + } + + [Test] + public void HasIdentifierReturnsFalseForFromMathImportWithoutIdentfier() + { + PythonImportExpression expression = new PythonImportExpression(engine, "from math import"); + Assert.IsFalse(expression.HasIdentifier); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FromSystemImportTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FromSystemImportTestFixture.cs new file mode 100644 index 0000000000..503183b148 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/FromSystemImportTestFixture.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using IronPython.Hosting; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class FromSystemImportTestFixture + { + PythonImportExpression expression; + + [SetUp] + public void Init() + { + string text = "from System import "; + expression = new PythonImportExpression(Python.CreateEngine(), text); + } + + [Test] + public void HasFromImportAndImportReturnsTrue() + { + Assert.IsTrue(expression.HasFromAndImport); + } + + [Test] + public void ModuleNameIsSystem() + { + Assert.AreEqual("System", expression.Module); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ImportNamespaceExpressionTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ImportNamespaceExpressionTests.cs new file mode 100644 index 0000000000..5c5639e198 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ImportNamespaceExpressionTests.cs @@ -0,0 +1,49 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using IronPython.Hosting; +using Microsoft.Scripting.Hosting; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class ImportNamespaceExpressionTests + { + ScriptEngine engine; + + [SetUp] + public void Init() + { + engine = Python.CreateEngine(); + } + + [Test] + public void ModuleNameReturnedIsSystemForImportSystemExpression() + { + PythonImportExpression expression = new PythonImportExpression(engine, "import System"); + Assert.AreEqual("System", expression.Module); + } + + [Test] + public void ModuleNameReturnedIsSystemForImportSystemExpressionWithWhitespaceBetweenImportAndSystem() + { + string code = "import \t System"; + PythonImportExpression expression = new PythonImportExpression(engine, code); + Assert.AreEqual("System", expression.Module); + } + + [Test] + public void ModuleNameIsEmptyStringWhenExpressionIsEmptyString() + { + PythonImportExpression expression = new PythonImportExpression(engine, String.Empty); + Assert.AreEqual(String.Empty, expression.Module); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/IsImportExpressionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/IsImportExpressionTestFixture.cs new file mode 100644 index 0000000000..ad7a20d7da --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/IsImportExpressionTestFixture.cs @@ -0,0 +1,81 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class IsImportExpressionTestFixture + { + [Test] + public void EmptyStringIsNotImportExpression() + { + string text = String.Empty; + int offset = 0; + Assert.IsFalse(PythonImportExpression.IsImportExpression(text, offset)); + } + + [Test] + public void ImportStringFollowedByWhitespaceIsImportExpression() + { + string text = "import "; + int offset = text.Length - 1; + Assert.IsTrue(PythonImportExpression.IsImportExpression(text, offset)); + } + + [Test] + public void ImportStringSurroundedByExtraWhitespaceIsImportExpression() + { + string text = " import "; + int offset = text.Length - 1; + Assert.IsTrue(PythonImportExpression.IsImportExpression(text, offset)); + } + + [Test] + public void ImportInsideAnotherStringIsNotImportExpression() + { + string text = "Start-import-End"; + int offset = text.Length - 1; + Assert.IsFalse(PythonImportExpression.IsImportExpression(text, offset)); + } + + [Test] + public void ImportSystemIsImportExpression() + { + string text = "import System"; + int offset = text.Length - 1; + Assert.IsTrue(PythonImportExpression.IsImportExpression(text, offset)); + } + + [Test] + public void IsImportExpressionReturnsFalseWhenOffsetIsMinusOne() + { + string text = "import a"; + int offset = -1; + Assert.IsFalse(PythonImportExpression.IsImportExpression(text, offset)); + } + + [Test] + public void IsImportExpressionReturnsTrueWhenExpressionContainsOnlyFromPart() + { + string text = "from a"; + int offset = text.Length - 1; + Assert.IsTrue(PythonImportExpression.IsImportExpression(text, offset)); + } + + [Test] + public void FromExpressionFollowedByWhitespaceIsImportExpression() + { + string text = "from "; + int offset = text.Length - 1; + Assert.IsTrue(PythonImportExpression.IsImportExpression(text, offset)); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseFromImportWithIdentifierTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseFromImportWithIdentifierTestFixture.cs new file mode 100644 index 0000000000..d7fb7936d4 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseFromImportWithIdentifierTestFixture.cs @@ -0,0 +1,44 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class ParseFromImportWithIdentifierTestFixture + { + PythonImportExpression importExpression; + + [SetUp] + public void Init() + { + string code = "from System import Console"; + importExpression = new PythonImportExpression(code); + } + + [Test] + public void HasImportAndFromReturnsTrue() + { + Assert.IsTrue(importExpression.HasFromAndImport); + } + + [Test] + public void ImportIdentifierIsConsole() + { + Assert.AreEqual("Console", importExpression.Identifier); + } + + [Test] + public void HasIdentifierReturnsTrue() + { + Assert.IsTrue(importExpression.HasIdentifier); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseFromImportWithoutImportedNameTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseFromImportWithoutImportedNameTestFixture.cs new file mode 100644 index 0000000000..89a0afdb22 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseFromImportWithoutImportedNameTestFixture.cs @@ -0,0 +1,41 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class FindExpressionFromImportWithoutImportedNameTestFixture + { + ExpressionResult expressionResult; + + [SetUp] + public void Init() + { + string code = "from System import "; + int offset = 19; + PythonExpressionFinder expressionFinder = new PythonExpressionFinder(); + expressionResult = expressionFinder.FindExpression(code, offset); + } + + [Test] + public void ExpressionResultContextIsImportExpression() + { + Assert.IsNotNull(expressionResult.Context as PythonImportExpressionContext); + } + + [Test] + public void ExpressionIsFullFromImportStatement() + { + Assert.AreSame("from System import ", expressionResult.Expression); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseImportExpressionOnlyTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseImportExpressionOnlyTestFixture.cs new file mode 100644 index 0000000000..c5ed2e9a01 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseImportExpressionOnlyTestFixture.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using IronPython.Hosting; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class ParseImportExpressionOnlyTestFixture + { + PythonImportExpression importExpression; + + [SetUp] + public void Init() + { + string text = "import"; + importExpression = new PythonImportExpression(Python.CreateEngine(), text); + } + + [Test] + public void ModuleNameIsEmptyString() + { + Assert.AreEqual(String.Empty, importExpression.Module); + } + + [Test] + public void HasFromAndImportIsFalse() + { + Assert.IsFalse(importExpression.HasFromAndImport); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseImportSystemConsoleExpressionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseImportSystemConsoleExpressionTestFixture.cs new file mode 100644 index 0000000000..9fa7df0ab8 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseImportSystemConsoleExpressionTestFixture.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using IronPython.Hosting; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class ParseImportSystemConsoleExpressionTestFixture + { + PythonImportExpression importExpression; + + [SetUp] + public void Init() + { + string text = "import System.Console"; + importExpression = new PythonImportExpression(Python.CreateEngine(), text); + } + + [Test] + public void ModuleNameIsSystem() + { + Assert.AreEqual("System.Console", importExpression.Module); + } + + [Test] + public void HasFromAndImportIsFalse() + { + Assert.IsFalse(importExpression.HasFromAndImport); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseImportSystemExpressionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseImportSystemExpressionTestFixture.cs new file mode 100644 index 0000000000..b0e444b9a5 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseImportSystemExpressionTestFixture.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using IronPython.Hosting; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class ParseImportSystemExpressionTestFixture + { + PythonImportExpression importExpression; + + [SetUp] + public void Init() + { + string text = "import System"; + importExpression = new PythonImportExpression(Python.CreateEngine(), text); + } + + [Test] + public void ModuleNameIsSystem() + { + Assert.AreEqual("System", importExpression.Module); + } + + [Test] + public void HasFromAndImportIsFalse() + { + Assert.IsFalse(importExpression.HasFromAndImport); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParsePartialFromImportStatementTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParsePartialFromImportStatementTestFixture.cs new file mode 100644 index 0000000000..78c2cb8d5c --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParsePartialFromImportStatementTestFixture.cs @@ -0,0 +1,123 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.IO; +using System.Text; + +using Microsoft.Scripting; +using Microsoft.Scripting.Hosting; +using Microsoft.Scripting.Hosting.Providers; +using Microsoft.Scripting.Runtime; +using ICSharpCode.PythonBinding; +using IronPython; +using IronPython.Compiler; +using IronPython.Compiler.Ast; +using IronPython.Hosting; +using IronPython.Runtime; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class ParsePartialFromImportStatementTestFixture + { + FromImportStatement fromStatement; + + public FromImportStatement ParseStatement(string text) + { + ScriptEngine engine = Python.CreateEngine(); + PythonContext context = HostingHelpers.GetLanguageContext(engine) as PythonContext; + + StringTextContentProvider textProvider = new StringTextContentProvider(text); + SourceUnit source = context.CreateSourceUnit(textProvider, String.Empty, SourceCodeKind.SingleStatement); + + PythonCompilerSink sink = new PythonCompilerSink(); + CompilerContext compilerContext = new CompilerContext(source, new PythonCompilerOptions(), sink); + + PythonOptions options = new PythonOptions(); + using (Parser parser = Parser.CreateParser(compilerContext, options)) { + return parser.ParseSingleStatement().Body as FromImportStatement; + } + } + + [Test] + public void FromSystemImportStatementFollowedByIdentifierHasModuleNameOfSystem() + { + string text = "from System import abc"; + fromStatement = ParseStatement(text); + Assert.AreEqual("System", fromStatement.Root.MakeString()); + } + + [Test] + public void FromSystemImportStatementFollowedByIdentifierHasIdentifierInNamesCollection() + { + FromSystemImportStatementFollowedByIdentifierHasModuleNameOfSystem(); + Assert.IsTrue(fromStatement.Names.Contains("abc")); + } + + [Test] + public void FromSystemImportStatementFollowedByEmptySpaceHasModuleNameOfSystem() + { + string text = "from System import "; + fromStatement = ParseStatement(text); + Assert.AreEqual("System", fromStatement.Root.MakeString()); + } + + [Test] + public void FromSystemStatementWithNoImportHasModuleNameOfSystem() + { + string text = "from System"; + fromStatement = ParseStatement(text); + Assert.AreEqual("System", fromStatement.Root.MakeString()); + } + + [Test] + public void FromStatementFollowedBySpaceCharButNoModuleNameHasModuleNameOfEmptyString() + { + string text = "from "; + fromStatement = ParseStatement(text); + Assert.AreEqual(String.Empty, fromStatement.Root.MakeString()); + } + + [Test] + [Ignore("Does not work")] + public void FromSystemImportStatementFollowedByIdentifierAsNameHasIdentifierAsNameInAsNamesCollection() + { + string text = "from System import abc as def"; + fromStatement = ParseStatement(text); + Assert.AreEqual("def", fromStatement.AsNames[0]); + } + + [Test] + [Ignore("Does not work")] + public void FromSystemImportStatementFollowedByIdentifierAsNameFollowedBySpaceHasIdentifierAsNameInAsNamesCollection() + { + string text = "from System import abc as def "; + fromStatement = ParseStatement(text); + Assert.AreEqual("def", fromStatement.AsNames[0]); + } + + [Test] + [Ignore("Does not work")] + public void FromSystemImportStatementFollowedByIdentifierAsNameFollowedByNewLineHasIdentifierAsNameInAsNamesCollection() + { + string text = "from System import abc as def\r\n"; + fromStatement = ParseStatement(text); + Assert.AreEqual("def", fromStatement.AsNames[0]); + } + + [Test] + [Ignore("Does not work")] + public void FromSystemImportStatementFollowedByMultipleIdentifierAsNameFollowedBySpaceHasIdentifierAsNameInAsNamesCollection() + { + string text = "from System import abc as def, ghi as jkl"; + fromStatement = ParseStatement(text); + Assert.AreEqual("def", fromStatement.AsNames[0]); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParsePartialFromImportStatementWithTokenizerTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParsePartialFromImportStatementWithTokenizerTestFixture.cs new file mode 100644 index 0000000000..87beefc4ae --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParsePartialFromImportStatementWithTokenizerTestFixture.cs @@ -0,0 +1,145 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.IO; +using System.Text; + +using Microsoft.Scripting; +using Microsoft.Scripting.Hosting; +using Microsoft.Scripting.Hosting.Providers; +using Microsoft.Scripting.Runtime; +using ICSharpCode.PythonBinding; +using IronPython; +using IPyCompiler = IronPython.Compiler; +using IronPython.Compiler.Ast; +using IronPython.Hosting; +using IronPython.Runtime; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class ParsePartialFromImportStatementWithTokenizerTestFixture + { + IPyCompiler.Tokenizer tokenizer; + + public IPyCompiler.Tokenizer CreateTokenizer(string text) + { + ScriptEngine engine = Python.CreateEngine(); + PythonContext context = HostingHelpers.GetLanguageContext(engine) as PythonContext; + + StringTextContentProvider textProvider = new StringTextContentProvider(text); + SourceUnit source = context.CreateSourceUnit(textProvider, String.Empty, SourceCodeKind.SingleStatement); + + PythonCompilerSink sink = new PythonCompilerSink(); + IPyCompiler.PythonCompilerOptions options = new IPyCompiler.PythonCompilerOptions(); + + tokenizer = new IPyCompiler.Tokenizer(sink, options); + tokenizer.Initialize(source); + return tokenizer; + } + + [Test] + public void FirstTokenIsFrom() + { + string text = "from"; + tokenizer = CreateTokenizer(text); + IPyCompiler.Token token = tokenizer.GetNextToken(); + Assert.AreEqual(IPyCompiler.TokenKind.KeywordFrom, token.Kind); + } + + [Test] + public void TokenAfterFromIsEof() + { + FirstTokenIsFrom(); + IPyCompiler.Token token = tokenizer.GetNextToken(); + + Assert.AreEqual(IPyCompiler.TokenKind.EndOfFile, token.Kind); + } + + [Test] + public void FromSystemImportSecondTokenIsModule() + { + string text = "from System"; + IPyCompiler.Token token = GetSecondToken(text); + + Assert.AreEqual(IPyCompiler.TokenKind.Name, token.Kind); + } + + IPyCompiler.Token GetSecondToken(string text) + { + return GetToken(text, 2); + } + + IPyCompiler.Token GetToken(string text, int tokenNumber) + { + tokenizer = CreateTokenizer(text); + + IPyCompiler.Token token = null; + for (int i = 0; i < tokenNumber; ++i) { + token = tokenizer.GetNextToken(); + } + return token; + } + + [Test] + public void FromSystemImportSecondTokenValueIsSystem() + { + string text = "from System"; + IPyCompiler.Token token = GetSecondToken(text); + + Assert.AreEqual("System", token.Value as String); + } + + [Test] + public void FromSystemConsoleImportSecondTokenValueIsSystem() + { + string text = "from System.Console"; + IPyCompiler.Token token = GetSecondToken(text); + + Assert.AreEqual("System", token.Value as String); + } + + [Test] + public void FromSystemConsoleImportThirdTokenValueIsDotCharacter() + { + FromSystemConsoleImportSecondTokenValueIsSystem(); + IPyCompiler.Token token = tokenizer.GetNextToken(); + + Assert.AreEqual(IPyCompiler.TokenKind.Dot, token.Kind); + } + + [Test] + public void FromSystemImportThirdTokenIsImportToken() + { + string text = "from System import"; + IPyCompiler.Token token = GetThirdToken(text); + + Assert.AreEqual(IPyCompiler.TokenKind.KeywordImport, token.Kind); + } + + IPyCompiler.Token GetThirdToken(string text) + { + return GetToken(text, 3); + } + + [Test] + public void FromSystemImportIdentifierFourthTokenIsIndentifierToken() + { + string text = "from System import abc"; + IPyCompiler.Token token = GetFourthToken(text); + + Assert.AreEqual("abc", token.Value as String); + } + + IPyCompiler.Token GetFourthToken(string text) + { + return GetToken(text, 4); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseSimpleImportExpressionTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseSimpleImportExpressionTestFixture.cs new file mode 100644 index 0000000000..a6077b85f9 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/ParseSimpleImportExpressionTestFixture.cs @@ -0,0 +1,58 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using IronPython.Compiler; +using IronPython.Hosting; +using Microsoft.Scripting.Hosting; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class ParseSimpleImportExpressionTestFixture + { + PythonExpression expression; + + [SetUp] + public void Init() + { + string code = "import"; + ScriptEngine engine = Python.CreateEngine(); + expression = new PythonExpression(engine, code); + } + + [Test] + public void FirstTokenIsImportKeyword() + { + Token token = expression.GetNextToken(); + Assert.AreEqual(TokenKind.KeywordImport, token.Kind); + } + + [Test] + public void SecondTokenIsEndOfFile() + { + expression.GetNextToken(); + Token token = expression.GetNextToken(); + Assert.AreEqual(TokenKind.EndOfFile, token.Kind); + } + + [Test] + public void CurrentTokenIsNull() + { + Assert.IsNull(expression.CurrentToken); + } + + [Test] + public void GetNextTokenSetsCurrentTokenToKeywordImport() + { + expression.GetNextToken(); + Assert.AreEqual(TokenKind.KeywordImport, expression.CurrentToken.Kind); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/StringTextContentProviderTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/StringTextContentProviderTests.cs new file mode 100644 index 0000000000..537333c86c --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Expressions/StringTextContentProviderTests.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using IronPython.Hosting; +using IronPython.Runtime; +using Microsoft.Scripting; +using Microsoft.Scripting.Hosting; +using Microsoft.Scripting.Hosting.Providers; +using NUnit.Framework; + +namespace PythonBinding.Tests.Expressions +{ + [TestFixture] + public class StringTextContentProviderTests + { + [Test] + public void ReadToEndFromStringTextContentProvider() + { + string text = "abc"; + StringTextContentProvider provider = new StringTextContentProvider(text); + using (SourceCodeReader reader = provider.GetReader()) { + Assert.AreEqual("abc", reader.ReadToEnd()); + } + } + + [Test] + public void StringTextContentProviderIsMicrosoftScriptingTextContentProvider() + { + StringTextContentProvider provider = new StringTextContentProvider(String.Empty); + Assert.IsNotNull(provider as TextContentProvider); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromMathImportAllTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromMathImportAllTestFixture.cs new file mode 100644 index 0000000000..673fbaabfd --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromMathImportAllTestFixture.cs @@ -0,0 +1,52 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace PythonBinding.Tests.Parsing +{ + [TestFixture] + public class ParseFromMathImportAllTestFixture + { + ICompilationUnit compilationUnit; + PythonFromImport import; + + [SetUp] + public void Init() + { + string python = "from math import *"; + + DefaultProjectContent projectContent = new DefaultProjectContent(); + PythonParser parser = new PythonParser(); + compilationUnit = parser.Parse(projectContent, @"C:\test.py", python); + import = compilationUnit.UsingScope.Usings[0] as PythonFromImport; + } + + [Test] + public void PythonImportContainsMathModuleName() + { + Assert.AreEqual("math", import.Module); + } + + [Test] + public void PythonImportImportsEverythingReturnsTrue() + { + Assert.IsTrue(import.ImportsEverything); + } + + [Test] + public void PythonImportGetIdentifierForAliasDoesNotThrowNullReferenceException() + { + string identifier = String.Empty; + Assert.DoesNotThrow(delegate { identifier = import.GetOriginalNameForAlias("unknown"); }); + Assert.IsNull(identifier); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromMathImportCosAndTanTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromMathImportCosAndTanTestFixture.cs new file mode 100644 index 0000000000..01024bf305 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromMathImportCosAndTanTestFixture.cs @@ -0,0 +1,62 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace PythonBinding.Tests.Parsing +{ + [TestFixture] + public class ParseFromMathImportCosAndTanTestFixture + { + ICompilationUnit compilationUnit; + PythonFromImport import; + + [SetUp] + public void Init() + { + string python = "from math import cos, tan"; + + DefaultProjectContent projectContent = new DefaultProjectContent(); + PythonParser parser = new PythonParser(); + compilationUnit = parser.Parse(projectContent, @"C:\test.py", python); + import = compilationUnit.UsingScope.Usings[0] as PythonFromImport; + } + + [Test] + public void UsingAsPythonImportHasCosIdentifier() + { + Assert.IsTrue(import.IsImportedName("cos")); + } + + [Test] + public void UsingAsPythonImportContainsMathModuleName() + { + Assert.AreEqual("math", import.Module); + } + + [Test] + public void UsingAsPythonImportHasTanIdentifier() + { + Assert.IsTrue(import.IsImportedName("tan")); + } + + [Test] + public void UsingAsPythonImportDoesNotHaveACosIdentifier() + { + Assert.IsFalse(import.IsImportedName("acos")); + } + + [Test] + public void PythonImportImportsEverythingReturnsFalse() + { + Assert.IsFalse(import.ImportsEverything); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportExitAsMyExitTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportExitAsMyExitTestFixture.cs new file mode 100644 index 0000000000..1e99815393 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportExitAsMyExitTestFixture.cs @@ -0,0 +1,50 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace PythonBinding.Tests.Parsing +{ + [TestFixture] + public class ParseFromSysImportExitAsMyExitTestFixture + { + ICompilationUnit compilationUnit; + PythonFromImport import; + + [SetUp] + public void Init() + { + string python = "from sys import exit as myexit"; + + DefaultProjectContent projectContent = new DefaultProjectContent(); + PythonParser parser = new PythonParser(); + compilationUnit = parser.Parse(projectContent, @"C:\test.py", python); + import = compilationUnit.UsingScope.Usings[0] as PythonFromImport; + } + + [Test] + public void UsingAsPythonImportHasMyExitIdentifier() + { + Assert.IsTrue(import.IsImportedName("myexit")); + } + + [Test] + public void UsingAsPythonImportDoesNotHaveExitIdentifier() + { + Assert.IsFalse(import.IsImportedName("exit")); + } + + [Test] + public void PythonImportGetIdentifierFromAliasReturnsExitForMyExit() + { + Assert.AreEqual("exit", import.GetOriginalNameForAlias("myexit")); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportExitTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportExitTestFixture.cs new file mode 100644 index 0000000000..f9e37a9624 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportExitTestFixture.cs @@ -0,0 +1,50 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace PythonBinding.Tests.Parsing +{ + [TestFixture] + public class ParseFromSysImportExitTestFixture + { + ICompilationUnit compilationUnit; + PythonFromImport import; + + [SetUp] + public void Init() + { + string python = "from sys import exit"; + + DefaultProjectContent projectContent = new DefaultProjectContent(); + PythonParser parser = new PythonParser(); + compilationUnit = parser.Parse(projectContent, @"C:\test.py", python); + import = compilationUnit.UsingScope.Usings[0] as PythonFromImport; + } + + [Test] + public void UsingAsPythonImportHasExitIdentifier() + { + Assert.IsTrue(import.IsImportedName("exit")); + } + + [Test] + public void UsingAsPythonImportDoesNotHaveUnknownIdentifier() + { + Assert.IsFalse(import.IsImportedName("unknown")); + } + + [Test] + public void UsingAsPythonImportContainsSysModuleName() + { + Assert.AreEqual("sys", import.Module); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportMissingImportTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportMissingImportTestFixture.cs new file mode 100644 index 0000000000..8eab7310b8 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportMissingImportTestFixture.cs @@ -0,0 +1,50 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace PythonBinding.Tests.Parsing +{ + [TestFixture] + public class ParseFromSysImportMissingImportTestFixture + { + ICompilationUnit compilationUnit; + PythonFromImport import; + + [SetUp] + public void Init() + { + string python = "from sys"; + + DefaultProjectContent projectContent = new DefaultProjectContent(); + PythonParser parser = new PythonParser(); + compilationUnit = parser.Parse(projectContent, @"C:\test.py", python); + import = compilationUnit.UsingScope.Usings[0] as PythonFromImport; + } + + [Test] + public void UsingAsPythonImportDoesNotHaveEmptyStringIdentifier() + { + Assert.IsFalse(import.IsImportedName(String.Empty)); + } + + [Test] + public void UsingAsPythonImportDoesNotHaveNullIdentifier() + { + Assert.IsFalse(import.IsImportedName(null)); + } + + [Test] + public void UsingAsPythonImportContainsSysModuleName() + { + Assert.AreEqual("sys", import.Module); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportWithoutImportedNameTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportWithoutImportedNameTestFixture.cs new file mode 100644 index 0000000000..92ff5a2687 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseFromSysImportWithoutImportedNameTestFixture.cs @@ -0,0 +1,50 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace PythonBinding.Tests.Parsing +{ + [TestFixture] + public class ParseFromSysImportWithoutImportedNameTestFixture + { + ICompilationUnit compilationUnit; + PythonFromImport import; + + [SetUp] + public void Init() + { + string python = "from sys import"; + + DefaultProjectContent projectContent = new DefaultProjectContent(); + PythonParser parser = new PythonParser(); + compilationUnit = parser.Parse(projectContent, @"C:\test.py", python); + import = compilationUnit.UsingScope.Usings[0] as PythonFromImport; + } + + [Test] + public void UsingAsPythonImportDoesNotHaveEmptyStringIdentifier() + { + Assert.IsFalse(import.IsImportedName(String.Empty)); + } + + [Test] + public void UsingAsPythonImportDoesNotHaveNullIdentifier() + { + Assert.IsFalse(import.IsImportedName(null)); + } + + [Test] + public void UsingAsPythonImportContainsSysModuleName() + { + Assert.AreEqual("sys", import.Module); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseImportMultipleModulesTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseImportMultipleModulesTestFixture.cs new file mode 100644 index 0000000000..446ead157b --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseImportMultipleModulesTestFixture.cs @@ -0,0 +1,52 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.TextEditor.Document; +using NUnit.Framework; +using PythonBinding.Tests; + +namespace PythonBinding.Tests.Parsing +{ + [TestFixture] + public class ParseImportMultipleModulesTestFixture + { + ICompilationUnit compilationUnit; + + [TestFixtureSetUp] + public void SetUpFixture() + { + string python = "import System, System.Console"; + + DefaultProjectContent projectContent = new DefaultProjectContent(); + PythonParser parser = new PythonParser(); + compilationUnit = parser.Parse(projectContent, @"C:\test.py", python); + } + + [Test] + public void OneUsingStatementCreatedByParser() + { + Assert.AreEqual(1, compilationUnit.UsingScope.Usings.Count); + } + + [Test] + public void FirstNamespaceImportedIsSystem() + { + Assert.AreEqual("System", compilationUnit.UsingScope.Usings[0].Usings[0]); + } + + [Test] + public void SecondNamespaceImportedIsSystemConsole() + { + Assert.AreEqual("System.Console", compilationUnit.UsingScope.Usings[0].Usings[1]); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseImportSysTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseImportSysTestFixture.cs new file mode 100644 index 0000000000..aded5a2ea0 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseImportSysTestFixture.cs @@ -0,0 +1,38 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; + +namespace PythonBinding.Tests.Parsing +{ + [TestFixture] + public class ParseImportSysTestFixture + { + ICompilationUnit compilationUnit; + PythonImport import; + + [SetUp] + public void Init() + { + string python = "import sys"; + + DefaultProjectContent projectContent = new DefaultProjectContent(); + PythonParser parser = new PythonParser(); + compilationUnit = parser.Parse(projectContent, @"C:\test.py", python); + import = compilationUnit.UsingScope.Usings[0] as PythonImport; + } + + [Test] + public void PythonImportHasExitIdentifier() + { + Assert.AreEqual("sys", import.Module); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj index a556abf4be..14b41fc3a1 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj @@ -57,14 +57,14 @@ False - 3.0 + 4.0 - 3.0 + 4.0 - 3.5 + 4.0 @@ -75,7 +75,7 @@ - 3.0 + 4.0 @@ -84,6 +84,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -259,6 +279,7 @@ + @@ -300,13 +321,25 @@ + + + + + + + + + + + + + + + - - - @@ -314,6 +347,14 @@ + + + + + + + + @@ -326,19 +367,41 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + @@ -396,8 +459,12 @@ + + + + @@ -447,8 +514,10 @@ + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/GetPythonModulesTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/GetPythonModulesTestFixture.cs deleted file mode 100644 index 5c439738cf..0000000000 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/GetPythonModulesTestFixture.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// -// -// -// $Revision$ -// - -using System; -using System.Text; -using NUnit.Framework; -using ICSharpCode.PythonBinding; - -namespace PythonBinding.Tests.Resolver -{ - /// - /// Tests the standard Python module names can be determined - /// from the IronPython assembly. - /// - [TestFixture] - public class GetPythonModulesTestFixture - { - string[] moduleNames; - - [TestFixtureSetUp] - public void SetUpFixture() - { - StandardPythonModules modules = new StandardPythonModules(); - moduleNames = modules.GetNames(); - } - - [Test] - public void ContainsSysModuleName() - { - Assert.Contains("sys", moduleNames); - } - - [Test] - public void ContainsBuiltInModule() - { - Assert.Contains("__builtin__", moduleNames, "Module names: " + WriteArray(moduleNames)); - } - - static string WriteArray(string[] items) - { - StringBuilder text = new StringBuilder(); - foreach (string item in items) { - text.AppendLine(item); - } - return text.ToString(); - } - } -} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ImportModuleResolveResultTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ImportModuleResolveResultTests.cs new file mode 100644 index 0000000000..3b824860a1 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ImportModuleResolveResultTests.cs @@ -0,0 +1,46 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ImportModuleResolveResultTests + { + [Test] + public void NamePropertyMatchesTextPassedToConstructor() + { + PythonImportExpression expression = new PythonImportExpression("import abc"); + PythonImportModuleResolveResult result = new PythonImportModuleResolveResult(expression); + Assert.AreEqual("abc", result.Name); + } + + [Test] + public void GetCompletionDataReturnsStandardMathPythonModuleWhenImportNameIsEmptyString() + { + PythonImportExpression expression = new PythonImportExpression(String.Empty); + PythonImportModuleResolveResult result = new PythonImportModuleResolveResult(expression); + MockProjectContent projectContent = new MockProjectContent(); + Assert.Contains(new NamespaceEntry("math"), result.GetCompletionData(projectContent)); + } + + [Test] + public void ClonedPythonModuleResultReturnsSameCompletionItems() + { + PythonImportExpression expression = new PythonImportExpression(String.Empty); + PythonImportModuleResolveResult result = new PythonImportModuleResolveResult(expression); + ResolveResult clonedResult = result.Clone(); + MockProjectContent projectContent = new MockProjectContent(); + Assert.Contains(new NamespaceEntry("math"), clonedResult.GetCompletionData(projectContent)); + } + } +} 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 1721983917..9cea39b099 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveConsoleWriteLineTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveConsoleWriteLineTestFixture.cs @@ -20,33 +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(); - mockProjectContent = new MockProjectContent(); - - systemConsoleClass = new MockClass(mockProjectContent, "System.Console"); - mockProjectContent.ClassToReturnFromGetClass = systemConsoleClass; - mockProjectContent.ClassNameForGetClass = "Console"; - - compilationUnit = new DefaultCompilationUnit(mockProjectContent); - ParseInformation parseInfo = new ParseInformation(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] @@ -61,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/ResolveExitMethodFromSysImportExitAsMyExitTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveExitMethodFromSysImportExitAsMyExitTestFixture.cs new file mode 100644 index 0000000000..f10af3e951 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveExitMethodFromSysImportExitAsMyExitTestFixture.cs @@ -0,0 +1,51 @@ +// +// +// +// +// $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 ResolveExitMethodFromSysImportExitAsMyExitTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("myexit", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "from sys import exit as myexit\r\n" + + "myexit\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; } + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveExitMethodFromSysImportExitTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveExitMethodFromSysImportExitTestFixture.cs new file mode 100644 index 0000000000..4247afbe4e --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveExitMethodFromSysImportExitTestFixture.cs @@ -0,0 +1,64 @@ +// +// +// +// +// $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 ResolveExitMethodFromSysImportExitTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("exit", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "from sys import exit\r\n" + + "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() + { + List methods = MethodResolveResult.ContainingType.GetMethods(); + return PythonCompletionItemsHelper.FindAllMethodsFromCollection("exit", -1, methods.ToArray()); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromImportTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromImportTestFixture.cs index cbda7458cd..9de2796c7f 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromImportTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromImportTestFixture.cs @@ -24,23 +24,23 @@ namespace PythonBinding.Tests.Resolver { PythonResolver resolver; MockProjectContent mockProjectContent; - NamespaceResolveResult resolveResult; + PythonImportModuleResolveResult resolveResult; [TestFixtureSetUp] public void SetUpFixture() { resolver = new PythonResolver(); - + mockProjectContent = new MockProjectContent(); - mockProjectContent.SetNamespaceExistsReturnValue(true); DefaultCompilationUnit cu = new DefaultCompilationUnit(mockProjectContent); cu.ErrorsDuringCompile = true; cu.FileName = @"C:\Projects\Test\test.py"; ParseInformation parseInfo = new ParseInformation(cu); - string python = "from System."; - ExpressionResult expressionResult = new ExpressionResult("from System", new DomRegion(1, 14), null, null); - resolveResult = resolver.Resolve(expressionResult, parseInfo, python) as NamespaceResolveResult; + string python = "from System"; + PythonExpressionFinder finder = new PythonExpressionFinder(); + ExpressionResult expressionResult = finder.FindExpression(python, python.Length); + resolveResult = resolver.Resolve(expressionResult, parseInfo, python) as PythonImportModuleResolveResult; } [Test] @@ -54,11 +54,5 @@ namespace PythonBinding.Tests.Resolver { Assert.AreEqual("System", resolveResult.Name); } - - [Test] - public void NamespaceSearchedFor() - { - Assert.AreEqual("System", mockProjectContent.NamespaceSearchedFor); - } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromMathImportedMathModuleCompletionItemsTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromMathImportedMathModuleCompletionItemsTestFixture.cs new file mode 100644 index 0000000000..7acb1de669 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveFromMathImportedMathModuleCompletionItemsTestFixture.cs @@ -0,0 +1,57 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ResolveFromMathImportedMathModuleCompletionItemsTestFixture : ResolveTestFixtureBase + { + List GetCompletionResults() + { + return resolveResult.GetCompletionData(projectContent); + } + + protected override ExpressionResult GetExpressionResult() + { + string code = GetPythonScript(); + PythonExpressionFinder finder = new PythonExpressionFinder(); + return finder.FindExpression(code, code.Length); + } + + protected override string GetPythonScript() + { + return "from math import"; + } + + [Test] + public void CompletionResultsContainCosMethodFromMathModule() + { + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("cos", GetCompletionResults()); + Assert.IsNotNull(method); + } + + [Test] + public void ExpressionResultContextShowItemReturnsTrueForIMethod() + { + MockProjectContent projectContent = new MockProjectContent(); + DefaultCompilationUnit unit = new DefaultCompilationUnit(projectContent); + DefaultClass c = new DefaultClass(unit, "MyClass"); + DefaultMethod method = new DefaultMethod(c, "Test"); + + Assert.IsTrue(expressionResult.Context.ShowEntry(method)); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveImportsTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveImportsTestFixture.cs index 0c2acd246c..4be282d745 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveImportsTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveImportsTestFixture.cs @@ -31,53 +31,26 @@ namespace PythonBinding.Tests.Resolver { resolver = new PythonResolver(); mockProjectContent = new MockProjectContent(); - mockProjectContent.NamespacesToAdd.Add("Test"); + List namespaceItems = new List(); + namespaceItems.Add(new NamespaceEntry("Test")); + mockProjectContent.AddExistingNamespaceContents(String.Empty, namespaceItems); ParseInformation parseInfo = new ParseInformation(new DefaultCompilationUnit(mockProjectContent)); - results = resolver.CtrlSpace(0, "import".Length, parseInfo, "import", ExpressionContext.Importable); - } - - [Test] - public void ProjectContentAddNamespaceContentsCalled() - { - Assert.IsTrue(mockProjectContent.AddNamespaceContentsCalled); + results = resolver.CtrlSpace(0, "import".Length, parseInfo, "import", ExpressionContext.Namespace); } [Test] public void NamespaceName() { - Assert.AreEqual(String.Empty, mockProjectContent.NamespaceAddedName); - } - - [Test] - public void LookInReferencesIsTrue() - { - Assert.IsTrue(mockProjectContent.LookInReferences); - } - - [Test] - public void ProjectContentLanguagePassedToAddNamespaceContents() - { - Assert.AreSame(mockProjectContent.Language, mockProjectContent.LanguagePassedToAddNamespaceContents); + Assert.AreEqual(String.Empty, mockProjectContent.NamespacePassedToGetNamespaceContentsMethod); } - + [Test] public void TestNamespaceAdded() { Assert.Contains(new NamespaceEntry("Test"), results); } - - /// - /// Tests that the resolver handles the parse info being null - /// - [Test] - public void NullParseInfo() - { - PythonResolver resolver = new PythonResolver(); - List results = resolver.CtrlSpace(0, 0, null, "abc", ExpressionContext.Importable); - Assert.AreEqual(0, results.Count); - } [Test] public void ContainsSysModule() diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveMethodFromUnknownImportAllTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveMethodFromUnknownImportAllTestFixture.cs new file mode 100644 index 0000000000..7f4ef1bbf7 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveMethodFromUnknownImportAllTestFixture.cs @@ -0,0 +1,41 @@ +// +// +// +// +// $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 ResolveMethodFromUnknownImportAllTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("methodcall", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "from unknown import *\r\n" + + "methodcall\r\n" + + "\r\n"; + } + + [Test] + public void ResolveResultIsNull() + { + Assert.IsNull(resolveResult); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveMethodWhenFromImportIsUnknownTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveMethodWhenFromImportIsUnknownTestFixture.cs new file mode 100644 index 0000000000..a6535ebb7d --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveMethodWhenFromImportIsUnknownTestFixture.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 ResolveMethodWhenFromImportIsUnknownTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("methodcall", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "from unknown import methodcall\r\n" + + "methodcall\r\n" + + "\r\n"; + } + + [Test] + public void ResolveResultIsNull() + { + Assert.IsNull(resolveResult); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveMethodWhenImportIsUnknownTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveMethodWhenImportIsUnknownTestFixture.cs new file mode 100644 index 0000000000..d32bf26924 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveMethodWhenImportIsUnknownTestFixture.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 ResolveMethodWhenImportIsUnknownTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("unknown.methodcall", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "from unknown import methodcall\r\n" + + "unknown.methodcall\r\n" + + "\r\n"; + } + + [Test] + public void ResolveResultIsNull() + { + Assert.IsNull(resolveResult); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveNullCtrlSpaceParseInfoTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveNullCtrlSpaceParseInfoTestFixture.cs new file mode 100644 index 0000000000..91090cd2bc --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveNullCtrlSpaceParseInfoTestFixture.cs @@ -0,0 +1,31 @@ +// +// +// +// +// $Revision$ +// + +using System; +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 ResolveNullCtrlSpaceParseInfoTestFixture + { + /// + /// Tests that the resolver handles the parse info being null + /// + [Test] + public void ResolveCtrlSpaceDoesNotThrowExceptionWhenNullParseInfoIsNull() + { + PythonResolver resolver = new PythonResolver(); + List results = resolver.CtrlSpace(0, 0, null, "abc", ExpressionContext.Namespace); + Assert.AreEqual(0, results.Count); + } + } +} 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/ResolveSysModuleImportedAsMySysTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleImportedAsMySysTestFixture.cs new file mode 100644 index 0000000000..8cf504b92f --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleImportedAsMySysTestFixture.cs @@ -0,0 +1,46 @@ +// +// +// +// +// $Revision$ +// + +using System; +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 ResolveSysModuleImportedAsMySysTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("mysys", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "import sys as mysys\r\n" + + "mysys\r\n" + + "\r\n"; + } + + [Test] + public void ResolveResultContainsExitMethod() + { + List items = GetCompletionItems(); + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("exit", items); + Assert.IsNotNull(method); + } + + List GetCompletionItems() + { + return resolveResult.GetCompletionData(projectContent); + } + } +} 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..c3e0f0248d --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSysModuleTestFixture.cs @@ -0,0 +1,61 @@ +// +// +// +// +// $Revision$ +// + +using System; +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 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() + { + List items = GetCompletionItems(); + IMethod method = PythonCompletionItemsHelper.FindMethodFromCollection("exit", items); + Assert.IsNotNull(method); + } + + List 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 d0d8f5636a..54ce93d922 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemImportTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemImportTestFixture.cs @@ -20,26 +20,18 @@ namespace PythonBinding.Tests.Resolver /// a namespace. /// [TestFixture] - public class ResolveSystemImportTestFixture + public class ResolveSystemImportTestFixture : ResolveTestFixtureBase { - PythonResolver resolver; - MockProjectContent mockProjectContent; - NamespaceResolveResult resolveResult; + protected override ExpressionResult GetExpressionResult() + { + string code = GetPythonScript(); + PythonExpressionFinder finder = new PythonExpressionFinder(); + return finder.FindExpression(code, code.Length); + } - [TestFixtureSetUp] - public void SetUpFixture() + protected override string GetPythonScript() { - resolver = new PythonResolver(); - mockProjectContent = new MockProjectContent(); - mockProjectContent.SetNamespaceExistsReturnValue(true); - DefaultCompilationUnit cu = new DefaultCompilationUnit(mockProjectContent); - cu.ErrorsDuringCompile = true; - cu.FileName = @"C:\Projects\Test\test.py"; - ParseInformation parseInfo = new ParseInformation(cu); - - string python = "import System."; - ExpressionResult expressionResult = new ExpressionResult("import System", new DomRegion(1, 14), null, null); - resolveResult = resolver.Resolve(expressionResult, parseInfo, python) as NamespaceResolveResult; + return "import System"; } [Test] @@ -51,13 +43,21 @@ namespace PythonBinding.Tests.Resolver [Test] public void NamespaceName() { - Assert.AreEqual("System", resolveResult.Name); + PythonImportModuleResolveResult importResolveResult = (PythonImportModuleResolveResult)resolveResult; + Assert.AreEqual("System", importResolveResult.Name); } [Test] - public void NamespaceSearchedFor() + public void ExpressionResultContextShowItemReturnsTrueForNamespaceEntry() { - Assert.AreEqual("System", mockProjectContent.NamespaceSearchedFor); - } + NamespaceEntry entry = new NamespaceEntry("abc"); + Assert.IsTrue(expressionResult.Context.ShowEntry(entry)); + } + + [Test] + public void ExpressionResultContextShowItemReturnsFalseForNull() + { + Assert.IsFalse(expressionResult.Context.ShowEntry(null)); + } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemImportedAsMySystemTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemImportedAsMySystemTestFixture.cs new file mode 100644 index 0000000000..67620cb5d9 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemImportedAsMySystemTestFixture.cs @@ -0,0 +1,72 @@ +// +// +// +// +// $Revision$ +// + +using System; +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 ResolveSystemImportedAsMySystemTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + List namespaceItems = new List(); + DefaultClass consoleClass = new DefaultClass(compilationUnit, "System.Console"); + namespaceItems.Add(consoleClass); + projectContent.AddExistingNamespaceContents("System", namespaceItems); + + return new ExpressionResult("MySystem", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "import System as MySystem\r\n" + + "MySystem.\r\n" + + "\r\n"; + } + + [Test] + public void ResolveResultContainsConsoleClass() + { + List items = GetCompletionItems(); + IClass consoleClass = PythonCompletionItemsHelper.FindClassFromCollection("Console", items); + Assert.IsNotNull(consoleClass); + } + + List GetCompletionItems() + { + return resolveResult.GetCompletionData(projectContent); + } + + [Test] + public void NamespaceResolveResultNameIsSystem() + { + NamespaceResolveResult namespaceResolveResult = resolveResult as NamespaceResolveResult; + Assert.AreEqual("System", namespaceResolveResult.Name); + } + + [Test] + public void MockProjectContentSystemNamespaceContentsIncludesConsoleClass() + { + List items = projectContent.GetNamespaceContents("System"); + IClass consoleClass = PythonCompletionItemsHelper.FindClassFromCollection("Console", items); + Assert.IsNotNull(consoleClass); + } + + [Test] + public void MockProjectContentNamespaceExistsReturnsTrueForSystem() + { + Assert.IsTrue(projectContent.NamespaceExists("System")); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemNamespaceTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemNamespaceTestFixture.cs index 09fdbb3514..650817ea03 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemNamespaceTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveSystemNamespaceTestFixture.cs @@ -6,7 +6,7 @@ // using System; -using System.Collections; +using System.Collections.Generic; using ICSharpCode.PythonBinding; using ICSharpCode.SharpDevelop.Dom; using NUnit.Framework; @@ -24,38 +24,28 @@ namespace PythonBinding.Tests.Resolver { PythonResolver resolver; MockProjectContent mockProjectContent; - ResolveResult resolveResult; + NamespaceResolveResult resolveResult; [TestFixtureSetUp] public void SetUpFixture() { resolver = new PythonResolver(); mockProjectContent = new MockProjectContent(); - mockProjectContent.SetNamespaceExistsReturnValue(true); + mockProjectContent.AddExistingNamespaceContents("System", new List()); DefaultCompilationUnit cu = new DefaultCompilationUnit(mockProjectContent); cu.ErrorsDuringCompile = true; cu.FileName = @"C:\Projects\Test\test.py"; ParseInformation parseInfo = new ParseInformation(cu); - string python = "import System\r\n" + - "class Test:\r\n" + - "\tdef __init__(self):\r\n" + - "\t\tSystem.\r\n"; + string python = + "import System\r\n" + + "class Test:\r\n" + + " def __init__(self):\r\n" + + " System.\r\n"; + ExpressionResult expressionResult = new ExpressionResult("System", new DomRegion(3, 2), null, null); - resolveResult = resolver.Resolve(expressionResult, parseInfo, python); - } - - [Test] - public void ResolveResultExists() - { - Assert.IsNotNull(resolveResult); - } - - [Test] - public void IsNamespaceResolveResult() - { - Assert.IsInstanceOf(typeof(NamespaceResolveResult), resolveResult); + resolveResult = resolver.Resolve(expressionResult, parseInfo, python) as NamespaceResolveResult; } [Test] @@ -67,14 +57,13 @@ namespace PythonBinding.Tests.Resolver [Test] public void NamespaceSearchedFor() { - Assert.AreEqual("System", mockProjectContent.NamespaceSearchedFor); + Assert.AreEqual("System", mockProjectContent.NamespacePassedToNamespaceExistsMethod); } [Test] public void NamespaceResolveResultHasSystemNamespace() { - NamespaceResolveResult nsResult = (NamespaceResolveResult)resolveResult; - Assert.AreEqual("System", nsResult.Name); + Assert.AreEqual("System", resolveResult.Name); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveTanMethodFromMathImportAllTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveTanMethodFromMathImportAllTestFixture.cs new file mode 100644 index 0000000000..25fee2ce65 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveTanMethodFromMathImportAllTestFixture.cs @@ -0,0 +1,67 @@ +// +// +// +// +// $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 ResolveTanMethodFromMathImportAllTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("tan", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "from sys import *\r\n" + + "from math import *\r\n" + + "from socket import *\r\n" + + "\r\n" + + "tan\r\n" + + "\r\n"; + } + + [Test] + public void ResolveResultIsMethodGroupResolveResult() + { + Assert.IsTrue(resolveResult is MethodGroupResolveResult); + } + + [Test] + public void ResolveResultMethodNameIsTan() + { + Assert.AreEqual("tan", MethodResolveResult.Name); + } + + MethodGroupResolveResult MethodResolveResult { + get { return (MethodGroupResolveResult)resolveResult; } + } + + [Test] + public void ResolveResultContainingTypeHasOneTanMethods() + { + List tanMethods = GetTanMethods(); + Assert.AreEqual(1, tanMethods.Count); + } + + List GetTanMethods() + { + List methods = MethodResolveResult.ContainingType.GetMethods(); + return PythonCompletionItemsHelper.FindAllMethodsFromCollection("tan", -1, methods.ToArray()); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveTanMethodFromMathImportCosAndTanTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveTanMethodFromMathImportCosAndTanTestFixture.cs new file mode 100644 index 0000000000..418aebe496 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveTanMethodFromMathImportCosAndTanTestFixture.cs @@ -0,0 +1,64 @@ +// +// +// +// +// $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 ResolveTanMethodFromMathImportCosAndTanTestFixture : ResolveTestFixtureBase + { + protected override ExpressionResult GetExpressionResult() + { + return new ExpressionResult("tan", ExpressionContext.Default); + } + + protected override string GetPythonScript() + { + return + "from math import cos, tan\r\n" + + "tan\r\n" + + "\r\n"; + } + + [Test] + public void ResolveResultIsMethodGroupResolveResult() + { + Assert.IsTrue(resolveResult is MethodGroupResolveResult); + } + + [Test] + public void ResolveResultMethodNameIsTan() + { + Assert.AreEqual("tan", MethodResolveResult.Name); + } + + MethodGroupResolveResult MethodResolveResult { + get { return (MethodGroupResolveResult)resolveResult; } + } + + [Test] + public void ResolveResultContainingTypeHasOneTanMethods() + { + List tanMethods = GetTanMethods(); + Assert.AreEqual(1, tanMethods.Count); + } + + List GetTanMethods() + { + List methods = MethodResolveResult.ContainingType.GetMethods(); + return PythonCompletionItemsHelper.FindAllMethodsFromCollection("tan", -1, methods.ToArray()); + } + } +} 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 6a35096077..7df791c2dd 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveUnknownNamespaceTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolveUnknownNamespaceTestFixture.cs @@ -6,7 +6,7 @@ // using System; -using System.Collections; +using System.Collections.Generic; using ICSharpCode.PythonBinding; using ICSharpCode.SharpDevelop.Dom; using NUnit.Framework; @@ -20,30 +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(); - mockProjectContent = new MockProjectContent(); - mockProjectContent.NamespacesToAdd.Add("Test"); - - DefaultCompilationUnit cu = new DefaultCompilationUnit(mockProjectContent); - cu.ErrorsDuringCompile = true; - cu.FileName = @"C:\Projects\Test\test.py"; - ParseInformation parseInfo = new ParseInformation(cu); + projectContent.AddExistingNamespaceContents("System", new List()); - 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] @@ -55,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/Resolver/ResolverContextGetModuleForImportedNameTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextGetModuleForImportedNameTests.cs new file mode 100644 index 0000000000..2d7dd9cae2 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextGetModuleForImportedNameTests.cs @@ -0,0 +1,51 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ResolverContextGetModuleForImportedNameTestFixture + { + PythonResolverContext resolverContext; + ParseInformation parseInfo; + + [SetUp] + public void Init() + { + string python = + "import math\r\n" + + "from sys import exit"; + + parseInfo = PythonParserHelper.CreateParseInfo(python); + resolverContext = new PythonResolverContext(parseInfo); + } + + [Test] + public void ResolverContextGetModuleForImportedNameReturnsSysForExitImportedName() + { + Assert.AreEqual("sys", resolverContext.GetModuleForImportedName("exit")); + } + + [Test] + public void ResolverContextGetModuleForImportedNameReturnsNullForUnknownImportedName() + { + Assert.IsNull(resolverContext.GetModuleForImportedName("unknown")); + } + + [Test] + public void ResolverContextUnaliasImportedNameReturnsExitForExitImportedName() + { + Assert.AreEqual("exit", resolverContext.UnaliasImportedName("exit")); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextGetModuleForNameImportedAsDifferentNameTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextGetModuleForNameImportedAsDifferentNameTestFixture.cs new file mode 100644 index 0000000000..54783b668e --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextGetModuleForNameImportedAsDifferentNameTestFixture.cs @@ -0,0 +1,56 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ResolverContextGetModuleForNameImportedAsDifferentNameTestFixture + { + PythonResolverContext resolverContext; + ParseInformation parseInfo; + + [SetUp] + public void Init() + { + string python = + "from sys import exit as myexit"; + + parseInfo = PythonParserHelper.CreateParseInfo(python); + resolverContext = new PythonResolverContext(parseInfo); + } + + [Test] + public void ResolverContextGetModuleForNameReturnsSysForMyExitName() + { + Assert.AreEqual("sys", resolverContext.GetModuleForImportedName("myexit")); + } + + [Test] + public void ResolverContextGetModuleForImportedNameReturnsNullForExitImportedName() + { + Assert.IsNull(resolverContext.GetModuleForImportedName("exit")); + } + + [Test] + public void ResolverContextUnaliasImportedNameReturnsMyExitForExitImportedName() + { + Assert.AreEqual("exit", resolverContext.UnaliasImportedName("myexit")); + } + + [Test] + public void ResolverContextUnaliasImportedNameReturnsOriginalNameWhenNoAliasIsFound() + { + Assert.AreEqual("unknown", resolverContext.UnaliasImportedName("unknown")); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextGetModulesThatImportEverythingTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextGetModulesThatImportEverythingTests.cs new file mode 100644 index 0000000000..c705aa9e54 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextGetModulesThatImportEverythingTests.cs @@ -0,0 +1,73 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.PythonBinding; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ResolverContextGetImportAllModulesTests + { + [Test] + public void GetModulesThatImportEverythingReturnsEmptyCollectionIfNotImportAll() + { + string code = "from math import tan"; + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + + PythonResolverContext resolverContext = new PythonResolverContext(parseInfo); + + string[] expectedModules = new string[0]; + Assert.AreEqual(expectedModules, resolverContext.GetModulesThatImportEverything()); + } + + [Test] + public void GetModulesThatImportEverythingReturnsSysForFromSysImportAllStatement() + { + string code = "from sys import *"; + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + + PythonResolverContext resolverContext = new PythonResolverContext(parseInfo); + + string[] expectedModules = new string[] { "sys" }; + Assert.AreEqual(expectedModules, resolverContext.GetModulesThatImportEverything()); + } + + [Test] + public void GetModulesThatImportEverythingReturnsSysAndMathForFromSysImportAllStatement() + { + string code = + "from sys import *\r\n" + + "from math import *"; + + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + + PythonResolverContext resolverContext = new PythonResolverContext(parseInfo); + + string[] expectedModules = new string[] { "sys", "math" }; + Assert.AreEqual(expectedModules, resolverContext.GetModulesThatImportEverything()); + } + + [Test] + public void GetModulesThatImportEverythingIgnoresNonFromImportStatement() + { + string code = + "import math\r\n" + + "from sys import *"; + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + + PythonResolverContext resolverContext = new PythonResolverContext(parseInfo); + + string[] expectedModules = new string[] { "sys" }; + Assert.AreEqual(expectedModules, resolverContext.GetModulesThatImportEverything()); + } + + } +} \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextHasImportTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextHasImportTests.cs new file mode 100644 index 0000000000..0a5010a6a4 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextHasImportTests.cs @@ -0,0 +1,69 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.PythonBinding; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ResolverContextHasImportTests + { + [Test] + public void HasImportReturnsFalseForImportThatDoesNotExistInCompilationUnit() + { + string code = "import abc"; + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + + PythonResolverContext resolverContext = new PythonResolverContext(parseInfo); + Assert.IsFalse(resolverContext.HasImport("Unknown")); + } + + [Test] + public void HasImportReturnsTrueForImportThatDoesExistInCompilationUnit() + { + string code = "import abc"; + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + + PythonResolverContext resolverContext = new PythonResolverContext(parseInfo); + Assert.IsTrue(resolverContext.HasImport("abc")); + } + + [Test] + public void HasImportReturnsTrueForImportThatDoesExistInCompilationUnitWithSingleUsingWithMultipleNamespaces() + { + string code = "import abc, ghi"; + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + + PythonResolverContext resolverContext = new PythonResolverContext(parseInfo); + Assert.IsTrue(resolverContext.HasImport("ghi")); + } + + [Test] + public void HasImportReturnsFalseForFromImport() + { + string code = "from import sys"; + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + + PythonResolverContext resolverContext = new PythonResolverContext(parseInfo); + Assert.IsFalse(resolverContext.HasImport("sys")); + } + + [Test] + public void HasImportReturnsTrueForImportedAsName() + { + string code = "import sys as something"; + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + + PythonResolverContext resolverContext = new PythonResolverContext(parseInfo); + Assert.IsTrue(resolverContext.HasImport("something")); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextUnaliasImportedModuleNameTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextUnaliasImportedModuleNameTestFixture.cs new file mode 100644 index 0000000000..66358c7c05 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/ResolverContextUnaliasImportedModuleNameTestFixture.cs @@ -0,0 +1,45 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Resolver +{ + [TestFixture] + public class ResolverContextUnaliasImportedModuleNameTestFixture + { + PythonResolverContext resolverContext; + ParseInformation parseInfo; + + [SetUp] + public void Init() + { + string python = + "import math as m\r\n" + + "import sys as s"; + + parseInfo = PythonParserHelper.CreateParseInfo(python); + resolverContext = new PythonResolverContext(parseInfo); + } + + [Test] + public void ResolverContextUnaliasImportedModuleReturnsSysForImportedAsName() + { + Assert.AreEqual("sys", resolverContext.UnaliasImportedModuleName("s")); + } + + [Test] + public void ResolverContextUnaliasImportedModuleReturnsMathForImportedAsName() + { + Assert.AreEqual("math", resolverContext.UnaliasImportedModuleName("m")); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedPythonCodeCompletionBinding.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedPythonCodeCompletionBinding.cs index 0206e9258b..1cfe264189 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedPythonCodeCompletionBinding.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedPythonCodeCompletionBinding.cs @@ -21,13 +21,12 @@ namespace PythonBinding.Tests.Utils /// public class DerivedPythonCodeCompletionBinding : PythonCodeCompletionBinding { - bool ctrlSpaceCompletionDataProviderCreated; + bool completionDataProviderCreated; bool codeCompletionWindowDisplayed; ICSharpCode.SharpDevelop.Editor.ITextEditor textEditorUsedToShowCompletionWindow; AbstractCompletionItemProvider completionProviderUsedWhenDisplayingCodeCompletionWindow; - CtrlSpaceCompletionItemProvider ctrlSpaceCompletionDataProvider; + AbstractCompletionItemProvider completionDataProvider; char completionCharacter = '\0'; - ExpressionContext expressionContext; public DerivedPythonCodeCompletionBinding() { @@ -37,8 +36,8 @@ namespace PythonBinding.Tests.Utils /// Gets whether the data provider was created by the /// base class PythonCodeCompletionBinding. /// - public bool IsCtrlSpaceCompletionDataProviderCreated { - get { return ctrlSpaceCompletionDataProviderCreated; } + public bool IsCompletionDataProviderCreated { + get { return completionDataProviderCreated; } } /// @@ -58,11 +57,11 @@ namespace PythonBinding.Tests.Utils } /// - /// Gets the CtrlSpaceCompletionDataProvider created via the - /// CreateCtrlSpaceCompletionDataProvider method. + /// Gets the CompletionDataProvider created via the + /// CreateCompletionDataProvider method. /// - public CtrlSpaceCompletionItemProvider CtrlSpaceCompletionDataProvider { - get { return ctrlSpaceCompletionDataProvider; } + public AbstractCompletionItemProvider CompletionDataProvider { + get { return completionDataProvider; } } /// @@ -73,24 +72,15 @@ namespace PythonBinding.Tests.Utils get { return completionCharacter; } } - /// - /// Gets the expression context used when the - /// CtrlSpaceCompletionDataProvider is created. - /// - public ExpressionContext ExpressionContext { - get { return expressionContext; } - } - /// /// Overrides the completion data provider creation to make sure /// it is called at the correct time. /// - protected override CtrlSpaceCompletionItemProvider CreateCtrlSpaceCompletionDataProvider(ExpressionContext expressionContext) + protected override AbstractCompletionItemProvider CreateCompletionDataProvider() { - ctrlSpaceCompletionDataProviderCreated = true; - this.expressionContext = expressionContext; - ctrlSpaceCompletionDataProvider = base.CreateCtrlSpaceCompletionDataProvider(expressionContext); - return ctrlSpaceCompletionDataProvider; + completionDataProviderCreated = true; + completionDataProvider = base.CreateCompletionDataProvider(); + return completionDataProvider; } /// diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs index 65d71245d7..2dad833569 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs @@ -17,12 +17,7 @@ namespace PythonBinding.Tests.Utils /// public class MockProjectContent : IProjectContent { - bool addNamespaceContentsCalled; - string namespaceAddedName; - string namespaceSearchedFor; - bool lookInReferences; - LanguageProperties languagePassedToAddNamespaceContents; - LanguageProperties language = new LanguageProperties(StringComparer.InvariantCulture); + string namespacePassedToNamespaceExistsMethod; List namespacesToAdd = new List(); SearchTypeResult searchTypeResult; bool searchTypeCalled; @@ -31,43 +26,17 @@ namespace PythonBinding.Tests.Utils bool getClassCalled; string getClassName; List classesInProjectContent = new List(); - List namespaceContents = new List(); - string namespaceContentsSearched = String.Empty; + string namespacePassedToGetNamespaceContentsMethod; string classNameForGetClass; - bool namespaceExistsReturnValue; bool namespaceExistsCalled; object project; + Dictionary> namespaceContents = new Dictionary>(); + LanguageProperties language = LanguageProperties.CSharp; public MockProjectContent() { } - - /// - /// Gets whether the AddNamespaceContents method was called. - /// - public bool AddNamespaceContentsCalled { - get { return addNamespaceContentsCalled; } - } - - /// - /// Gets the namespace passed to the AddNamespaceContents method. - /// - public string NamespaceAddedName { - get { return namespaceAddedName; } - } - - /// - /// Gets the LookInReferences flag that was passed to the - /// AddNamespaceContents method. - /// - public bool LookInReferences { - get { return lookInReferences; } - } - - public LanguageProperties LanguagePassedToAddNamespaceContents { - get { return languagePassedToAddNamespaceContents; } - } - + /// /// Gets the namespaces that will be added when the /// AddNamespaceContents method is called. @@ -83,13 +52,8 @@ namespace PythonBinding.Tests.Utils get { return namespaceExistsCalled; } } - /// - /// Gets the namespace passed to the SearchNamespace method and - /// searched for. - /// - public string NamespaceSearchedFor { - get { return namespaceSearchedFor; } - set { namespaceSearchedFor = value; } + public string NamespacePassedToNamespaceExistsMethod { + get { return namespacePassedToNamespaceExistsMethod; } } /// @@ -148,25 +112,17 @@ namespace PythonBinding.Tests.Utils get { return getClassName; } } - /// - /// Gets the namespace contents to return from the - /// GetNamespaceContents method. - /// - public List NamespaceContentsToReturn { - get { return namespaceContents; } - } - - /// - /// Returns the namespace that was passed to the - /// GetNamespaceContents method. - /// - public string NamespaceContentsSearched { - get { return namespaceContentsSearched; } + public string NamespacePassedToGetNamespaceContentsMethod { + get { return namespacePassedToGetNamespaceContentsMethod; } } #region IProjectContent public event EventHandler ReferencedContentsChanged; - + + public LanguageProperties Language { + get { return language; } + } + public XmlDoc XmlDoc { get { return null; @@ -197,10 +153,6 @@ namespace PythonBinding.Tests.Utils } } - public LanguageProperties Language { - get { return language; } - } - public IUsing DefaultImports { get { return null; } } @@ -253,22 +205,28 @@ namespace PythonBinding.Tests.Utils return classToReturnFromGetClass; } - public void SetNamespaceExistsReturnValue(bool returnValue) + public void AddExistingNamespaceContents(string namespaceName, List items) { - namespaceExistsReturnValue = returnValue; + namespaceContents.Add(namespaceName, items); } public bool NamespaceExists(string name) { namespaceExistsCalled = true; - namespaceSearchedFor = name; - return namespaceExistsReturnValue; + namespacePassedToNamespaceExistsMethod = name; + + return namespaceContents.ContainsKey(name); } public List GetNamespaceContents(string nameSpace) { - namespaceContentsSearched = nameSpace; - return namespaceContents; + namespacePassedToGetNamespaceContentsMethod = nameSpace; + + List items; + if (namespaceContents.TryGetValue(nameSpace, out items)) { + return items; + } + return new List(); } public IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, GetClassOptions options) @@ -283,11 +241,6 @@ namespace PythonBinding.Tests.Utils public void AddNamespaceContents(List list, string subNameSpace, LanguageProperties language, bool lookInReferences) { - addNamespaceContentsCalled = true; - namespaceAddedName = subNameSpace; - this.lookInReferences = lookInReferences; - languagePassedToAddNamespaceContents = language; - // Add the namespaces to the list. foreach (string ns in namespacesToAdd) { list.Add(new NamespaceEntry(ns)); @@ -355,7 +308,7 @@ namespace PythonBinding.Tests.Utils throw new NotImplementedException(); } - public string AssemblyName { + public string AssemblyName { get { throw new NotImplementedException(); } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockTextEditorViewContent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockTextEditorViewContent.cs index 9c9b8be575..cf8c1ffaeb 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockTextEditorViewContent.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockTextEditorViewContent.cs @@ -11,6 +11,7 @@ using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Dom.Refactoring; using ICSharpCode.TextEditor; +using ICSharpCode.TextEditor.Document; namespace PythonBinding.Tests.Utils { diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/PythonCompletionItemsHelper.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/PythonCompletionItemsHelper.cs new file mode 100644 index 0000000000..ede65d23f3 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/PythonCompletionItemsHelper.cs @@ -0,0 +1,97 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; + +namespace PythonBinding.Tests.Utils +{ + public class PythonCompletionItemsHelper + { + 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) { + if (match(item, name)) { + return item; + } + } + return null; + } + + static bool IsMethodMatch(object obj, string name) + { + 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 false; + } + + public static List FindAllMethodsFromCollection(string name, int parameterCount, ICollection items) + { + List matchedMethods = new List(); + foreach (object item in items) { + if (IsMethodMatch(item, name, parameterCount)) { + matchedMethods.Add((IMethod)item); + } + } + 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/PythonParserHelper.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/PythonParserHelper.cs index 108d776397..708d5c8de0 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/PythonParserHelper.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/PythonParserHelper.cs @@ -5,17 +5,15 @@ // $Revision$ // -using ICSharpCode.SharpDevelop; using System; using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; using IronPython.Compiler.Ast; namespace PythonBinding.Tests.Utils { - /// - /// Description of PythonParserHelper. - /// - public class PythonParserHelper + public static class PythonParserHelper { /// /// Parses the code and returns the first statement as an assignment statement. @@ -27,7 +25,7 @@ namespace PythonBinding.Tests.Utils /// /// Parses the code and returns the first statement's expression as call expression. - /// + /// public static CallExpression GetCallExpression(string code) { ExpressionStatement expressionStatement = GetFirstStatement(code) as ExpressionStatement; @@ -41,5 +39,13 @@ namespace PythonBinding.Tests.Utils SuiteStatement suiteStatement = (SuiteStatement)ast.Body; return suiteStatement.Statements[0]; } + + public static ParseInformation CreateParseInfo(string code) + { + DefaultProjectContent projectContent = new DefaultProjectContent(); + PythonParser parser = new PythonParser(); + ICompilationUnit compilationUnit = parser.Parse(projectContent, @"C:\test.py", code); + return new ParseInformation(compilationUnit); + } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/MockProjectContentTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/MockProjectContentTests.cs new file mode 100644 index 0000000000..213ae4e4ab --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/MockProjectContentTests.cs @@ -0,0 +1,147 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.PythonBinding; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Utils.Tests +{ + [TestFixture] + public class MockProjectContentTests + { + MockProjectContent projectContent; + List items; + + [SetUp] + public void Init() + { + projectContent = new MockProjectContent(); + items = new List(); + } + + [Test] + public void AddNamespaceContentsAddsNamespaces() + { + projectContent.NamespacesToAdd.Add("test"); + projectContent.AddNamespaceContents(items, String.Empty, PythonLanguageProperties.Default, false); + + List expectedItems = new List(); + expectedItems.Add(new NamespaceEntry("test")); + + Assert.AreEqual(expectedItems, items); + } + + [Test] + public void AddNamespaceContentsAddsClasses() + { + MockClass c = new MockClass(new MockProjectContent(), "TestClass"); + projectContent.ClassesInProjectContent.Add(c); + projectContent.AddNamespaceContents(items, String.Empty, PythonLanguageProperties.Default, false); + + List expectedItems = new List(); + expectedItems.Add(c); + + Assert.AreEqual(expectedItems, items); + } + + [Test] + public void NamespaceContentsSearchedIsNullByDefault() + { + Assert.IsNull(projectContent.NamespacePassedToGetNamespaceContentsMethod); + } + + [Test] + public void NamespacePassedToGetNamespaceMethodIsSaved() + { + projectContent.GetNamespaceContents("abc"); + Assert.AreEqual("abc", projectContent.NamespacePassedToGetNamespaceContentsMethod); + } + + [Test] + public void GetNamespaceContentsReturnsExpectedItems() + { + List namespaceItems = new List(); + namespaceItems.Add(new NamespaceEntry("test")); + projectContent.AddExistingNamespaceContents(String.Empty, namespaceItems); + items = projectContent.GetNamespaceContents(String.Empty); + + List expectedItems = new List(); + expectedItems.Add(new NamespaceEntry("test")); + + Assert.AreEqual(expectedItems, items); + } + + [Test] + public void NamespaceExistsReturnsTrueForAddedExistingNamespace() + { + List items = new List(); + projectContent.AddExistingNamespaceContents("System", items); + + Assert.IsTrue(projectContent.NamespaceExists("System")); + } + + [Test] + public void NamespaceExistsReturnsFalseForUnknownNamespace() + { + List items = new List(); + projectContent.AddExistingNamespaceContents("System", items); + + Assert.IsFalse(projectContent.NamespaceExists("Unknown")); + } + + [Test] + public void GetNamespaceContentsReturnsItemsForAddedExistingNamespace() + { + List items = new List(); + items.Add(new NamespaceEntry("test")); + + projectContent.AddExistingNamespaceContents("Math", new List()); + projectContent.AddExistingNamespaceContents("System", items); + + List expectedItems = new List(); + expectedItems.Add(new NamespaceEntry("test")); + + Assert.AreEqual(expectedItems, projectContent.GetNamespaceContents("System")); + } + + [Test] + public void GetNamespaceContentsReturnsEmptyArrayListForUnknownNamespace() + { + List items = new List(); + items.Add(new NamespaceEntry("test")); + projectContent.AddExistingNamespaceContents("System", items); + + List expectedItems = new List(); + + Assert.AreEqual(expectedItems, projectContent.GetNamespaceContents("Unknown")); + } + + [Test] + public void NamespaceUsedWhenCallingNamespaceExistsIsSaved() + { + projectContent.NamespaceExists("System"); + Assert.AreEqual("System", projectContent.NamespacePassedToNamespaceExistsMethod); + } + + [Test] + public void NamespaceExistsCalledIsFalseInitially() + { + Assert.IsFalse(projectContent.NamespaceExistsCalled); + } + + [Test] + public void NamespaceExistsCalledReturnsTrueAfterMethodCall() + { + projectContent.NamespaceExists("System"); + Assert.IsTrue(projectContent.NamespaceExistsCalled); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/PythonCompletionItemsHelperTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/PythonCompletionItemsHelperTests.cs new file mode 100644 index 0000000000..3b768670dc --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/PythonCompletionItemsHelperTests.cs @@ -0,0 +1,151 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Utils.Tests +{ + [TestFixture] + public class PythonCompletionItemsHelperTests + { + [Test] + public void FindMethodFromArrayReturnsExpectedMethod() + { + DefaultClass c = CreateClass(); + DefaultMethod method = new DefaultMethod(c, "abc"); + + ArrayList items = new ArrayList(); + items.Add(method); + + Assert.AreEqual(method, PythonCompletionItemsHelper.FindMethodFromCollection("abc", items)); + } + + DefaultClass CreateClass() + { + return new DefaultClass(new DefaultCompilationUnit(new DefaultProjectContent()), "Test"); + } + + [Test] + public void FindMethodFromArrayReturnsNullForUnknownMethod() + { + DefaultClass c = new DefaultClass(new DefaultCompilationUnit(new DefaultProjectContent()), "Test"); + DefaultMethod method = new DefaultMethod(c, "abc"); + + ArrayList items = new ArrayList(); + items.Add(method); + + Assert.IsNull(PythonCompletionItemsHelper.FindMethodFromCollection("unknown", items)); + } + + [Test] + public void FindFieldFromArrayReturnsExpectedField() + { + DefaultClass c = CreateClass(); + DefaultField field = new DefaultField(c, "field"); + + ArrayList items = new ArrayList(); + items.Add(field); + + Assert.AreEqual(field, PythonCompletionItemsHelper.FindFieldFromCollection("field", items)); + } + + [Test] + public void FindFieldFromArrayReturnsExpectedNullForUnknownField() + { + DefaultClass c = CreateClass(); + DefaultField field = new DefaultField(c, "field"); + + ArrayList items = new ArrayList(); + items.Add(field); + + Assert.IsNull(PythonCompletionItemsHelper.FindFieldFromCollection("unknown-field-name", items)); + } + + [Test] + public void FindClassFromArrayReturnsExpectedClass() + { + DefaultClass c = CreateClass(); + + ArrayList items = new ArrayList(); + items.Add(c); + + Assert.AreEqual(c, PythonCompletionItemsHelper.FindClassFromCollection("Test", items)); + } + + [Test] + public void FindClassFromArrayReturnsExpectedNullForUnknownClassName() + { + DefaultClass c = CreateClass(); + + ArrayList items = new ArrayList(); + items.Add(c); + + 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); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/PythonParserHelperTests.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/PythonParserHelperTests.cs new file mode 100644 index 0000000000..fe966eb180 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/Tests/PythonParserHelperTests.cs @@ -0,0 +1,54 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using IronPython.Compiler.Ast; +using NUnit.Framework; +using PythonBinding.Tests.Utils; + +namespace PythonBinding.Tests.Utils.Tests +{ + [TestFixture] + public class PythonParserHelperTests + { + [Test] + public void CreateParseInfoReturnsParseInfoWithSingleClass() + { + string code = + "class foo:\r\n" + + "pass"; + + ParseInformation parseInfo = PythonParserHelper.CreateParseInfo(code); + Assert.AreEqual("foo", parseInfo.MostRecentCompilationUnit.Classes[0].Name); + } + + [Test] + public void GetAssignmentStatementReturnsFirstAssignmentStatementInCode() + { + string code = + "i = 10"; + + AssignmentStatement assignment = PythonParserHelper.GetAssignmentStatement(code); + NameExpression nameExpression = assignment.Left[0] as NameExpression; + + Assert.AreEqual("i", nameExpression.Name); + } + + [Test] + public void GetCallExpressionReturnsFirstCallStatementInCode() + { + string code = + "run()"; + + CallExpression call = PythonParserHelper.GetCallExpression(code); + NameExpression nameExpression = call.Target as NameExpression; + + Assert.AreEqual("run", nameExpression.Name); + } + } +}