Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Refactoring/NamingHelper.cs @ 17197

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

#2077: created branch and added first version

File size: 6.9 KB
Line 
1//
2// NamingHelper.cs
3//
4// Author:
5//       Simon Lindgren <simon.n.lindgren@gmail.com>
6//
7// Copyright (c) 2012 Simon Lindgren
8//
9// Permission is hereby granted, free of charge, to any person obtaining a copy
10// of this software and associated documentation files (the "Software"), to deal
11// in the Software without restriction, including without limitation the rights
12// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13// copies of the Software, and to permit persons to whom the Software is
14// furnished to do so, subject to the following conditions:
15//
16// The above copyright notice and this permission notice shall be included in
17// all copies or substantial portions of the Software.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25// THE SOFTWARE.
26using System;
27using System.Collections.Generic;
28using System.Text;
29using ICSharpCode.NRefactory.TypeSystem;
30using ICSharpCode.NRefactory.Semantics;
31
32namespace ICSharpCode.NRefactory.CSharp.Refactoring
33{
34  public class NamingHelper
35  {
36    ISet<string> usedVariableNames;
37    RefactoringContext context;
38
39    public NamingHelper(RefactoringContext context)
40    {
41      this.context = context;
42      if (usedVariableNames == null) {
43        var visitor = new VariableFinderVisitor();
44        var astNode = context.GetNode<Statement>();
45        astNode.AcceptVisitor(visitor);
46        usedVariableNames = visitor.VariableNames;
47      }
48    }
49
50    public static IEnumerable<string> GenerateNameProposals(AstType type)
51    {
52      if (type is PrimitiveType) {
53        var pt = (PrimitiveType)type;
54        switch (pt.Keyword) {
55          case "object":
56            yield return "o";
57            yield return "obj";
58            break;
59          case "bool":
60            yield return "b";
61            yield return "pred";
62            break;
63          case "double":
64          case "float":
65          case "decimal":
66            yield return "d";
67            yield return "f";
68            yield return "m";
69            break;
70          case "char":
71            yield return "c";
72            break;
73          default:
74            yield return "i";
75            yield return "j";
76            yield return "k";
77            break;
78        }
79        yield break;
80      }
81      string name;
82      if (type is SimpleType) {
83        name = ((SimpleType)type).Identifier;
84      } else if (type is MemberType) {
85        name = ((MemberType)type).MemberName;
86      } else {
87        yield break;
88      }
89
90      var names = WordParser.BreakWords(name);
91      if (names.Count > 0) {
92        names [0] = Char.ToLower(names [0] [0]) + names [0].Substring(1);
93      }
94      yield return string.Join("", names);
95    }
96
97    /// <summary>
98    /// Generates a variable name for a variable of the specified type.
99    /// </summary>
100    /// <returns>
101    /// The variable name.
102    /// </returns>
103    /// <param name='type'>
104    /// The type of the variable.
105    /// </param>
106    /// <param name='baseName'>
107    /// Suggested base name.
108    /// </param>
109    public string GenerateVariableName(AstType type, string baseName = null)
110    {
111      if (baseName == null) {
112        foreach (var name in NamingHelper.GenerateNameProposals(type)) {
113          baseName = baseName ?? name;
114          if (NameIsUnused(name)) {
115            usedVariableNames.Add(name);
116            return name;
117          }
118        }
119      } else if (NameIsUnused(baseName)) {
120        return baseName;
121      }
122
123      // If we get here, all of the standard suggestions are already used.
124      // This will at least be the second variable named based on firstSuggestion, so start at 2
125      int counter = 2;
126      string proposedName;
127      do {
128        proposedName = baseName + counter++;
129      } while (!NameIsUnused(proposedName));
130      usedVariableNames.Add(proposedName);
131      return proposedName;
132    }
133
134    bool NameIsUnused(string name)
135    {
136      return !usedVariableNames.Contains(name) && LookupVariable(name) == null;
137    }
138
139    /// <summary>
140    /// Generates a variable name for a variable of the specified type.
141    /// </summary>
142    /// <returns>
143    /// The variable name.
144    /// </returns>
145    /// <param name='type'>
146    /// The type of the variable.
147    /// </param>
148    /// <param name='baseName'>
149    /// Suggested base name.
150    /// </param>
151    public string GenerateVariableName(IType type, string baseName = null)
152    {
153      AstType astType = ToAstType(type);
154      return GenerateVariableName(astType, baseName);
155    }
156
157    AstType ToAstType(IType type)
158    {
159      switch (type.FullName) {
160        case "System.Object":
161          return new PrimitiveType("object");
162        case "System.String":
163          return new PrimitiveType("string");
164        case "System.Boolean":
165          return new PrimitiveType("bool");
166        case "System.Char":
167          return new PrimitiveType("char");
168        case "System.SByte":
169          return new PrimitiveType("sbyte");
170        case "System.Byte":
171          return new PrimitiveType("byte");
172        case "System.Int16":
173          return new PrimitiveType("short");
174        case "System.UInt16":
175          return new PrimitiveType("ushort");
176        case "System.Int32":
177          return new PrimitiveType("int");
178        case "System.UInt32":
179          return new PrimitiveType("uint");
180        case "System.Int64":
181          return new PrimitiveType("long");
182        case "System.UInt64":
183          return new PrimitiveType("ulong");
184        case "System.Single":
185          return new PrimitiveType("float");
186        case "System.Double":
187          return new PrimitiveType("double");
188        case "System.Decimal":
189          return new PrimitiveType("decimal");
190        default:
191          return new SimpleType(type.Name);
192      }
193    }
194
195    IVariable LookupVariable(string name)
196    {
197      var blockStatement = context.GetNode<BlockStatement>();
198      var resolverState = context.GetResolverStateAfter(blockStatement.RBraceToken.PrevSibling);
199      var simpleNameRR = resolverState.ResolveSimpleName(name, new List<IType>()) as LocalResolveResult;
200      if (simpleNameRR == null)
201        return null;
202      return simpleNameRR.Variable;
203    }
204
205    class VariableFinderVisitor : DepthFirstAstVisitor
206    {
207
208      public ISet<string> VariableNames = new HashSet<string>();
209
210      public override void VisitVariableInitializer(VariableInitializer variableInitializer)
211      {
212        ProcessName(variableInitializer.Name);
213        base.VisitVariableInitializer(variableInitializer);
214      }
215
216      public override void VisitQueryLetClause(QueryLetClause queryLetClause)
217      {
218        ProcessName(queryLetClause.Identifier);
219        base.VisitQueryLetClause(queryLetClause);
220      }
221
222      public override void VisitQueryFromClause(QueryFromClause queryFromClause)
223      {
224        ProcessName(queryFromClause.Identifier);
225        base.VisitQueryFromClause(queryFromClause);
226      }
227
228      public override void VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause)
229      {
230        ProcessName(queryContinuationClause.Identifier);
231        base.VisitQueryContinuationClause(queryContinuationClause);
232      }
233
234      void ProcessName(string name)
235      {
236        if (!VariableNames.Contains(name))
237          VariableNames.Add(name);
238      }
239    }
240  }
241}
242
Note: See TracBrowser for help on using the repository browser.