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/ConstantValues.cs @ 11700

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

#2077: created branch and added first version

File size: 16.8 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.Linq;
22using ICSharpCode.NRefactory.CSharp.Analysis;
23using ICSharpCode.NRefactory.CSharp.Resolver;
24using ICSharpCode.NRefactory.Semantics;
25using ICSharpCode.NRefactory.TypeSystem;
26using ICSharpCode.NRefactory.TypeSystem.Implementation;
27using ICSharpCode.NRefactory.Utils;
28
29namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues
30{
31  // Contains representations for constant C# expressions.
32  // We use these instead of storing the full AST to reduce the memory usage.
33 
34  [Serializable]
35  public abstract class ConstantExpression : IConstantValue
36  {
37    public abstract ResolveResult Resolve(CSharpResolver resolver);
38   
39    public ResolveResult Resolve(ITypeResolveContext context)
40    {
41      var csContext = (CSharpTypeResolveContext)context;
42      if (context.CurrentAssembly != context.Compilation.MainAssembly) {
43        // The constant needs to be resolved in a different compilation.
44        IProjectContent pc = context.CurrentAssembly as IProjectContent;
45        if (pc != null) {
46          ICompilation nestedCompilation = context.Compilation.SolutionSnapshot.GetCompilation(pc);
47          if (nestedCompilation != null) {
48            var nestedContext = MapToNestedCompilation(csContext, nestedCompilation);
49            ResolveResult rr = Resolve(new CSharpResolver(nestedContext));
50            return MapToNewContext(rr, context);
51          }
52        }
53      }
54      // Resolve in current context.
55      return Resolve(new CSharpResolver(csContext));
56    }
57   
58    CSharpTypeResolveContext MapToNestedCompilation(CSharpTypeResolveContext context, ICompilation nestedCompilation)
59    {
60      var nestedContext = new CSharpTypeResolveContext(nestedCompilation.MainAssembly);
61      if (context.CurrentUsingScope != null) {
62        nestedContext = nestedContext.WithUsingScope(context.CurrentUsingScope.UnresolvedUsingScope.Resolve(nestedCompilation));
63      }
64      if (context.CurrentTypeDefinition != null) {
65        nestedContext = nestedContext.WithCurrentTypeDefinition(nestedCompilation.Import(context.CurrentTypeDefinition));
66      }
67      return nestedContext;
68    }
69   
70    static ResolveResult MapToNewContext(ResolveResult rr, ITypeResolveContext newContext)
71    {
72      if (rr is TypeOfResolveResult) {
73        return new TypeOfResolveResult(
74          rr.Type.ToTypeReference().Resolve(newContext),
75          ((TypeOfResolveResult)rr).ReferencedType.ToTypeReference().Resolve(newContext));
76      } else if (rr is ArrayCreateResolveResult) {
77        ArrayCreateResolveResult acrr = (ArrayCreateResolveResult)rr;
78        return new ArrayCreateResolveResult(
79          acrr.Type.ToTypeReference().Resolve(newContext),
80          MapToNewContext(acrr.SizeArguments, newContext),
81          MapToNewContext(acrr.InitializerElements, newContext));
82      } else if (rr.IsCompileTimeConstant) {
83        return new ConstantResolveResult(
84          rr.Type.ToTypeReference().Resolve(newContext),
85          rr.ConstantValue
86        );
87      } else {
88        return new ErrorResolveResult(rr.Type.ToTypeReference().Resolve(newContext));
89      }
90    }
91   
92    static ResolveResult[] MapToNewContext(IList<ResolveResult> input, ITypeResolveContext newContext)
93    {
94      if (input == null)
95        return null;
96      ResolveResult[] output = new ResolveResult[input.Count];
97      for (int i = 0; i < output.Length; i++) {
98        output[i] = MapToNewContext(input[i], newContext);
99      }
100      return output;
101    }
102  }
103 
104  /// <summary>
105  /// Used for constants that could not be converted to IConstantValue.
106  /// </summary>
107  [Serializable]
108  public sealed class ErrorConstantValue : IConstantValue
109  {
110    readonly ITypeReference type;
111   
112    public ErrorConstantValue(ITypeReference type)
113    {
114      if (type == null)
115        throw new ArgumentNullException("type");
116      this.type = type;
117    }
118   
119    public ResolveResult Resolve(ITypeResolveContext context)
120    {
121      return new ErrorResolveResult(type.Resolve(context));
122    }
123  }
124 
125  /// <summary>
126  /// Increments an integer <see cref="IConstantValue"/> by a fixed amount without changing the type.
127  /// </summary>
128  [Serializable]
129  public sealed class IncrementConstantValue : IConstantValue, ISupportsInterning
130  {
131    readonly IConstantValue baseValue;
132    readonly int incrementAmount;
133   
134    public IncrementConstantValue(IConstantValue baseValue, int incrementAmount = 1)
135    {
136      if (baseValue == null)
137        throw new ArgumentNullException("baseValue");
138      IncrementConstantValue icv = baseValue as IncrementConstantValue;
139      if (icv != null) {
140        this.baseValue = icv.baseValue;
141        this.incrementAmount = icv.incrementAmount + incrementAmount;
142      } else {
143        this.baseValue = baseValue;
144        this.incrementAmount = incrementAmount;
145      }
146    }
147   
148    public ResolveResult Resolve(ITypeResolveContext context)
149    {
150      ResolveResult rr = baseValue.Resolve(context);
151      if (rr.IsCompileTimeConstant && rr.ConstantValue != null) {
152        object val = rr.ConstantValue;
153        TypeCode typeCode = Type.GetTypeCode(val.GetType());
154        if (typeCode >= TypeCode.SByte && typeCode <= TypeCode.UInt64) {
155          long intVal = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false);
156          object newVal = CSharpPrimitiveCast.Cast(typeCode, unchecked(intVal + incrementAmount), false);
157          return new ConstantResolveResult(rr.Type, newVal);
158        }
159      }
160      return new ErrorResolveResult(rr.Type);
161    }
162   
163    int ISupportsInterning.GetHashCodeForInterning()
164    {
165      unchecked {
166        return baseValue.GetHashCode() * 33 ^ incrementAmount;
167      }
168    }
169   
170    bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
171    {
172      IncrementConstantValue o = other as IncrementConstantValue;
173      return o != null && baseValue == o.baseValue && incrementAmount == o.incrementAmount;
174    }
175  }
176 
177  /// <summary>
178  /// C#'s equivalent to the SimpleConstantValue.
179  /// </summary>
180  [Serializable]
181  public sealed class PrimitiveConstantExpression : ConstantExpression, ISupportsInterning
182  {
183    readonly ITypeReference type;
184    readonly object value;
185   
186    public ITypeReference Type {
187      get { return type; }
188    }
189   
190    public object Value {
191      get { return value; }
192    }
193   
194    public PrimitiveConstantExpression(ITypeReference type, object value)
195    {
196      if (type == null)
197        throw new ArgumentNullException("type");
198      this.type = type;
199      this.value = value;
200    }
201   
202    public override ResolveResult Resolve(CSharpResolver resolver)
203    {
204      return new ConstantResolveResult(type.Resolve(resolver.CurrentTypeResolveContext), value);
205    }
206   
207    int ISupportsInterning.GetHashCodeForInterning()
208    {
209      return type.GetHashCode() ^ (value != null ? value.GetHashCode() : 0);
210    }
211   
212    bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
213    {
214      PrimitiveConstantExpression scv = other as PrimitiveConstantExpression;
215      return scv != null && type == scv.type && value == scv.value;
216    }
217  }
218 
219  [Serializable]
220  public sealed class TypeOfConstantExpression : ConstantExpression
221  {
222    readonly ITypeReference type;
223   
224    public ITypeReference Type {
225      get { return type; }
226    }
227   
228    public TypeOfConstantExpression(ITypeReference type)
229    {
230      this.type = type;
231    }
232   
233    public override ResolveResult Resolve(CSharpResolver resolver)
234    {
235      return resolver.ResolveTypeOf(type.Resolve(resolver.CurrentTypeResolveContext));
236    }
237  }
238 
239  [Serializable]
240  public sealed class ConstantCast : ConstantExpression, ISupportsInterning
241  {
242    readonly ITypeReference targetType;
243    readonly ConstantExpression expression;
244    readonly bool allowNullableConstants;
245   
246    public ConstantCast(ITypeReference targetType, ConstantExpression expression, bool allowNullableConstants)
247    {
248      if (targetType == null)
249        throw new ArgumentNullException("targetType");
250      if (expression == null)
251        throw new ArgumentNullException("expression");
252      this.targetType = targetType;
253      this.expression = expression;
254      this.allowNullableConstants = allowNullableConstants;
255    }
256   
257    public override ResolveResult Resolve(CSharpResolver resolver)
258    {
259      var type = targetType.Resolve(resolver.CurrentTypeResolveContext);
260      var resolveResult = expression.Resolve(resolver);
261      if (allowNullableConstants && NullableType.IsNullable(type)) {
262        resolveResult = resolver.ResolveCast(NullableType.GetUnderlyingType(type), resolveResult);
263        if (resolveResult.IsCompileTimeConstant)
264          return new ConstantResolveResult(type, resolveResult.ConstantValue);
265      }
266      return resolver.ResolveCast(type, resolveResult);
267    }
268   
269    int ISupportsInterning.GetHashCodeForInterning()
270    {
271      unchecked {
272        return targetType.GetHashCode() + expression.GetHashCode() * 1018829;
273      }
274    }
275   
276    bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
277    {
278      ConstantCast cast = other as ConstantCast;
279      return cast != null
280        && this.targetType == cast.targetType && this.expression == cast.expression && this.allowNullableConstants == cast.allowNullableConstants;
281    }
282  }
283 
284  [Serializable]
285  public sealed class ConstantIdentifierReference : ConstantExpression
286  {
287    readonly string identifier;
288    readonly IList<ITypeReference> typeArguments;
289   
290    public ConstantIdentifierReference(string identifier, IList<ITypeReference> typeArguments = null)
291    {
292      if (identifier == null)
293        throw new ArgumentNullException("identifier");
294      this.identifier = identifier;
295      this.typeArguments = typeArguments ?? EmptyList<ITypeReference>.Instance;
296    }
297   
298    public override ResolveResult Resolve(CSharpResolver resolver)
299    {
300      return resolver.ResolveSimpleName(identifier, typeArguments.Resolve(resolver.CurrentTypeResolveContext));
301    }
302  }
303 
304  [Serializable]
305  public sealed class ConstantMemberReference : ConstantExpression
306  {
307    readonly ITypeReference targetType;
308    readonly ConstantExpression targetExpression;
309    readonly string memberName;
310    readonly IList<ITypeReference> typeArguments;
311   
312    public ConstantMemberReference(ITypeReference targetType, string memberName, IList<ITypeReference> typeArguments = null)
313    {
314      if (targetType == null)
315        throw new ArgumentNullException("targetType");
316      if (memberName == null)
317        throw new ArgumentNullException("memberName");
318      this.targetType = targetType;
319      this.memberName = memberName;
320      this.typeArguments = typeArguments ?? EmptyList<ITypeReference>.Instance;
321    }
322   
323    public ConstantMemberReference(ConstantExpression targetExpression, string memberName, IList<ITypeReference> typeArguments = null)
324    {
325      if (targetExpression == null)
326        throw new ArgumentNullException("targetExpression");
327      if (memberName == null)
328        throw new ArgumentNullException("memberName");
329      this.targetExpression = targetExpression;
330      this.memberName = memberName;
331      this.typeArguments = typeArguments ?? EmptyList<ITypeReference>.Instance;
332    }
333   
334    public override ResolveResult Resolve(CSharpResolver resolver)
335    {
336      ResolveResult rr;
337      if (targetType != null)
338        rr = new TypeResolveResult(targetType.Resolve(resolver.CurrentTypeResolveContext));
339      else
340        rr = targetExpression.Resolve(resolver);
341      return resolver.ResolveMemberAccess(rr, memberName, typeArguments.Resolve(resolver.CurrentTypeResolveContext));
342    }
343  }
344 
345  [Serializable]
346  public sealed class ConstantCheckedExpression : ConstantExpression
347  {
348    readonly bool checkForOverflow;
349    readonly ConstantExpression expression;
350   
351    public ConstantCheckedExpression(bool checkForOverflow, ConstantExpression expression)
352    {
353      if (expression == null)
354        throw new ArgumentNullException("expression");
355      this.checkForOverflow = checkForOverflow;
356      this.expression = expression;
357    }
358   
359    public override ResolveResult Resolve(CSharpResolver resolver)
360    {
361      return expression.Resolve(resolver.WithCheckForOverflow(checkForOverflow));
362    }
363  }
364 
365  [Serializable]
366  public sealed class ConstantDefaultValue : ConstantExpression, ISupportsInterning
367  {
368    readonly ITypeReference type;
369   
370    public ConstantDefaultValue(ITypeReference type)
371    {
372      if (type == null)
373        throw new ArgumentNullException("type");
374      this.type = type;
375    }
376   
377    public override ResolveResult Resolve(CSharpResolver resolver)
378    {
379      return resolver.ResolveDefaultValue(type.Resolve(resolver.CurrentTypeResolveContext));
380    }
381   
382    int ISupportsInterning.GetHashCodeForInterning()
383    {
384      return type.GetHashCode();
385    }
386   
387    bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
388    {
389      ConstantDefaultValue o = other as ConstantDefaultValue;
390      return o != null && this.type == o.type;
391    }
392  }
393 
394  [Serializable]
395  public sealed class ConstantUnaryOperator : ConstantExpression
396  {
397    readonly UnaryOperatorType operatorType;
398    readonly ConstantExpression expression;
399   
400    public ConstantUnaryOperator(UnaryOperatorType operatorType, ConstantExpression expression)
401    {
402      if (expression == null)
403        throw new ArgumentNullException("expression");
404      this.operatorType = operatorType;
405      this.expression = expression;
406    }
407   
408    public override ResolveResult Resolve(CSharpResolver resolver)
409    {
410      return resolver.ResolveUnaryOperator(operatorType, expression.Resolve(resolver));
411    }
412  }
413
414  [Serializable]
415  public sealed class ConstantBinaryOperator : ConstantExpression
416  {
417    readonly ConstantExpression left;
418    readonly BinaryOperatorType operatorType;
419    readonly ConstantExpression right;
420   
421    public ConstantBinaryOperator(ConstantExpression left, BinaryOperatorType operatorType, ConstantExpression right)
422    {
423      if (left == null)
424        throw new ArgumentNullException("left");
425      if (right == null)
426        throw new ArgumentNullException("right");
427      this.left = left;
428      this.operatorType = operatorType;
429      this.right = right;
430    }
431   
432    public override ResolveResult Resolve(CSharpResolver resolver)
433    {
434      ResolveResult lhs = left.Resolve(resolver);
435      ResolveResult rhs = right.Resolve(resolver);
436      return resolver.ResolveBinaryOperator(operatorType, lhs, rhs);
437    }
438  }
439 
440  [Serializable]
441  public sealed class ConstantConditionalOperator : ConstantExpression
442  {
443    readonly ConstantExpression condition, trueExpr, falseExpr;
444   
445    public ConstantConditionalOperator(ConstantExpression condition, ConstantExpression trueExpr, ConstantExpression falseExpr)
446    {
447      if (condition == null)
448        throw new ArgumentNullException("condition");
449      if (trueExpr == null)
450        throw new ArgumentNullException("trueExpr");
451      if (falseExpr == null)
452        throw new ArgumentNullException("falseExpr");
453      this.condition = condition;
454      this.trueExpr = trueExpr;
455      this.falseExpr = falseExpr;
456    }
457   
458    public override ResolveResult Resolve(CSharpResolver resolver)
459    {
460      return resolver.ResolveConditional(
461        condition.Resolve(resolver),
462        trueExpr.Resolve(resolver),
463        falseExpr.Resolve(resolver)
464      );
465    }
466  }
467 
468  /// <summary>
469  /// Represents an array creation (as used within an attribute argument)
470  /// </summary>
471  [Serializable]
472  public sealed class ConstantArrayCreation : ConstantExpression
473  {
474    // type may be null when the element is being inferred
475    readonly ITypeReference elementType;
476    readonly IList<ConstantExpression> arrayElements;
477   
478    public ConstantArrayCreation(ITypeReference type, IList<ConstantExpression> arrayElements)
479    {
480      if (arrayElements == null)
481        throw new ArgumentNullException("arrayElements");
482      this.elementType = type;
483      this.arrayElements = arrayElements;
484    }
485   
486    public override ResolveResult Resolve(CSharpResolver resolver)
487    {
488      ResolveResult[] elements = new ResolveResult[arrayElements.Count];
489      for (int i = 0; i < elements.Length; i++) {
490        elements[i] = arrayElements[i].Resolve(resolver);
491      }
492      int[] sizeArguments = { elements.Length };
493      if (elementType != null) {
494        return resolver.ResolveArrayCreation(elementType.Resolve(resolver.CurrentTypeResolveContext), sizeArguments, elements);
495      } else {
496        return resolver.ResolveArrayCreation(null, sizeArguments, elements);
497      }
498    }
499  }
500
501  /// <summary>
502  /// Used for sizeof() expressions in constants.
503  /// </summary>
504  [Serializable]
505  public sealed class SizeOfConstantValue : ConstantExpression
506  {
507    readonly ITypeReference type;
508   
509    public SizeOfConstantValue(ITypeReference type)
510    {
511      if (type == null)
512        throw new ArgumentNullException("type");
513      this.type = type;
514    }
515   
516    public override ResolveResult Resolve(CSharpResolver resolver)
517    {
518      return resolver.ResolveSizeOf(type.Resolve(resolver.CurrentTypeResolveContext));
519    }
520  }
521}
Note: See TracBrowser for help on using the repository browser.