@@ -71,10 +71,7 @@ private static TranslationSettings GetTranslationSettings(
7171 /// </summary>
7272 /// <param name="expression">The <see cref="Expression"/> to translate.</param>
7373 /// <returns>A source code translation of the given <paramref name="expression"/>.</returns>
74- public string Translate ( Expression expression )
75- {
76- return _globalTranslator . Invoke ( expression , this ) ;
77- }
74+ public string Translate ( Expression expression ) => _globalTranslator . Invoke ( expression , this ) ;
7875
7976 internal string TranslateAsCodeBlock ( Expression expression )
8077 {
@@ -130,7 +127,7 @@ internal ParameterSet TranslateParameters(
130127 public bool IsNotJoinedAssignment ( Expression expression )
131128 {
132129 return ( expression . NodeType != ExpressionType . Assign ) ||
133- ! _analyzer . JoinedAssignments . Contains ( expression ) ;
130+ ! _analyzer . JoinedAssignments . Contains ( expression ) ;
134131 }
135132
136133 /// <summary>
@@ -143,9 +140,19 @@ public bool IsNotJoinedAssignment(Expression expression)
143140 /// otherwise false.
144141 /// </returns>
145142 public bool IsReferencedByGoto ( LabelTarget labelTarget )
146- {
147- return _analyzer . NamedLabelTargets . Contains ( labelTarget ) ;
148- }
143+ => _analyzer . NamedLabelTargets . Contains ( labelTarget ) ;
144+
145+ /// <summary>
146+ /// Returns a value indicating whether the given <paramref name="goto"/> goes to the
147+ /// final statement in a block, and so should be rendered as a return statement.
148+ /// </summary>
149+ /// <param name="goto">The GotoExpression for which to make the determination.</param>
150+ /// <returns>
151+ /// True if the given <paramref name="goto"/> goes to the final statement in a block,
152+ /// otherwise false.
153+ /// </returns>
154+ public bool GoesToReturnLabel ( GotoExpression @goto )
155+ => _analyzer . GotoReturnGotos . Contains ( @goto ) ;
149156
150157 /// <summary>
151158 /// Returns a value indicating whether the given <paramref name="methodCall"/> is part of a chain
@@ -161,11 +168,14 @@ public bool IsPartOfMethodCallChain(Expression methodCall)
161168 return _analyzer . ChainedMethodCalls . Contains ( methodCall ) ;
162169 }
163170
171+ #region Helper Class
172+
164173 private class ExpressionAnalysisVisitor : ExpressionVisitor
165174 {
166175 private readonly Dictionary < BinaryExpression , object > _constructsByAssignment ;
167176 private readonly List < ParameterExpression > _accessedVariables ;
168177 private readonly List < Expression > _assignedAssignments ;
178+ private readonly Stack < BlockExpression > _blocks ;
169179 private readonly Stack < object > _constructs ;
170180
171181 private ExpressionAnalysisVisitor ( )
@@ -176,7 +186,9 @@ private ExpressionAnalysisVisitor()
176186 JoinedAssignments = new List < BinaryExpression > ( ) ;
177187 _assignedAssignments = new List < Expression > ( ) ;
178188 NamedLabelTargets = new List < LabelTarget > ( ) ;
189+ GotoReturnGotos = new List < GotoExpression > ( ) ;
179190 ChainedMethodCalls = new List < MethodCallExpression > ( ) ;
191+ _blocks = new Stack < BlockExpression > ( ) ;
180192 _constructs = new Stack < object > ( ) ;
181193 }
182194
@@ -226,6 +238,8 @@ private static Expression GetCoreExpression(Expression expression)
226238
227239 public ICollection < LabelTarget > NamedLabelTargets { get ; }
228240
241+ public ICollection < GotoExpression > GotoReturnGotos { get ; }
242+
229243 public List < MethodCallExpression > ChainedMethodCalls { get ; }
230244
231245 protected override Expression VisitParameter ( ParameterExpression variable )
@@ -263,6 +277,17 @@ protected override Expression VisitParameter(ParameterExpression variable)
263277 return base . VisitParameter ( variable ) ;
264278 }
265279
280+ protected override Expression VisitBlock ( BlockExpression block )
281+ {
282+ _blocks . Push ( block ) ;
283+
284+ var result = base . VisitBlock ( block ) ;
285+
286+ _blocks . Pop ( ) ;
287+
288+ return result ;
289+ }
290+
266291 protected override Expression VisitBinary ( BinaryExpression binary )
267292 {
268293 if ( ( binary . NodeType == ExpressionType . Assign ) &&
@@ -320,11 +345,27 @@ private void AddAssignmentIfAppropriate(Expression assignedValue)
320345
321346 protected override Expression VisitGoto ( GotoExpression @goto )
322347 {
323- if ( @goto . Kind == GotoExpressionKind . Goto )
348+ if ( @goto . Kind != GotoExpressionKind . Goto )
349+ {
350+ return base . VisitGoto ( @goto ) ;
351+ }
352+
353+ var currentBlockFinalExpression = _blocks . Peek ( ) ? . Expressions . Last ( ) ;
354+
355+ if ( currentBlockFinalExpression ? . NodeType == ExpressionType . Label )
324356 {
325- NamedLabelTargets . Add ( @goto . Target ) ;
357+ var returnLabel = ( LabelExpression ) currentBlockFinalExpression ;
358+
359+ if ( @goto . Target == returnLabel . Target )
360+ {
361+ GotoReturnGotos . Add ( @goto ) ;
362+
363+ return base . VisitGoto ( @goto ) ;
364+ }
326365 }
327366
367+ NamedLabelTargets . Add ( @goto . Target ) ;
368+
328369 return base . VisitGoto ( @goto ) ;
329370 }
330371
@@ -398,5 +439,7 @@ private TResult VisitConstruct<TArg, TResult>(TArg expression, Func<TArg, TResul
398439
399440 #endregion
400441 }
442+
443+ #endregion
401444 }
402445}
0 commit comments