@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -119,7 +119,7 @@ namespace ICSharpCode.Decompiler.CSharp
var blockContainer = blockStatement . Annotation < BlockContainer > ( ) ;
if ( blockContainer ! = null )
{
StartSequencePoint ( blockStatement . LBraceToken ) ;
StartSequencePoint ( blockStatement ) ;
int intervalStart ;
if ( blockContainer . Parent is TryCatchHandler handler & & ! handler . ExceptionSpecifierILRange . IsEmpty )
{
@ -140,7 +140,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -140,7 +140,7 @@ namespace ICSharpCode.Decompiler.CSharp
intervals . Add ( interval ) ;
current . Intervals . AddRange ( intervals ) ;
current . Function = blockContainer . Ancestors . OfType < ILFunction > ( ) . FirstOrDefault ( ) ;
EndSequencePoint ( blockStatement . LBraceToken . StartLocation , blockStatement . LBraceToken . EndLocation ) ;
EndSequencePoint ( blockStatement . StartLocation , Offset ( blockStatement . StartLocation , 1 ) ) ;
}
else
{
@ -157,9 +157,9 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -157,9 +157,9 @@ namespace ICSharpCode.Decompiler.CSharp
var implicitReturn = blockStatement . Annotation < ImplicitReturnAnnotation > ( ) ;
if ( implicitReturn ! = null & & ! isEnhancedUsing )
{
StartSequencePoint ( blockStatement . RBraceToken ) ;
StartSequencePoint ( blockStatement ) ;
AddToSequencePoint ( implicitReturn . Leave ) ;
EndSequencePoint ( blockStatement . RBraceToken . StartLocation , blockStatement . RBraceToken . EndLocation ) ;
EndSequencePoint ( Offset ( blockStatement . EndLocation , - 1 ) , blockStatement . EndLocation ) ;
}
}
@ -214,7 +214,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -214,7 +214,7 @@ namespace ICSharpCode.Decompiler.CSharp
// add switch statement itself to sequence point
// (call only after the sections are visited)
AddToSequencePoint ( switchStatement ) ;
EndSequencePoint ( switchStatement . StartLocation , switchStatement . RParToke n. EndLocation ) ;
EndSequencePoint ( switchStatement . StartLocation , Offset ( switchStatement . Expressio n. EndLocation , 1 ) ) ;
}
public override void VisitSwitchSection ( Syntax . SwitchSection switchSection )
@ -298,7 +298,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -298,7 +298,7 @@ namespace ICSharpCode.Decompiler.CSharp
if ( usingStatement . IsEnhanced )
EndSequencePoint ( usingStatement . StartLocation , usingStatement . ResourceAcquisition . EndLocation ) ;
else
EndSequencePoint ( usingStatement . StartLocation , usingStatement . RParToke n . EndLocation ) ;
EndSequencePoint ( usingStatement . StartLocation , Offset ( usingStatement . ResourceAcquisitio n . EndLocation , 1 ) ) ;
}
public override void VisitForeachStatement ( ForeachStatement foreachStatement )
@ -317,7 +317,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -317,7 +317,7 @@ namespace ICSharpCode.Decompiler.CSharp
StartSequencePoint ( foreachStatement ) ;
AddToSequencePoint ( foreachInfo . MoveNextCall ) ;
EndSequencePoint ( foreachStatement . InToken . StartLocation , foreachStatement . InToke n. EndLocation ) ;
EndSequencePoint ( Offset ( foreachStatement . VariableDesignation . EndLocation , 1 ) , Offset ( foreachStatement . VariableDesignatio n. EndLocation , 1 + "in" . Length ) ) ;
StartSequencePoint ( foreachStatement ) ;
AddToSequencePoint ( foreachInfo . GetCurrentCall ) ;
@ -332,7 +332,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -332,7 +332,7 @@ namespace ICSharpCode.Decompiler.CSharp
lockStatement . Expression . AcceptVisitor ( this ) ;
VisitAsSequencePoint ( lockStatement . EmbeddedStatement ) ;
AddToSequencePoint ( lockStatement ) ;
EndSequencePoint ( lockStatement . StartLocation , lockStatement . RParToke n. EndLocation ) ;
EndSequencePoint ( lockStatement . StartLocation , Offset ( lockStatement . Expressio n. EndLocation , 1 ) ) ;
}
public override void VisitIfElseStatement ( IfElseStatement ifElseStatement )
@ -342,7 +342,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -342,7 +342,7 @@ namespace ICSharpCode.Decompiler.CSharp
VisitAsSequencePoint ( ifElseStatement . TrueStatement ) ;
VisitAsSequencePoint ( ifElseStatement . FalseStatement ) ;
AddToSequencePoint ( ifElseStatement ) ;
EndSequencePoint ( ifElseStatement . StartLocation , ifElseStatement . RParToke n. EndLocation ) ;
EndSequencePoint ( ifElseStatement . StartLocation , Offset ( ifElseStatement . Conditio n. EndLocation , 1 ) ) ;
}
public override void VisitWhileStatement ( WhileStatement whileStatement )
@ -351,7 +351,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -351,7 +351,7 @@ namespace ICSharpCode.Decompiler.CSharp
whileStatement . Condition . AcceptVisitor ( this ) ;
VisitAsSequencePoint ( whileStatement . EmbeddedStatement ) ;
AddToSequencePoint ( whileStatement ) ;
EndSequencePoint ( whileStatement . StartLocation , whileStatement . RParToke n. EndLocation ) ;
EndSequencePoint ( whileStatement . StartLocation , Offset ( whileStatement . Conditio n. EndLocation , 1 ) ) ;
}
public override void VisitDoWhileStatement ( DoWhileStatement doWhileStatement )
@ -360,7 +360,8 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -360,7 +360,8 @@ namespace ICSharpCode.Decompiler.CSharp
VisitAsSequencePoint ( doWhileStatement . EmbeddedStatement ) ;
doWhileStatement . Condition . AcceptVisitor ( this ) ;
AddToSequencePoint ( doWhileStatement ) ;
EndSequencePoint ( doWhileStatement . WhileToken . StartLocation , doWhileStatement . RParToken . EndLocation ) ;
// The trailing 'while (' precedes the condition: "while" + ' ' + '('.
EndSequencePoint ( Offset ( doWhileStatement . Condition . StartLocation , - ( "while" . Length + 2 ) ) , Offset ( doWhileStatement . Condition . EndLocation , 1 ) ) ;
}
public override void VisitFixedStatement ( FixedStatement fixedStatement )
@ -389,17 +390,18 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -389,17 +390,18 @@ namespace ICSharpCode.Decompiler.CSharp
var tryCatchHandler = catchClause . Annotation < TryCatchHandler > ( ) ;
if ( tryCatchHandler ! = null & & ! tryCatchHandler . ExceptionSpecifierILRange . IsEmpty )
{
StartSequencePoint ( catchClause . CatchToken ) ;
StartSequencePoint ( catchClause ) ;
var function = tryCatchHandler . Ancestors . OfType < ILFunction > ( ) . FirstOrDefault ( ) ;
AddToSequencePointRaw ( function , new [ ] { tryCatchHandler . ExceptionSpecifierILRange } ) ;
EndSequencePoint ( catchClause . CatchToken . StartLocation , catchClause . RParToken . IsNull ? catchClause . CatchToken . EndLocation : catchClause . RParToken . EndLocation ) ;
EndSequencePoint ( catchClause . StartLocation , CatchHeaderEnd ( catchClause ) ) ;
}
}
else
{
StartSequencePoint ( catchClause . WhenToken ) ;
StartSequencePoint ( catchClause ) ;
AddToSequencePoint ( catchClause . Condition ) ;
EndSequencePoint ( catchClause . WhenToken . StartLocation , catchClause . CondRParToken . EndLocation ) ;
// The 'when (' precedes the condition: "when" + ' ' + '('.
EndSequencePoint ( Offset ( catchClause . Condition . StartLocation , - ( "when" . Length + 2 ) ) , Offset ( catchClause . Condition . EndLocation , 1 ) ) ;
}
VisitAsSequencePoint ( catchClause . Body ) ;
}
@ -413,6 +415,29 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -413,6 +415,29 @@ namespace ICSharpCode.Decompiler.CSharp
current = new StatePerSequencePoint ( primaryNode ) ;
}
// Token nodes are not part of the AST, so the brace/parenthesis/keyword positions that
// statement-header sequence points address are derived from the surrounding real nodes plus a
// fixed column offset. The offsets assume the decompiler's own formatting -- one space before a
// header's '(' and none within it, single spaces around keywords -- which holds because output is
// always printed with DecompilerSettings.CSharpFormattingOptions (CreateAllman plus those
// overrides). Sequence points are only valid under that formatting: printing the tree with a
// customized CSharpFormattingOptions (e.g. SpacesWithinWhileParentheses) before generating them
// would shift these columns and produce wrong PDB line/column mappings.
static TextLocation Offset ( TextLocation location , int columns )
{
return new TextLocation ( location . Line , location . Column + columns ) ;
}
// End of a 'catch' header: the ')' after the variable (or the type, if unnamed), or just past
// the 'catch' keyword when there is no exception specifier.
static TextLocation CatchHeaderEnd ( CatchClause catchClause )
{
if ( catchClause . Type . IsNull )
return Offset ( catchClause . StartLocation , "catch" . Length ) ;
AstNode beforeRParen = catchClause . VariableNameToken . IsNull ? catchClause . Type : catchClause . VariableNameToken ;
return Offset ( beforeRParen . EndLocation , 1 ) ;
}
void EndSequencePoint ( TextLocation startLocation , TextLocation endLocation )
{
Debug . Assert ( ! startLocation . IsEmpty , "missing startLocation" ) ;