1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
20
using System.Collections;
21
using System.Collections.Generic;
24
using ICSharpCode.NRefactory.CSharp.Resolver;
25
using ICSharpCode.NRefactory.CSharp.TypeSystem;
26
using ICSharpCode.NRefactory.TypeSystem;
27
using ICSharpCode.NRefactory.TypeSystem.Implementation;
28
using NUnit.Framework;
30
namespace ICSharpCode.NRefactory.CSharp.Refactoring
33
public class TypeSystemAstBuilderTests
35
const string mainProgram = @"
37
using System.Collections.Generic;
41
public class Nested<X> { }
42
public class Sibling { }
44
class Derived<T, S> : Base<S> { }
47
using R = global::System.Reflection;
58
ICompilation compilation;
59
ITypeDefinition baseClass, derivedClass, nestedClass, siblingClass, systemClass;
60
CSharpUnresolvedFile unresolvedFile;
67
baseClass = compilation.RootNamespace.GetTypeDefinition("Base", 1);
68
nestedClass = baseClass.NestedTypes.Single(t => t.Name == "Nested");
69
siblingClass = baseClass.NestedTypes.Single(t => t.Name == "Sibling");
70
derivedClass = compilation.RootNamespace.GetTypeDefinition("Derived", 2);
71
systemClass = compilation.RootNamespace.GetChildNamespace("NS").GetTypeDefinition("System", 0);
74
void Init(string program)
76
pc = new CSharpProjectContent();
77
pc = pc.SetAssemblyName("MyAssembly");
78
unresolvedFile = SyntaxTree.Parse(program, "program.cs").ToTypeSystem();
79
pc = pc.AddOrUpdateFiles(unresolvedFile);
80
pc = pc.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib });
82
compilation = pc.CreateCompilation();
85
TypeSystemAstBuilder CreateBuilder(ITypeDefinition currentTypeDef = null)
87
UsingScope usingScope = currentTypeDef != null ? unresolvedFile.GetUsingScope(currentTypeDef.Region.Begin) : unresolvedFile.RootUsingScope;
88
return new TypeSystemAstBuilder(new CSharpResolver(
89
new CSharpTypeResolveContext(compilation.MainAssembly, usingScope.Resolve(compilation), currentTypeDef)));
92
string TypeToString(IType type, ITypeDefinition currentTypeDef = null, Action<TypeSystemAstBuilder> builderAction = null)
94
var builder = CreateBuilder(currentTypeDef);
95
if (builderAction != null)
96
builderAction (builder);
97
AstType node = builder.ConvertType(type);
98
return node.ToString();
102
public void PrimitiveTypeNames()
104
Assert.AreEqual("void", TypeToString(compilation.FindType(KnownTypeCode.Void)));
105
Assert.AreEqual("int", TypeToString(compilation.FindType(KnownTypeCode.Int32)));
106
Assert.AreEqual("decimal", TypeToString(compilation.FindType(KnownTypeCode.Decimal)));
110
public void SystemType()
112
Assert.AreEqual("Type", TypeToString(compilation.FindType(KnownTypeCode.Type)));
116
public void ListOfNSSystem()
118
var type = new ParameterizedType(compilation.FindType(typeof(List<>)).GetDefinition(), new[] { systemClass });
119
Assert.AreEqual("List<NS.System>", TypeToString(type));
120
Assert.AreEqual("List<System>", TypeToString(type, systemClass));
124
public void NonGenericIEnumerable()
126
Assert.AreEqual("System.Collections.IEnumerable", TypeToString(compilation.FindType(typeof(IEnumerable))));
130
public void NonGenericIEnumerableWithSystemNamespaceCollision()
132
Assert.AreEqual("global::System.Collections.IEnumerable", TypeToString(compilation.FindType(typeof(IEnumerable)), systemClass));
136
public void AliasedNamespace()
138
var type = compilation.FindType(typeof(System.Reflection.Assembly));
139
Assert.AreEqual("R.Assembly", TypeToString(type, systemClass));
143
public void AliasedType()
145
var type = new ParameterizedType(compilation.FindType(typeof(List<>)).GetDefinition(), new[] { compilation.FindType(KnownTypeCode.Char) });
146
Assert.AreEqual("List<char>", TypeToString(type));
147
Assert.AreEqual("L", TypeToString(type, systemClass));
151
public void AliasedTypeWrongTypeArgument()
153
var type = new ParameterizedType(compilation.FindType(typeof(List<>)).GetDefinition(), new[] { compilation.FindType(KnownTypeCode.Int32) });
154
Assert.AreEqual("List<int>", TypeToString(type, systemClass));
158
public void UnboundType()
160
Assert.AreEqual("Base<>", TypeToString(baseClass));
161
Assert.AreEqual("Base<>.Nested<>", TypeToString(nestedClass));
165
public void UnboundTypeConvertUnboundTypeArgumentsOption()
167
Assert.AreEqual("Base<T>", TypeToString(baseClass, null, builder => builder.ConvertUnboundTypeArguments = true));
168
Assert.AreEqual("Base<T>.Nested<X>", TypeToString(nestedClass, null, builder => builder.ConvertUnboundTypeArguments = true));
172
public void NestedType()
174
var type = new ParameterizedType(nestedClass, new[] { compilation.FindType(KnownTypeCode.Char), compilation.FindType(KnownTypeCode.String) });
175
Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type));
176
// The short form "Nested<string>" refers to "Base<T>.Nested<string>",
177
// so we need to use the long form to specify that T=char.
178
Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type, baseClass));
179
Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type, nestedClass));
180
Assert.AreEqual("Base<char>.Nested<string>", TypeToString(type, derivedClass));
184
public void NestedTypeInCurrentClass()
186
var type = new ParameterizedType(nestedClass, new[] { baseClass.TypeParameters[0], compilation.FindType(KnownTypeCode.String) });
187
Assert.AreEqual("Nested<string>", TypeToString(type, baseClass));
188
Assert.AreEqual("Nested<string>", TypeToString(type, nestedClass));
192
public void NestedTypeInDerivedClass()
194
var type1 = new ParameterizedType(nestedClass, new[] { derivedClass.TypeParameters[0], compilation.FindType(KnownTypeCode.String) });
195
// short form "Nested<string>" cannot be used as it would refer to "Base<S>.Nested<string>"
196
Assert.AreEqual("Base<T>.Nested<string>", TypeToString(type1, derivedClass));
198
var type2 = new ParameterizedType(nestedClass, new[] { derivedClass.TypeParameters[1], compilation.FindType(KnownTypeCode.String) });
199
Assert.AreEqual("Nested<string>", TypeToString(type2, derivedClass));
203
public void SiblingClass()
205
var type = new ParameterizedType(siblingClass, new[] { baseClass.TypeParameters[0] });
206
Assert.AreEqual("Sibling", TypeToString(type, nestedClass));
210
public void GenericClass()
212
var type = new ParameterizedType(nestedClass, new[] { baseClass.TypeParameters[0], compilation.FindType(KnownTypeCode.String) });
213
Assert.AreEqual("Nested<string>", TypeToString(type, siblingClass));
217
public void MultidimensionalArray()
219
Assert.AreEqual("byte[][,]", TypeToString(compilation.FindType(typeof(byte[][,]))));
223
public void Pointer()
225
Assert.AreEqual("long*", TypeToString(compilation.FindType(typeof(long*))));
229
public void NullableType()
231
Assert.AreEqual("ulong?", TypeToString(compilation.FindType(typeof(ulong?))));
235
public void AmbiguousType()
237
Assert.AreEqual("System.Array", TypeToString(compilation.FindType(typeof(Array))));
238
Assert.AreEqual("OtherNS.Array", TypeToString(compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName("OtherNS", "Array"))));
242
public void NestedFooCollidingWithProperty_SameType()
244
string program = @"class MainClass {
245
public enum Foo { Value1, Value2 }
248
Foo Foo { get; set; }
252
var foo = compilation.MainAssembly.GetTypeDefinition(new FullTypeName("MainClass+Foo"));
253
var test = compilation.MainAssembly.GetTypeDefinition(new FullTypeName("MainClass+Test"));
254
Assert.AreEqual("Foo", TypeToString(foo, test));
258
public void NestedFooCollidingWithProperty_DifferentType()
260
string program = @"class MainClass {
261
public enum Foo { Value1, Value2 }
264
int Foo { get; set; }
268
var foo = compilation.MainAssembly.GetTypeDefinition(new FullTypeName("MainClass+Foo"));
269
var test = compilation.MainAssembly.GetTypeDefinition(new FullTypeName("MainClass+Test"));
270
Assert.AreEqual("MainClass.Foo", TypeToString(foo, test));