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.Concurrent;
21
using System.Collections.Generic;
22
using System.Diagnostics;
24
using System.Runtime.Serialization;
25
using System.Threading;
27
using ICSharpCode.NRefactory.Semantics;
28
using ICSharpCode.NRefactory.Utils;
30
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
33
/// Default implementation for <see cref="IUnresolvedAssembly"/>.
36
public class DefaultUnresolvedAssembly : AbstractFreezable, IUnresolvedAssembly
39
string fullAssemblyName;
40
IList<IUnresolvedAttribute> assemblyAttributes;
41
IList<IUnresolvedAttribute> moduleAttributes;
42
Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> typeDefinitions = new Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition>(TopLevelTypeNameComparer.Ordinal);
43
Dictionary<TopLevelTypeName, ITypeReference> typeForwarders = new Dictionary<TopLevelTypeName, ITypeReference>(TopLevelTypeNameComparer.Ordinal);
45
protected override void FreezeInternal()
47
base.FreezeInternal();
48
assemblyAttributes = FreezableHelper.FreezeListAndElements(assemblyAttributes);
49
moduleAttributes = FreezableHelper.FreezeListAndElements(moduleAttributes);
50
foreach (var type in typeDefinitions.Values) {
51
FreezableHelper.Freeze(type);
56
/// Creates a new unresolved assembly.
58
/// <param name="assemblyName">Full assembly name</param>
59
public DefaultUnresolvedAssembly(string assemblyName)
61
if (assemblyName == null)
62
throw new ArgumentNullException("assemblyName");
63
this.fullAssemblyName = assemblyName;
64
int pos = assemblyName != null ? assemblyName.IndexOf(',') : -1;
65
this.assemblyName = pos < 0 ? assemblyName : assemblyName.Substring(0, pos);
66
this.assemblyAttributes = new List<IUnresolvedAttribute>();
67
this.moduleAttributes = new List<IUnresolvedAttribute>();
71
/// Gets/Sets the short assembly name.
74
/// This class handles the short and the full name independently;
75
/// if you change the short name, you should also change the full name.
77
public string AssemblyName {
78
get { return assemblyName; }
81
throw new ArgumentNullException("value");
82
FreezableHelper.ThrowIfFrozen(this);
88
/// Gets/Sets the full assembly name.
91
/// This class handles the short and the full name independently;
92
/// if you change the full name, you should also change the short name.
94
public string FullAssemblyName {
95
get { return fullAssemblyName; }
98
throw new ArgumentNullException("value");
99
FreezableHelper.ThrowIfFrozen(this);
100
fullAssemblyName = value;
105
public string Location {
110
FreezableHelper.ThrowIfFrozen(this);
115
public IList<IUnresolvedAttribute> AssemblyAttributes {
116
get { return assemblyAttributes; }
119
IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.AssemblyAttributes {
120
get { return assemblyAttributes; }
123
public IList<IUnresolvedAttribute> ModuleAttributes {
124
get { return moduleAttributes; }
127
IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.ModuleAttributes {
128
get { return moduleAttributes; }
131
public IEnumerable<IUnresolvedTypeDefinition> TopLevelTypeDefinitions {
132
get { return typeDefinitions.Values; }
136
/// Adds a new top-level type definition to this assembly.
138
/// <remarks>DefaultUnresolvedAssembly does not support partial classes.
139
/// Adding more than one part of a type will cause an ArgumentException.</remarks>
140
public void AddTypeDefinition(IUnresolvedTypeDefinition typeDefinition)
142
if (typeDefinition == null)
143
throw new ArgumentNullException("typeDefinition");
144
if (typeDefinition.DeclaringTypeDefinition != null)
145
throw new ArgumentException("Cannot add nested types.");
146
FreezableHelper.ThrowIfFrozen(this);
147
var key = new TopLevelTypeName(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameters.Count);
148
typeDefinitions.Add(key, typeDefinition);
151
static readonly ITypeReference typeForwardedToAttributeTypeRef = typeof(System.Runtime.CompilerServices.TypeForwardedToAttribute).ToTypeReference();
154
/// Adds a type forwarder.
155
/// This adds both an assembly attribute and an internal forwarder entry, which will be used
156
/// by the resolved assembly to provide the forwarded types.
158
/// <param name="typeName">The name of the type.</param>
159
/// <param name="referencedType">The reference used to look up the type in the target assembly.</param>
160
public void AddTypeForwarder(TopLevelTypeName typeName, ITypeReference referencedType)
162
if (referencedType == null)
163
throw new ArgumentNullException("referencedType");
164
FreezableHelper.ThrowIfFrozen(this);
165
var attribute = new DefaultUnresolvedAttribute(typeForwardedToAttributeTypeRef, new[] { KnownTypeReference.Type });
166
attribute.PositionalArguments.Add(new TypeOfConstantValue(referencedType));
167
assemblyAttributes.Add(attribute);
169
typeForwarders[typeName] = referencedType;
173
sealed class TypeOfConstantValue : IConstantValue
175
readonly ITypeReference typeRef;
177
public TypeOfConstantValue(ITypeReference typeRef)
179
this.typeRef = typeRef;
182
public ResolveResult Resolve(ITypeResolveContext context)
184
return new TypeOfResolveResult(context.Compilation.FindType(KnownTypeCode.Type), typeRef.Resolve(context));
188
public IUnresolvedTypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount)
190
var key = new TopLevelTypeName(ns ?? string.Empty, name, typeParameterCount);
191
IUnresolvedTypeDefinition td;
192
if (typeDefinitions.TryGetValue(key, out td))
198
public IAssembly Resolve(ITypeResolveContext context)
201
throw new ArgumentNullException("context");
203
var cache = context.Compilation.CacheManager;
204
IAssembly asm = (IAssembly)cache.GetShared(this);
208
asm = new DefaultResolvedAssembly(context.Compilation, this);
209
return (IAssembly)cache.GetOrAddShared(this, asm);
213
public override string ToString()
215
return "[" + GetType().Name + " " + assemblyName + "]";
219
//List<Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition>> cachedTypeDictionariesPerNameComparer;
221
Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> GetTypeDictionary(StringComparer nameComparer)
223
Debug.Assert(IsFrozen);
224
if (nameComparer == StringComparer.Ordinal)
225
return typeDefinitions;
227
throw new NotImplementedException();
230
#region UnresolvedNamespace
231
sealed class UnresolvedNamespace
233
internal readonly string FullName;
234
internal readonly string Name;
235
internal readonly List<UnresolvedNamespace> Children = new List<UnresolvedNamespace>();
237
public UnresolvedNamespace(string fullName, string name)
239
this.FullName = fullName;
245
List<KeyValuePair<StringComparer, UnresolvedNamespace>> unresolvedNamespacesPerNameComparer;
247
UnresolvedNamespace GetUnresolvedRootNamespace(StringComparer nameComparer)
249
Debug.Assert(IsFrozen);
250
LazyInitializer.EnsureInitialized(ref unresolvedNamespacesPerNameComparer);
251
lock (unresolvedNamespacesPerNameComparer) {
252
foreach (var pair in unresolvedNamespacesPerNameComparer) {
253
if (pair.Key == nameComparer)
256
var root = new UnresolvedNamespace(string.Empty, string.Empty);
257
var dict = new Dictionary<string, UnresolvedNamespace>(nameComparer);
258
dict.Add(root.FullName, root);
259
foreach (var typeName in typeDefinitions.Keys) {
260
GetOrAddNamespace(dict, typeName.Namespace);
262
unresolvedNamespacesPerNameComparer.Add(new KeyValuePair<StringComparer, UnresolvedNamespace>(nameComparer, root));
267
static UnresolvedNamespace GetOrAddNamespace(Dictionary<string, UnresolvedNamespace> dict, string fullName)
269
UnresolvedNamespace ns;
270
if (dict.TryGetValue(fullName, out ns))
272
int pos = fullName.LastIndexOf('.');
273
UnresolvedNamespace parent;
276
parent = dict[string.Empty]; // root
279
parent = GetOrAddNamespace(dict, fullName.Substring(0, pos));
280
name = fullName.Substring(pos + 1);
282
ns = new UnresolvedNamespace(fullName, name);
283
parent.Children.Add(ns);
284
dict.Add(fullName, ns);
289
sealed class DefaultResolvedAssembly : IAssembly
291
readonly DefaultUnresolvedAssembly unresolvedAssembly;
292
readonly ICompilation compilation;
293
readonly ITypeResolveContext context;
294
readonly Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> unresolvedTypeDict;
295
readonly ConcurrentDictionary<IUnresolvedTypeDefinition, ITypeDefinition> typeDict = new ConcurrentDictionary<IUnresolvedTypeDefinition, ITypeDefinition>();
296
readonly INamespace rootNamespace;
298
public DefaultResolvedAssembly(ICompilation compilation, DefaultUnresolvedAssembly unresolved)
300
this.compilation = compilation;
301
this.unresolvedAssembly = unresolved;
302
this.unresolvedTypeDict = unresolved.GetTypeDictionary(compilation.NameComparer);
303
this.rootNamespace = new NS(this, unresolved.GetUnresolvedRootNamespace(compilation.NameComparer), null);
304
this.context = new SimpleTypeResolveContext(this);
305
this.AssemblyAttributes = unresolved.AssemblyAttributes.CreateResolvedAttributes(context);
306
this.ModuleAttributes = unresolved.ModuleAttributes.CreateResolvedAttributes(context);
309
public IUnresolvedAssembly UnresolvedAssembly {
310
get { return unresolvedAssembly; }
313
public bool IsMainAssembly {
314
get { return this.Compilation.MainAssembly == this; }
317
public string AssemblyName {
318
get { return unresolvedAssembly.AssemblyName; }
321
public string FullAssemblyName {
322
get { return unresolvedAssembly.FullAssemblyName; }
325
public IList<IAttribute> AssemblyAttributes { get; private set; }
326
public IList<IAttribute> ModuleAttributes { get; private set; }
328
public INamespace RootNamespace {
329
get { return rootNamespace; }
332
public ICompilation Compilation {
333
get { return compilation; }
336
public bool InternalsVisibleTo(IAssembly assembly)
338
return assembly == this;
341
public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
343
IUnresolvedTypeDefinition td;
344
ITypeReference typeRef;
345
if (unresolvedAssembly.typeDefinitions.TryGetValue(topLevelTypeName, out td))
346
return GetTypeDefinition(td);
347
else if (unresolvedAssembly.typeForwarders.TryGetValue(topLevelTypeName, out typeRef))
348
return typeRef.Resolve(compilation.TypeResolveContext).GetDefinition();
353
ITypeDefinition GetTypeDefinition(IUnresolvedTypeDefinition unresolved)
355
return typeDict.GetOrAdd(unresolved, t => CreateTypeDefinition(t));
358
ITypeDefinition CreateTypeDefinition(IUnresolvedTypeDefinition unresolved)
360
if (unresolved.DeclaringTypeDefinition != null) {
361
ITypeDefinition declaringType = GetTypeDefinition(unresolved.DeclaringTypeDefinition);
362
return new DefaultResolvedTypeDefinition(context.WithCurrentTypeDefinition(declaringType), unresolved);
363
} else if (unresolved.Name == "Void" && unresolved.Namespace == "System" && unresolved.TypeParameters.Count == 0) {
364
return new VoidTypeDefinition(context, unresolved);
366
return new DefaultResolvedTypeDefinition(context, unresolved);
370
public IEnumerable<ITypeDefinition> TopLevelTypeDefinitions {
372
return unresolvedAssembly.TopLevelTypeDefinitions.Select(t => GetTypeDefinition(t));
376
public override string ToString()
378
return "[DefaultResolvedAssembly " + AssemblyName + "]";
381
sealed class NS : INamespace
383
readonly DefaultResolvedAssembly assembly;
384
readonly UnresolvedNamespace ns;
385
readonly INamespace parentNamespace;
386
readonly IList<NS> childNamespaces;
387
IEnumerable<ITypeDefinition> types;
389
public NS(DefaultResolvedAssembly assembly, UnresolvedNamespace ns, INamespace parentNamespace)
391
this.assembly = assembly;
393
this.parentNamespace = parentNamespace;
394
this.childNamespaces = new ProjectedList<NS, UnresolvedNamespace, NS>(
395
this, ns.Children, (self, c) => new NS(self.assembly, c, self));
398
string INamespace.ExternAlias {
402
string INamespace.FullName {
403
get { return ns.FullName; }
406
string INamespace.Name {
407
get { return ns.Name; }
410
INamespace INamespace.ParentNamespace {
411
get { return parentNamespace; }
414
IEnumerable<IAssembly> INamespace.ContributingAssemblies {
415
get { return new [] { assembly }; }
418
IEnumerable<INamespace> INamespace.ChildNamespaces {
419
get { return childNamespaces; }
422
INamespace INamespace.GetChildNamespace(string name)
424
var nameComparer = assembly.compilation.NameComparer;
425
for (int i = 0; i < childNamespaces.Count; i++) {
426
if (nameComparer.Equals(name, ns.Children[i].Name))
427
return childNamespaces[i];
432
ICompilation ICompilationProvider.Compilation {
433
get { return assembly.compilation; }
436
IEnumerable<ITypeDefinition> INamespace.Types {
438
var result = LazyInit.VolatileRead(ref this.types);
439
if (result != null) {
442
var hashSet = new HashSet<ITypeDefinition>();
443
foreach (IUnresolvedTypeDefinition typeDef in assembly.UnresolvedAssembly.TopLevelTypeDefinitions) {
444
if (typeDef.Namespace == ns.FullName)
445
hashSet.Add(assembly.GetTypeDefinition(typeDef));
447
return LazyInit.GetOrSet(ref this.types, hashSet.ToArray());
452
ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount)
454
var key = new TopLevelTypeName(ns.FullName, name, typeParameterCount);
455
IUnresolvedTypeDefinition unresolvedTypeDef;
456
if (assembly.unresolvedTypeDict.TryGetValue(key, out unresolvedTypeDef))
457
return assembly.GetTypeDefinition(unresolvedTypeDef);