// // ParameterCompletionTests.cs // // Author: // Mike Krüger // // Copyright (C) 2008 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Collections.Generic; using NUnit.Framework; using ICSharpCode.NRefactory.Completion; using ICSharpCode.NRefactory.CSharp.Completion; using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.TypeSystem; using System.Linq; using ICSharpCode.NRefactory.CSharp.TypeSystem; namespace ICSharpCode.NRefactory.CSharp.CodeCompletion { [TestFixture] public class ParameterCompletionTests : TestBase { internal class TestFactory : IParameterCompletionDataFactory { // IProjectContent ctx; public TestFactory (IProjectContent ctx) { // this.ctx = ctx; } internal class Provider : IParameterDataProvider { public IEnumerable Data { get; set; } #region IParameterDataProvider implementation public int StartOffset { get { return 0; } } public string GetHeading (int overload, string[] parameterDescription, int currentParameter) { return ""; } public string GetDescription (int overload, int currentParameter) { return ""; } public string GetParameterDescription (int overload, int paramIndex) { return ""; } public string GetParameterName(int overload, int currentParameter) { return ""; } public int GetParameterCount (int overload) { var method = Data.ElementAt (overload); return method.Parameters.Count; } public bool AllowParameterList (int overload) { return false; } public int Count { get { return Data.Count (); } } #endregion } class IndexerProvider : IParameterDataProvider { public IEnumerable Data { get; set; } #region IParameterDataProvider implementation public int StartOffset { get { return 0; } } public string GetHeading (int overload, string[] parameterDescription, int currentParameter) { return ""; } public string GetDescription (int overload, int currentParameter) { return ""; } public string GetParameterDescription (int overload, int paramIndex) { return ""; } public string GetParameterName(int overload, int currentParameter) { return ""; } public int GetParameterCount (int overload) { var method = Data.ElementAt (overload); return method.Parameters.Count; } public bool AllowParameterList (int overload) { return false; } public int Count { get { return Data.Count (); } } #endregion } class ArrayProvider : IParameterDataProvider { #region IParameterDataProvider implementation public int StartOffset { get { return 0; } } public string GetHeading (int overload, string[] parameterDescription, int currentParameter) { return ""; } public string GetDescription (int overload, int currentParameter) { return ""; } public string GetParameterDescription (int overload, int paramIndex) { return ""; } public int GetParameterCount (int overload) { return 1; } public string GetParameterName(int overload, int currentParameter) { return ""; } public bool AllowParameterList (int overload) { return false; } public int Count { get { return 1; } } #endregion } class TypeParameterDataProvider : IParameterDataProvider { public IEnumerable Data { get; set; } #region IParameterDataProvider implementation public int StartOffset { get { return 0; } } public string GetHeading (int overload, string[] parameterDescription, int currentParameter) { return ""; } public string GetDescription (int overload, int currentParameter) { return ""; } public string GetParameterDescription (int overload, int paramIndex) { return ""; } public string GetParameterName(int overload, int currentParameter) { return ""; } public int GetParameterCount (int overload) { var data = Data.ElementAt (overload); return data.TypeParameterCount; } public bool AllowParameterList (int overload) { return false; } public int Count { get { return Data.Count (); } } #endregion } class MethodTypeParameterDataProvider : IParameterDataProvider { public IEnumerable Data { get; set; } #region IParameterDataProvider implementation public int StartOffset { get { return 0; } } public string GetHeading (int overload, string[] parameterDescription, int currentParameter) { return ""; } public string GetDescription (int overload, int currentParameter) { return ""; } public string GetParameterDescription (int overload, int paramIndex) { return ""; } public string GetParameterName(int overload, int currentParameter) { return ""; } public int GetParameterCount (int overload) { var data = Data.ElementAt (overload); return data.TypeArguments.Count; } public bool AllowParameterList (int overload) { return false; } public int Count { get { return Data.Count (); } } #endregion } #region IParameterCompletionDataFactory implementation public IParameterDataProvider CreateConstructorProvider(int startOffset, IType type) { Assert.IsTrue(type.Kind != TypeKind.Unknown); return new Provider { Data = type.GetConstructors (m => m.Accessibility == Accessibility.Public) }; } public IParameterDataProvider CreateConstructorProvider(int startOffset, IType type, AstNode skipNode) { Assert.IsTrue(type.Kind != TypeKind.Unknown); return new Provider { Data = type.GetConstructors (m => m.Accessibility == Accessibility.Public) }; } public IParameterDataProvider CreateMethodDataProvider (int startOffset, IEnumerable methods) { return new Provider { Data = methods }; } public IParameterDataProvider CreateDelegateDataProvider(int startOffset, IType type) { Assert.IsTrue(type.Kind != TypeKind.Unknown); return new Provider { Data = new [] { type.GetDelegateInvokeMethod () } }; } public IParameterDataProvider CreateIndexerParameterDataProvider(int startOffset, IType type, IEnumerable accessibleIndexers, AstNode resolvedNode) { Assert.IsTrue(type.Kind != TypeKind.Unknown); if (type.Kind == TypeKind.Array) return new ArrayProvider (); return new IndexerProvider { Data = accessibleIndexers }; } public IParameterDataProvider CreateTypeParameterDataProvider (int startOffset, IEnumerable types) { return new TypeParameterDataProvider { Data = types }; } public IParameterDataProvider CreateTypeParameterDataProvider (int startOffset, IEnumerable methods) { return new MethodTypeParameterDataProvider { Data = methods }; } #endregion } internal static IParameterDataProvider CreateProvider(string text) { string parsedText; string editorText; int cursorPosition = text.IndexOf('$'); int endPos = text.IndexOf('$', cursorPosition + 1); if (endPos == -1) { parsedText = editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1); } else { parsedText = text.Substring(0, cursorPosition) + new string(' ', endPos - cursorPosition) + text.Substring(endPos + 1); editorText = text.Substring(0, cursorPosition) + text.Substring(cursorPosition + 1, endPos - cursorPosition - 1) + text.Substring(endPos + 1); cursorPosition = endPos - 1; } var doc = new ReadOnlyDocument(editorText); IProjectContent pctx = new CSharpProjectContent(); pctx = pctx.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore }); var syntaxTree = new CSharpParser().Parse(parsedText, "program.cs"); syntaxTree.Freeze(); var unresolvedFile = syntaxTree.ToTypeSystem(); pctx = pctx.AddOrUpdateFiles(unresolvedFile); var cmp = pctx.CreateCompilation(); var loc = doc.GetLocation(cursorPosition); var rctx = new CSharpTypeResolveContext(cmp.MainAssembly); rctx = rctx.WithUsingScope(unresolvedFile.GetUsingScope(loc).Resolve(cmp)); var curDef = unresolvedFile.GetInnermostTypeDefinition(loc); if (curDef != null) { rctx = rctx.WithCurrentTypeDefinition(curDef.Resolve(rctx).GetDefinition()); var curMember = unresolvedFile.GetMember(loc); if (curMember != null) { rctx = rctx.WithCurrentMember(curMember.CreateResolved(rctx)); } } var mb = new DefaultCompletionContextProvider(doc, unresolvedFile); var engine = new CSharpParameterCompletionEngine (doc, mb, new TestFactory (pctx), pctx, rctx); return engine.GetParameterDataProvider (cursorPosition, doc.GetCharAt (cursorPosition - 1)); } /// /// Bug 427448 - Code Completion: completion of constructor parameters not working /// [Test] public void TestBug427448 () { IParameterDataProvider provider = CreateProvider ( @"class Test { public Test (int a) { } public Test (string b) { } protected Test () { } Test (double d, float m) { } } class AClass { void A() { $Test t = new Test ($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (2, provider.Count); } /// /// Bug 432437 - No completion when invoking delegates /// [Test] public void TestBug432437 () { IParameterDataProvider provider = CreateProvider ( @"public delegate void MyDel (int value); class Test { MyDel d; void A() { $d ($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } /// /// Bug 432658 - Incorrect completion when calling an extension method from inside another extension method /// [Test] public void TestBug432658 () { IParameterDataProvider provider = CreateProvider ( @"static class Extensions { public static void Ext1 (this int start) { } public static void Ext2 (this int end) { $Ext1($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count, "There should be one overload"); Assert.AreEqual (1, provider.GetParameterCount(0), "Parameter 'start' should exist"); } /// /// Bug 432727 - No completion if no constructor /// [Test] public void TestBug432727 () { IParameterDataProvider provider = CreateProvider ( @"class A { void Method () { $A aTest = new A ($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } /// /// Bug 434705 - No autocomplete offered if not assigning result of 'new' to a variable /// [Test] public void TestBug434705 () { IParameterDataProvider provider = CreateProvider ( @"class Test { public Test (int a) { } } class AClass { Test A() { $return new Test ($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } /// /// Bug 434705 - No autocomplete offered if not assigning result of 'new' to a variable /// [Test] public void TestBug434705B () { IParameterDataProvider provider = CreateProvider ( @" class Test { public Test (T t) { } } class TestClass { void TestMethod () { $Test l = new Test ($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } /// /// Bug 434701 - No autocomplete in attributes /// [Test] public void TestBug434701 () { IParameterDataProvider provider = CreateProvider ( @"namespace Test { class TestAttribute : System.Attribute { public Test (int a) { } } $[Test ($ class AClass { } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } /// /// Bug 447985 - Exception display tip is inaccurate for derived (custom) exceptions /// [Test] public void TestBug447985 () { IParameterDataProvider provider = CreateProvider ( @" namespace System { public class Exception { public Exception () {} } } class MyException : System.Exception { public MyException (int test) {} } class AClass { public void Test () { $throw new MyException($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); Assert.AreEqual (1, provider.GetParameterCount(0), "Parameter 'test' should exist"); } /// /// Bug 1760 - [New Resolver] Parameter tooltip not shown for indexers /// [Test] public void Test1760 () { var provider = CreateProvider ( @" class TestClass { public static void Main (string[] args) { $args[$ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } [Test] public void TestSecondIndexerParameter () { var provider = CreateProvider ( @" class TestClass { public int this[int i, int j] { get { return 0; } } public void Test () { $this[1,$ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } [Test] public void TestSecondMethodParameter () { var provider = CreateProvider ( @" class TestClass { public int TestMe (int i, int j) { return 0; } public void Test () { $TestMe (1,$ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } [Test] public void TestMethodParameterWithSpacesTabsNewLines () { var provider = CreateProvider (@"class TestClass { public int TestMe (int x) { return 0; } public void Test () { $TestMe ( $ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } [Test] public void TestMethodParameterNestedArray () { var provider = CreateProvider (@"using System; class TestClass { TestClass () { var str = new string[2,2]; $Console.WriteLine ( str [1,$ } } "); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } /// Bug 599 - Regression: No intellisense over Func delegate [Test] public void TestBug599 () { var provider = CreateProvider ( @"using System; using System.Core; class TestClass { void A (Func f) { $f ($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } /// Bug 3307 - Chained linq methods do not work correctly [Test] public void TestBug3307 () { var provider = CreateProvider ( @"using System; using System.Linq; class TestClass { public static void Main (string[] args) { $args.Select ($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.IsTrue (provider.Count > 0); } [Test] public void TestBug3307FollowUp () { var provider = CodeCompletionBugTests.CreateProvider ( @"using System; using System.Linq; public class MainClass { static void TestMe (Action act) { } public static void Main (string[] args) { $TestMe (x$ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.IsFalse (provider.AutoSelect, "auto select enabled !"); } [Test] public void TestBug3307FollowUp2 () { var provider = CodeCompletionBugTests.CreateProvider ( @"using System; using System.Linq; public class MainClass { public static void Main (string[] args) { $args.Select (x$ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.IsFalse (provider.AutoSelect, "auto select enabled !"); } [Test] public void TestConstructor () { IParameterDataProvider provider = CreateProvider ( @"class Foo { public Foo (int a) {} } class A { void Method () { $Bar = new Foo ($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } [Test] public void TestConstructorCase2 () { IParameterDataProvider provider = CreateProvider ( @" namespace Test { struct TestMe { public TestMe (string a) { } } class A { void Method () { $new TestMe ($ } } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (2, provider.Count); } [Test] public void TestTypeParameter () { IParameterDataProvider provider = CreateProvider ( @"using System; namespace Test { class A { void Method () { $Action<$ } } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (16, provider.Count); } [Test] public void TestSecondTypeParameter () { IParameterDataProvider provider = CreateProvider ( @"using System; namespace Test { class A { void Method () { $Action() { } void Method () { $TestMethod<$ } } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } [Ignore("TODO")] [Test] public void TestSecondMethodTypeParameter () { IParameterDataProvider provider = CreateProvider ( @"using System; namespace Test { class A { void TestMethod() { } void Method () { $TestMethod /// Bug 3645 - [New Resolver]Parameter completion shows all static and non-static overloads /// [Test] public void TestBug3645 () { IParameterDataProvider provider = CreateProvider ( @"class Main { public static void FooBar (string str) { } public void FooBar (int i) { } public static void Main (string[] args) { $FooBar ($ } }"); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } /// /// Bug 3991 - constructor argument completion not working for attributes applied to methods or parameters /// [Test] public void TestBug3991() { IParameterDataProvider provider = CreateProvider( @"using System; namespace Test { class TestClass { [Obsolete$($] TestClass() { } } } "); Assert.IsNotNull(provider, "provider was not created."); Assert.Greater(provider.Count, 0); } /// /// Bug 4087 - code completion handles object and collection initializers (braces) incorrectly in method calls /// [Test] public void TestBug4087() { IParameterDataProvider provider = CreateProvider( @"using System; class TestClass { TestClass() { $Console.WriteLine (new int[]{ 4, 5,$ } } "); Assert.IsTrue (provider == null || provider.Count == 0); } /// /// Bug 4927 - [New Resolver] Autocomplete shows non-static methods when using class name /// [Test] public void TestBug4927 () { IParameterDataProvider provider = CreateProvider ( @" public class A { // static method public static void Method(string someParameter, object anotherParameter) { } // instance method public void Method() { } } public class B { public static void Main() { $A.Method($ } } "); Assert.IsNotNull (provider, "provider was not created."); Assert.AreEqual (1, provider.Count); } [Test] public void TestLambdaCase() { IParameterDataProvider provider = CreateProvider( @"using System; class TestClass { void F (Action i, int foo) { $F (()=> Something(),$ } } "); Assert.IsTrue (provider != null && provider.Count == 1); } [Test] public void TestJaggedArrayCreation() { IParameterDataProvider provider = CreateProvider( @"using System; class TestClass { void F (Action i, int foo) { $new foo[1,2][$ } } "); Assert.IsTrue (provider == null || provider.Count == 0); } [Test] public void TestJaggedArrayCreationCase2() { IParameterDataProvider provider = CreateProvider( @"using System; class TestClass { void F (Action i, int foo) { $new foo[1,2][1,$ } } "); Assert.IsTrue (provider == null || provider.Count == 0); } /// /// Bug 9301 - Inaccessible indexer overload in completion /// [Test] public void TestBug9301() { IParameterDataProvider provider = CreateProvider( @"using System; public class A { public virtual int this [int i, string s] { get { return 1; } } } public class B : A { public new bool this [int i, string s2] { get { return true; } } } public class Test { public static int Main () { B p = new B (); $p[$ return 0; } } "); Assert.AreEqual (1, provider.Count); } [Test] public void TestBug9301Case2() { IParameterDataProvider provider = CreateProvider( @"using System; public class A { public virtual int Test (int i, string s) { return 1; } } public class B : A { public new bool Test (int i, string s2) { return true; } } public class Test { public static int Main () { B p = new B (); $p.Test($ return 0; } } "); Assert.AreEqual (1, provider.Count); } [Test] public void TestExtensionMethod() { var provider = CreateProvider(@"static class Ext { public static void Foo(this object o, string str) {} } class Test { public static void Main (string[] args) { $args.Foo($ } }"); Assert.AreEqual (1, provider.Count); Assert.AreEqual (1, provider.GetParameterCount (0)); } [Test] public void TestExtensionMethodStaticInvocation() { var provider = CreateProvider(@"static class Ext { public static void Foo(this object o, string str) {} } class Test { public static void Main (string[] args) { $Ext.Foo($ } }"); Assert.AreEqual (1, provider.Count); Assert.AreEqual (2, provider.GetParameterCount (0)); } [Test] public void TypeArgumentsInIncompleteMethodCall () { var provider = CreateProvider ( @"using System.Collections.Generic; using System.Linq; class NUnitTestClass { public ICollection NestedTestCollection { get; set; } public NUnitTestMethod FindTestMethodWithShortName(string name) { this.NestedTestCollection$.OfType<$.LastOrDefault( } }"); Assert.AreEqual (1, provider.Count); } /// /// Bug 12824 - Invalid argument intellisense inside lambda /// [Test] public void TestBug12824 () { var provider = (TestFactory.Provider)CreateProvider ( @"using System.Threading.Tasks; using System; public class MyEventArgs { public static void Main (string[] args) { Task.Factory.StartNew (() => { $throw new Exception ($ }); } }"); string name = provider.Data.First().FullName; Assert.AreEqual ("System.Exception..ctor", name); } [Test] public void TestAfterGreaterSign () { var provider = CreateProvider (@" class Test { static void Foo (int num) {} public static void Main (string[] args) { int i = 0; if (i > 0) Foo ($ } }"); Assert.AreEqual (1, provider.Count); Assert.AreEqual (1, provider.GetParameterCount (0)); } } }