Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Old SE: Handle unsupported syntax gracefully #6768

Merged
merged 22 commits into from Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c6704f1
Fix unsupported pattern kinds and add tests
martin-strecker-sonarsource Feb 17, 2023
a0020f2
Remove ifs and throw statement from BuildPatternExpression
martin-strecker-sonarsource Feb 21, 2023
93d37ca
Change handling of unsupported pattern to align with exisitng logic
martin-strecker-sonarsource Feb 21, 2023
270968c
Align test to exisitng implementation
martin-strecker-sonarsource Feb 21, 2023
4353d2c
Better exception validation
martin-strecker-sonarsource Feb 21, 2023
512c549
Fix test for type pattern
martin-strecker-sonarsource Feb 21, 2023
718d128
Fix test for type pattern
martin-strecker-sonarsource Feb 21, 2023
8a04810
Fix test in debug mode
martin-strecker-sonarsource Feb 21, 2023
6345e4f
Improve ExplodedGraph_IsPattern_Parentesized test
martin-strecker-sonarsource Feb 21, 2023
eb75766
Change test name
martin-strecker-sonarsource Feb 21, 2023
15735f9
Fix failing test on Release
martin-strecker-sonarsource Feb 21, 2023
9d278e8
Simplify ExplodedGraph_SwitchStatement_TypePattern test
martin-strecker-sonarsource Feb 21, 2023
b455abe
Fix code smell
martin-strecker-sonarsource Feb 21, 2023
774c4cd
Add TypePattern as unsupported
martin-strecker-sonarsource Feb 21, 2023
2c1dd92
Add test in S2259 for parenthesized pattern
martin-strecker-sonarsource Feb 23, 2023
0d8026e
Add more pattern for switch cases
martin-strecker-sonarsource Feb 23, 2023
0e21b8f
Remove commentd
martin-strecker-sonarsource Feb 24, 2023
7360dc9
Remove comments
martin-strecker-sonarsource Feb 24, 2023
b0a8ade
Fix test to cover switch cases instead of is pattern
martin-strecker-sonarsource Feb 24, 2023
8b43176
Remove throw in SonarExplodedGraph
martin-strecker-sonarsource Feb 28, 2023
4c3daa3
Code review
martin-strecker-sonarsource Feb 28, 2023
1f58b1a
Remove all pattern cases and just do default: nothing.
martin-strecker-sonarsource Feb 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -1286,6 +1286,36 @@ private Block BuildPatternExpression(PatternSyntaxWrapper patternSyntaxWrapper,
currentBlock.ReversedInstructions.Add(patternSyntaxWrapper);
return currentBlock;
}
else if (ParenthesizedPatternSyntaxWrapper.IsInstance(patternSyntaxWrapper))
{
var parenthesized = (ParenthesizedPatternSyntaxWrapper)patternSyntaxWrapper;
return BuildPatternExpression(parenthesized.Pattern, currentBlock);
}
else if (BinaryPatternSyntaxWrapper.IsInstance(patternSyntaxWrapper))
{
// Unsupported
return currentBlock;
}
else if (UnaryPatternSyntaxWrapper.IsInstance(patternSyntaxWrapper))
{
// Unsupported
return currentBlock;
}
else if (VarPatternSyntaxWrapper.IsInstance(patternSyntaxWrapper))
{
// Unsupported
return currentBlock;
}
else if (RelationalPatternSyntaxWrapper.IsInstance(patternSyntaxWrapper))
{
// Unsupported
return currentBlock;
}
else if (ListPatternSyntaxWrapper.IsInstance(patternSyntaxWrapper))
{
// Unsupported
return currentBlock;
}
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved

throw new NotSupportedException($"{patternSyntaxWrapper.SyntaxNode.Kind()}");
}
Expand Down
Expand Up @@ -515,7 +515,14 @@ protected override void VisitInstruction(ExplodedGraphNode node)
}
else
{
throw new NotSupportedException($"{instruction.Kind()}");
// Unsupported patten kinds:
// * ParenthesizedPattern
// * BinaryPattern
// * UnaryPattern
// * VarPattern
// * RelationalPattern
// * ListPattern
// * SlicePattern
}
break;

Expand Down
Expand Up @@ -28,7 +28,6 @@
using SonarAnalyzer.LiveVariableAnalysis.CSharp;
using SonarAnalyzer.SymbolicExecution.Constraints;
using SonarAnalyzer.SymbolicExecution.Sonar;
using SonarAnalyzer.SymbolicExecution.Sonar.Constraints;
using SonarAnalyzer.UnitTest.CFG.Sonar;
using SonarAnalyzer.UnitTest.Helpers;

Expand Down Expand Up @@ -901,6 +900,249 @@ public void ExplodedGraph_IsPattern_WithPositionalPattern()
context.WalkWithInstructions(4);
}

[TestMethod]
pavel-mikula-sonarsource marked this conversation as resolved.
Show resolved Hide resolved
public void ExplodedGraph_IsPattern_Parentesized()
{
const string testInput = @"var x = obj is (string s);";

var context = new ExplodedGraphContext(testInput);
var sSymbol = context.GetSymbol("s", ExplodedGraphContext.SymbolType.Declaration);

context.ExplodedGraph.InstructionProcessed += (sender, args) =>
{
var instruction = args.Instruction.ToString();

switch (instruction)
{
case "obj":
args.ProgramState.GetSymbolValue(sSymbol).Should().BeNull();
break;

case "obj is (string s)":
args.ProgramState.GetSymbolValue(sSymbol).Should().BeNull();
args.ProgramState.HasValue.Should().BeTrue();
break;

case "x = obj is (string s)":
args.ProgramState.GetSymbolValue(sSymbol).Should().BeNull();
args.ProgramState.HasValue.Should().BeFalse();
break;

default:
throw new NotImplementedException();
}
};

context.WalkWithInstructions(3);
}

