Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Refactoring/TypeSystemAstBuilder.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: 33.0 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 ICSharpCode.NRefactory.CSharp.Resolver;
24using ICSharpCode.NRefactory.CSharp.TypeSystem;
25using ICSharpCode.NRefactory.Semantics;
26using ICSharpCode.NRefactory.TypeSystem;
27using ICSharpCode.NRefactory.TypeSystem.Implementation;
28using ICSharpCode.NRefactory.Utils;
29
30namespace ICSharpCode.NRefactory.CSharp.Refactoring
31{
32  /// <summary>
33  /// Converts from type system to the C# AST.
34  /// </summary>
35  public class TypeSystemAstBuilder
36  {
37    readonly CSharpResolver resolver;
38   
39    #region Constructor
40    /// <summary>
41    /// Creates a new TypeSystemAstBuilder.
42    /// </summary>
43    /// <param name="resolver">
44    /// A resolver initialized for the position where the type will be inserted.
45    /// </param>
46    public TypeSystemAstBuilder(CSharpResolver resolver)
47    {
48      if (resolver == null)
49        throw new ArgumentNullException("resolver");
50      this.resolver = resolver;
51      InitProperties();
52    }
53   
54    /// <summary>
55    /// Creates a new TypeSystemAstBuilder.
56    /// </summary>
57    public TypeSystemAstBuilder()
58    {
59      InitProperties();
60    }
61    #endregion
62   
63    #region Properties
64    void InitProperties()
65    {
66      this.ShowAccessibility = true;
67      this.ShowModifiers = true;
68      this.ShowBaseTypes = true;
69      this.ShowTypeParameters = true;
70      this.ShowTypeParameterConstraints = true;
71      this.ShowParameterNames = true;
72      this.ShowConstantValues = true;
73      this.UseAliases = true;
74    }
75   
76    /// <summary>
77    /// Specifies whether the ast builder should add annotations to type references.
78    /// The default value is <c>false</c>.
79    /// </summary>
80    public bool AddAnnotations { get; set; }
81   
82    /// <summary>
83    /// Controls the accessibility modifiers are shown.
84    /// The default value is <c>true</c>.
85    /// </summary>
86    public bool ShowAccessibility { get; set; }
87   
88    /// <summary>
89    /// Controls the non-accessibility modifiers are shown.
90    /// The default value is <c>true</c>.
91    /// </summary>
92    public bool ShowModifiers { get; set; }
93   
94    /// <summary>
95    /// Controls whether base type references are shown.
96    /// The default value is <c>true</c>.
97    /// </summary>
98    public bool ShowBaseTypes { get; set; }
99   
100    /// <summary>
101    /// Controls whether type parameter declarations are shown.
102    /// The default value is <c>true</c>.
103    /// </summary>
104    public bool ShowTypeParameters { get; set; }
105   
106    /// <summary>
107    /// Controls whether constraints on type parameter declarations are shown.
108    /// Has no effect if ShowTypeParameters is false.
109    /// The default value is <c>true</c>.
110    /// </summary>
111    public bool ShowTypeParameterConstraints { get; set; }
112   
113    /// <summary>
114    /// Controls whether the names of parameters are shown.
115    /// The default value is <c>true</c>.
116    /// </summary>
117    public bool ShowParameterNames { get; set; }
118   
119    /// <summary>
120    /// Controls whether to show default values of optional parameters, and the values of constant fields.
121    /// The default value is <c>true</c>.
122    /// </summary>
123    public bool ShowConstantValues { get; set; }
124   
125    /// <summary>
126    /// Controls whether to use fully-qualified type names or short type names.
127    /// The default value is <c>false</c>.
128    /// </summary>
129    public bool AlwaysUseShortTypeNames { get; set; }
130   
131    /// <summary>
132    /// Controls whether to generate a body that throws a <c>System.NotImplementedException</c>.
133    /// The default value is <c>false</c>.
134    /// </summary>
135    public bool GenerateBody { get; set; }
136   
137    /// <summary>
138    /// Controls whether to generate custom events.
139    /// The default value is <c>false</c>.
140    /// </summary>
141    public bool UseCustomEvents { get; set; }
142
143    /// <summary>
144    /// Controls if unbound type argument names are inserted in the ast or not.
145    /// The default value is <c>false</c>.
146    /// </summary>
147    public bool ConvertUnboundTypeArguments { get; set;}
148
149    /// <summary>
150    /// Controls if aliases should be used inside the type name or not.
151    /// The default value is <c>true</c>.
152    /// </summary>
153    public bool UseAliases { get; set;}
154    #endregion
155   
156    #region Convert Type
157    public AstType ConvertType(IType type)
158    {
159      if (type == null)
160        throw new ArgumentNullException("type");
161      AstType astType = ConvertTypeHelper(type);
162      if (AddAnnotations)
163        astType.AddAnnotation(type);
164      return astType;
165    }
166   
167    public AstType ConvertType(FullTypeName fullTypeName)
168    {
169      if (resolver != null) {
170        foreach (var asm in resolver.Compilation.Assemblies) {
171          var def = asm.GetTypeDefinition(fullTypeName);
172          if (def != null) {
173            return ConvertType(def);
174          }
175        }
176      }
177      TopLevelTypeName top = fullTypeName.TopLevelTypeName;
178      AstType type;
179      if (string.IsNullOrEmpty(top.Namespace)) {
180        type = new SimpleType(top.Name);
181      } else {
182        type = new SimpleType(top.Namespace).MemberType(top.Name);
183      }
184      for (int i = 0; i < fullTypeName.NestingLevel; i++) {
185        type = type.MemberType(fullTypeName.GetNestedTypeName(i));
186      }
187      return type;
188    }
189   
190    AstType ConvertTypeHelper(IType type)
191    {
192      TypeWithElementType typeWithElementType = type as TypeWithElementType;
193      if (typeWithElementType != null) {
194        if (typeWithElementType is PointerType) {
195          return ConvertType(typeWithElementType.ElementType).MakePointerType();
196        } else if (typeWithElementType is ArrayType) {
197          return ConvertType(typeWithElementType.ElementType).MakeArrayType(((ArrayType)type).Dimensions);
198        } else {
199          // e.g. ByReferenceType; not supported as type in C#
200          return ConvertType(typeWithElementType.ElementType);
201        }
202      }
203      ParameterizedType pt = type as ParameterizedType;
204      if (pt != null) {
205        if (pt.Name == "Nullable" && pt.Namespace == "System" && pt.TypeParameterCount == 1) {
206          return ConvertType(pt.TypeArguments[0]).MakeNullableType();
207        }
208        return ConvertTypeHelper(pt.GetDefinition(), pt.TypeArguments);
209      }
210      ITypeDefinition typeDef = type as ITypeDefinition;
211      if (typeDef != null) {
212        if (typeDef.TypeParameterCount > 0) {
213          // Unbound type
214          IType[] typeArguments = new IType[typeDef.TypeParameterCount];
215          for (int i = 0; i < typeArguments.Length; i++) {
216            typeArguments[i] = SpecialType.UnboundTypeArgument;
217          }
218          return ConvertTypeHelper(typeDef, typeArguments);
219        } else {
220          return ConvertTypeHelper(typeDef, EmptyList<IType>.Instance);
221        }
222      }
223      return new SimpleType(type.Name);
224    }
225   
226    AstType ConvertTypeHelper(ITypeDefinition typeDef, IList<IType> typeArguments)
227    {
228      Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount);
229     
230      string keyword = KnownTypeReference.GetCSharpNameByTypeCode(typeDef.KnownTypeCode);
231      if (keyword != null)
232        return new PrimitiveType(keyword);
233     
234      // The number of type parameters belonging to outer classes
235      int outerTypeParameterCount;
236      if (typeDef.DeclaringType != null)
237        outerTypeParameterCount = typeDef.DeclaringType.TypeParameterCount;
238      else
239        outerTypeParameterCount = 0;
240     
241      if (resolver != null) {
242        // Look if there's an alias to the target type
243        if (UseAliases) {
244          for (ResolvedUsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) {
245            foreach (var pair in usingScope.UsingAliases) {
246              if (pair.Value is TypeResolveResult) {
247                if (TypeMatches(pair.Value.Type, typeDef, typeArguments))
248                  return new SimpleType(pair.Key);
249              }
250            }
251          }
252        }
253       
254        IList<IType> localTypeArguments;
255        if (typeDef.TypeParameterCount > outerTypeParameterCount) {
256          localTypeArguments = new IType[typeDef.TypeParameterCount - outerTypeParameterCount];
257          for (int i = 0; i < localTypeArguments.Count; i++) {
258            localTypeArguments[i] = typeArguments[outerTypeParameterCount + i];
259          }
260        } else {
261          localTypeArguments = EmptyList<IType>.Instance;
262        }
263        ResolveResult rr = resolver.ResolveSimpleName(typeDef.Name, localTypeArguments);
264        TypeResolveResult trr = rr as TypeResolveResult;
265        if (trr != null || (localTypeArguments.Count == 0 && resolver.IsVariableReferenceWithSameType(rr, typeDef.Name, out trr))) {
266          if (!trr.IsError && TypeMatches(trr.Type, typeDef, typeArguments)) {
267            // We can use the short type name
268            SimpleType shortResult = new SimpleType(typeDef.Name);
269            AddTypeArguments(shortResult, typeDef, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount);
270            return shortResult;
271          }
272        }
273      }
274     
275      if (AlwaysUseShortTypeNames) {
276        var shortResult = new SimpleType(typeDef.Name);
277        AddTypeArguments(shortResult, typeDef, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount);
278        return shortResult;
279      }
280      MemberType result = new MemberType();
281      if (typeDef.DeclaringTypeDefinition != null) {
282        // Handle nested types
283        result.Target = ConvertTypeHelper(typeDef.DeclaringTypeDefinition, typeArguments);
284      } else {
285        // Handle top-level types
286        if (string.IsNullOrEmpty(typeDef.Namespace)) {
287          result.Target = new SimpleType("global");
288          result.IsDoubleColon = true;
289        } else {
290          result.Target = ConvertNamespace(typeDef.Namespace);
291        }
292      }
293      result.MemberName = typeDef.Name;
294      AddTypeArguments(result, typeDef, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount);
295      return result;
296    }
297   
298    /// <summary>
299    /// Gets whether 'type' is the same as 'typeDef' parameterized with the given type arguments.
300    /// </summary>
301    bool TypeMatches(IType type, ITypeDefinition typeDef, IList<IType> typeArguments)
302    {
303      if (typeDef.TypeParameterCount == 0) {
304        return typeDef.Equals(type);
305      } else {
306        if (!typeDef.Equals(type.GetDefinition()))
307          return false;
308        ParameterizedType pt = type as ParameterizedType;
309        if (pt == null) {
310          return typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument);
311        }
312        var ta = pt.TypeArguments;
313        for (int i = 0; i < ta.Count; i++) {
314          if (!ta[i].Equals(typeArguments[i]))
315            return false;
316        }
317        return true;
318      }
319    }
320   
321    /// <summary>
322    /// Adds type arguments to the result type.
323    /// </summary>
324    /// <param name="result">The result AST node (a SimpleType or MemberType)</param>
325    /// <param name="typeDef">The type definition that owns the type parameters</param>
326    /// <param name="typeArguments">The list of type arguments</param>
327    /// <param name="startIndex">Index of first type argument to add</param>
328    /// <param name="endIndex">Index after last type argument to add</param>
329    void AddTypeArguments(AstType result, ITypeDefinition typeDef, IList<IType> typeArguments, int startIndex, int endIndex)
330    {
331      Debug.Assert(endIndex <= typeDef.TypeParameterCount);
332      for (int i = startIndex; i < endIndex; i++) {
333        if (ConvertUnboundTypeArguments && typeArguments[i].Kind == TypeKind.UnboundTypeArgument) {
334          result.AddChild(new SimpleType(typeDef.TypeParameters[i].Name), Roles.TypeArgument);
335        } else {
336          result.AddChild(ConvertType(typeArguments[i]), Roles.TypeArgument);
337        }
338      }
339    }
340   
341    public AstType ConvertNamespace(string namespaceName)
342    {
343      if (resolver != null) {
344        // Look if there's an alias to the target namespace
345        if (UseAliases) {
346          for (ResolvedUsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) {
347            foreach (var pair in usingScope.UsingAliases) {
348              NamespaceResolveResult nrr = pair.Value as NamespaceResolveResult;
349              if (nrr != null && nrr.NamespaceName == namespaceName)
350                return new SimpleType(pair.Key);
351            }
352          }
353        }
354      }
355     
356      int pos = namespaceName.LastIndexOf('.');
357      if (pos < 0) {
358        if (IsValidNamespace(namespaceName)) {
359          return new SimpleType(namespaceName);
360        } else {
361          return new MemberType {
362            Target = new SimpleType("global"),
363            IsDoubleColon = true,
364            MemberName = namespaceName
365          };
366        }
367      } else {
368        string parentNamespace = namespaceName.Substring(0, pos);
369        string localNamespace = namespaceName.Substring(pos + 1);
370        return new MemberType {
371          Target = ConvertNamespace(parentNamespace),
372          MemberName = localNamespace
373        };
374      }
375    }
376   
377    bool IsValidNamespace(string firstNamespacePart)
378    {
379      if (resolver == null)
380        return true; // just assume namespaces are valid if we don't have a resolver
381      NamespaceResolveResult nrr = resolver.ResolveSimpleName(firstNamespacePart, EmptyList<IType>.Instance) as NamespaceResolveResult;
382      return nrr != null && !nrr.IsError && nrr.NamespaceName == firstNamespacePart;
383    }
384    #endregion
385   
386    #region Convert Attribute
387    public Attribute ConvertAttribute(IAttribute attribute)
388    {
389      Attribute attr = new Attribute();
390      attr.Type = ConvertType(attribute.AttributeType);
391      SimpleType st = attr.Type as SimpleType;
392      MemberType mt = attr.Type as MemberType;
393      if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) {
394        st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - 9);
395      } else if (mt != null && mt.MemberName.EndsWith("Attribute", StringComparison.Ordinal)) {
396        mt.MemberName = mt.MemberName.Substring(0, mt.MemberName.Length - 9);
397      }
398      foreach (ResolveResult arg in attribute.PositionalArguments) {
399        attr.Arguments.Add(ConvertConstantValue(arg));
400      }
401      foreach (var pair in attribute.NamedArguments) {
402        attr.Arguments.Add(new NamedExpression(pair.Key.Name, ConvertConstantValue(pair.Value)));
403      }
404      return attr;
405    }
406    #endregion
407   
408    #region Convert Constant Value
409    public Expression ConvertConstantValue(ResolveResult rr)
410    {
411      if (rr == null)
412        throw new ArgumentNullException("rr");
413      if (rr is ConversionResolveResult) {
414        // unpack ConversionResolveResult if necessary
415        // (e.g. a boxing conversion or string->object reference conversion)
416        rr = ((ConversionResolveResult)rr).Input;
417      }
418     
419      if (rr is TypeOfResolveResult) {
420        return new TypeOfExpression(ConvertType(rr.Type));
421      } else if (rr is ArrayCreateResolveResult) {
422        ArrayCreateResolveResult acrr = (ArrayCreateResolveResult)rr;
423        ArrayCreateExpression ace = new ArrayCreateExpression();
424        ace.Type = ConvertType(acrr.Type);
425        ComposedType composedType = ace.Type as ComposedType;
426        if (composedType != null) {
427          composedType.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
428          if (!composedType.HasNullableSpecifier && composedType.PointerRank == 0)
429            ace.Type = composedType.BaseType;
430        }
431       
432        if (acrr.SizeArguments != null && acrr.InitializerElements == null) {
433          ace.AdditionalArraySpecifiers.FirstOrNullObject().Remove();
434          ace.Arguments.AddRange(acrr.SizeArguments.Select(ConvertConstantValue));
435        }
436        if (acrr.InitializerElements != null) {
437          ArrayInitializerExpression initializer = new ArrayInitializerExpression();
438          initializer.Elements.AddRange(acrr.InitializerElements.Select(ConvertConstantValue));
439          ace.Initializer = initializer;
440        }
441        return ace;
442      } else if (rr.IsCompileTimeConstant) {
443        return ConvertConstantValue(rr.Type, rr.ConstantValue);
444      } else {
445        return new ErrorExpression();
446      }
447    }
448   
449    public Expression ConvertConstantValue(IType type, object constantValue)
450    {
451      if (type == null)
452        throw new ArgumentNullException("type");
453      if (constantValue == null) {
454        if (type.IsReferenceType == true)
455          return new NullReferenceExpression();
456        else
457          return new DefaultValueExpression(ConvertType(type));
458      } else if (type.Kind == TypeKind.Enum) {
459        return ConvertEnumValue(type, (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false));
460      } else {
461        return new PrimitiveExpression(constantValue);
462      }
463    }
464   
465    bool IsFlagsEnum(ITypeDefinition type)
466    {
467      IType flagsAttributeType = type.Compilation.FindType(typeof(System.FlagsAttribute));
468      return type.GetAttribute(flagsAttributeType) != null;
469    }
470   
471    Expression ConvertEnumValue(IType type, long val)
472    {
473      ITypeDefinition enumDefinition = type.GetDefinition();
474      TypeCode enumBaseTypeCode = ReflectionHelper.GetTypeCode(enumDefinition.EnumUnderlyingType);
475      foreach (IField field in enumDefinition.Fields) {
476        if (field.IsConst && object.Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false), val))
477          return ConvertType(type).Member(field.Name);
478      }
479      if (IsFlagsEnum(enumDefinition)) {
480        long enumValue = val;
481        Expression expr = null;
482        long negatedEnumValue = ~val;
483        // limit negatedEnumValue to the appropriate range
484        switch (enumBaseTypeCode) {
485          case TypeCode.Byte:
486          case TypeCode.SByte:
487            negatedEnumValue &= byte.MaxValue;
488            break;
489          case TypeCode.Int16:
490          case TypeCode.UInt16:
491            negatedEnumValue &= ushort.MaxValue;
492            break;
493          case TypeCode.Int32:
494          case TypeCode.UInt32:
495            negatedEnumValue &= uint.MaxValue;
496            break;
497        }
498        Expression negatedExpr = null;
499        foreach (IField field in enumDefinition.Fields.Where(fld => fld.IsConst)) {
500          long fieldValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false);
501          if (fieldValue == 0)
502            continue; // skip None enum value
503
504          if ((fieldValue & enumValue) == fieldValue) {
505            var fieldExpression = ConvertType(type).Member(field.Name);
506            if (expr == null)
507              expr = fieldExpression;
508            else
509              expr = new BinaryOperatorExpression(expr, BinaryOperatorType.BitwiseOr, fieldExpression);
510
511            enumValue &= ~fieldValue;
512          }
513          if ((fieldValue & negatedEnumValue) == fieldValue) {
514            var fieldExpression = ConvertType(type).Member(field.Name);
515            if (negatedExpr == null)
516              negatedExpr = fieldExpression;
517            else
518              negatedExpr = new BinaryOperatorExpression(negatedExpr, BinaryOperatorType.BitwiseOr, fieldExpression);
519
520            negatedEnumValue &= ~fieldValue;
521          }
522        }
523        if (enumValue == 0 && expr != null) {
524          if (!(negatedEnumValue == 0 && negatedExpr != null && negatedExpr.Descendants.Count() < expr.Descendants.Count())) {
525            return expr;
526          }
527        }
528        if (negatedEnumValue == 0 && negatedExpr != null) {
529          return new UnaryOperatorExpression(UnaryOperatorType.BitNot, negatedExpr);
530        }
531      }
532      return new PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(type));
533    }
534   
535    #endregion
536   
537    #region Convert Parameter
538    public ParameterDeclaration ConvertParameter(IParameter parameter)
539    {
540      if (parameter == null)
541        throw new ArgumentNullException("parameter");
542      ParameterDeclaration decl = new ParameterDeclaration();
543      if (parameter.IsRef) {
544        decl.ParameterModifier = ParameterModifier.Ref;
545      } else if (parameter.IsOut) {
546        decl.ParameterModifier = ParameterModifier.Out;
547      } else if (parameter.IsParams) {
548        decl.ParameterModifier = ParameterModifier.Params;
549      }
550      decl.Type = ConvertType(parameter.Type);
551      if (this.ShowParameterNames) {
552        decl.Name = parameter.Name;
553      }
554      if (parameter.IsOptional && this.ShowConstantValues) {
555        decl.DefaultExpression = ConvertConstantValue(parameter.Type, parameter.ConstantValue);
556      }
557      return decl;
558    }
559    #endregion
560   
561    #region Convert Entity
562    public AstNode ConvertSymbol(ISymbol symbol)
563    {
564      if (symbol == null)
565        throw new ArgumentNullException("symbol");
566      switch (symbol.SymbolKind) {
567        case SymbolKind.Namespace:
568          return ConvertNamespaceDeclaration((INamespace)symbol);
569        case SymbolKind.Variable:
570          return ConvertVariable((IVariable)symbol);
571        case SymbolKind.Parameter:
572          return ConvertParameter((IParameter)symbol);
573        case SymbolKind.TypeParameter:
574          return ConvertTypeParameter((ITypeParameter)symbol);
575        default:
576          IEntity entity = symbol as IEntity;
577          if (entity != null)
578            return ConvertEntity(entity);
579          throw new ArgumentException("Invalid value for SymbolKind: " + symbol.SymbolKind);
580      }
581    }
582   
583    public EntityDeclaration ConvertEntity(IEntity entity)
584    {
585      if (entity == null)
586        throw new ArgumentNullException("entity");
587      switch (entity.SymbolKind) {
588        case SymbolKind.TypeDefinition:
589          return ConvertTypeDefinition((ITypeDefinition)entity);
590        case SymbolKind.Field:
591          return ConvertField((IField)entity);
592        case SymbolKind.Property:
593          return ConvertProperty((IProperty)entity);
594        case SymbolKind.Indexer:
595          return ConvertIndexer((IProperty)entity);
596        case SymbolKind.Event:
597          return ConvertEvent((IEvent)entity);
598        case SymbolKind.Method:
599          return ConvertMethod((IMethod)entity);
600        case SymbolKind.Operator:
601          return ConvertOperator((IMethod)entity);
602        case SymbolKind.Constructor:
603          return ConvertConstructor((IMethod)entity);
604        case SymbolKind.Destructor:
605          return ConvertDestructor((IMethod)entity);
606        case SymbolKind.Accessor:
607          IMethod accessor = (IMethod)entity;
608          return ConvertAccessor(accessor, accessor.AccessorOwner != null ? accessor.AccessorOwner.Accessibility : Accessibility.None);
609        default:
610          throw new ArgumentException("Invalid value for SymbolKind: " + entity.SymbolKind);
611      }
612    }
613   
614    EntityDeclaration ConvertTypeDefinition(ITypeDefinition typeDefinition)
615    {
616      Modifiers modifiers = Modifiers.None;
617      if (this.ShowAccessibility) {
618        modifiers |= ModifierFromAccessibility(typeDefinition.Accessibility);
619      }
620      if (this.ShowModifiers) {
621        if (typeDefinition.IsStatic) {
622          modifiers |= Modifiers.Static;
623        } else if (typeDefinition.IsAbstract) {
624          modifiers |= Modifiers.Abstract;
625        } else if (typeDefinition.IsSealed) {
626          modifiers |= Modifiers.Sealed;
627        }
628        if (typeDefinition.IsShadowing) {
629          modifiers |= Modifiers.New;
630        }
631      }
632     
633      ClassType classType;
634      switch (typeDefinition.Kind) {
635        case TypeKind.Struct:
636          classType = ClassType.Struct;
637          modifiers &= ~Modifiers.Sealed;
638          break;
639        case TypeKind.Enum:
640          classType = ClassType.Enum;
641          modifiers &= ~Modifiers.Sealed;
642          break;
643        case TypeKind.Interface:
644          classType = ClassType.Interface;
645          modifiers &= ~Modifiers.Abstract;
646          break;
647        case TypeKind.Delegate:
648          IMethod invoke = typeDefinition.GetDelegateInvokeMethod();
649          if (invoke != null) {
650            return ConvertDelegate(invoke, modifiers);
651          } else {
652            goto default;
653          }
654        default:
655          classType = ClassType.Class;
656          break;
657      }
658     
659      var decl = new TypeDeclaration();
660      decl.ClassType = classType;
661      decl.Modifiers = modifiers;
662      decl.Name = typeDefinition.Name;
663     
664      int outerTypeParameterCount = (typeDefinition.DeclaringTypeDefinition == null) ? 0 : typeDefinition.DeclaringTypeDefinition.TypeParameterCount;
665     
666      if (this.ShowTypeParameters) {
667        foreach (ITypeParameter tp in typeDefinition.TypeParameters.Skip(outerTypeParameterCount)) {
668          decl.TypeParameters.Add(ConvertTypeParameter(tp));
669        }
670      }
671     
672      if (this.ShowBaseTypes) {
673        foreach (IType baseType in typeDefinition.DirectBaseTypes) {
674          decl.BaseTypes.Add(ConvertType(baseType));
675        }
676      }
677     
678      if (this.ShowTypeParameters && this.ShowTypeParameterConstraints) {
679        foreach (ITypeParameter tp in typeDefinition.TypeParameters) {
680          var constraint = ConvertTypeParameterConstraint(tp);
681          if (constraint != null)
682            decl.Constraints.Add(constraint);
683        }
684      }
685      return decl;
686    }
687   
688    DelegateDeclaration ConvertDelegate(IMethod invokeMethod, Modifiers modifiers)
689    {
690      ITypeDefinition d = invokeMethod.DeclaringTypeDefinition;
691     
692      DelegateDeclaration decl = new DelegateDeclaration();
693      decl.Modifiers = modifiers & ~Modifiers.Sealed;
694      decl.ReturnType = ConvertType(invokeMethod.ReturnType);
695      decl.Name = d.Name;
696     
697      if (this.ShowTypeParameters) {
698        foreach (ITypeParameter tp in d.TypeParameters) {
699          decl.TypeParameters.Add(ConvertTypeParameter(tp));
700        }
701      }
702     
703      foreach (IParameter p in invokeMethod.Parameters) {
704        decl.Parameters.Add(ConvertParameter(p));
705      }
706     
707      if (this.ShowTypeParameters && this.ShowTypeParameterConstraints) {
708        foreach (ITypeParameter tp in d.TypeParameters) {
709          var constraint = ConvertTypeParameterConstraint(tp);
710          if (constraint != null)
711            decl.Constraints.Add(constraint);
712        }
713      }
714      return decl;
715    }
716   
717    FieldDeclaration ConvertField(IField field)
718    {
719      FieldDeclaration decl = new FieldDeclaration();
720      if (ShowModifiers) {
721        Modifiers m = GetMemberModifiers(field);
722        if (field.IsConst) {
723          m &= ~Modifiers.Static;
724          m |= Modifiers.Const;
725        } else if (field.IsReadOnly) {
726          m |= Modifiers.Readonly;
727        } else if (field.IsVolatile) {
728          m |= Modifiers.Volatile;
729        }
730        decl.Modifiers = m;
731      }
732      decl.ReturnType = ConvertType(field.ReturnType);
733      Expression initializer = null;
734      if (field.IsConst && this.ShowConstantValues)
735        initializer = ConvertConstantValue(field.Type, field.ConstantValue);
736      decl.Variables.Add(new VariableInitializer(field.Name, initializer));
737      return decl;
738    }
739   
740    BlockStatement GenerateBodyBlock()
741    {
742      if (GenerateBody) {
743        return new BlockStatement {
744          new ThrowStatement(new ObjectCreateExpression(ConvertType(new TopLevelTypeName("System", "NotImplementedException", 0))))
745        };
746      } else {
747        return BlockStatement.Null;
748      }
749    }
750   
751    Accessor ConvertAccessor(IMethod accessor, Accessibility ownerAccessibility)
752    {
753      if (accessor == null)
754        return Accessor.Null;
755      Accessor decl = new Accessor();
756      if (this.ShowAccessibility && accessor.Accessibility != ownerAccessibility)
757        decl.Modifiers = ModifierFromAccessibility(accessor.Accessibility);
758      decl.Body = GenerateBodyBlock();
759      return decl;
760    }
761   
762    PropertyDeclaration ConvertProperty(IProperty property)
763    {
764      PropertyDeclaration decl = new PropertyDeclaration();
765      decl.Modifiers = GetMemberModifiers(property);
766      decl.ReturnType = ConvertType(property.ReturnType);
767      decl.Name = property.Name;
768      decl.Getter = ConvertAccessor(property.Getter, property.Accessibility);
769      decl.Setter = ConvertAccessor(property.Setter, property.Accessibility);
770      return decl;
771    }
772   
773    IndexerDeclaration ConvertIndexer(IProperty indexer)
774    {
775      IndexerDeclaration decl = new IndexerDeclaration();
776      decl.Modifiers = GetMemberModifiers(indexer);
777      decl.ReturnType = ConvertType(indexer.ReturnType);
778      foreach (IParameter p in indexer.Parameters) {
779        decl.Parameters.Add(ConvertParameter(p));
780      }
781      decl.Getter = ConvertAccessor(indexer.Getter, indexer.Accessibility);
782      decl.Setter = ConvertAccessor(indexer.Setter, indexer.Accessibility);
783      return decl;
784    }
785   
786    EntityDeclaration ConvertEvent(IEvent ev)
787    {
788      if (this.UseCustomEvents) {
789        CustomEventDeclaration decl = new CustomEventDeclaration();
790        decl.Modifiers = GetMemberModifiers(ev);
791        decl.ReturnType = ConvertType(ev.ReturnType);
792        decl.Name = ev.Name;
793        decl.AddAccessor    = ConvertAccessor(ev.AddAccessor, ev.Accessibility);
794        decl.RemoveAccessor = ConvertAccessor(ev.RemoveAccessor, ev.Accessibility);
795        return decl;
796      } else {
797        EventDeclaration decl = new EventDeclaration();
798        decl.Modifiers = GetMemberModifiers(ev);
799        decl.ReturnType = ConvertType(ev.ReturnType);
800        decl.Variables.Add(new VariableInitializer(ev.Name));
801        return decl;
802      }
803    }
804   
805    MethodDeclaration ConvertMethod(IMethod method)
806    {
807      MethodDeclaration decl = new MethodDeclaration();
808      decl.Modifiers = GetMemberModifiers(method);
809      if (method.IsAsync && ShowModifiers)
810        decl.Modifiers |= Modifiers.Async;
811      decl.ReturnType = ConvertType(method.ReturnType);
812      decl.Name = method.Name;
813     
814      if (this.ShowTypeParameters) {
815        foreach (ITypeParameter tp in method.TypeParameters) {
816          decl.TypeParameters.Add(ConvertTypeParameter(tp));
817        }
818      }
819     
820      foreach (IParameter p in method.Parameters) {
821        decl.Parameters.Add(ConvertParameter(p));
822      }
823      if (method.IsExtensionMethod && method.ReducedFrom == null && decl.Parameters.Any() && decl.Parameters.First().ParameterModifier == ParameterModifier.None)
824        decl.Parameters.First().ParameterModifier = ParameterModifier.This;
825     
826      if (this.ShowTypeParameters && this.ShowTypeParameterConstraints && !method.IsOverride && !method.IsExplicitInterfaceImplementation) {
827        foreach (ITypeParameter tp in method.TypeParameters) {
828          var constraint = ConvertTypeParameterConstraint(tp);
829          if (constraint != null)
830            decl.Constraints.Add(constraint);
831        }
832      }
833      decl.Body = GenerateBodyBlock();
834      return decl;
835    }
836   
837    EntityDeclaration ConvertOperator(IMethod op)
838    {
839      OperatorType? opType = OperatorDeclaration.GetOperatorType(op.Name);
840      if (opType == null)
841        return ConvertMethod(op);
842     
843      OperatorDeclaration decl = new OperatorDeclaration();
844      decl.Modifiers = GetMemberModifiers(op);
845      decl.OperatorType = opType.Value;
846      decl.ReturnType = ConvertType(op.ReturnType);
847      foreach (IParameter p in op.Parameters) {
848        decl.Parameters.Add(ConvertParameter(p));
849      }
850      decl.Body = GenerateBodyBlock();
851      return decl;
852    }
853   
854    ConstructorDeclaration ConvertConstructor(IMethod ctor)
855    {
856      ConstructorDeclaration decl = new ConstructorDeclaration();
857      decl.Modifiers = GetMemberModifiers(ctor);
858      if (ctor.DeclaringTypeDefinition != null)
859        decl.Name = ctor.DeclaringTypeDefinition.Name;
860      foreach (IParameter p in ctor.Parameters) {
861        decl.Parameters.Add(ConvertParameter(p));
862      }
863      decl.Body = GenerateBodyBlock();
864      return decl;
865    }
866   
867    DestructorDeclaration ConvertDestructor(IMethod dtor)
868    {
869      DestructorDeclaration decl = new DestructorDeclaration();
870      if (dtor.DeclaringTypeDefinition != null)
871        decl.Name = dtor.DeclaringTypeDefinition.Name;
872      decl.Body = GenerateBodyBlock();
873      return decl;
874    }
875    #endregion
876   
877    #region Convert Modifiers
878    public static Modifiers ModifierFromAccessibility(Accessibility accessibility)
879    {
880      switch (accessibility) {
881        case Accessibility.Private:
882          return Modifiers.Private;
883        case Accessibility.Public:
884          return Modifiers.Public;
885        case Accessibility.Protected:
886          return Modifiers.Protected;
887        case Accessibility.Internal:
888          return Modifiers.Internal;
889        case Accessibility.ProtectedOrInternal:
890        case Accessibility.ProtectedAndInternal:
891          return Modifiers.Protected | Modifiers.Internal;
892        default:
893          return Modifiers.None;
894      }
895    }
896   
897    Modifiers GetMemberModifiers(IMember member)
898    {
899      bool isInterfaceMember = member.DeclaringType.Kind == TypeKind.Interface;
900      Modifiers m = Modifiers.None;
901      if (this.ShowAccessibility && !isInterfaceMember) {
902        m |= ModifierFromAccessibility(member.Accessibility);
903      }
904      if (this.ShowModifiers) {
905        if (member.IsStatic) {
906          m |= Modifiers.Static;
907        } else {
908          if (member.IsAbstract && !isInterfaceMember)
909            m |= Modifiers.Abstract;
910          if (member.IsOverride)
911            m |= Modifiers.Override;
912          if (member.IsVirtual && !member.IsAbstract && !member.IsOverride)
913            m |= Modifiers.Virtual;
914          if (member.IsSealed)
915            m |= Modifiers.Sealed;
916        }
917        if (member.IsShadowing)
918          m |= Modifiers.New;
919      }
920      return m;
921    }
922    #endregion
923   
924    #region Convert Type Parameter
925    TypeParameterDeclaration ConvertTypeParameter(ITypeParameter tp)
926    {
927      TypeParameterDeclaration decl = new TypeParameterDeclaration();
928      decl.Variance = tp.Variance;
929      decl.Name = tp.Name;
930      return decl;
931    }
932   
933    Constraint ConvertTypeParameterConstraint(ITypeParameter tp)
934    {
935      if (!tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint && tp.DirectBaseTypes.All(IsObjectOrValueType)) {
936        return null;
937      }
938      Constraint c = new Constraint();
939      c.TypeParameter = new SimpleType (tp.Name);
940      if (tp.HasReferenceTypeConstraint) {
941        c.BaseTypes.Add(new PrimitiveType("class"));
942      } else if (tp.HasValueTypeConstraint) {
943        c.BaseTypes.Add(new PrimitiveType("struct"));
944      }
945      foreach (IType t in tp.DirectBaseTypes) {
946        if (!IsObjectOrValueType(t))
947          c.BaseTypes.Add(ConvertType(t));
948      }
949      if (tp.HasDefaultConstructorConstraint) {
950        c.BaseTypes.Add(new PrimitiveType("new"));
951      }
952      return c;
953    }
954   
955    static bool IsObjectOrValueType(IType type)
956    {
957      ITypeDefinition d = type.GetDefinition();
958      return d != null && (d.KnownTypeCode == KnownTypeCode.Object || d.KnownTypeCode == KnownTypeCode.ValueType);
959    }
960    #endregion
961   
962    #region Convert Variable
963    public VariableDeclarationStatement ConvertVariable(IVariable v)
964    {
965      VariableDeclarationStatement decl = new VariableDeclarationStatement();
966      decl.Modifiers = v.IsConst ? Modifiers.Const : Modifiers.None;
967      decl.Type = ConvertType(v.Type);
968      Expression initializer = null;
969      if (v.IsConst)
970        initializer = ConvertConstantValue(v.Type, v.ConstantValue);
971      decl.Variables.Add(new VariableInitializer(v.Name, initializer));
972      return decl;
973    }
974    #endregion
975   
976    NamespaceDeclaration ConvertNamespaceDeclaration(INamespace ns)
977    {
978      return new NamespaceDeclaration(ns.FullName);
979    }
980  }
981}
Note: See TracBrowser for help on using the repository browser.