예제 #1
0
        private static void CheckIteratorOverloading(
            string source,
            Func <MethodSymbol, bool> isDesiredOverload
            )
        {
            var comp1 = CreateCompilation(source, options: TestOptions.DebugDll);
            var ref1  = comp1.EmitToImageReference();
            var comp2 = CreateCompilation("", new[] { ref1 }, options: TestOptions.DebugDll);

            var originalType   = comp2.GlobalNamespace.GetMember <NamedTypeSymbol>("C");
            var iteratorMethod = originalType
                                 .GetMembers("M")
                                 .OfType <MethodSymbol>()
                                 .Single(isDesiredOverload);

            var stateMachineType = originalType
                                   .GetMembers()
                                   .OfType <NamedTypeSymbol>()
                                   .Single(t => GeneratedNames.GetKind(t.Name) == GeneratedNameKind.StateMachineType);
            var moveNextMethod = stateMachineType.GetMember <MethodSymbol>("MoveNext");

            var guessedIterator = CompilationContext.GetSubstitutedSourceMethod(
                moveNextMethod,
                sourceMethodMustBeInstance: true
                );

            Assert.Equal(iteratorMethod, guessedIterator.OriginalDefinition);
        }
예제 #2
0
        public void LambdaLocations_Static()
        {
            var source = @"
using System;

class C
{
    static int f = ((Func<int, int>)(x => ((Func<int>)(() => x + 2))() + x))(1);

    static C()
    {
        int l = ((Func<int, int>)(x => ((Func<int>)(() => x + 4))() + x))(1);
    }

    static int P
    {
        get
        {
            return ((Func<int, int>)(x => ((Func<int>)(() => x + 7))() + x))(1);
        }
        set
        {
            value = ((Func<int, int>)(x => ((Func<int>)(() => x + 8))() + x))(1);
        }
    }

    static event Action E
    {
        add
        {
            int l = ((Func<int, int>)(x => ((Func<int>)(() => x + 11))() + x))(1);
        }
        remove
        {
            int l = ((Func<int, int>)(x => ((Func<int>)(() => x + 12))() + x))(1);
        }
    }
}
";

            var comp    = CreateCompilationWithMscorlib(source, options: TestOptions.DebugDll, assemblyName: ExpressionCompilerUtilities.GenerateUniqueName());
            var runtime = CreateRuntimeInstance(comp);

            var dummyComp         = CreateCompilationWithMscorlib("", new[] { comp.EmitToImageReference() }, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All));
            var typeC             = dummyComp.GlobalNamespace.GetMember <NamedTypeSymbol>("C");
            var displayClassTypes = typeC.GetMembers().OfType <NamedTypeSymbol>();

            Assert.True(displayClassTypes.Any());
            foreach (var displayClassType in displayClassTypes)
            {
                var displayClassName = displayClassType.Name;
                Assert.Equal(GeneratedNameKind.LambdaDisplayClass, GeneratedNames.GetKind(displayClassName));
                foreach (var displayClassMethod in displayClassType.GetMembers().OfType <MethodSymbol>().Where(m => GeneratedNames.GetKind(m.Name) == GeneratedNameKind.LambdaMethod))
                {
                    var lambdaMethodName = string.Format("C.{0}.{1}", displayClassName, displayClassMethod.Name);
                    var context          = CreateMethodContext(runtime, lambdaMethodName);
                    VerifyNoThis(context);
                }
            }
        }