[TestMethod]
public void ExplodedGraph_IsPattern_OrPattern_NotSupported()
{
const string testInput = "var x = obj is 1 or 2;";

var context = new ExplodedGraphContext(testInput);
context.ExplodedGraph.InstructionProcessed += (sender, args) =>
{
var instruction = args.Instruction.ToString();

switch (instruction)
{
case "obj":
case "obj is 1 or 2":
case "x = obj is 1 or 2":
break;
default:
throw new NotImplementedException();
}
};

context.WalkWithInstructions(3);
}

[TestMethod]
public void ExplodedGraph_IsPattern_AndPattern_NotSupported()
{
const string testInput = "var x = obj is 1 and 2;";

var context = new ExplodedGraphContext(testInput);
context.ExplodedGraph.InstructionProcessed += (sender, args) =>
{
var instruction = args.Instruction.ToString();

switch (instruction)
{
case "obj":
case "obj is 1 and 2":
case "x = obj is 1 and 2":
break;
default:
throw new NotImplementedException();
}
};

context.WalkWithInstructions(3);
}

[TestMethod]
public void ExplodedGraph_IsPattern_NotPattern_NotSupported()
{
const string testInput = "var x = obj is not 1;";

var context = new ExplodedGraphContext(testInput);
context.ExplodedGraph.InstructionProcessed += (sender, args) =>
{
var instruction = args.Instruction.ToString();

switch (instruction)
{
case "obj":
case "obj is not 1":
case "x = obj is not 1":
break;
default:
throw new NotImplementedException();
}
};

context.WalkWithInstructions(3);
}

[TestMethod]
public void ExplodedGraph_IsPattern_VarPattern_NotSupported()
{
const string testInput = """
var x = obj is var i;
i++;
""";

var context = new ExplodedGraphContext(testInput);
var symbolNotFound = () => context.GetSymbol("o", ExplodedGraphContext.SymbolType.Declaration);
symbolNotFound.Should().Throw<InvalidOperationException>("var pattern is not supported");

context.ExplodedGraph.InstructionProcessed += (sender, args) =>
{
var instruction = args.Instruction.ToString();

switch (instruction)
{
case "obj":
case "obj is var i":
case "x = obj is var i":
case "i":
case "i++":
break;

default:
throw new NotImplementedException(instruction);
}
};
context.WalkWithInstructions(5);
}

[TestMethod]
public void ExplodedGraph_IsPattern_RelationalPattern_NotSupported()
{
const string testInput = """
var x = obj is > 5;
""";

var context = new ExplodedGraphContext(testInput);

context.ExplodedGraph.InstructionProcessed += (sender, args) =>
{
var instruction = args.Instruction.ToString();

switch (instruction)
{
case "obj":
case "obj is > 5":
case "x = obj is > 5":
break;
default:
throw new NotImplementedException(instruction);
}
};
context.WalkWithInstructions(3);
}

[TestMethod]
public void ExplodedGraph_IsPattern_ListPattern_NotSupported()
{
const string testInput = """
var x = new object[] { } is [] empty;
empty.ToString();
""";

var context = new ExplodedGraphContext(testInput);
var emptySymbol = context.GetSymbol("empty", ExplodedGraphContext.SymbolType.Declaration);

context.ExplodedGraph.InstructionProcessed += (sender, args) =>
{
var instruction = args.Instruction.ToString();

switch (instruction)
{
case "":
args.ProgramState.GetSymbolValue(emptySymbol).Should().BeNull();
break;
case "object[]":
args.ProgramState.GetSymbolValue(emptySymbol).Should().BeNull();
break;
case "new object[] { }":
args.ProgramState.GetSymbolValue(emptySymbol).Should().BeNull();
break;
case "{ }":
args.ProgramState.GetSymbolValue(emptySymbol).Should().BeNull();
break;
case "new object[] { } is [] empty":
args.ProgramState.GetSymbolValue(emptySymbol).Should().BeNull();
break;
case "x = new object[] { } is [] empty":
args.ProgramState.GetSymbolValue(emptySymbol).Should().BeNull();
break;
case "empty":
args.ProgramState.GetSymbolValue(emptySymbol).Should().BeNull();
break;
case "empty.ToString":
args.ProgramState.GetSymbolValue(emptySymbol).Should().BeNull();
break;
case "empty.ToString()":
args.ProgramState.GetSymbolValue(emptySymbol).Should().BeNull();
break;
default:
throw new NotImplementedException(instruction);
}
};
context.WalkWithInstructions(9);
}

[TestMethod]
public void ExplodedGraph_SwitchExpression_TypePattern_NotSupported()
{
const string testInput = """
var x = new object() switch { Exception => true };
""";

var context = new ExplodedGraphContext(testInput);

context.ExplodedGraph.InstructionProcessed += (sender, args) =>
{
var instruction = args.Instruction.ToString();

switch (instruction)
{
case "Exception":
case "true":
case "x = new object() switch { Exception => true }":
break;
default:
throw new NotImplementedException(instruction);
}
};
context.WalkWithInstructions(3);
}

[TestMethod]
public void ExplodedGraph_SwitchExpressionVisit()
{
Expand Down