~ubuntu-branches/ubuntu/utopic/monodevelop/utopic

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/UnreachableCodeIssue.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-10-10 14:50:04 UTC
  • mfrom: (10.3.4)
  • Revision ID: package-import@ubuntu.com-20131010145004-80l130sny21b17sb
Tags: 4.0.12+dfsg-1
* [5dcb6e1] Fix debian/watch for new source tarball name format
* [5c68cb5] Refresh list of files removed by get-orig-source to 
  reflect 4.0.12
* [96d60a0] Imported Upstream version 4.0.12+dfsg
* [b989752] Refresh debian/patches/no_appmenu to ensure it applies
* [2a4c351] Ensure every assembly in external/ is cleaned properly
* [92762f7] Add more excluded Mac-specific modulerefs
* [bc698ba] Add symlinks to NUnit assemblies (Closes: #714246)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// 
2
 
// UnreachableCodeIssue.cs
3
 
// 
4
 
// Author:
5
 
//      Mansheng Yang <lightyang0@gmail.com>
6
 
// 
7
 
// Copyright (c) 2012 Mansheng Yang <lightyang0@gmail.com>
8
 
// 
9
 
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
 
// of this software and associated documentation files (the "Software"), to deal
11
 
// in the Software without restriction, including without limitation the rights
12
 
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 
// copies of the Software, and to permit persons to whom the Software is
14
 
// furnished to do so, subject to the following conditions:
15
 
// 
16
 
// The above copyright notice and this permission notice shall be included in
17
 
// all copies or substantial portions of the Software.
18
 
// 
19
 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
 
// THE SOFTWARE.
26
 
 
27
 
using System;
28
 
using System.Collections.Generic;
29
 
using ICSharpCode.NRefactory.CSharp.Analysis;
30
 
using System.Linq;
31
 
 
32
 
namespace ICSharpCode.NRefactory.CSharp.Refactoring
33
 
{
34
 
        [IssueDescription ("Code is unreachable",
35
 
                                                Description = "Code is unreachable.",
36
 
                                                Category = IssueCategories.Redundancies,
37
 
                                                Severity = Severity.Warning,
38
 
                                                IssueMarker = IssueMarker.GrayOut)]
39
 
        public class UnreachableCodeIssue : ICodeIssueProvider
40
 
        {
41
 
                public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context)
42
 
                {
43
 
                        return new GatherVisitor (context).GetIssues ();
44
 
                }
45
 
 
46
 
                class GatherVisitor : GatherVisitorBase<UnreachableCodeIssue>
47
 
                {
48
 
                        HashSet<AstNode> unreachableNodes;
49
 
 
50
 
                        public GatherVisitor (BaseRefactoringContext ctx)
51
 
                                : base (ctx)
52
 
                        {
53
 
                                unreachableNodes = new HashSet<AstNode> ();
54
 
                        }
55
 
 
56
 
                        public override void VisitMethodDeclaration (MethodDeclaration methodDeclaration)
57
 
                        {
58
 
                                StatementIssueCollector.Collect (this, methodDeclaration.Body);
59
 
 
60
 
                                base.VisitMethodDeclaration (methodDeclaration);
61
 
                        }
62
 
 
63
 
                        public override void VisitLambdaExpression (LambdaExpression lambdaExpression)
64
 
                        {
65
 
                                var blockStatement = lambdaExpression.Body as BlockStatement;
66
 
                                if (blockStatement != null)
67
 
                                        StatementIssueCollector.Collect (this, blockStatement);
68
 
 
69
 
                                base.VisitLambdaExpression (lambdaExpression);
70
 
                        }
71
 
 
72
 
                        public override void VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression)
73
 
                        {
74
 
                                StatementIssueCollector.Collect (this, anonymousMethodExpression.Body);
75
 
 
76
 
                                base.VisitAnonymousMethodExpression (anonymousMethodExpression);
77
 
                        }
78
 
 
79
 
                        public override void VisitConditionalExpression (ConditionalExpression conditionalExpression)
80
 
                        {
81
 
                                var resolveResult = ctx.Resolve (conditionalExpression.Condition);
82
 
                                if (resolveResult.ConstantValue is bool) {
83
 
                                        var condition = (bool)resolveResult.ConstantValue;
84
 
                                        Expression resultExpr, unreachableExpr;
85
 
                                        if (condition) {
86
 
                                                resultExpr = conditionalExpression.TrueExpression;
87
 
                                                unreachableExpr = conditionalExpression.FalseExpression;
88
 
                                        } else {
89
 
                                                resultExpr = conditionalExpression.FalseExpression;
90
 
                                                unreachableExpr = conditionalExpression.TrueExpression;
91
 
                                        }
92
 
                                        unreachableNodes.Add (unreachableExpr);
93
 
 
94
 
                                        AddIssue (unreachableExpr, ctx.TranslateString ("Remove unreachable code"),
95
 
                                                script => script.Replace (conditionalExpression, resultExpr.Clone ()));
96
 
                                }
97
 
                                base.VisitConditionalExpression (conditionalExpression);
98
 
                        }
99
 
 
100
 
                        protected override void VisitChildren (AstNode node)
101
 
                        {
102
 
                                // skip unreachable nodes
103
 
                                if (!unreachableNodes.Contains (node))
104
 
                                        base.VisitChildren (node);
105
 
                        }
106
 
 
107
 
                        class StatementIssueCollector : DepthFirstAstVisitor
108
 
                        {
109
 
                                GatherVisitor visitor;
110
 
                                ReachabilityAnalysis reachability;
111
 
                                HashSet<Statement> collectedStatements;
112
 
 
113
 
                                private StatementIssueCollector (GatherVisitor visitor, ReachabilityAnalysis reachability)
114
 
                                {
115
 
                                        collectedStatements = new HashSet<Statement> ();
116
 
                                        this.visitor = visitor;
117
 
                                        this.reachability = reachability;
118
 
                                }
119
 
 
120
 
                                public static void Collect (GatherVisitor visitor, BlockStatement body)
121
 
                                {
122
 
                                        if (body.IsNull)
123
 
                                                return;
124
 
                                        var reachability = visitor.ctx.CreateReachabilityAnalysis (body);
125
 
 
126
 
                                        var collector = new StatementIssueCollector (visitor, reachability);
127
 
                                        collector.VisitBlockStatement (body);
128
 
                                }
129
 
 
130
 
                                protected override void VisitChildren (AstNode node)
131
 
                                {
132
 
                                        var statement = node as Statement;
133
 
                                        if (statement == null || !AddStatement (statement))
134
 
                                                base.VisitChildren (node);
135
 
                                }
136
 
 
137
 
                                bool AddStatement(Statement statement)
138
 
                                {
139
 
                                        if (reachability.IsReachable (statement))
140
 
                                                return false;
141
 
                                        if (collectedStatements.Contains (statement))
142
 
                                                return true;
143
 
                                        var prevEnd = statement.GetPrevNode (n => !(n is NewLineNode)).EndLocation;
144
 
 
145
 
                                        // group multiple continuous statements into one issue
146
 
                                        var start = statement.StartLocation;
147
 
                                        collectedStatements.Add (statement);
148
 
                                        visitor.unreachableNodes.Add (statement);
149
 
                                        while (statement.GetNextSibling (s => s is Statement) != null) {
150
 
                                                statement = (Statement)statement.GetNextSibling (s => s is Statement);
151
 
                                                collectedStatements.Add (statement);
152
 
                                                visitor.unreachableNodes.Add (statement);
153
 
                                        }
154
 
                                        var end = statement.EndLocation;
155
 
 
156
 
                                        var removeAction = new CodeAction (visitor.ctx.TranslateString ("Remove unreachable code"),
157
 
                                                script =>
158
 
                                                {
159
 
                                                        var startOffset = script.GetCurrentOffset (prevEnd);
160
 
                                                        var endOffset = script.GetCurrentOffset (end);
161
 
                                                        script.RemoveText (startOffset, endOffset - startOffset);
162
 
                                                }, collectedStatements.First().StartLocation, collectedStatements.Last().EndLocation);
163
 
                                        var commentAction = new CodeAction(visitor.ctx.TranslateString("Comment unreachable code"),
164
 
                                                script =>
165
 
                                        {
166
 
                                                var startOffset = script.GetCurrentOffset(prevEnd);
167
 
                                                script.InsertText(startOffset, Environment.NewLine + "/*");
168
 
                                                var endOffset = script.GetCurrentOffset(end);
169
 
                                                script.InsertText(endOffset, Environment.NewLine + "*/");
170
 
                                        }, collectedStatements.First().StartLocation, collectedStatements.Last().EndLocation);
171
 
                                        var actions = new [] { removeAction, commentAction };
172
 
                                        visitor.AddIssue (start, end, visitor.ctx.TranslateString ("Code is unreachable"), actions);
173
 
                                        return true;
174
 
                                }
175
 
 
176
 
                                // skip lambda and anonymous method
177
 
                                public override void VisitLambdaExpression (LambdaExpression lambdaExpression)
178
 
                                {
179
 
                                }
180
 
 
181
 
                                public override void VisitAnonymousMethodExpression (
182
 
                                        AnonymousMethodExpression anonymousMethodExpression)
183
 
                                {
184
 
                                }
185
 
                        }
186
 
                }
187
 
        }
188
 
}