예제 #3
0
        private BoundExpression GenerateThisReference(SyntaxNode syntax)
        {
            var thisProxy = CompilationContext.GetThisProxy(_displayClassVariables);

            if (thisProxy != null)
            {
                return(thisProxy.ToBoundExpression(syntax));
            }
            if ((object)_thisParameter != null)
            {
                var typeNameKind = GeneratedNames.GetKind(
                    _thisParameter.TypeWithAnnotations.Type.Name
                    );
                if (
                    typeNameKind != GeneratedNameKind.None &&
                    typeNameKind != GeneratedNameKind.AnonymousType
                    )
                {
                    Debug.Assert(
                        typeNameKind == GeneratedNameKind.LambdaDisplayClass ||
                        typeNameKind == GeneratedNameKind.StateMachineType,
                        $"Unexpected typeNameKind '{typeNameKind}'"
                        );
                    return(null);
                }
                return(new BoundParameter(syntax, _thisParameter));
            }
            return(null);
        }
예제 #4
0
 internal DisplayClassInstanceFromParameter(ParameterSymbol parameter)
 {
     Debug.Assert((object)parameter != null);
     Debug.Assert(parameter.Name.EndsWith("this", StringComparison.Ordinal) ||
                  GeneratedNames.GetKind(parameter.Name) == GeneratedNameKind.TransparentIdentifier);
     this.Parameter = parameter;
 }
예제 #5
0
        internal override void LookupSymbolsInSingleBinder(
            LookupResult result,
            string name,
            int arity,
            ConsList <TypeSymbol> basesBeingResolved,
            LookupOptions options,
            Binder originalBinder,
            bool diagnose,
            ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo
            )
        {
            _sourceBinder.LookupSymbolsInSingleBinder(
                result,
                name,
                arity,
                basesBeingResolved,
                options,
                this,
                diagnose,
                ref useSiteInfo
                );

            var symbols = result.Symbols;

            for (int i = 0; i < symbols.Count; i++)
            {
                // Type parameters requiring mapping to the target type and
                // should be found by WithMethodTypeParametersBinder instead.
                var parameter = (ParameterSymbol)symbols[i];
                Debug.Assert(parameter.ContainingSymbol == _sourceBinder.ContainingMemberOrLambda);
                Debug.Assert(GeneratedNames.GetKind(parameter.Name) == GeneratedNameKind.None);
                symbols[i] = _targetParameters[parameter.Ordinal + _parameterOffset];
            }
        }
예제 #6
0
        internal override void AppendFullName(StringBuilder builder, MethodSymbol method)
        {
            var displayFormat =
                ((method.MethodKind == MethodKind.PropertyGet) || (method.MethodKind == MethodKind.PropertySet)) ?
                s_propertyDisplayFormat :
                DisplayFormat;

            var parts    = method.ToDisplayParts(displayFormat);
            var numParts = parts.Length;

            for (int i = 0; i < numParts; i++)
            {
                var part          = parts[i];
                var displayString = part.ToString();

                switch (part.Kind)
                {
                case SymbolDisplayPartKind.ClassName:
                    if (GeneratedNames.GetKind(displayString) != GeneratedNameKind.LambdaDisplayClass)
                    {
                        builder.Append(displayString);
                    }
                    else
                    {
                        // Drop any remaining display class name parts and the subsequent dot...
                        do
                        {
                            i++;
                        }while ((i < numParts) && parts[i].Kind != SymbolDisplayPartKind.MethodName);
                        i--;
                    }
                    break;

                case SymbolDisplayPartKind.MethodName:
                    GeneratedNameKind kind;
                    int openBracketOffset, closeBracketOffset;
                    if (GeneratedNames.TryParseGeneratedName(displayString, out kind, out openBracketOffset, out closeBracketOffset) &&
                        (kind == GeneratedNameKind.LambdaMethod))
                    {
                        builder.Append(displayString, openBracketOffset + 1, closeBracketOffset - openBracketOffset - 1);     // source method name
                        builder.Append('.');
                        builder.Append(AnonymousMethodName);
                        // NOTE: The old implementation only appended the first ordinal number.  Since this is not useful
                        // in uniquely identifying the lambda, we'll append the entire ordinal suffix (which may contain
                        // multiple numbers, as well as '-' or '_').
                        builder.Append(displayString.Substring(closeBracketOffset + 2));     // ordinal suffix (e.g. "__1")
                    }
                    else
                    {
                        builder.Append(displayString);
                    }
                    break;

                default:
                    builder.Append(displayString);
                    break;
                }
            }
        }
