1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
22
using System.Threading;
23
using ICSharpCode.NRefactory.CSharp.Resolver;
24
using ICSharpCode.NRefactory.TypeSystem;
25
using ICSharpCode.NRefactory.TypeSystem.Implementation;
26
using NUnit.Framework;
28
namespace ICSharpCode.NRefactory.CSharp.Analysis
31
public class DefiniteAssignmentTests
33
DefiniteAssignmentAnalysis CreateDefiniteAssignmentAnalysis(Statement rootStatement)
35
var resolver = new CSharpAstResolver(new CSharpResolver(new SimpleCompilation(CecilLoaderTests.Mscorlib)), rootStatement);
36
return new DefiniteAssignmentAnalysis(rootStatement, resolver, CancellationToken.None);
40
public void TryFinally()
42
BlockStatement block = new BlockStatement {
43
new TryCatchStatement {
44
TryBlock = new BlockStatement {
45
new GotoStatement("LABEL"),
46
new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(1))
50
Body = new BlockStatement {
51
new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(3))
55
FinallyBlock = new BlockStatement {
56
new AssignmentExpression(new IdentifierExpression("j"), new PrimitiveExpression(5))
59
new LabelStatement { Label = "LABEL" },
62
TryCatchStatement tryCatchStatement = (TryCatchStatement)block.Statements.First();
63
Statement stmt1 = tryCatchStatement.TryBlock.Statements.ElementAt(1);
64
Statement stmt3 = tryCatchStatement.CatchClauses.Single().Body.Statements.Single();
65
Statement stmt5 = tryCatchStatement.FinallyBlock.Statements.Single();
66
LabelStatement label = (LabelStatement)block.Statements.ElementAt(1);
68
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(block);
70
Assert.AreEqual(0, da.UnassignedVariableUses.Count);
71
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(tryCatchStatement));
72
Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusBefore(stmt1));
73
Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(stmt1));
74
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt3));
75
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(stmt3));
76
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt5));
77
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(stmt5));
78
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(tryCatchStatement));
79
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(label));
80
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(label));
83
Assert.AreEqual(0, da.UnassignedVariableUses.Count);
84
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(tryCatchStatement));
85
Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusBefore(stmt1));
86
Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(stmt1));
87
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt3));
88
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(stmt3));
89
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt5));
90
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(stmt5));
91
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(tryCatchStatement));
92
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(label));
93
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(label));
97
public void ConditionalAnd()
99
IfElseStatement ifStmt = new IfElseStatement {
100
Condition = new BinaryOperatorExpression {
101
Left = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.GreaterThan, new PrimitiveExpression(0)),
102
Operator = BinaryOperatorType.ConditionalAnd,
103
Right = new BinaryOperatorExpression {
104
Left = new ParenthesizedExpression {
105
Expression = new AssignmentExpression {
106
Left = new IdentifierExpression("i"),
107
Operator = AssignmentOperatorType.Assign,
108
Right = new IdentifierExpression("y")
111
Operator = BinaryOperatorType.GreaterThanOrEqual,
112
Right = new PrimitiveExpression(0)
115
TrueStatement = new BlockStatement(),
116
FalseStatement = new BlockStatement()
118
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(ifStmt);
120
Assert.AreEqual(0, da.UnassignedVariableUses.Count);
121
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt));
122
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(ifStmt.TrueStatement));
123
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt.FalseStatement));
124
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(ifStmt));
128
public void ConditionalOr()
130
IfElseStatement ifStmt = new IfElseStatement {
131
Condition = new BinaryOperatorExpression {
132
Left = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.GreaterThan, new PrimitiveExpression(0)),
133
Operator = BinaryOperatorType.ConditionalOr,
134
Right = new BinaryOperatorExpression {
135
Left = new ParenthesizedExpression {
136
Expression = new AssignmentExpression {
137
Left = new IdentifierExpression("i"),
138
Operator = AssignmentOperatorType.Assign,
139
Right = new IdentifierExpression("y")
142
Operator = BinaryOperatorType.GreaterThanOrEqual,
143
Right = new PrimitiveExpression(0)
146
TrueStatement = new BlockStatement(),
147
FalseStatement = new BlockStatement()
149
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(ifStmt);
151
Assert.AreEqual(0, da.UnassignedVariableUses.Count);
152
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt));
153
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt.TrueStatement));
154
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(ifStmt.FalseStatement));
155
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(ifStmt));
159
public void WhileTrue()
161
WhileStatement loop = new WhileStatement {
162
Condition = new PrimitiveExpression(true),
163
EmbeddedStatement = new BlockStatement {
164
new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(0)),
168
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(loop);
170
Assert.AreEqual(0, da.UnassignedVariableUses.Count);
171
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop));
172
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.EmbeddedStatement));
173
Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(loop.EmbeddedStatement));
174
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop));
178
public void ForLoop()
180
ForStatement loop = new ForStatement {
182
new ExpressionStatement(
183
new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(0))
186
Condition = new BinaryOperatorExpression(new IdentifierExpression("i"), BinaryOperatorType.LessThan, new PrimitiveExpression(1000)),
188
new ExpressionStatement(
189
new AssignmentExpression {
190
Left = new IdentifierExpression("i"),
191
Operator = AssignmentOperatorType.Add,
192
Right = new IdentifierExpression("j")
196
EmbeddedStatement = new ExpressionStatement(
197
new AssignmentExpression(new IdentifierExpression("j"), new IdentifierExpression("i"))
200
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(loop);
202
Assert.AreEqual(0, da.UnassignedVariableUses.Count);
203
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop));
204
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.Initializers.Single()));
205
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.Initializers.Single()));
206
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBeforeLoopCondition(loop));
207
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(loop.EmbeddedStatement));
208
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.EmbeddedStatement));
209
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(loop.Iterators.Single()));
210
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.Iterators.Single()));
211
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop));
214
Assert.AreEqual(0, da.UnassignedVariableUses.Count);
215
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop));
216
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.Initializers.Single()));
217
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(loop.Initializers.Single()));
218
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBeforeLoopCondition(loop));
219
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.EmbeddedStatement));
220
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.EmbeddedStatement));
221
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(loop.Iterators.Single()));
222
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.Iterators.Single()));
223
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(loop));
227
public void SwitchWithGotoDefault()
229
SwitchStatement @switch = new SwitchStatement {
231
new SwitchSection { // case 0:
232
CaseLabels = { new CaseLabel(new PrimitiveExpression(0)) },
233
Statements = { new GotoDefaultStatement() }
235
new SwitchSection { // default:
236
CaseLabels = { new CaseLabel() },
238
new ExpressionStatement(new AssignmentExpression(new IdentifierExpression("a"), new PrimitiveExpression(1))),
244
SwitchSection case0 = @switch.SwitchSections.ElementAt(0);
245
SwitchSection defaultSection = @switch.SwitchSections.ElementAt(1);
247
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(@switch);
249
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(@switch));
250
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(case0.Statements.First()));
251
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(defaultSection.Statements.First()));
252
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(defaultSection.Statements.Last()));
253
Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(defaultSection.Statements.Last()));
254
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(@switch));
258
public void SwitchWithGotoCase()
260
SwitchStatement @switch = new SwitchStatement {
261
Expression = new PrimitiveExpression(1),
263
new SwitchSection { // case 0:
264
CaseLabels = { new CaseLabel(new PrimitiveExpression(0)) },
265
Statements = { new BreakStatement() }
267
new SwitchSection { // case 1:
268
CaseLabels = { new CaseLabel(new PrimitiveExpression(1)) },
270
new ExpressionStatement(new AssignmentExpression(new IdentifierExpression("a"), new PrimitiveExpression(0))),
271
new GotoCaseStatement { LabelExpression = new PrimitiveExpression(2) }
274
new SwitchSection { // case 2:
275
CaseLabels = { new CaseLabel(new PrimitiveExpression(2)) },
276
Statements = { new BreakStatement() }
280
SwitchSection case0 = @switch.SwitchSections.ElementAt(0);
281
SwitchSection case1 = @switch.SwitchSections.ElementAt(1);
282
SwitchSection case2 = @switch.SwitchSections.ElementAt(2);
284
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(@switch);
286
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(@switch));
287
Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusBefore(case0.Statements.First()));
288
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(case1.Statements.First()));
289
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(case2.Statements.First()));
290
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(@switch));
294
public void ConditionalExpression1()
296
string code = "int a; int b = X ? (a = 1) : 0;";
297
var block = new BlockStatement();
298
block.Statements.AddRange(new CSharpParser().ParseStatements(code));
300
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(block);
302
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(block));
306
public void ConditionalExpression2()
308
string code = "int a; int b = X ? (a = 1) : (a = 2);";
309
var block = new BlockStatement();
310
block.Statements.AddRange(new CSharpParser().ParseStatements(code));
312
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(block);
314
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(block));
318
public void ConditionalExpression3()
320
string code = "int a; int b = true ? (a = 1) : 0;";
321
var block = new BlockStatement();
322
block.Statements.AddRange(new CSharpParser().ParseStatements(code));
324
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(block);
326
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(block));