359 lines
19 KiB
C#
359 lines
19 KiB
C#
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using Microsoft.Cci;
|
|
using Microsoft.CodeAnalysis.CSharp.Emit.NoPia;
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
using Microsoft.CodeAnalysis.CodeGen;
|
|
using Microsoft.CodeAnalysis.Collections;
|
|
using Microsoft.CodeAnalysis.Emit;
|
|
using Microsoft.CodeAnalysis.PooledObjects;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal abstract class StateMachineRewriter
|
|
{
|
|
protected readonly BoundStatement body;
|
|
|
|
protected readonly MethodSymbol method;
|
|
|
|
protected readonly BindingDiagnosticBag diagnostics;
|
|
|
|
protected readonly SyntheticBoundNodeFactory F;
|
|
|
|
protected readonly SynthesizedContainer stateMachineType;
|
|
|
|
protected readonly VariableSlotAllocator? slotAllocatorOpt;
|
|
|
|
protected readonly SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals;
|
|
|
|
protected readonly ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder;
|
|
|
|
protected FieldSymbol? stateField;
|
|
|
|
protected FieldSymbol? instanceIdField;
|
|
|
|
protected IReadOnlyDictionary<Symbol, CapturedSymbolReplacement>? nonReusableLocalProxies;
|
|
|
|
protected int nextFreeHoistedLocalSlot;
|
|
|
|
protected IOrderedReadOnlySet<Symbol>? hoistedVariables;
|
|
|
|
protected Dictionary<Symbol, CapturedSymbolReplacement>? initialParameters;
|
|
|
|
protected FieldSymbol? initialThreadIdField;
|
|
|
|
protected abstract bool PreserveInitialParameterValuesAndThreadId { get; }
|
|
|
|
protected StateMachineRewriter(BoundStatement body, MethodSymbol method, SynthesizedContainer stateMachineType, ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder, VariableSlotAllocator? slotAllocatorOpt, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics)
|
|
{
|
|
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0036: Expected O, but got Unknown
|
|
this.body = body;
|
|
this.method = method;
|
|
this.stateMachineType = stateMachineType;
|
|
this.stateMachineStateDebugInfoBuilder = stateMachineStateDebugInfoBuilder;
|
|
this.slotAllocatorOpt = slotAllocatorOpt;
|
|
synthesizedLocalOrdinals = new SynthesizedLocalOrdinalsDispenser();
|
|
this.diagnostics = diagnostics;
|
|
F = new SyntheticBoundNodeFactory(method, body.Syntax, compilationState, diagnostics);
|
|
}
|
|
|
|
protected abstract void GenerateControlFields();
|
|
|
|
protected abstract void InitializeStateMachine(ArrayBuilder<BoundStatement> bodyBuilder, NamedTypeSymbol frameType, LocalSymbol stateMachineLocal);
|
|
|
|
protected abstract BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> proxies);
|
|
|
|
protected abstract void GenerateMethodImplementations();
|
|
|
|
protected BoundStatement Rewrite()
|
|
{
|
|
if (body.HasErrors)
|
|
{
|
|
return body;
|
|
}
|
|
F.OpenNestedType(stateMachineType);
|
|
GenerateControlFields();
|
|
if (PreserveInitialParameterValuesAndThreadId && CanGetThreadId())
|
|
{
|
|
initialThreadIdField = F.StateMachineField(F.SpecialType((SpecialType)13), GeneratedNames.MakeIteratorCurrentThreadIdFieldName());
|
|
}
|
|
if (PreserveInitialParameterValuesAndThreadId)
|
|
{
|
|
initialParameters = new Dictionary<Symbol, CapturedSymbolReplacement>();
|
|
}
|
|
OrderedSet<Symbol> variablesToHoist = IteratorAndAsyncCaptureWalker.Analyze(F.Compilation, method, body, ((BindingDiagnosticBag)diagnostics).DiagnosticBag);
|
|
if (((BindingDiagnosticBag)diagnostics).HasAnyErrors())
|
|
{
|
|
return new BoundBadStatement(F.Syntax, ImmutableArray<BoundNode>.Empty, hasErrors: true);
|
|
}
|
|
CreateNonReusableLocalProxies((IEnumerable<Symbol>)variablesToHoist, out nonReusableLocalProxies, out nextFreeHoistedLocalSlot);
|
|
hoistedVariables = (IOrderedReadOnlySet<Symbol>?)(object)variablesToHoist;
|
|
GenerateMethodImplementations();
|
|
return GenerateKickoffMethodBody();
|
|
}
|
|
|
|
private void CreateNonReusableLocalProxies(IEnumerable<Symbol> variablesToHoist, out IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> proxies, out int nextFreeHoistedLocalSlot)
|
|
{
|
|
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0028: Invalid comparison between Unknown and I4
|
|
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_006c: Invalid comparison between Unknown and I4
|
|
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0144: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
|
|
Dictionary<Symbol, CapturedSymbolReplacement> dictionary = new Dictionary<Symbol, CapturedSymbolReplacement>();
|
|
TypeMap typeMap = stateMachineType.TypeMap;
|
|
bool flag = (int)((CompilationOptions)F.Compilation.Options).OptimizationLevel == 0;
|
|
bool flag2 = flag && slotAllocatorOpt != null;
|
|
nextFreeHoistedLocalSlot = (flag2 ? slotAllocatorOpt.PreviousHoistedLocalSlotCount : 0);
|
|
LocalDebugId none = default(LocalDebugId);
|
|
int num4 = default(int);
|
|
foreach (Symbol item in variablesToHoist)
|
|
{
|
|
if ((int)item.Kind == 8)
|
|
{
|
|
LocalSymbol localSymbol = (LocalSymbol)item;
|
|
SynthesizedLocalKind synthesizedKind = localSymbol.SynthesizedKind;
|
|
if (!SynthesizedLocalKindExtensions.MustSurviveStateMachineSuspension(synthesizedKind) || localSymbol.IsConst || (int)localSymbol.RefKind != 0)
|
|
{
|
|
continue;
|
|
}
|
|
StateMachineFieldSymbol stateMachineFieldSymbol = null;
|
|
if (ShouldPreallocateNonReusableProxy(localSymbol))
|
|
{
|
|
TypeSymbol type = typeMap.SubstituteType(localSymbol.Type).Type;
|
|
int num = -1;
|
|
if (flag)
|
|
{
|
|
SyntaxNode declaratorSyntax = localSymbol.GetDeclaratorSyntax();
|
|
int num2 = method.CalculateLocalSyntaxOffset(LambdaUtilities.GetDeclaratorPosition(declaratorSyntax), declaratorSyntax.SyntaxTree);
|
|
int num3 = synthesizedLocalOrdinals.AssignLocalOrdinal(synthesizedKind, num2);
|
|
((LocalDebugId)(ref none))._002Ector(num2, num3);
|
|
if (flag2 && slotAllocatorOpt.TryGetPreviousHoistedLocalSlotIndex(declaratorSyntax, ((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)F.ModuleBuilderOpt).Translate(type, declaratorSyntax, ((BindingDiagnosticBag)diagnostics).DiagnosticBag), synthesizedKind, none, ((BindingDiagnosticBag)diagnostics).DiagnosticBag, ref num4))
|
|
{
|
|
num = num4;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
none = LocalDebugId.None;
|
|
}
|
|
if (num == -1)
|
|
{
|
|
num = nextFreeHoistedLocalSlot++;
|
|
}
|
|
string name = GeneratedNames.MakeHoistedLocalFieldName(synthesizedKind, num, localSymbol.Name);
|
|
stateMachineFieldSymbol = F.StateMachineField(type, name, new LocalSlotDebugInfo(synthesizedKind, none), num);
|
|
}
|
|
if (stateMachineFieldSymbol != null)
|
|
{
|
|
dictionary.Add(localSymbol, new CapturedToStateMachineFieldReplacement(stateMachineFieldSymbol, isReusable: false));
|
|
}
|
|
continue;
|
|
}
|
|
ParameterSymbol parameterSymbol = (ParameterSymbol)item;
|
|
if (parameterSymbol.IsThis)
|
|
{
|
|
NamedTypeSymbol containingType = method.ContainingType;
|
|
StateMachineFieldSymbol stateMachineFieldSymbol2 = F.StateMachineField(containingType, GeneratedNames.ThisProxyFieldName(), isPublic: true, isThis: true);
|
|
dictionary.Add(parameterSymbol, new CapturedToStateMachineFieldReplacement(stateMachineFieldSymbol2, isReusable: false));
|
|
if (PreserveInitialParameterValuesAndThreadId)
|
|
{
|
|
StateMachineFieldSymbol hoistedField = (containingType.IsStructType() ? F.StateMachineField(containingType, GeneratedNames.StateMachineThisParameterProxyName(), isPublic: true, isThis: true) : stateMachineFieldSymbol2);
|
|
initialParameters.Add(parameterSymbol, new CapturedToStateMachineFieldReplacement(hoistedField, isReusable: false));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
StateMachineFieldSymbol hoistedField2 = F.StateMachineField(typeMap.SubstituteType(parameterSymbol.Type).Type, parameterSymbol.Name, !PreserveInitialParameterValuesAndThreadId);
|
|
dictionary.Add(parameterSymbol, new CapturedToStateMachineFieldReplacement(hoistedField2, isReusable: false));
|
|
if (PreserveInitialParameterValuesAndThreadId)
|
|
{
|
|
StateMachineFieldSymbol hoistedField3 = F.StateMachineField(typeMap.SubstituteType(parameterSymbol.Type).Type, GeneratedNames.StateMachineParameterProxyFieldName(parameterSymbol.Name), isPublic: true);
|
|
initialParameters.Add(parameterSymbol, new CapturedToStateMachineFieldReplacement(hoistedField3, isReusable: false));
|
|
}
|
|
}
|
|
}
|
|
proxies = dictionary;
|
|
}
|
|
|
|
private bool ShouldPreallocateNonReusableProxy(LocalSymbol local)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001f: Invalid comparison between Unknown and I4
|
|
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
|
|
SynthesizedLocalKind synthesizedKind = local.SynthesizedKind;
|
|
OptimizationLevel optimizationLevel = ((CompilationOptions)F.Compilation.Options).OptimizationLevel;
|
|
if ((int)optimizationLevel == 1 && (int)synthesizedKind == 0)
|
|
{
|
|
return false;
|
|
}
|
|
return !SynthesizedLocalKindExtensions.IsSlotReusable(synthesizedKind, optimizationLevel);
|
|
}
|
|
|
|
private BoundStatement GenerateKickoffMethodBody()
|
|
{
|
|
F.CurrentFunction = method;
|
|
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance();
|
|
NamedTypeSymbol namedTypeSymbol = (method.IsGenericMethod ? stateMachineType.Construct(method.TypeArgumentsWithAnnotations, unbound: false) : stateMachineType);
|
|
LocalSymbol localSymbol = F.SynthesizedLocal(namedTypeSymbol, null, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0, (SynthesizedLocalKind)(-2));
|
|
InitializeStateMachine(instance, namedTypeSymbol, localSymbol);
|
|
IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> readOnlyDictionary;
|
|
if (!PreserveInitialParameterValuesAndThreadId)
|
|
{
|
|
readOnlyDictionary = nonReusableLocalProxies;
|
|
}
|
|
else
|
|
{
|
|
IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> readOnlyDictionary2 = initialParameters;
|
|
readOnlyDictionary = readOnlyDictionary2;
|
|
}
|
|
IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> proxies = readOnlyDictionary;
|
|
instance.Add(GenerateStateMachineCreation(localSymbol, namedTypeSymbol, proxies));
|
|
return F.Block(ImmutableArray.Create(localSymbol), instance.ToImmutableAndFree());
|
|
}
|
|
|
|
protected BoundStatement GenerateParameterStorage(LocalSymbol stateMachineVariable, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> proxies)
|
|
{
|
|
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance();
|
|
if (!method.IsStatic && proxies.TryGetValue(method.ThisParameter, out var value))
|
|
{
|
|
instance.Add((BoundStatement)F.Assignment(value.Replacement(F.Syntax, (NamedTypeSymbol frameType1) => F.Local(stateMachineVariable)), F.This()));
|
|
}
|
|
ImmutableArray<ParameterSymbol>.Enumerator enumerator = method.Parameters.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
ParameterSymbol current = enumerator.Current;
|
|
if (proxies.TryGetValue(current, out var value2))
|
|
{
|
|
instance.Add((BoundStatement)F.Assignment(value2.Replacement(F.Syntax, (NamedTypeSymbol frameType1) => F.Local(stateMachineVariable)), F.Parameter(current)));
|
|
}
|
|
}
|
|
ImmutableArray<BoundStatement> statements = instance.ToImmutableAndFree();
|
|
return F.Block(statements);
|
|
}
|
|
|
|
protected SynthesizedImplementationMethod OpenMethodImplementation(MethodSymbol methodToImplement, string methodName = null, bool hasMethodBodyDependency = false)
|
|
{
|
|
SynthesizedStateMachineDebuggerHiddenMethod synthesizedStateMachineDebuggerHiddenMethod = new SynthesizedStateMachineDebuggerHiddenMethod(methodName, methodToImplement, (StateMachineTypeSymbol)F.CurrentType, null, hasMethodBodyDependency);
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)F.ModuleBuilderOpt).AddSynthesizedDefinition(F.CurrentType, (IMethodDefinition)(object)synthesizedStateMachineDebuggerHiddenMethod.GetCciAdapter());
|
|
F.CurrentFunction = synthesizedStateMachineDebuggerHiddenMethod;
|
|
return synthesizedStateMachineDebuggerHiddenMethod;
|
|
}
|
|
|
|
protected MethodSymbol OpenPropertyImplementation(MethodSymbol getterToImplement)
|
|
{
|
|
SynthesizedStateMachineProperty synthesizedStateMachineProperty = new SynthesizedStateMachineProperty(getterToImplement, (StateMachineTypeSymbol)F.CurrentType);
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)F.ModuleBuilderOpt).AddSynthesizedDefinition(F.CurrentType, (IPropertyDefinition)(object)synthesizedStateMachineProperty.GetCciAdapter());
|
|
MethodSymbol getMethod = synthesizedStateMachineProperty.GetMethod;
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)F.ModuleBuilderOpt).AddSynthesizedDefinition(F.CurrentType, (IMethodDefinition)(object)getMethod.GetCciAdapter());
|
|
F.CurrentFunction = getMethod;
|
|
return getMethod;
|
|
}
|
|
|
|
protected SynthesizedImplementationMethod OpenMoveNextMethodImplementation(MethodSymbol methodToImplement)
|
|
{
|
|
SynthesizedStateMachineMoveNextMethod synthesizedStateMachineMoveNextMethod = new SynthesizedStateMachineMoveNextMethod(methodToImplement, (StateMachineTypeSymbol)F.CurrentType);
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)F.ModuleBuilderOpt).AddSynthesizedDefinition(F.CurrentType, (IMethodDefinition)(object)synthesizedStateMachineMoveNextMethod.GetCciAdapter());
|
|
F.CurrentFunction = synthesizedStateMachineMoveNextMethod;
|
|
return synthesizedStateMachineMoveNextMethod;
|
|
}
|
|
|
|
protected BoundExpression MakeCurrentThreadId()
|
|
{
|
|
PropertySymbol propertySymbol = (PropertySymbol)F.WellKnownMember((WellKnownMember)305, isOptional: true);
|
|
if ((object)propertySymbol != null)
|
|
{
|
|
MethodSymbol getMethod = propertySymbol.GetMethod;
|
|
if ((object)getMethod != null)
|
|
{
|
|
return F.Call(null, getMethod);
|
|
}
|
|
}
|
|
return F.Property(F.Property((WellKnownMember)145), (WellKnownMember)146);
|
|
}
|
|
|
|
protected SynthesizedImplementationMethod GenerateIteratorGetEnumerator(MethodSymbol getEnumeratorMethod, ref BoundExpression managedThreadId, StateMachineState initialState)
|
|
{
|
|
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
|
|
SynthesizedImplementationMethod result = OpenMethodImplementation(getEnumeratorMethod);
|
|
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance();
|
|
LocalSymbol resultVariable = F.SynthesizedLocal(stateMachineType, null, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0, (SynthesizedLocalKind)(-2));
|
|
BoundStatement boundStatement = F.Assignment(F.Local(resultVariable), F.New(stateMachineType.Constructor, F.Literal(initialState)));
|
|
GeneratedLabelSymbol label = F.GenerateLabel("thisInitialized");
|
|
if ((object)initialThreadIdField != null)
|
|
{
|
|
managedThreadId = MakeCurrentThreadId();
|
|
ArrayBuilder<BoundStatement> instance2 = ArrayBuilder<BoundStatement>.GetInstance(4);
|
|
GenerateResetInstance(instance2, initialState);
|
|
instance2.Add((BoundStatement)F.Assignment(F.Local(resultVariable), F.This()));
|
|
if (method.IsStatic || method.ThisParameter.Type.IsReferenceType)
|
|
{
|
|
instance2.Add((BoundStatement)F.Goto(label));
|
|
}
|
|
boundStatement = F.If(F.LogicalAnd(F.IntEqual(F.Field(F.This(), stateField), F.Literal((StateMachineState)(-2))), F.IntEqual(F.Field(F.This(), initialThreadIdField), managedThreadId)), F.Block(instance2.ToImmutableAndFree()), boundStatement);
|
|
}
|
|
instance.Add(boundStatement);
|
|
Dictionary<Symbol, CapturedSymbolReplacement> dictionary = initialParameters;
|
|
IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> readOnlyDictionary = nonReusableLocalProxies;
|
|
if (!method.IsStatic && readOnlyDictionary.TryGetValue(method.ThisParameter, out var value))
|
|
{
|
|
instance.Add((BoundStatement)F.Assignment(value.Replacement(F.Syntax, (NamedTypeSymbol stateMachineType) => F.Local(resultVariable)), dictionary[method.ThisParameter].Replacement(F.Syntax, (NamedTypeSymbol stateMachineType) => F.This())));
|
|
}
|
|
instance.Add((BoundStatement)F.Label(label));
|
|
ImmutableArray<ParameterSymbol>.Enumerator enumerator = method.Parameters.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
ParameterSymbol current = enumerator.Current;
|
|
if (readOnlyDictionary.TryGetValue(current, out var value2))
|
|
{
|
|
BoundExpression resultParameter = value2.Replacement(F.Syntax, (NamedTypeSymbol stateMachineType) => F.Local(resultVariable));
|
|
BoundExpression parameterProxy = dictionary[current].Replacement(F.Syntax, (NamedTypeSymbol stateMachineType) => F.This());
|
|
BoundStatement boundStatement2 = InitializeParameterField(getEnumeratorMethod, current, resultParameter, parameterProxy);
|
|
instance.Add(boundStatement2);
|
|
}
|
|
}
|
|
instance.Add((BoundStatement)F.Return(F.Local(resultVariable)));
|
|
F.CloseMethod(F.Block(ImmutableArray.Create(resultVariable), instance.ToImmutableAndFree()));
|
|
return result;
|
|
}
|
|
|
|
protected virtual void GenerateResetInstance(ArrayBuilder<BoundStatement> builder, StateMachineState initialState)
|
|
{
|
|
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
|
|
builder.Add((BoundStatement)F.Assignment(F.Field(F.This(), stateField), F.Literal(initialState)));
|
|
}
|
|
|
|
protected virtual BoundStatement InitializeParameterField(MethodSymbol getEnumeratorMethod, ParameterSymbol parameter, BoundExpression resultParameter, BoundExpression parameterProxy)
|
|
{
|
|
return F.Assignment(resultParameter, parameterProxy);
|
|
}
|
|
|
|
protected bool CanGetThreadId()
|
|
{
|
|
if ((object)F.WellKnownMember((WellKnownMember)146, isOptional: true) == null)
|
|
{
|
|
return (object)F.WellKnownMember((WellKnownMember)305, isOptional: true) != null;
|
|
}
|
|
return true;
|
|
}
|
|
}
|