예제 #7
0
 private static FieldSymbol SubstituteField(FieldSymbol field, TypeMap typeMap)
 {
     Debug.Assert(!field.IsStatic);
     Debug.Assert(!field.IsReadOnly || GeneratedNames.GetKind(field.Name) == GeneratedNameKind.AnonymousTypeField);
     // CONSIDER: Instead of digging fields out of the unsubstituted type and then performing substitution
     // on each one individually, we could dig fields out of the substituted type.
     return(new EEDisplayClassFieldSymbol(typeMap.SubstituteNamedType(field.ContainingType), field.Name, typeMap.SubstituteType(field.Type)));
 }
예제 #8
0
 internal DisplayClassInstanceFromParameter(ParameterSymbol parameter)
 {
     Debug.Assert((object)parameter != null);
     Debug.Assert(parameter.Name.EndsWith("this", StringComparison.Ordinal) ||
                  parameter.Name.Length == 0 ||                               // unnamed
                  parameter.Name.Equals("value", StringComparison.Ordinal) || // display class instance passed to local function as parameter
                  GeneratedNames.GetKind(parameter.Name) == GeneratedNameKind.TransparentIdentifier);
     this.Parameter = parameter;
 }
예제 #9
0
        private BoundExpression RewriteParameter(SyntaxNode syntax, ParameterSymbol symbol, BoundExpression node)
        {
            // This can happen in error scenarios (e.g. user binds "this" in a lambda in a static method).
            if ((object)symbol == null)
            {
                ReportMissingThis(node.Kind, syntax);
                return(node);
            }

            var variable = this.GetVariable(symbol.Name);

            if (variable == null)
            {
                var typeNameKind = GeneratedNames.GetKind(symbol.Type.Name);
                if (typeNameKind != GeneratedNameKind.None &&
                    typeNameKind != GeneratedNameKind.AnonymousType)
                {
                    // The state machine case is for async lambdas.  The state machine
                    // will have a hoisted "this" field if it needs to access the
                    // containing display class, but the display class may not have a
                    // "this" field.
                    Debug.Assert(typeNameKind == GeneratedNameKind.LambdaDisplayClass ||
                                 typeNameKind == GeneratedNameKind.StateMachineType,
                                 $"Unexpected typeNameKind '{typeNameKind}'");
                    ReportMissingThis(node.Kind, syntax);
                    return(node);
                }

                return((node as BoundParameter) ?? new BoundParameter(syntax, symbol));
            }

            var result = variable.ToBoundExpression(syntax);

            Debug.Assert(node.Kind == BoundKind.BaseReference
                ? result.Type.BaseType.Equals(node.Type, TypeCompareKind.IgnoreDynamicAndTupleNames)
                : result.Type.Equals(node.Type, TypeCompareKind.IgnoreDynamicAndTupleNames));
            return(result);
        }
