525 lines
26 KiB
C#
525 lines
26 KiB
C#
using System;
|
|||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Collections.Immutable;
|
||
|
|
using System.Diagnostics.CodeAnalysis;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Threading;
|
||
|
|
using Microsoft.Cci;
|
||
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
||
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||
|
|
using Microsoft.CodeAnalysis.CodeGen;
|
||
|
|
using Microsoft.CodeAnalysis.PooledObjects;
|
||
|
|
using Microsoft.CodeAnalysis.Shared.Collections;
|
||
|
|
using Microsoft.CodeAnalysis.Text;
|
||
|
|
using Roslyn.Utilities;
|
||
|
|
|
||
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
||
|
|
|
||
|
|
internal sealed class CodeCoverageInstrumenter : CompoundInstrumenter
|
||
|
|
{
|
||
|
|
private readonly MethodSymbol _method;
|
||
|
|
|
||
|
|
private readonly BoundStatement _methodBody;
|
||
|
|
|
||
|
|
private readonly MethodSymbol _createPayloadForMethodsSpanningSingleFile;
|
||
|
|
|
||
|
|
private readonly MethodSymbol _createPayloadForMethodsSpanningMultipleFiles;
|
||
|
|
|
||
|
|
private readonly ArrayBuilder<SourceSpan> _spansBuilder;
|
||
|
|
|
||
|
|
private ImmutableArray<SourceSpan> _dynamicAnalysisSpans = ImmutableArray<SourceSpan>.Empty;
|
||
|
|
|
||
|
|
private readonly BoundStatement? _methodEntryInstrumentation;
|
||
|
|
|
||
|
|
private readonly ArrayTypeSymbol _payloadType;
|
||
|
|
|
||
|
|
private readonly LocalSymbol _methodPayload;
|
||
|
|
|
||
|
|
private readonly BindingDiagnosticBag _diagnostics;
|
||
|
|
|
||
|
|
private readonly DebugDocumentProvider _debugDocumentProvider;
|
||
|
|
|
||
|
|
private readonly SyntheticBoundNodeFactory _methodBodyFactory;
|
||
|
|
|
||
|
|
public ImmutableArray<SourceSpan> DynamicAnalysisSpans => _dynamicAnalysisSpans;
|
||
|
|
|
||
|
|
public static bool TryCreate(MethodSymbol method, BoundStatement methodBody, SyntheticBoundNodeFactory methodBodyFactory, BindingDiagnosticBag diagnostics, DebugDocumentProvider debugDocumentProvider, Instrumenter previous, [NotNullWhen(true)] out CodeCoverageInstrumenter? instrumenter)
|
||
|
|
{
|
||
|
|
instrumenter = null;
|
||
|
|
if (method.IsImplicitlyDeclared && !method.IsImplicitConstructor)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (IsExcludedFromCodeCoverage(method))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
MethodSymbol createPayloadOverload = GetCreatePayloadOverload(methodBodyFactory.Compilation, (WellKnownMember)354, methodBody.Syntax, diagnostics);
|
||
|
|
MethodSymbol createPayloadOverload2 = GetCreatePayloadOverload(methodBodyFactory.Compilation, (WellKnownMember)355, methodBody.Syntax, diagnostics);
|
||
|
|
if ((object)createPayloadOverload == null || (object)createPayloadOverload2 == null)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (method.Equals(createPayloadOverload) || method.Equals(createPayloadOverload2))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
instrumenter = new CodeCoverageInstrumenter(method, methodBody, methodBodyFactory, createPayloadOverload, createPayloadOverload2, diagnostics, debugDocumentProvider, previous);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private CodeCoverageInstrumenter(MethodSymbol method, BoundStatement methodBody, SyntheticBoundNodeFactory methodBodyFactory, MethodSymbol createPayloadForMethodsSpanningSingleFile, MethodSymbol createPayloadForMethodsSpanningMultipleFiles, BindingDiagnosticBag diagnostics, DebugDocumentProvider debugDocumentProvider, Instrumenter previous)
|
||
|
|
: base(previous)
|
||
|
|
{
|
||
|
|
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
_createPayloadForMethodsSpanningSingleFile = createPayloadForMethodsSpanningSingleFile;
|
||
|
|
_createPayloadForMethodsSpanningMultipleFiles = createPayloadForMethodsSpanningMultipleFiles;
|
||
|
|
_method = method;
|
||
|
|
_methodBody = methodBody;
|
||
|
|
_spansBuilder = ArrayBuilder<SourceSpan>.GetInstance();
|
||
|
|
TypeSymbol typeSymbol = methodBodyFactory.SpecialType((SpecialType)7);
|
||
|
|
_payloadType = ArrayTypeSymbol.CreateCSharpArray(methodBodyFactory.Compilation.Assembly, TypeWithAnnotations.Create(typeSymbol));
|
||
|
|
_diagnostics = diagnostics;
|
||
|
|
_debugDocumentProvider = debugDocumentProvider;
|
||
|
|
_methodBodyFactory = methodBodyFactory;
|
||
|
|
MethodSymbol currentFunction = methodBodyFactory.CurrentFunction;
|
||
|
|
methodBodyFactory.CurrentFunction = method;
|
||
|
|
_methodPayload = methodBodyFactory.SynthesizedLocal(_payloadType, methodBody.Syntax, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0, (SynthesizedLocalKind)34);
|
||
|
|
SyntaxNode val = MethodDeclarationIfAvailable(methodBody.Syntax);
|
||
|
|
if (!method.IsImplicitlyDeclared && !(method is SynthesizedSimpleProgramEntryPointSymbol))
|
||
|
|
{
|
||
|
|
_methodEntryInstrumentation = AddAnalysisPoint(val, SkipAttributes(val), methodBodyFactory);
|
||
|
|
}
|
||
|
|
methodBodyFactory.CurrentFunction = currentFunction;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected override CompoundInstrumenter WithPreviousImpl(Instrumenter previous)
|
||
|
|
{
|
||
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/Instrumentation/CodeCoverageInstrumenter.cs", 139);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool IsExcludedFromCodeCoverage(MethodSymbol method)
|
||
|
|
{
|
||
|
|
NamedTypeSymbol containingType = method.ContainingType;
|
||
|
|
while ((object)containingType != null)
|
||
|
|
{
|
||
|
|
if (containingType.IsDirectlyExcludedFromCodeCoverage)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
containingType = containingType.ContainingType;
|
||
|
|
}
|
||
|
|
if ((object)method != null)
|
||
|
|
{
|
||
|
|
if (method.IsDirectlyExcludedFromCodeCoverage)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
Symbol associatedSymbol = method.AssociatedSymbol;
|
||
|
|
if (associatedSymbol is PropertySymbol propertySymbol)
|
||
|
|
{
|
||
|
|
if (propertySymbol.IsDirectlyExcludedFromCodeCoverage)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (associatedSymbol is EventSymbol { IsDirectlyExcludedFromCodeCoverage: not false })
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static BoundExpressionStatement GetCreatePayloadStatement(ImmutableArray<SourceSpan> dynamicAnalysisSpans, SyntaxNode methodBodySyntax, LocalSymbol methodPayload, MethodSymbol createPayloadForMethodsSpanningSingleFile, MethodSymbol createPayloadForMethodsSpanningMultipleFiles, BoundExpression mvid, BoundExpression methodToken, BoundExpression payloadSlot, SyntheticBoundNodeFactory methodBodyFactory, DebugDocumentProvider debugDocumentProvider)
|
||
|
|
{
|
||
|
|
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
MethodSymbol method;
|
||
|
|
BoundExpression boundExpression;
|
||
|
|
if (dynamicAnalysisSpans.IsEmpty)
|
||
|
|
{
|
||
|
|
method = createPayloadForMethodsSpanningSingleFile;
|
||
|
|
DebugSourceDocument sourceDocument = GetSourceDocument(debugDocumentProvider, methodBodySyntax);
|
||
|
|
boundExpression = methodBodyFactory.SourceDocumentIndex(sourceDocument);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
PooledHashSet<DebugSourceDocument> instance = PooledHashSet<DebugSourceDocument>.GetInstance();
|
||
|
|
ArrayBuilder<BoundExpression> instance2 = ArrayBuilder<BoundExpression>.GetInstance();
|
||
|
|
ImmutableArray<SourceSpan>.Enumerator enumerator = dynamicAnalysisSpans.GetEnumerator();
|
||
|
|
while (enumerator.MoveNext())
|
||
|
|
{
|
||
|
|
DebugSourceDocument document = enumerator.Current.Document;
|
||
|
|
if (((HashSet<DebugSourceDocument>)(object)instance).Add(document))
|
||
|
|
{
|
||
|
|
instance2.Add(methodBodyFactory.SourceDocumentIndex(document));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
instance.Free();
|
||
|
|
if (instance2.Count == 1)
|
||
|
|
{
|
||
|
|
method = createPayloadForMethodsSpanningSingleFile;
|
||
|
|
boundExpression = ((IEnumerable<BoundExpression>)instance2).Single();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
method = createPayloadForMethodsSpanningMultipleFiles;
|
||
|
|
boundExpression = methodBodyFactory.Array(methodBodyFactory.SpecialType((SpecialType)13), instance2.ToImmutable());
|
||
|
|
}
|
||
|
|
instance2.Free();
|
||
|
|
}
|
||
|
|
return methodBodyFactory.Assignment(methodBodyFactory.Local(methodPayload), methodBodyFactory.Call(null, method, mvid, methodToken, boundExpression, payloadSlot, methodBodyFactory.Literal(dynamicAnalysisSpans.Length)));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override void InstrumentBlock(BoundBlock original, LocalRewriter rewriter, ref TemporaryArray<LocalSymbol> additionalLocals, out BoundStatement? prologue, out BoundStatement? epilogue, out BoundBlockInstrumentation? instrumentation)
|
||
|
|
{
|
||
|
|
base.InstrumentBlock(original, rewriter, ref additionalLocals, out BoundStatement prologue2, out epilogue, out instrumentation);
|
||
|
|
if (original != rewriter.CurrentMethodBody)
|
||
|
|
{
|
||
|
|
prologue = prologue2;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
_dynamicAnalysisSpans = _spansBuilder.ToImmutableAndFree();
|
||
|
|
ArrayTypeSymbol payloadType = ArrayTypeSymbol.CreateCSharpArray(_methodBodyFactory.Compilation.Assembly, TypeWithAnnotations.Create(_payloadType));
|
||
|
|
BoundStatement boundStatement = _methodBodyFactory.Assignment(_methodBodyFactory.Local(_methodPayload), _methodBodyFactory.ArrayAccess(_methodBodyFactory.InstrumentationPayloadRoot(0, payloadType), ImmutableArray.Create(_methodBodyFactory.MethodDefIndex(_method))));
|
||
|
|
BoundExpression mvid = _methodBodyFactory.ModuleVersionId();
|
||
|
|
BoundExpression methodToken = _methodBodyFactory.MethodDefIndex(_method);
|
||
|
|
BoundExpression payloadSlot = _methodBodyFactory.ArrayAccess(_methodBodyFactory.InstrumentationPayloadRoot(0, payloadType), ImmutableArray.Create(_methodBodyFactory.MethodDefIndex(_method)));
|
||
|
|
BoundStatement createPayloadStatement = GetCreatePayloadStatement(_dynamicAnalysisSpans, _methodBody.Syntax, _methodPayload, _createPayloadForMethodsSpanningSingleFile, _createPayloadForMethodsSpanningMultipleFiles, mvid, methodToken, payloadSlot, _methodBodyFactory, _debugDocumentProvider);
|
||
|
|
BoundExpression condition = _methodBodyFactory.Binary(BinaryOperatorKind.ObjectEqual, _methodBodyFactory.SpecialType((SpecialType)7), _methodBodyFactory.Local(_methodPayload), _methodBodyFactory.Null(_payloadType));
|
||
|
|
BoundStatement boundStatement2 = _methodBodyFactory.If(condition, createPayloadStatement);
|
||
|
|
additionalLocals.Add(_methodPayload);
|
||
|
|
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance(2 + ((_methodEntryInstrumentation != null) ? 1 : 0) + ((prologue2 != null) ? 1 : 0));
|
||
|
|
instance.Add(boundStatement);
|
||
|
|
instance.Add(boundStatement2);
|
||
|
|
if (_methodEntryInstrumentation != null)
|
||
|
|
{
|
||
|
|
instance.Add(_methodEntryInstrumentation);
|
||
|
|
}
|
||
|
|
if (prologue2 != null)
|
||
|
|
{
|
||
|
|
instance.Add(prologue2);
|
||
|
|
}
|
||
|
|
prologue = _methodBodyFactory.StatementList(instance.ToImmutableAndFree());
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentNoOpStatement(BoundNoOpStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentNoOpStatement(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentBreakStatement(BoundBreakStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentBreakStatement(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentContinueStatement(BoundContinueStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentContinueStatement(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentExpressionStatement(BoundExpressionStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentExpressionStatement(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentFieldOrPropertyInitializer(BoundStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentFieldOrPropertyInitializer(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentGotoStatement(BoundGotoStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentGotoStatement(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentThrowStatement(BoundThrowStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentThrowStatement(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentYieldBreakStatement(BoundYieldBreakStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentYieldBreakStatement(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentYieldReturnStatement(BoundYieldReturnStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentYieldReturnStatement(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentForEachStatementIterationVarDeclaration(BoundForEachStatement original, BoundStatement iterationVarDecl)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentForEachStatementIterationVarDeclaration(original, iterationVarDecl));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentForEachStatementDeconstructionVariablesDeclaration(BoundForEachStatement original, BoundStatement iterationVarDecl)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentForEachStatementDeconstructionVariablesDeclaration(original, iterationVarDecl));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentIfStatement(BoundIfStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentIfStatement(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentWhileStatementConditionalGotoStartOrBreak(BoundWhileStatement original, BoundStatement ifConditionGotoStart)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentWhileStatementConditionalGotoStartOrBreak(original, ifConditionGotoStart));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentUserDefinedLocalInitialization(BoundLocalDeclaration original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentUserDefinedLocalInitialization(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentLockTargetCapture(BoundLockStatement original, BoundStatement lockTargetCapture)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentLockTargetCapture(original, lockTargetCapture));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentReturnStatement(BoundReturnStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
rewritten = base.InstrumentReturnStatement(original, rewritten);
|
||
|
|
if (ReturnsValueWithinExpressionBodiedConstruct(original))
|
||
|
|
{
|
||
|
|
return CollectDynamicAnalysis(original, rewritten);
|
||
|
|
}
|
||
|
|
return AddDynamicAnalysis(original, rewritten);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool ReturnsValueWithinExpressionBodiedConstruct(BoundReturnStatement returnStatement)
|
||
|
|
{
|
||
|
|
if (returnStatement.WasCompilerGenerated && returnStatement.ExpressionOpt != null && returnStatement.ExpressionOpt.Syntax != null)
|
||
|
|
{
|
||
|
|
SyntaxKind syntaxKind = returnStatement.ExpressionOpt.Syntax.Parent.Kind();
|
||
|
|
if (syntaxKind - 8642 <= SyntaxKind.List || syntaxKind == SyntaxKind.ArrowExpressionClause)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentSwitchStatement(BoundSwitchStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentSwitchStatement(original, rewritten));
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentSwitchWhenClauseConditionalGotoBody(BoundExpression original, BoundStatement ifConditionGotoBody)
|
||
|
|
{
|
||
|
|
ifConditionGotoBody = base.InstrumentSwitchWhenClauseConditionalGotoBody(original, ifConditionGotoBody);
|
||
|
|
WhenClauseSyntax whenClauseSyntax = original.Syntax.FirstAncestorOrSelf<WhenClauseSyntax>((Func<WhenClauseSyntax, bool>)null, true);
|
||
|
|
SyntheticBoundNodeFactory syntheticBoundNodeFactory = new SyntheticBoundNodeFactory(_method, (SyntaxNode)(object)whenClauseSyntax, _methodBodyFactory.CompilationState, _diagnostics);
|
||
|
|
return syntheticBoundNodeFactory.StatementList(AddAnalysisPoint((SyntaxNode)(object)whenClauseSyntax, syntheticBoundNodeFactory), ifConditionGotoBody);
|
||
|
|
}
|
||
|
|
|
||
|
|
public override BoundStatement InstrumentUsingTargetCapture(BoundUsingStatement original, BoundStatement usingTargetCapture)
|
||
|
|
{
|
||
|
|
return AddDynamicAnalysis(original, base.InstrumentUsingTargetCapture(original, usingTargetCapture));
|
||
|
|
}
|
||
|
|
|
||
|
|
private BoundStatement AddDynamicAnalysis(BoundStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
if (!original.WasCompilerGenerated && (!original.IsConstructorInitializer() || original.Syntax.Kind() != SyntaxKind.ConstructorDeclaration))
|
||
|
|
{
|
||
|
|
return CollectDynamicAnalysis(original, rewritten);
|
||
|
|
}
|
||
|
|
return rewritten;
|
||
|
|
}
|
||
|
|
|
||
|
|
private BoundStatement CollectDynamicAnalysis(BoundStatement original, BoundStatement rewritten)
|
||
|
|
{
|
||
|
|
SyntheticBoundNodeFactory syntheticBoundNodeFactory = new SyntheticBoundNodeFactory(_method, original.Syntax, _methodBodyFactory.CompilationState, _diagnostics);
|
||
|
|
return syntheticBoundNodeFactory.StatementList(AddAnalysisPoint(SyntaxForSpan(original), syntheticBoundNodeFactory), rewritten);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static DebugSourceDocument GetSourceDocument(DebugDocumentProvider debugDocumentProvider, SyntaxNode syntax)
|
||
|
|
{
|
||
|
|
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
return GetSourceDocument(debugDocumentProvider, syntax, syntax.GetLocation().GetMappedLineSpan());
|
||
|
|
}
|
||
|
|
|
||
|
|
private static DebugSourceDocument GetSourceDocument(DebugDocumentProvider debugDocumentProvider, SyntaxNode syntax, FileLinePositionSpan span)
|
||
|
|
{
|
||
|
|
string text = ((FileLinePositionSpan)(ref span)).Path;
|
||
|
|
if (text.Length == 0)
|
||
|
|
{
|
||
|
|
text = syntax.SyntaxTree.FilePath;
|
||
|
|
}
|
||
|
|
return debugDocumentProvider.Invoke(text, "");
|
||
|
|
}
|
||
|
|
|
||
|
|
private BoundStatement AddAnalysisPoint(SyntaxNode syntaxForSpan, TextSpan alternateSpan, SyntheticBoundNodeFactory statementFactory)
|
||
|
|
{
|
||
|
|
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
return AddAnalysisPoint(syntaxForSpan, syntaxForSpan.SyntaxTree.GetMappedLineSpan(alternateSpan, default(CancellationToken)), statementFactory);
|
||
|
|
}
|
||
|
|
|
||
|
|
private BoundStatement AddAnalysisPoint(SyntaxNode syntaxForSpan, SyntheticBoundNodeFactory statementFactory)
|
||
|
|
{
|
||
|
|
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
return AddAnalysisPoint(syntaxForSpan, syntaxForSpan.GetLocation().GetMappedLineSpan(), statementFactory);
|
||
|
|
}
|
||
|
|
|
||
|
|
private BoundStatement AddAnalysisPoint(SyntaxNode syntaxForSpan, FileLinePositionSpan span, SyntheticBoundNodeFactory statementFactory)
|
||
|
|
{
|
||
|
|
//IL_0019: 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)
|
||
|
|
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0053: 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)
|
||
|
|
int count = _spansBuilder.Count;
|
||
|
|
ArrayBuilder<SourceSpan> spansBuilder = _spansBuilder;
|
||
|
|
DebugSourceDocument sourceDocument = GetSourceDocument(_debugDocumentProvider, syntaxForSpan, span);
|
||
|
|
LinePosition val = ((FileLinePositionSpan)(ref span)).StartLinePosition;
|
||
|
|
int line = ((LinePosition)(ref val)).Line;
|
||
|
|
val = ((FileLinePositionSpan)(ref span)).StartLinePosition;
|
||
|
|
int character = ((LinePosition)(ref val)).Character;
|
||
|
|
val = ((FileLinePositionSpan)(ref span)).EndLinePosition;
|
||
|
|
int line2 = ((LinePosition)(ref val)).Line;
|
||
|
|
val = ((FileLinePositionSpan)(ref span)).EndLinePosition;
|
||
|
|
spansBuilder.Add(new SourceSpan(sourceDocument, line, character, line2, ((LinePosition)(ref val)).Character));
|
||
|
|
BoundArrayAccess left = statementFactory.ArrayAccess(statementFactory.Local(_methodPayload), statementFactory.Literal(count));
|
||
|
|
return statementFactory.Assignment(left, statementFactory.Literal(value: true));
|
||
|
|
}
|
||
|
|
|
||
|
|
private static SyntaxNode SyntaxForSpan(BoundStatement statement)
|
||
|
|
{
|
||
|
|
switch (statement.Kind)
|
||
|
|
{
|
||
|
|
case BoundKind.IfStatement:
|
||
|
|
return ((BoundIfStatement)statement).Condition.Syntax;
|
||
|
|
case BoundKind.WhileStatement:
|
||
|
|
return ((BoundWhileStatement)statement).Condition.Syntax;
|
||
|
|
case BoundKind.ForEachStatement:
|
||
|
|
return ((BoundForEachStatement)statement).Expression.Syntax;
|
||
|
|
case BoundKind.DoStatement:
|
||
|
|
return ((BoundDoStatement)statement).Condition.Syntax;
|
||
|
|
case BoundKind.UsingStatement:
|
||
|
|
{
|
||
|
|
BoundUsingStatement boundUsingStatement = (BoundUsingStatement)statement;
|
||
|
|
return ((BoundNode)(((object)boundUsingStatement.ExpressionOpt) ?? ((object)boundUsingStatement.DeclarationsOpt))).Syntax;
|
||
|
|
}
|
||
|
|
case BoundKind.FixedStatement:
|
||
|
|
return ((BoundFixedStatement)statement).Declarations.Syntax;
|
||
|
|
case BoundKind.LockStatement:
|
||
|
|
return ((BoundLockStatement)statement).Argument.Syntax;
|
||
|
|
case BoundKind.SwitchStatement:
|
||
|
|
return ((BoundSwitchStatement)statement).Expression.Syntax;
|
||
|
|
default:
|
||
|
|
return statement.Syntax;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static MethodSymbol GetCreatePayloadOverload(CSharpCompilation compilation, WellKnownMember overload, SyntaxNode syntax, BindingDiagnosticBag diagnostics)
|
||
|
|
{
|
||
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
return (MethodSymbol)Binder.GetWellKnownTypeMember(compilation, overload, diagnostics, null, syntax);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static SyntaxNode MethodDeclarationIfAvailable(SyntaxNode body)
|
||
|
|
{
|
||
|
|
SyntaxNode parent = body.Parent;
|
||
|
|
if (parent != null)
|
||
|
|
{
|
||
|
|
switch (parent.Kind())
|
||
|
|
{
|
||
|
|
case SyntaxKind.MethodDeclaration:
|
||
|
|
case SyntaxKind.OperatorDeclaration:
|
||
|
|
case SyntaxKind.ConstructorDeclaration:
|
||
|
|
case SyntaxKind.PropertyDeclaration:
|
||
|
|
case SyntaxKind.GetAccessorDeclaration:
|
||
|
|
case SyntaxKind.SetAccessorDeclaration:
|
||
|
|
case SyntaxKind.InitAccessorDeclaration:
|
||
|
|
return parent;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return body;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static TextSpan SkipAttributes(SyntaxNode syntax)
|
||
|
|
{
|
||
|
|
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00c4: 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)
|
||
|
|
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
switch (syntax.Kind())
|
||
|
|
{
|
||
|
|
case SyntaxKind.MethodDeclaration:
|
||
|
|
{
|
||
|
|
MethodDeclarationSyntax methodDeclarationSyntax = (MethodDeclarationSyntax)(object)syntax;
|
||
|
|
return SkipAttributes(syntax, methodDeclarationSyntax.AttributeLists, methodDeclarationSyntax.Modifiers, default(SyntaxToken), methodDeclarationSyntax.ReturnType);
|
||
|
|
}
|
||
|
|
case SyntaxKind.PropertyDeclaration:
|
||
|
|
{
|
||
|
|
PropertyDeclarationSyntax propertyDeclarationSyntax = (PropertyDeclarationSyntax)(object)syntax;
|
||
|
|
return SkipAttributes(syntax, propertyDeclarationSyntax.AttributeLists, propertyDeclarationSyntax.Modifiers, default(SyntaxToken), propertyDeclarationSyntax.Type);
|
||
|
|
}
|
||
|
|
case SyntaxKind.GetAccessorDeclaration:
|
||
|
|
case SyntaxKind.SetAccessorDeclaration:
|
||
|
|
case SyntaxKind.InitAccessorDeclaration:
|
||
|
|
{
|
||
|
|
AccessorDeclarationSyntax accessorDeclarationSyntax = (AccessorDeclarationSyntax)(object)syntax;
|
||
|
|
return SkipAttributes(syntax, accessorDeclarationSyntax.AttributeLists, accessorDeclarationSyntax.Modifiers, accessorDeclarationSyntax.Keyword, null);
|
||
|
|
}
|
||
|
|
case SyntaxKind.ConstructorDeclaration:
|
||
|
|
{
|
||
|
|
ConstructorDeclarationSyntax constructorDeclarationSyntax = (ConstructorDeclarationSyntax)(object)syntax;
|
||
|
|
return SkipAttributes(syntax, constructorDeclarationSyntax.AttributeLists, constructorDeclarationSyntax.Modifiers, constructorDeclarationSyntax.Identifier, null);
|
||
|
|
}
|
||
|
|
case SyntaxKind.OperatorDeclaration:
|
||
|
|
{
|
||
|
|
OperatorDeclarationSyntax operatorDeclarationSyntax = (OperatorDeclarationSyntax)(object)syntax;
|
||
|
|
return SkipAttributes(syntax, operatorDeclarationSyntax.AttributeLists, operatorDeclarationSyntax.Modifiers, operatorDeclarationSyntax.OperatorKeyword, null);
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
return syntax.Span;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static TextSpan SkipAttributes(SyntaxNode syntax, SyntaxList<AttributeListSyntax> attributes, SyntaxTokenList modifiers, SyntaxToken keyword, TypeSyntax? type)
|
||
|
|
{
|
||
|
|
//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_0061: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_003c: 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_002e: 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)
|
||
|
|
TextSpan span = syntax.Span;
|
||
|
|
if (attributes.Count > 0)
|
||
|
|
{
|
||
|
|
TextSpan val = ((((SyntaxTokenList)(ref modifiers)).Node != null) ? ((SyntaxTokenList)(ref modifiers)).Span : ((((SyntaxToken)(ref keyword)).Node != null) ? ((SyntaxToken)(ref keyword)).Span : ((SyntaxNode)type).Span));
|
||
|
|
return new TextSpan(((TextSpan)(ref val)).Start, ((TextSpan)(ref span)).Length - (((TextSpan)(ref val)).Start - ((TextSpan)(ref span)).Start));
|
||
|
|
}
|
||
|
|
return span;
|
||
|
|
}
|
||
|
|
}
|