233 lines
10 KiB
C#
233 lines
10 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Threading;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Microsoft.CodeAnalysis.Text;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
|
|
internal sealed class SynthesizedSimpleProgramEntryPointSymbol : SourceMemberMethodSymbol
|
|
{
|
|
private readonly SingleTypeDeclaration _declaration;
|
|
|
|
private readonly TypeSymbol _returnType;
|
|
|
|
private readonly ImmutableArray<ParameterSymbol> _parameters;
|
|
|
|
private WeakReference<ExecutableCodeBinder>? _weakBodyBinder;
|
|
|
|
private WeakReference<ExecutableCodeBinder>? _weakIgnoreAccessibilityBodyBinder;
|
|
|
|
public override string Name => "<Main>$";
|
|
|
|
internal override MethodImplAttributes ImplementationAttributes => MethodImplAttributes.IL;
|
|
|
|
public override ImmutableArray<TypeParameterSymbol> TypeParameters => ImmutableArray<TypeParameterSymbol>.Empty;
|
|
|
|
internal override int ParameterCount => 1;
|
|
|
|
public override ImmutableArray<ParameterSymbol> Parameters => _parameters;
|
|
|
|
public override TypeWithAnnotations ReturnTypeWithAnnotations => TypeWithAnnotations.Create(_returnType);
|
|
|
|
public override FlowAnalysisAnnotations ReturnTypeFlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
|
|
|
|
public override ImmutableHashSet<string> ReturnNotNullIfParameterNotNull => ImmutableHashSet<string>.Empty;
|
|
|
|
public override FlowAnalysisAnnotations FlowAnalysisAnnotations => FlowAnalysisAnnotations.None;
|
|
|
|
public override ImmutableArray<CustomModifier> RefCustomModifiers => ImmutableArray<CustomModifier>.Empty;
|
|
|
|
public sealed override bool IsImplicitlyDeclared => false;
|
|
|
|
internal sealed override bool GenerateDebugInfo => true;
|
|
|
|
protected override object MethodChecksLockObject => _declaration;
|
|
|
|
internal CompilationUnitSyntax CompilationUnit => (CompilationUnitSyntax)SyntaxNode;
|
|
|
|
public SyntaxNode ReturnTypeSyntax => (SyntaxNode)(object)((IEnumerable<MemberDeclarationSyntax>)(object)CompilationUnit.Members).First((MemberDeclarationSyntax m) => m.Kind() == SyntaxKind.GlobalStatement);
|
|
|
|
internal SynthesizedSimpleProgramEntryPointSymbol(SourceMemberContainerTypeSymbol containingType, SingleTypeDeclaration declaration, BindingDiagnosticBag diagnostics)
|
|
: base(containingType, declaration.SyntaxReference, declaration.SyntaxReference.GetLocation(), declaration.IsIterator, MakeModifiersAndFlags(containingType, declaration))
|
|
{
|
|
_declaration = declaration;
|
|
bool hasAwaitExpressions = declaration.HasAwaitExpressions;
|
|
bool hasReturnWithExpression = declaration.HasReturnWithExpression;
|
|
CSharpCompilation declaringCompilation = containingType.DeclaringCompilation;
|
|
if (hasAwaitExpressions)
|
|
{
|
|
if (!hasReturnWithExpression)
|
|
{
|
|
_returnType = Binder.GetWellKnownType(declaringCompilation, (WellKnownType)95, diagnostics, NoLocation.Singleton);
|
|
}
|
|
else
|
|
{
|
|
_returnType = Binder.GetWellKnownType(declaringCompilation, (WellKnownType)96, diagnostics, NoLocation.Singleton).Construct(Binder.GetSpecialType(declaringCompilation, (SpecialType)13, NoLocation.Singleton, diagnostics));
|
|
}
|
|
}
|
|
else if (!hasReturnWithExpression)
|
|
{
|
|
_returnType = Binder.GetSpecialType(declaringCompilation, (SpecialType)6, NoLocation.Singleton, diagnostics);
|
|
}
|
|
else
|
|
{
|
|
_returnType = Binder.GetSpecialType(declaringCompilation, (SpecialType)13, NoLocation.Singleton, diagnostics);
|
|
}
|
|
_parameters = ImmutableArray.Create(SynthesizedParameterSymbol.Create(this, TypeWithAnnotations.Create(ArrayTypeSymbol.CreateCSharpArray(declaringCompilation.Assembly, TypeWithAnnotations.Create(Binder.GetSpecialType(declaringCompilation, (SpecialType)20, NoLocation.Singleton, diagnostics)))), 0, (RefKind)0, "args", (ScopedKind)0));
|
|
}
|
|
|
|
private static (DeclarationModifiers, Flags) MakeModifiersAndFlags(SourceMemberContainerTypeSymbol containingType, SingleTypeDeclaration declaration)
|
|
{
|
|
bool hasAwaitExpressions = declaration.HasAwaitExpressions;
|
|
bool hasReturnWithExpression = declaration.HasReturnWithExpression;
|
|
DeclarationModifiers declarationModifiers = (DeclarationModifiers)(0x104 | (hasAwaitExpressions ? 1048576 : 0));
|
|
CSharpCompilation declaringCompilation = containingType.DeclaringCompilation;
|
|
CompilationUnitSyntax syntax = (CompilationUnitSyntax)(object)declaration.SyntaxReference.GetSyntax(default(CancellationToken));
|
|
bool isNullableAnalysisEnabled = IsNullableAnalysisEnabled(declaringCompilation, syntax);
|
|
Flags item = SourceMemberMethodSymbol.MakeFlags((MethodKind)10, (RefKind)0, declarationModifiers, !hasAwaitExpressions && !hasReturnWithExpression, returnsVoidIsSet: true, isExpressionBodied: false, isExtensionMethod: false, isNullableAnalysisEnabled, isVarArg: false, isExplicitInterfaceImplementation: false);
|
|
return (declarationModifiers, item);
|
|
}
|
|
|
|
internal static SynthesizedSimpleProgramEntryPointSymbol? GetSimpleProgramEntryPoint(CSharpCompilation compilation, CompilationUnitSyntax compilationUnit, bool fallbackToMainEntryPoint)
|
|
{
|
|
SourceNamedTypeSymbol simpleProgramNamedTypeSymbol = GetSimpleProgramNamedTypeSymbol(compilation);
|
|
if ((object)simpleProgramNamedTypeSymbol == null)
|
|
{
|
|
return null;
|
|
}
|
|
ImmutableArray<SynthesizedSimpleProgramEntryPointSymbol> simpleProgramEntryPoints = simpleProgramNamedTypeSymbol.GetSimpleProgramEntryPoints();
|
|
ImmutableArray<SynthesizedSimpleProgramEntryPointSymbol>.Enumerator enumerator = simpleProgramEntryPoints.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
SynthesizedSimpleProgramEntryPointSymbol current = enumerator.Current;
|
|
if (current.SyntaxTree == compilationUnit.SyntaxTree && current.SyntaxNode == compilationUnit)
|
|
{
|
|
return current;
|
|
}
|
|
}
|
|
if (!fallbackToMainEntryPoint)
|
|
{
|
|
return null;
|
|
}
|
|
return simpleProgramEntryPoints[0];
|
|
}
|
|
|
|
internal static SynthesizedSimpleProgramEntryPointSymbol? GetSimpleProgramEntryPoint(CSharpCompilation compilation)
|
|
{
|
|
return GetSimpleProgramNamedTypeSymbol(compilation)?.GetSimpleProgramEntryPoints().First();
|
|
}
|
|
|
|
private static SourceNamedTypeSymbol? GetSimpleProgramNamedTypeSymbol(CSharpCompilation compilation)
|
|
{
|
|
return compilation.SourceModule.GlobalNamespace.GetTypeMembers("Program").OfType<SourceNamedTypeSymbol>().SingleOrDefault((SourceNamedTypeSymbol s) => s.IsSimpleProgram);
|
|
}
|
|
|
|
internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree)
|
|
{
|
|
return localPosition;
|
|
}
|
|
|
|
protected override void MethodChecks(BindingDiagnosticBag diagnostics)
|
|
{
|
|
}
|
|
|
|
public override ImmutableArray<ImmutableArray<TypeWithAnnotations>> GetTypeParameterConstraintTypes()
|
|
{
|
|
return ImmutableArray<ImmutableArray<TypeWithAnnotations>>.Empty;
|
|
}
|
|
|
|
public override ImmutableArray<TypeParameterConstraintKind> GetTypeParameterConstraintKinds()
|
|
{
|
|
return ImmutableArray<TypeParameterConstraintKind>.Empty;
|
|
}
|
|
|
|
internal override ExecutableCodeBinder TryGetBodyBinder(BinderFactory? binderFactoryOpt = null, bool ignoreAccessibility = false)
|
|
{
|
|
return GetBodyBinder(ignoreAccessibility);
|
|
}
|
|
|
|
private ExecutableCodeBinder CreateBodyBinder(bool ignoreAccessibility)
|
|
{
|
|
CSharpCompilation declaringCompilation = DeclaringCompilation;
|
|
CSharpSyntaxNode syntaxNode = SyntaxNode;
|
|
Binder next = new BuckStopsHereBinder(declaringCompilation, FileIdentifier.Create(syntaxNode.SyntaxTree));
|
|
NamespaceSymbol globalNamespace = declaringCompilation.GlobalNamespace;
|
|
SourceNamespaceSymbol declaringSymbol = (SourceNamespaceSymbol)declaringCompilation.SourceModule.GlobalNamespace;
|
|
next = WithExternAndUsingAliasesBinder.Create(declaringSymbol, syntaxNode, WithUsingNamespacesAndTypesBinder.Create(declaringSymbol, syntaxNode, next));
|
|
next = new InContainerBinder(globalNamespace, next);
|
|
next = new InContainerBinder(ContainingType, next);
|
|
next = new InMethodBinder(this, next);
|
|
next = next.WithAdditionalFlags(ignoreAccessibility ? BinderFlags.IgnoreAccessibility : BinderFlags.None);
|
|
return new ExecutableCodeBinder((SyntaxNode)(object)syntaxNode, this, next);
|
|
}
|
|
|
|
internal ExecutableCodeBinder GetBodyBinder(bool ignoreAccessibility)
|
|
{
|
|
ref WeakReference<ExecutableCodeBinder> reference = ref ignoreAccessibility ? ref _weakIgnoreAccessibilityBodyBinder : ref _weakBodyBinder;
|
|
WeakReference<ExecutableCodeBinder> weakReference;
|
|
ExecutableCodeBinder executableCodeBinder;
|
|
do
|
|
{
|
|
weakReference = reference;
|
|
if (weakReference != null && weakReference.TryGetTarget(out var target))
|
|
{
|
|
return target;
|
|
}
|
|
executableCodeBinder = CreateBodyBinder(ignoreAccessibility);
|
|
}
|
|
while (Interlocked.CompareExchange(ref reference, new WeakReference<ExecutableCodeBinder>(executableCodeBinder), weakReference) != weakReference);
|
|
return executableCodeBinder;
|
|
}
|
|
|
|
public override bool IsDefinedInSourceTree(SyntaxTree tree, TextSpan? definedWithinSpan, CancellationToken cancellationToken)
|
|
{
|
|
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
|
|
if (_declaration.SyntaxReference.SyntaxTree == tree)
|
|
{
|
|
if (!definedWithinSpan.HasValue)
|
|
{
|
|
return true;
|
|
}
|
|
TextSpan valueOrDefault = definedWithinSpan.GetValueOrDefault();
|
|
foreach (GlobalStatementSyntax item in ((IEnumerable)(object)((CompilationUnitSyntax)(object)tree.GetRoot(cancellationToken)).Members).OfType<GlobalStatementSyntax>())
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
TextSpan span = ((SyntaxNode)item).Span;
|
|
if (((TextSpan)(ref span)).IntersectsWith(valueOrDefault))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static bool IsNullableAnalysisEnabled(CSharpCompilation compilation, CompilationUnitSyntax syntax)
|
|
{
|
|
//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_0009: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
|
Enumerator<MemberDeclarationSyntax> enumerator = syntax.Members.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
MemberDeclarationSyntax current = enumerator.Current;
|
|
if (current.Kind() == SyntaxKind.GlobalStatement && compilation.IsNullableAnalysisEnabledIn((SyntaxNode)(object)current))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|