Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory-5.5.0/Analysis/SymbolCollector.cs @ 13397

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

#2077: created branch and added first version

File size: 5.4 KB
Line 
1// Copyright (c) 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 ICSharpCode.NRefactory.TypeSystem;
22using System.Linq;
23
24namespace ICSharpCode.NRefactory.Analysis
25{
26  /// <summary>
27  /// The symbol collector collects related symbols that form a group of symbols that should be renamed
28  /// when a name of one symbol changes. For example if a type definition name should be changed
29  /// the constructors and destructor names should change as well.
30  /// </summary>
31  public class SymbolCollector
32  {
33    /// <summary>
34    /// Gets or sets a value indicating whether this <see cref="ICSharpCode.NRefactory.Analysis.SymbolCollector"/> should include overloads.
35    /// </summary>
36    /// <value><c>true</c> if overloads should be included; otherwise, <c>false</c>.</value>
37    public bool IncludeOverloads {
38      get;
39      set;
40    }
41
42    public bool GroupForRenaming {
43      get;
44      set;
45    }
46
47    static IEnumerable<ISymbol> CollectTypeRelatedMembers (ITypeDefinition type)
48    {
49      yield return type;
50      foreach (var c in type.GetDefinition ().GetMembers (m => !m.IsSynthetic && (m.SymbolKind == SymbolKind.Constructor || m.SymbolKind == SymbolKind.Destructor), GetMemberOptions.IgnoreInheritedMembers)) {
51        yield return c;
52      }
53    }
54
55    static IEnumerable<ISymbol> CollectOverloads (IMethod method)
56    {
57      return method.DeclaringType
58        .GetMethods (m => m.Name == method.Name)
59        .Where (m => m != method);
60    }
61
62    static IMember SearchMember (ITypeDefinition derivedType, IMember method)
63    {
64      foreach (var m in derivedType.Members) {
65        if (m.ImplementedInterfaceMembers.Contains (method))
66          return m;
67      }
68      return null;
69    }
70
71    static IEnumerable<ISymbol> MakeUnique (List<ISymbol> symbols)
72    {
73      HashSet<ISymbol> taken = new HashSet<ISymbol> ();
74      foreach (var sym in symbols) {
75        if (taken.Contains (sym))
76          continue;
77        taken.Add (sym);
78        yield return sym;
79      }
80    }
81
82    /// <summary>
83    /// Gets the related symbols.
84    /// </summary>
85    /// <returns>The related symbols.</returns>
86    /// <param name="g">The type graph.</param>
87    /// <param name="m">The symbol to search</param>
88    public IEnumerable<ISymbol> GetRelatedSymbols(Lazy<TypeGraph> g, ISymbol m)
89    {
90      switch (m.SymbolKind) {
91      case SymbolKind.TypeDefinition:
92        return CollectTypeRelatedMembers ((ITypeDefinition)m);
93 
94      case SymbolKind.Field:
95      case SymbolKind.Operator:
96      case SymbolKind.Variable:
97      case SymbolKind.Parameter:
98      case SymbolKind.TypeParameter:
99        return new ISymbol[] { m };
100 
101      case SymbolKind.Constructor:
102        if (GroupForRenaming)
103          return GetRelatedSymbols (g, ((IMethod)m).DeclaringTypeDefinition);
104        List<ISymbol> constructorSymbols = new List<ISymbol> ();
105        if (IncludeOverloads) {
106          foreach (var m3 in CollectOverloads ((IMethod)m)) {
107            constructorSymbols.Add (m3);
108          }
109        }
110        return constructorSymbols;
111
112      case SymbolKind.Destructor:
113        if (GroupForRenaming)
114          return GetRelatedSymbols (g, ((IMethod)m).DeclaringTypeDefinition);
115        return new ISymbol[] { m };
116
117      case SymbolKind.Indexer:
118      case SymbolKind.Event:
119      case SymbolKind.Property:
120      case SymbolKind.Method: {
121        var member = (IMember)m;
122        List<ISymbol> symbols = new List<ISymbol> ();
123        if (!member.IsExplicitInterfaceImplementation)
124          symbols.Add (member);
125        if (GroupForRenaming) {
126          foreach (var m2 in member.ImplementedInterfaceMembers) {
127            symbols.AddRange (GetRelatedSymbols (g, m2));
128          }
129        } else {
130          symbols.AddRange(member.ImplementedInterfaceMembers);
131        }
132
133        if (member.DeclaringType.Kind == TypeKind.Interface) {
134          var declaringTypeNode = g.Value.GetNode(member.DeclaringTypeDefinition);
135          if (declaringTypeNode != null) {
136            foreach (var derivedType in declaringTypeNode.DerivedTypes) {
137              var mem = SearchMember (derivedType.TypeDefinition, member);
138              if (mem != null)
139                symbols.Add (mem);
140            }
141          }
142        }
143
144
145        if (IncludeOverloads) {
146          IncludeOverloads = false;
147          if (member is IMethod) {
148            foreach (var m3 in CollectOverloads ((IMethod)member)) {
149              symbols.AddRange (GetRelatedSymbols (g, m3));
150            }
151          } else if (member.SymbolKind == SymbolKind.Indexer) {
152            symbols.AddRange (member.DeclaringTypeDefinition.GetProperties (p => p.IsIndexer));
153          }
154        }
155        return MakeUnique (symbols);
156      }
157      case SymbolKind.Namespace:
158        // TODO?
159        return new ISymbol[] { m };
160      default:
161        throw new ArgumentOutOfRangeException ("symbol:"+m.SymbolKind);
162      }
163    }
164  }
165}
Note: See TracBrowser for help on using the repository browser.