You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
864 lines
23 KiB
864 lines
23 KiB
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team |
|
// |
|
// 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; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
|
|
using ICSharpCode.NRefactory.Semantics; |
|
using ICSharpCode.NRefactory.TypeSystem; |
|
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
|
using NUnit.Framework; |
|
|
|
namespace ICSharpCode.NRefactory.CSharp.Resolver |
|
{ |
|
[TestFixture] |
|
public class NameLookupTests : ResolverTestBase |
|
{ |
|
[Test] |
|
public void SimpleNameLookupWithoutContext() |
|
{ |
|
// nothing should be found without specifying any UsingScope - however, the resolver also must not crash |
|
resolver.CurrentUsingScope = null; |
|
Assert.IsTrue(resolver.ResolveSimpleName("System", new IType[0]).IsError); |
|
} |
|
|
|
[Test] |
|
public void SimpleNamespaceLookup() |
|
{ |
|
NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveSimpleName("System", new IType[0]); |
|
Assert.AreEqual("System", nrr.NamespaceName); |
|
Assert.AreSame(SharedTypes.UnknownType, nrr.Type); |
|
} |
|
|
|
[Test] |
|
public void NamespaceInParentNamespaceLookup() |
|
{ |
|
resolver.CurrentUsingScope = MakeUsingScope("System.Collections.Generic"); |
|
NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveSimpleName("Text", new IType[0]); |
|
Assert.AreEqual("System.Text", nrr.NamespaceName); |
|
} |
|
|
|
[Test] |
|
public void NamespacesAreNotImported() |
|
{ |
|
AddUsing("System"); |
|
Assert.IsTrue(resolver.ResolveSimpleName("Collections", new IType[0]).IsError); |
|
} |
|
|
|
[Test] |
|
public void ImportedType() |
|
{ |
|
AddUsing("System"); |
|
TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("String", new IType[0]); |
|
Assert.AreEqual("System.String", trr.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void UnknownIdentifierTest() |
|
{ |
|
UnknownIdentifierResolveResult uirr = (UnknownIdentifierResolveResult)resolver.ResolveSimpleName("xyz", new IType[0]); |
|
Assert.IsTrue(uirr.IsError); |
|
Assert.AreEqual("xyz", uirr.Identifier); |
|
} |
|
|
|
[Test] |
|
public void GlobalIsUnknownIdentifier() |
|
{ |
|
Assert.IsTrue(resolver.ResolveSimpleName("global", new IType[0]).IsError); |
|
} |
|
|
|
[Test] |
|
public void GlobalIsAlias() |
|
{ |
|
NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveAlias("global"); |
|
Assert.AreEqual("", nrr.NamespaceName); |
|
} |
|
|
|
[Test] |
|
public void AliasToImportedType() |
|
{ |
|
AddUsing("System"); |
|
AddUsingAlias("x", "String"); |
|
TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("x", new IType[0]); |
|
// Unknown type (as String isn't looked up in System) |
|
Assert.AreSame(SharedTypes.UnknownType, trr.Type); |
|
} |
|
|
|
[Test] |
|
public void AliasToImportedType2() |
|
{ |
|
AddUsing("System"); |
|
resolver.CurrentUsingScope = new UsingScope(resolver.CurrentUsingScope, "SomeNamespace"); |
|
AddUsingAlias("x", "String"); |
|
TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("x", new IType[0]); |
|
Assert.AreEqual("System.String", trr.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void AliasOperatorOnTypeAlias() |
|
{ |
|
AddUsingAlias("x", "System.String"); |
|
Assert.IsTrue(resolver.ResolveAlias("x").IsError); |
|
} |
|
|
|
[Test] |
|
public void AliasOperatorOnNamespaceAlias() |
|
{ |
|
AddUsingAlias("x", "System.Collections.Generic"); |
|
NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveAlias("x"); |
|
Assert.AreEqual("System.Collections.Generic", nrr.NamespaceName); |
|
} |
|
|
|
[Test] |
|
public void AliasOperatorOnNamespace() |
|
{ |
|
Assert.IsTrue(resolver.ResolveAlias("System").IsError); |
|
} |
|
|
|
[Test] |
|
public void FindClassInCurrentNamespace() |
|
{ |
|
resolver.CurrentUsingScope = MakeUsingScope("System.Collections"); |
|
TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("String", new IType[0]); |
|
Assert.AreEqual("System.String", trr.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void FindNeighborNamespace() |
|
{ |
|
resolver.CurrentUsingScope = MakeUsingScope("System.Collections"); |
|
NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveSimpleName("Text", new IType[0]); |
|
Assert.AreEqual("System.Text", nrr.NamespaceName); |
|
} |
|
|
|
[Test] |
|
public void FindTypeParameters() |
|
{ |
|
resolver.CurrentUsingScope = MakeUsingScope("System.Collections.Generic"); |
|
resolver.CurrentTypeDefinition = context.GetTypeDefinition(typeof(List<>)); |
|
resolver.CurrentMember = resolver.CurrentTypeDefinition.Methods.Single(m => m.Name == "ConvertAll"); |
|
|
|
TypeResolveResult trr; |
|
trr = (TypeResolveResult)resolver.ResolveSimpleName("TOutput", new IType[0]); |
|
Assert.AreSame(((IMethod)resolver.CurrentMember).TypeParameters[0], trr.Type); |
|
|
|
trr = (TypeResolveResult)resolver.ResolveSimpleName("T", new IType[0]); |
|
Assert.AreSame(resolver.CurrentTypeDefinition.TypeParameters[0], trr.Type); |
|
} |
|
|
|
[Test] |
|
public void SimpleParameter() |
|
{ |
|
string program = @"class A { |
|
void Method(string a) { |
|
string b = $a$; |
|
} |
|
} |
|
"; |
|
LocalResolveResult result = Resolve<LocalResolveResult>(program); |
|
Assert.AreEqual("a", result.Variable.Name); |
|
Assert.IsTrue(result.IsParameter); |
|
Assert.AreEqual("System.String", result.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void SimpleLocalVariable() |
|
{ |
|
string program = @"class A { |
|
void Method() { |
|
string a; |
|
string b = $a$; |
|
} |
|
} |
|
"; |
|
LocalResolveResult result = Resolve<LocalResolveResult>(program); |
|
Assert.AreEqual("a", result.Variable.Name); |
|
Assert.IsFalse(result.IsParameter); |
|
|
|
Assert.AreEqual("System.String", result.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void UnknownTypeTest() |
|
{ |
|
string program = @"class A { |
|
void Method($StringBuilder$ b) { |
|
} |
|
} |
|
"; |
|
UnknownIdentifierResolveResult result = Resolve<UnknownIdentifierResolveResult>(program); |
|
Assert.AreEqual("StringBuilder", result.Identifier); |
|
|
|
Assert.AreSame(SharedTypes.UnknownType, result.Type); |
|
} |
|
|
|
const string propertyNameAmbiguousWithTypeNameProgram = @"class A { |
|
public Color Color { get; set; } |
|
|
|
void Method() { |
|
$ |
|
} |
|
} |
|
class Color { |
|
public static readonly Color Empty = null; |
|
public static int M() { } |
|
public int M(int a) { } |
|
} |
|
"; |
|
|
|
[Test] |
|
public void PropertyNameAmbiguousWithTypeName() |
|
{ |
|
string program = propertyNameAmbiguousWithTypeNameProgram; |
|
TypeResolveResult trr = Resolve<TypeResolveResult>(program.Replace("$", "$Color$ c;")); |
|
Assert.AreEqual("Color", trr.Type.Name); |
|
|
|
MemberResolveResult mrr = Resolve<MemberResolveResult>(program.Replace("$", "x = $Color$;")); |
|
Assert.AreEqual("Color", mrr.Member.Name); |
|
} |
|
|
|
[Test] |
|
public void PropertyNameAmbiguousWithTypeName_MemberAccessOnAmbiguousIdentifier() |
|
{ |
|
string program = propertyNameAmbiguousWithTypeNameProgram; |
|
Resolve<MemberResolveResult>(program.Replace("$", "$Color$ = Color.Empty;")); |
|
Resolve<TypeResolveResult>(program.Replace("$", "Color = $Color$.Empty;")); |
|
} |
|
|
|
[Test] |
|
public void PropertyNameAmbiguousWithTypeName_MethodInvocationOnAmbiguousIdentifier() |
|
{ |
|
string program = propertyNameAmbiguousWithTypeNameProgram; |
|
Resolve<MemberResolveResult>(program.Replace("$", "x = $Color$.M(1);")); |
|
Resolve<TypeResolveResult>(program.Replace("$", "x = $Color$.M();")); |
|
} |
|
|
|
[Test] |
|
public void ValueInsideSetterTest() |
|
{ |
|
string program = @"class A { |
|
public string Property { |
|
set { |
|
var a = $value$; |
|
} |
|
} |
|
} |
|
"; |
|
LocalResolveResult result = Resolve<LocalResolveResult>(program); |
|
Assert.AreEqual("System.String", result.Type.FullName); |
|
Assert.AreEqual("value", result.Variable.Name); |
|
} |
|
|
|
[Test] |
|
public void ValueInsideEventTest() |
|
{ |
|
string program = @"using System; class A { |
|
public event EventHandler Ev { |
|
add { |
|
var a = $value$; |
|
} |
|
remove {} |
|
} |
|
} |
|
"; |
|
LocalResolveResult result = Resolve<LocalResolveResult>(program); |
|
Assert.AreEqual("System.EventHandler", result.Type.FullName); |
|
Assert.AreEqual("value", result.Variable.Name); |
|
} |
|
|
|
[Test] |
|
public void ValueInsideIndexerSetterTest() |
|
{ |
|
string program = @"using System; class A { |
|
public string this[int arg] { |
|
set { |
|
var a = $value$; |
|
} |
|
} |
|
} |
|
"; |
|
LocalResolveResult result = Resolve<LocalResolveResult>(program); |
|
Assert.AreEqual("System.String", result.Type.FullName); |
|
Assert.AreEqual("value", result.Variable.Name); |
|
} |
|
|
|
[Test] |
|
public void AnonymousMethodParameters() |
|
{ |
|
string program = @"using System; |
|
class A { |
|
void Method() { |
|
SomeEvent += delegate(object sender, EventArgs e) { |
|
$e$.ToString(); |
|
}; |
|
} } |
|
"; |
|
LocalResolveResult result = Resolve<LocalResolveResult>(program); |
|
Assert.AreEqual("System.EventArgs", result.Type.FullName); |
|
Assert.AreEqual("e", result.Variable.Name); |
|
} |
|
|
|
[Test] |
|
public void DefaultTypeCSharp() |
|
{ |
|
string program = @"class A { |
|
void Method() { |
|
$int$ a; |
|
} } |
|
"; |
|
TypeResolveResult result = Resolve<TypeResolveResult>(program); |
|
Assert.AreEqual("System.Int32", result.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void LoopVariableScopeTest() |
|
{ |
|
string program = @"using System; |
|
class TestClass { |
|
void Test() { |
|
for (int i = 0; i < 10; i++) { |
|
$1$.ToString(); |
|
} |
|
for (long i = 0; i < 10; i++) { |
|
$2$.ToString(); |
|
} |
|
} |
|
} |
|
"; |
|
LocalResolveResult lr = Resolve<LocalResolveResult>(program.Replace("$1$", "$i$").Replace("$2$", "i")); |
|
Assert.AreEqual("System.Int32", lr.Type.ReflectionName); |
|
|
|
lr = Resolve<LocalResolveResult>(program.Replace("$1$", "i").Replace("$2$", "$i$")); |
|
Assert.AreEqual("System.Int64", lr.Type.ReflectionName); |
|
} |
|
|
|
[Test] |
|
public void NamespacePreferenceTest() |
|
{ |
|
// Classes in the current namespace are preferred over classes from |
|
// imported namespaces |
|
string program = @"using System; |
|
namespace Testnamespace { |
|
class A { |
|
$Activator$ a; |
|
} |
|
|
|
class Activator { |
|
|
|
} |
|
} |
|
"; |
|
var result = Resolve<TypeResolveResult>(program); |
|
Assert.AreEqual("Testnamespace.Activator", result.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void ParentNamespaceTypeLookup() |
|
{ |
|
string program = @"using System; |
|
namespace Root { |
|
class Alpha {} |
|
} |
|
namespace Root.Child { |
|
class Beta { |
|
$Alpha$ a; |
|
} |
|
} |
|
"; |
|
var result = Resolve<TypeResolveResult>(program); |
|
Assert.AreEqual("Root.Alpha", result.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void ImportAliasTest() |
|
{ |
|
string program = @"using COL = System.Collections; |
|
class TestClass { |
|
COL.ArrayList ff; |
|
} |
|
"; |
|
TypeResolveResult type = Resolve<TypeResolveResult>(program.Replace("COL.ArrayList", "$COL.ArrayList$")); |
|
Assert.IsNotNull(type, "COL.ArrayList should resolve to a type"); |
|
Assert.AreEqual("System.Collections.ArrayList", type.Type.FullName, "TypeResolveResult"); |
|
|
|
MemberResolveResult member = Resolve<MemberResolveResult>(program.Replace("ff", "$ff$")); |
|
Assert.AreEqual("System.Collections.ArrayList", member.Type.FullName, "the full type should be resolved"); |
|
} |
|
|
|
[Test] |
|
public void ImportAliasNamespaceResolveTest() |
|
{ |
|
NamespaceResolveResult ns; |
|
string program = "using COL = System.Collections;\r\nclass A {\r\n$.ArrayList a;\r\n}\r\n"; |
|
ns = Resolve<NamespaceResolveResult>(program.Replace("$", "$COL$")); |
|
Assert.AreEqual("System.Collections", ns.NamespaceName, "COL"); |
|
ns = Resolve<NamespaceResolveResult>(program.Replace("$", "$COL.Generic$")); |
|
Assert.AreEqual("System.Collections.Generic", ns.NamespaceName, "COL.Generic"); |
|
} |
|
|
|
[Test] |
|
public void ImportAliasClassResolveTest() |
|
{ |
|
string program = @"using COL = System.Collections.ArrayList; |
|
class TestClass { |
|
void Test() { |
|
COL a = new COL(); |
|
|
|
} |
|
} |
|
"; |
|
TypeResolveResult trr = Resolve<TypeResolveResult>(program.Replace("COL a", "$COL$ a")); |
|
Assert.AreEqual("System.Collections.ArrayList", trr.Type.FullName, "COL"); |
|
ResolveResult rr = Resolve<CSharpInvocationResolveResult>(program.Replace("new COL()", "$new COL()$")); |
|
Assert.AreEqual("System.Collections.ArrayList", rr.Type.FullName, "a"); |
|
} |
|
|
|
[Test] |
|
public void ImportSubnamespaceWithAliasTest() |
|
{ |
|
string program = @"namespace PC |
|
{ |
|
// Define an alias for the nested namespace. |
|
using Project = PC.MyCompany.Project; |
|
class A |
|
{ |
|
Project.MyClass M() |
|
{ |
|
// Use the alias |
|
$Project.MyClass$ mc = new Project.MyClass(); |
|
return mc; |
|
} |
|
} |
|
namespace MyCompany |
|
{ |
|
namespace Project |
|
{ |
|
public class MyClass { } |
|
} |
|
} |
|
} |
|
"; |
|
var mrr = Resolve(program); |
|
Assert.AreEqual("PC.MyCompany.Project.MyClass", mrr.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void ResolveNamespaceSD_863() |
|
{ |
|
string program = @"using System; |
|
namespace A.C { class D {} } |
|
namespace A.B.C { class D {} } |
|
namespace A.B { |
|
class TestClass { |
|
void Test() { |
|
C.D x; |
|
} |
|
} |
|
} |
|
"; |
|
NamespaceResolveResult nrr = Resolve<NamespaceResolveResult>(program.Replace("C.D", "$C$.D")); |
|
Assert.AreEqual("A.B.C", nrr.NamespaceName, "nrr.Name"); |
|
TypeResolveResult trr = Resolve<TypeResolveResult>(program.Replace("C.D", "$C.D$")); |
|
Assert.AreEqual("A.B.C.D", trr.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void ResolveTypeSD_863() |
|
{ |
|
string program = @"using System; |
|
namespace A { class C {} } |
|
namespace A.B { |
|
class C {} |
|
class TestClass { |
|
void Test() { |
|
$C$ a; |
|
} |
|
} |
|
} |
|
"; |
|
TypeResolveResult trr = Resolve<TypeResolveResult>(program); |
|
Assert.AreEqual("A.B.C", trr.Type.FullName); |
|
} |
|
|
|
|
|
[Test] |
|
public void InnerTypeResolve1 () |
|
{ |
|
string program = @"public class C<T> { public class Inner { } } |
|
class TestClass { |
|
void Test() { |
|
$C<string>.Inner$ a; |
|
} |
|
} |
|
"; |
|
TypeResolveResult trr = Resolve<TypeResolveResult>(program); |
|
Assert.AreEqual("C.Inner", trr.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void InnerTypeResolve2 () |
|
{ |
|
string program = @"public class C<T> { public class D<S,U> { public class Inner { } }} |
|
class TestClass { |
|
void Test() { |
|
$C<string>.D<int,TestClass>.Inner$ a; |
|
} |
|
} |
|
"; |
|
TypeResolveResult trr = Resolve<TypeResolveResult>(program); |
|
Assert.AreEqual("C.D.Inner", trr.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void ShortMaxValueTest() |
|
{ |
|
string program = @"using System; |
|
class TestClass { |
|
object a = $short.MaxValue$; |
|
} |
|
"; |
|
MemberResolveResult rr = Resolve<MemberResolveResult>(program); |
|
Assert.AreEqual("System.Int16", rr.Type.FullName); |
|
Assert.AreEqual("System.Int16.MaxValue", rr.Member.FullName); |
|
Assert.AreEqual(short.MaxValue, rr.ConstantValue); |
|
} |
|
|
|
[Test] |
|
public void ClassWithSameNameAsNamespace() |
|
{ |
|
string program = @"using System; namespace XX { |
|
class Test { |
|
static void X() { |
|
a = $; |
|
} |
|
} |
|
class XX { |
|
public static void Test() {} |
|
} }"; |
|
TypeResolveResult trr = Resolve<TypeResolveResult>(program.Replace("$", "$XX$")); |
|
Assert.AreEqual("XX.XX", trr.Type.FullName); |
|
|
|
NamespaceResolveResult nrr = Resolve<NamespaceResolveResult>(program.Replace("$", "$global::XX$.T")); |
|
Assert.AreEqual("XX", nrr.NamespaceName); |
|
|
|
trr = Resolve<TypeResolveResult>(program.Replace("$", "$global::XX.XX$")); |
|
Assert.AreEqual("XX.XX", trr.Type.FullName); |
|
|
|
InvocationResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$XX.Test()$")); |
|
Assert.AreEqual("XX.XX.Test", mrr.Member.FullName); |
|
} |
|
|
|
[Test] |
|
public void ClassNameLookup1() |
|
{ |
|
string program = @"namespace MainNamespace { |
|
using Test.Subnamespace; |
|
class Program { |
|
static void M($Test.TheClass$ c) {} |
|
} |
|
} |
|
|
|
namespace Test { public class TheClass { } } |
|
namespace Test.Subnamespace { |
|
public class Test { public class TheClass { } } |
|
} |
|
"; |
|
TypeResolveResult trr = Resolve<TypeResolveResult>(program); |
|
Assert.AreEqual("Test.Subnamespace.Test.TheClass", trr.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void ClassNameLookup2() |
|
{ |
|
string program = @"using Test.Subnamespace; |
|
namespace MainNamespace { |
|
class Program { |
|
static void M($Test.TheClass$ c) {} |
|
} |
|
} |
|
|
|
namespace Test { public class TheClass { } } |
|
namespace Test.Subnamespace { |
|
public class Test { public class TheClass { } } |
|
} |
|
"; |
|
TypeResolveResult trr = Resolve<TypeResolveResult>(program); |
|
Assert.AreEqual("Test.TheClass", trr.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void ClassNameLookup3() |
|
{ |
|
string program = @"namespace MainNamespace { |
|
using Test.Subnamespace; |
|
class Program { |
|
static void M($Test$ c) {} |
|
} |
|
} |
|
|
|
namespace Test { public class TheClass { } } |
|
namespace Test.Subnamespace { |
|
public class Test { public class TheClass { } } |
|
} |
|
"; |
|
TypeResolveResult trr = Resolve<TypeResolveResult>(program); |
|
Assert.AreEqual("Test.Subnamespace.Test", trr.Type.FullName); |
|
} |
|
|
|
[Test] |
|
public void ClassNameLookup4() |
|
{ |
|
string program = @"using Test.Subnamespace; |
|
namespace MainNamespace { |
|
class Program { |
|
static void M($Test$ c) {} |
|
} |
|
} |
|
|
|
namespace Test { public class TheClass { } } |
|
namespace Test.Subnamespace { |
|
public class Test { public class TheClass { } } |
|
} |
|
"; |
|
NamespaceResolveResult nrr = Resolve<NamespaceResolveResult>(program); |
|
Assert.AreEqual("Test", nrr.NamespaceName); |
|
} |
|
|
|
[Test] |
|
public void ClassNameLookup5() |
|
{ |
|
string program = @"namespace MainNamespace { |
|
using A; |
|
|
|
class M { |
|
void X($Test$ a) {} |
|
} |
|
namespace Test { class B {} } |
|
} |
|
|
|
namespace A { |
|
class Test {} |
|
}"; |
|
NamespaceResolveResult nrr = Resolve<NamespaceResolveResult>(program); |
|
Assert.AreEqual("MainNamespace.Test", nrr.NamespaceName); |
|
} |
|
|
|
[Test] |
|
public void InvocableRule() |
|
{ |
|
string program = @"using System; |
|
class DerivedClass : BaseClass { |
|
static void X() { |
|
a = $; |
|
} |
|
private static new int Test; |
|
} |
|
class BaseClass { |
|
public static string Test() {} |
|
}"; |
|
MemberResolveResult mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$BaseClass.Test()$")); |
|
Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); |
|
|
|
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$Test$")); |
|
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); |
|
|
|
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$DerivedClass.Test$")); |
|
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); |
|
|
|
// returns BaseClass.Test because DerivedClass.Test is not invocable |
|
mrr = Resolve<CSharpInvocationResolveResult>(program.Replace("$", "$DerivedClass.Test()$")); |
|
Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); |
|
} |
|
|
|
[Test] |
|
public void InvocableRule2() |
|
{ |
|
string program = @"using System; |
|
class DerivedClass : BaseClass { |
|
static void X() { |
|
a = $; |
|
} |
|
private static new int Test; |
|
} |
|
delegate string SomeDelegate(); |
|
class BaseClass { |
|
public static SomeDelegate Test; |
|
}"; |
|
MemberResolveResult mrr = Resolve<MemberResolveResult>(program.Replace("$", "$BaseClass.Test$()")); |
|
Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); |
|
|
|
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$Test$")); |
|
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); |
|
|
|
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$DerivedClass.Test$")); |
|
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); |
|
|
|
// returns BaseClass.Test because DerivedClass.Test is not invocable |
|
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$DerivedClass.Test$()")); |
|
Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); |
|
} |
|
|
|
[Test] |
|
public void AccessibleRule() |
|
{ |
|
string program = @"using System; |
|
class BaseClass { |
|
static void X() { |
|
a = $DerivedClass.Test$; |
|
} |
|
public static int Test; |
|
} |
|
class DerivedClass : BaseClass { |
|
private static new int Test; |
|
} |
|
"; |
|
// returns BaseClass.Test because DerivedClass.Test is not accessible |
|
MemberResolveResult mrr = Resolve<MemberResolveResult>(program); |
|
Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); |
|
} |
|
|
|
[Test] |
|
public void FieldHidingProperty() |
|
{ |
|
string program = @"using System; |
|
class DerivedClass : BaseClass { |
|
static void X() { |
|
a = $Test$; |
|
} |
|
public static new int Test; |
|
} |
|
class BaseClass { |
|
public static int Test { get { return 0; } } |
|
} |
|
"; |
|
MemberResolveResult mrr = Resolve<MemberResolveResult>(program); |
|
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); |
|
} |
|
|
|
[Test] |
|
public void PropertyHidingField() |
|
{ |
|
string program = @"using System; |
|
class DerivedClass : BaseClass { |
|
static void X() { |
|
a = $Test$; |
|
} |
|
public static new int Test { get { return 0; } } |
|
} |
|
class BaseClass { |
|
public static int Test; |
|
} |
|
"; |
|
MemberResolveResult mrr = Resolve<MemberResolveResult>(program); |
|
Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); |
|
} |
|
|
|
[Test] |
|
public void SD_1487() |
|
{ |
|
string program = @"using System; |
|
class C2 : C1 { |
|
public static void M() { |
|
a = $; |
|
} |
|
} |
|
class C1 { |
|
protected static int Field; |
|
}"; |
|
MemberResolveResult mrr; |
|
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$Field$")); |
|
Assert.IsFalse(mrr.IsError); |
|
Assert.AreEqual("C1.Field", mrr.Member.FullName); |
|
|
|
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$C1.Field$")); |
|
Assert.IsFalse(mrr.IsError); |
|
Assert.AreEqual("C1.Field", mrr.Member.FullName); |
|
|
|
mrr = Resolve<MemberResolveResult>(program.Replace("$", "$C2.Field$")); |
|
Assert.IsFalse(mrr.IsError); |
|
Assert.AreEqual("C1.Field", mrr.Member.FullName); |
|
} |
|
|
|
[Test] |
|
public void NullableValue() |
|
{ |
|
string program = @"using System; |
|
class Test { |
|
public static void M(int? a) { |
|
$a.Value$.ToString(); |
|
} |
|
}"; |
|
MemberResolveResult rr = Resolve<MemberResolveResult>(program); |
|
Assert.AreEqual("System.Nullable.Value", rr.Member.FullName); |
|
Assert.AreEqual("System.Int32", rr.Member.ReturnType.Resolve(context).FullName); |
|
} |
|
|
|
[Test] |
|
public void MethodHidesEvent() |
|
{ |
|
// see SD-1542 |
|
string program = @"using System; |
|
class Test : Form { |
|
public Test() { |
|
a = $base.KeyDown$; |
|
} |
|
void KeyDown(object sender, EventArgs e) {} |
|
} |
|
class Form { |
|
public event EventHandler KeyDown; |
|
}"; |
|
var mrr = Resolve<MemberResolveResult>(program); |
|
Assert.AreEqual("Form.KeyDown", mrr.Member.FullName); |
|
|
|
var mgrr = Resolve<MethodGroupResolveResult>(program.Replace("base", "this")); |
|
Assert.AreEqual("Test.KeyDown", mgrr.Methods.Single().FullName); |
|
} |
|
|
|
[Test] |
|
public void ProtectedMemberVisibleWhenBaseTypeReferenceIsInOtherPart() |
|
{ |
|
string program = @"using System; |
|
partial class A { |
|
void M1() { |
|
$x$ = 0; |
|
} |
|
} |
|
partial class A : B { } |
|
class B |
|
{ |
|
protected int x; |
|
}"; |
|
var mrr = Resolve<MemberResolveResult>(program); |
|
Assert.AreEqual("B.x", mrr.Member.FullName); |
|
} |
|
|
|
[Test, Ignore("Parser produces incorrect positions")] |
|
public void SubstituteClassAndMethodTypeParametersAtOnce() |
|
{ |
|
string program = @"class C<X> { static void M<T>(X a, T b) { $C<T>.M<X>$(b, a); } }"; |
|
var rr = Resolve<MethodGroupResolveResult>(program); |
|
Assert.AreEqual("X", rr.TypeArguments.Single().Name); |
|
|
|
var m = (SpecializedMethod)rr.Methods.Single(); |
|
Assert.AreSame(rr.TypeArguments.Single(), m.TypeArguments.Single()); |
|
Assert.AreEqual("T", m.Parameters[0].Type.Resolve(context).Name); |
|
Assert.AreEqual("X", m.Parameters[1].Type.Resolve(context).Name); |
|
} |
|
} |
|
}
|
|
|