Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/TypeSystem/CSharpAssembly.cs @ 11700

Last change on this file since 11700 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 10.1 KB
Line 
1// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
2//
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:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
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.
18
19using System;
20using System.Collections.Generic;
21using System.Diagnostics;
22using System.Linq;
23using System.Threading;
24using ICSharpCode.NRefactory.TypeSystem;
25using ICSharpCode.NRefactory.TypeSystem.Implementation;
26using ICSharpCode.NRefactory.Utils;
27
28namespace ICSharpCode.NRefactory.CSharp.TypeSystem
29{
30  public class CSharpAssembly : IAssembly
31  {
32    readonly ICompilation compilation;
33    readonly ITypeResolveContext context;
34    readonly CSharpProjectContent projectContent;
35    IList<IAttribute> assemblyAttributes;
36    IList<IAttribute> moduleAttributes;
37   
38    internal CSharpAssembly(ICompilation compilation, CSharpProjectContent projectContent)
39    {
40      this.compilation = compilation;
41      this.projectContent = projectContent;
42      this.context = new SimpleTypeResolveContext(this);
43    }
44   
45    public bool IsMainAssembly {
46      get { return compilation.MainAssembly == this; }
47    }
48   
49    public IUnresolvedAssembly UnresolvedAssembly {
50      get { return projectContent; }
51    }
52   
53    public string AssemblyName {
54      get { return projectContent.AssemblyName; }
55    }
56   
57    public string FullAssemblyName {
58      get { return projectContent.FullAssemblyName; }
59    }
60   
61    public IList<IAttribute> AssemblyAttributes {
62      get {
63        return GetAttributes(ref assemblyAttributes, true);
64      }
65    }
66   
67    public IList<IAttribute> ModuleAttributes {
68      get {
69        return GetAttributes(ref moduleAttributes, false);
70      }
71    }
72   
73    IList<IAttribute> GetAttributes(ref IList<IAttribute> field, bool assemblyAttributes)
74    {
75      IList<IAttribute> result = LazyInit.VolatileRead(ref field);
76      if (result != null) {
77        return result;
78      } else {
79        result = new List<IAttribute>();
80        foreach (var unresolvedFile in projectContent.Files.OfType<CSharpUnresolvedFile>()) {
81          var attributes = assemblyAttributes ? unresolvedFile.AssemblyAttributes : unresolvedFile.ModuleAttributes;
82          var context = new CSharpTypeResolveContext(this, unresolvedFile.RootUsingScope.Resolve(compilation));
83          foreach (var unresolvedAttr in attributes) {
84            result.Add(unresolvedAttr.CreateResolvedAttribute(context));
85          }
86        }
87        return LazyInit.GetOrSet(ref field, result);
88      }
89    }
90   
91    NS rootNamespace;
92   
93    public INamespace RootNamespace {
94      get {
95        NS root = LazyInit.VolatileRead(ref this.rootNamespace);
96        if (root != null) {
97          return root;
98        } else {
99          root = new NS(this);
100          Dictionary<string, NS> dict = new Dictionary<string, NS>(compilation.NameComparer);
101          dict.Add(string.Empty, root);
102          // Add namespaces declared in C# files, even if they're empty:
103          foreach (var usingScope in projectContent.Files.OfType<CSharpUnresolvedFile>().SelectMany(f => f.UsingScopes)) {
104            GetOrAddNamespace(dict, usingScope.NamespaceName);
105          }
106          foreach (var pair in GetTypes()) {
107            NS ns = GetOrAddNamespace(dict, pair.Key.Namespace);
108            if (ns.types != null)
109              ns.types[pair.Key] = pair.Value;
110          }
111          return LazyInit.GetOrSet(ref this.rootNamespace, root);
112        }
113      }
114    }
115   
116    static NS GetOrAddNamespace(Dictionary<string, NS> dict, string fullName)
117    {
118      NS ns;
119      if (dict.TryGetValue(fullName, out ns))
120        return ns;
121      int pos = fullName.LastIndexOf('.');
122      NS parent;
123      string name;
124      if (pos < 0) {
125        parent = dict[string.Empty]; // root
126        name = fullName;
127      } else {
128        parent = GetOrAddNamespace(dict, fullName.Substring(0, pos));
129        name = fullName.Substring(pos + 1);
130      }
131      ns = new NS(parent, fullName, name);
132      parent.childNamespaces.Add(ns);
133      dict.Add(fullName, ns);
134      return ns;
135    }
136   
137    public ICompilation Compilation {
138      get { return compilation; }
139    }
140   
141    public bool InternalsVisibleTo(IAssembly assembly)
142    {
143      if (this == assembly)
144        return true;
145      foreach (string shortName in GetInternalsVisibleTo()) {
146        if (assembly.AssemblyName == shortName)
147          return true;
148      }
149      return false;
150    }
151   
152    volatile string[] internalsVisibleTo;
153   
154    string[] GetInternalsVisibleTo()
155    {
156      var result = this.internalsVisibleTo;
157      if (result != null) {
158        return result;
159      } else {
160        using (var busyLock = BusyManager.Enter(this)) {
161          Debug.Assert(busyLock.Success);
162          if (!busyLock.Success) {
163            return new string[0];
164          }
165          internalsVisibleTo = (
166            from attr in this.AssemblyAttributes
167            where attr.AttributeType.Name == "InternalsVisibleToAttribute"
168            && attr.AttributeType.Namespace == "System.Runtime.CompilerServices"
169            && attr.PositionalArguments.Count == 1
170            select GetShortName(attr.PositionalArguments.Single().ConstantValue as string)
171          ).ToArray();
172        }
173        return internalsVisibleTo;
174      }
175    }
176   
177    static string GetShortName(string fullAssemblyName)
178    {
179      if (fullAssemblyName == null)
180        return null;
181      int pos = fullAssemblyName.IndexOf(',');
182      if (pos < 0)
183        return fullAssemblyName;
184      else
185        return fullAssemblyName.Substring(0, pos);
186    }
187   
188    Dictionary<TopLevelTypeName, ITypeDefinition> typeDict;
189   
190    Dictionary<TopLevelTypeName, ITypeDefinition> GetTypes()
191    {
192      var dict = LazyInit.VolatileRead(ref this.typeDict);
193      if (dict != null) {
194        return dict;
195      } else {
196        // Always use the ordinal comparer for the main dictionary so that partial classes
197        // get merged correctly.
198        // The compilation's comparer will be used for the per-namespace dictionaries.
199        var comparer = TopLevelTypeNameComparer.Ordinal;
200        dict = projectContent.TopLevelTypeDefinitions
201          .GroupBy(t => new TopLevelTypeName(t.Namespace, t.Name, t.TypeParameters.Count), comparer)
202          .ToDictionary(g => g.Key, g => CreateResolvedTypeDefinition(g.ToArray()), comparer);
203        return LazyInit.GetOrSet(ref this.typeDict, dict);
204      }
205    }
206   
207    ITypeDefinition CreateResolvedTypeDefinition(IUnresolvedTypeDefinition[] parts)
208    {
209      return new DefaultResolvedTypeDefinition(context, parts);
210    }
211   
212    public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
213    {
214      ITypeDefinition def;
215      if (GetTypes().TryGetValue(topLevelTypeName, out def))
216        return def;
217      else
218        return null;
219    }
220   
221    public IEnumerable<ITypeDefinition> TopLevelTypeDefinitions {
222      get {
223        return GetTypes().Values;
224      }
225    }
226   
227    public override string ToString()
228    {
229      return "[CSharpAssembly " + this.AssemblyName + "]";
230    }
231   
232    sealed class NS : INamespace
233    {
234      readonly CSharpAssembly assembly;
235      readonly NS parentNamespace;
236      readonly string fullName;
237      readonly string name;
238      internal readonly List<NS> childNamespaces = new List<NS>();
239      internal readonly Dictionary<TopLevelTypeName, ITypeDefinition> types;
240     
241      public NS(CSharpAssembly assembly)
242      {
243        this.assembly = assembly;
244        this.fullName = string.Empty;
245        this.name = string.Empty;
246        // Our main dictionary for the CSharpAssembly is using an ordinal comparer.
247        // If the compilation's comparer isn't ordinal, we need to create a new dictionary with the compilation's comparer.
248        if (assembly.compilation.NameComparer != StringComparer.Ordinal) {
249          this.types = new Dictionary<TopLevelTypeName, ITypeDefinition>(new TopLevelTypeNameComparer(assembly.compilation.NameComparer));
250        }
251      }
252     
253      public NS(NS parentNamespace, string fullName, string name)
254      {
255        this.assembly = parentNamespace.assembly;
256        this.parentNamespace = parentNamespace;
257        this.fullName = fullName;
258        this.name = name;
259        if (parentNamespace.types != null)
260          this.types = new Dictionary<TopLevelTypeName, ITypeDefinition>(parentNamespace.types.Comparer);
261      }
262     
263      string INamespace.ExternAlias {
264        get { return null; }
265      }
266     
267      string INamespace.FullName {
268        get { return fullName; }
269      }
270     
271      public string Name {
272        get { return name; }
273      }
274     
275      SymbolKind ISymbol.SymbolKind {
276        get { return SymbolKind.Namespace; }
277      }
278     
279      INamespace INamespace.ParentNamespace {
280        get { return parentNamespace; }
281      }
282     
283      IEnumerable<INamespace> INamespace.ChildNamespaces {
284        get { return childNamespaces; }
285      }
286     
287      IEnumerable<ITypeDefinition> INamespace.Types {
288        get {
289          if (types != null)
290            return types.Values;
291          else
292            return (
293              from t in assembly.GetTypes()
294              where t.Key.Namespace == fullName
295              select t.Value
296            );
297        }
298      }
299     
300      ICompilation ICompilationProvider.Compilation {
301        get { return assembly.Compilation; }
302      }
303     
304      IEnumerable<IAssembly> INamespace.ContributingAssemblies {
305        get { return new [] { assembly }; }
306      }
307     
308      INamespace INamespace.GetChildNamespace(string name)
309      {
310        var nameComparer = assembly.compilation.NameComparer;
311        foreach (NS childNamespace in childNamespaces) {
312          if (nameComparer.Equals(name, childNamespace.name))
313            return childNamespace;
314        }
315        return null;
316      }
317     
318      ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount)
319      {
320        var key = new TopLevelTypeName(fullName, name, typeParameterCount);
321        if (types != null) {
322          ITypeDefinition typeDef;
323          if (types.TryGetValue(key, out typeDef))
324            return typeDef;
325          else
326            return null;
327        } else {
328          return assembly.GetTypeDefinition(key);
329        }
330      }
331
332      public ISymbolReference ToReference()
333      {
334        return new NamespaceReference(new DefaultAssemblyReference(assembly.AssemblyName), fullName);
335      }
336    }
337  }
338}
Note: See TracBrowser for help on using the repository browser.