예제 #10
0
        public void LambdaLocations_Instance()
        {
            var source = @"
using System;

class C
{
    int _toBeCaptured;

    C()
    {
        int l = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 4))() + x))(1);
    }

    ~C()
    {
        int l = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 6))() + x))(1);
    }

    int P
    {
        get
        {
            return ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 7))() + x))(1);
        }
        set
        {
            value = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 8))() + x))(1);
        }
    }

    int this[int p]
    {
        get
        {
            return ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 9))() + x))(1);
        }
        set
        {
            value = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 10))() + x))(1);
        }
    }

    event Action E
    {
        add
        {
            int l = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 11))() + x))(1);
        }
        remove
        {
            int l = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 12))() + x))(1);
        }
    }
}
";

            var expectedILTemplate = @"
{{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C C.{0}.<>4__this""
  IL_0006:  ret
}}";

            var comp = CreateCompilationWithMscorlib(source, options: TestOptions.DebugDll, assemblyName: ExpressionCompilerUtilities.GenerateUniqueName());

            WithRuntimeInstance(comp, runtime =>
            {
                var dummyComp         = CreateCompilationWithMscorlib("", new[] { comp.EmitToImageReference() }, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All));
                var typeC             = dummyComp.GlobalNamespace.GetMember <NamedTypeSymbol>("C");
                var displayClassTypes = typeC.GetMembers().OfType <NamedTypeSymbol>();
                Assert.True(displayClassTypes.Any());
                foreach (var displayClassType in displayClassTypes)
                {
                    var displayClassName = displayClassType.Name;
                    Assert.Equal(GeneratedNameKind.LambdaDisplayClass, GeneratedNames.GetKind(displayClassName));
                    foreach (var displayClassMethod in displayClassType.GetMembers().OfType <MethodSymbol>().Where(m => GeneratedNames.GetKind(m.Name) == GeneratedNameKind.LambdaMethod))
                    {
                        var lambdaMethodName = string.Format("C.{0}.{1}", displayClassName, displayClassMethod.Name);
                        var context          = CreateMethodContext(runtime, lambdaMethodName);
                        var expectedIL       = string.Format(expectedILTemplate, displayClassName);
                        VerifyHasThis(context, "C", expectedIL);
                    }
                }
            });
        }
예제 #11
0
        protected override void GetStateMachineFieldMapFromMetadata(
            ITypeSymbol stateMachineType,
            ImmutableArray <LocalSlotDebugInfo> localSlotDebugInfo,
            out IReadOnlyDictionary <EncHoistedLocalInfo, int> hoistedLocalMap,
            out IReadOnlyDictionary <Cci.ITypeReference, int> awaiterMap,
            out int awaiterSlotCount)
        {
            // we are working with PE symbols
            Debug.Assert(stateMachineType.ContainingAssembly is PEAssemblySymbol);

            var hoistedLocals       = new Dictionary <EncHoistedLocalInfo, int>();
            var awaiters            = new Dictionary <Cci.ITypeReference, int>();
            int maxAwaiterSlotIndex = -1;

            foreach (var member in stateMachineType.GetMembers())
            {
                if (member.Kind == SymbolKind.Field)
                {
                    string name = member.Name;
                    int    slotIndex;

                    switch (GeneratedNames.GetKind(name))
                    {
                    case GeneratedNameKind.AwaiterField:
                        if (GeneratedNames.TryParseSlotIndex(name, out slotIndex))
                        {
                            var field = (IFieldSymbol)member;

                            // correct metadata won't contain duplicates, but malformed might, ignore the duplicate:
                            awaiters[(Cci.ITypeReference)field.Type] = slotIndex;

                            if (slotIndex > maxAwaiterSlotIndex)
                            {
                                maxAwaiterSlotIndex = slotIndex;
                            }
                        }

                        break;

                    case GeneratedNameKind.HoistedLocalField:
                    case GeneratedNameKind.HoistedSynthesizedLocalField:
                        if (GeneratedNames.TryParseSlotIndex(name, out slotIndex))
                        {
                            var field = (IFieldSymbol)member;
                            if (slotIndex >= localSlotDebugInfo.Length)
                            {
                                // invalid or missing metadata
                                continue;
                            }

                            var key = new EncHoistedLocalInfo(localSlotDebugInfo[slotIndex], (Cci.ITypeReference)field.Type);

                            // correct metadata won't contain duplicate ids, but malformed might, ignore the duplicate:
                            hoistedLocals[key] = slotIndex;
                        }

                        break;
                    }
                }
            }

            hoistedLocalMap  = hoistedLocals;
            awaiterMap       = awaiters;
            awaiterSlotCount = maxAwaiterSlotIndex + 1;
        }