private static FieldSymbol SubstituteField(FieldSymbol field, TypeMap typeMap) { Debug.Assert(!field.IsStatic); Debug.Assert(!field.IsReadOnly || GeneratedNameParser.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.TypeWithAnnotations))); }
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 GeneratedNameParser.GetKind(parameter.Name) == GeneratedNameKind.TransparentIdentifier); this.Parameter = parameter; }
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(GeneratedNameParser.GetKind(parameter.Name) == GeneratedNameKind.None); symbols[i] = _targetParameters[parameter.Ordinal + _parameterOffset]; } }
private BoundExpression GenerateThisReference(SyntaxNode syntax) { var thisProxy = CompilationContext.GetThisProxy(_displayClassVariables); if (thisProxy != null) { return(thisProxy.ToBoundExpression(syntax)); } if ((object)_thisParameter != null) { var typeNameKind = GeneratedNameParser.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); }
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 (GeneratedNameParser.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 (GeneratedNameParser.TryParseGeneratedName(displayString, out kind, out openBracketOffset, out closeBracketOffset) && (kind == GeneratedNameKind.LambdaMethod || kind == GeneratedNameKind.LocalFunction)) { builder.Append(displayString, openBracketOffset + 1, closeBracketOffset - openBracketOffset - 1); // source method name builder.Append('.'); if (kind == GeneratedNameKind.LambdaMethod) { builder.Append(AnonymousMethodName); } // NOTE: Local functions include the local function name inside the suffix ("<Main>__Local1_1") // 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; } } }
protected override void GetStateMachineFieldMapFromMetadata( ITypeSymbolInternal 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>(Cci.SymbolEquivalentEqualityComparer.Instance); int maxAwaiterSlotIndex = -1; foreach (var member in ((TypeSymbol)stateMachineType).GetMembers()) { if (member.Kind == SymbolKind.Field) { string name = member.Name; int slotIndex; switch (GeneratedNameParser.GetKind(name)) { case GeneratedNameKind.AwaiterField: if (GeneratedNameParser.TryParseSlotIndex(name, out slotIndex)) { var field = (FieldSymbol)member; // correct metadata won't contain duplicates, but malformed might, ignore the duplicate: awaiters[(Cci.ITypeReference)field.Type.GetCciAdapter()] = slotIndex; if (slotIndex > maxAwaiterSlotIndex) { maxAwaiterSlotIndex = slotIndex; } } break; case GeneratedNameKind.HoistedLocalField: case GeneratedNameKind.HoistedSynthesizedLocalField: if (GeneratedNameParser.TryParseSlotIndex(name, out slotIndex)) { var field = (FieldSymbol)member; if (slotIndex >= localSlotDebugInfo.Length) { // invalid or missing metadata continue; } var key = new EncHoistedLocalInfo(localSlotDebugInfo[slotIndex], (Cci.ITypeReference)field.Type.GetCciAdapter()); // correct metadata won't contain duplicate ids, but malformed might, ignore the duplicate: hoistedLocals[key] = slotIndex; } break; } } } hoistedLocalMap = hoistedLocals; awaiterMap = awaiters; awaiterSlotCount = maxAwaiterSlotIndex + 1; }
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 = CreateCompilation(source, options: TestOptions.DebugDll, assemblyName: ExpressionCompilerUtilities.GenerateUniqueName()); WithRuntimeInstance(comp, runtime => { var dummyComp = CreateCompilation("", 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, GeneratedNameParser.GetKind(displayClassName)); foreach (var displayClassMethod in displayClassType.GetMembers().OfType <MethodSymbol>().Where(m => GeneratedNameParser.GetKind(m.Name) == GeneratedNameKind.LambdaMethod)) { var lambdaMethodName = string.Format("C.{0}.{1}", displayClassName, displayClassMethod.Name); var context = CreateMethodContext(runtime, lambdaMethodName); VerifyNoThis(context); } } }); }
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 = CreateCompilation(source, options: TestOptions.DebugDll, assemblyName: ExpressionCompilerUtilities.GenerateUniqueName()); WithRuntimeInstance(comp, runtime => { var dummyComp = CreateCompilation("", 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, GeneratedNameParser.GetKind(displayClassName)); foreach (var displayClassMethod in displayClassType.GetMembers().OfType <MethodSymbol>().Where(m => GeneratedNameParser.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); } } }); }
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 => GeneratedNameParser.GetKind(t.Name) == GeneratedNameKind.StateMachineType); var moveNextMethod = stateMachineType.GetMember <MethodSymbol>("MoveNext"); var guessedIterator = CompilationContext.GetSubstitutedSourceMethod(moveNextMethod, sourceMethodMustBeInstance: true); Assert.Equal(iteratorMethod, guessedIterator.OriginalDefinition); }