Esempio n. 1
0
        public void ExplodedGraph_NullCoalesceAssignmentVisit()
        {
            const string testInput = @"string s = null; s ??= ""N/A""; s.ToString();";
            var          context   = new ExplodedGraphContext(testInput);
            var          sSymbol   = context.GetSymbol("s");

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                var instruction = args.Instruction.ToString();
                switch (instruction)
                {
                case "s = null":
                    args.ProgramState.GetSymbolValue(sSymbol).Should().NotBeNull();
                    sSymbol.HasConstraint(ObjectConstraint.NotNull, args.ProgramState).Should().BeFalse();
                    break;

                case "s ??= \"N/A\"":
                    args.ProgramState.GetSymbolValue(sSymbol).Should().NotBeNull();
                    sSymbol.HasConstraint(ObjectConstraint.NotNull, args.ProgramState).Should().BeTrue();
                    break;
                }
            };

            context.WalkWithInstructions(8);
        }
Esempio n. 2
0
        public void ExplodedGraph_SequentialInput()
        {
            const string testInput = "var a = true; var b = false; b = !b; a = (b);";
            var          context   = new ExplodedGraphContext(testInput);
            var          aSymbol   = context.GetSymbol("a");
            var          bSymbol   = context.GetSymbol("b");

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                if (args.Instruction.ToString() == "a = true")
                {
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "b = false")
                {
                    args.ProgramState.GetSymbolValue(bSymbol).Should().Be(SymbolicValue.False);
                }
                if (args.Instruction.ToString() == "b = !b")
                {
                    args.ProgramState.GetSymbolValue(bSymbol).Should().NotBe(SymbolicValue.False);
                    args.ProgramState.GetSymbolValue(bSymbol).Should().NotBe(SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "a = (b)")
                {
                    args.ProgramState.GetSymbolValue(bSymbol)
                    .Should().Be(args.ProgramState.GetSymbolValue(aSymbol));
                }
            };

            context.WalkWithInstructions(9);
        }
Esempio n. 3
0
        public void ExplodedGraph_DefaultLiteral()
        {
            const string testInput = "var i = default(int); int j = default; System.IO.File k = default;";
            var          context   = new ExplodedGraphContext(testInput);
            var          iSymbol   = context.GetSymbol("i");
            var          jSymbol   = context.GetSymbol("j");
            var          kSymbol   = context.GetSymbol("k");

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                var instruction = args.Instruction.ToString();
                if (instruction == "i = default(int)")
                {
                    args.ProgramState.GetSymbolValue(iSymbol).Should().NotBeNull();
                    iSymbol.HasConstraint(ObjectConstraint.NotNull, args.ProgramState).Should().BeTrue();
                }
                if (instruction == "j = default")
                {
                    args.ProgramState.GetSymbolValue(jSymbol).Should().NotBeNull();
                    jSymbol.HasConstraint(ObjectConstraint.NotNull, args.ProgramState).Should().BeTrue();
                }
                if (instruction == "k = default")
                {
                    args.ProgramState.GetSymbolValue(kSymbol).Should().NotBeNull();
                    kSymbol.HasConstraint(ObjectConstraint.NotNull, args.ProgramState).Should().BeFalse();
                    kSymbol.HasConstraint(ObjectConstraint.Null, args.ProgramState).Should().BeTrue();
                }
            };

            context.WalkWithInstructions(6);
        }
Esempio n. 4
0
        public void ExplodedGraph_AllBranchesVisited()
        {
            const string testInput = "int i = 1; switch (i) { case 1: default: cw1(); break; case 2: cw2(); break; }";
            var          context   = new ExplodedGraphContext(testInput);
            var          numberOfCw1InstructionVisits = 0;
            var          numberOfCw2InstructionVisits = 0;

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                if (args.Instruction.ToString() == "cw1()")
                {
                    numberOfCw1InstructionVisits++;
                }
                if (args.Instruction.ToString() == "cw2()")
                {
                    numberOfCw2InstructionVisits++;
                }
            };

            context.WalkWithInstructions(11);

            numberOfCw1InstructionVisits.Should().Be(2);
            numberOfCw2InstructionVisits.Should().Be(1);
        }
Esempio n. 5
0
        public void ExplodedGraph_TupleExpressions()
        {
            const string testInput     = "var myTuple = (1, 2); (object a, object b) c = (1, null); (object d, object e) = (1, null);";
            var          context       = new ExplodedGraphContext(testInput);
            var          myTupleSymbol = context.GetSymbol("myTuple");
            var          cSymbol       = context.GetSymbol("c");

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

                if (instruction == "myTuple = (1, 2)")
                {
                    args.ProgramState.GetSymbolValue(myTupleSymbol).Should().NotBeNull();
                }
                if (instruction == "c = (1, null)")
                {
                    args.ProgramState.GetSymbolValue(cSymbol).Should().NotBeNull();
                }

                // Symbolic value for tuples are in the stack for compatibility
                if (instruction == "(object d, object e)")
                {
                    args.ProgramState.HasValue.Should().BeTrue();
                }
                // Stack is clean after assignment
                if (instruction == "(object d, object e) = (1, null)")
                {
                    args.ProgramState.HasValue.Should().BeFalse();
                }
            };

            context.WalkWithInstructions(7);
        }
Esempio n. 6
0
        public void ExplodedGraph_RefExpressions()
        {
            const string testInput = @"
using System;

namespace Test
{
    public class Program
    {
        public static Program Empty = new Program();
        protected ref readonly Program Main() => ref Empty;
    }
}
";
            var          context   = new ExplodedGraphContext(TestHelper.Compile(testInput));

            var identifierSymbol = context.GetSymbol("Empty", ExplodedGraphContext.SymbolType.Identifier);

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                args.ProgramPoint.Block.Instructions.Should().HaveCount(2);
                args.ProgramPoint.Block.Instructions.Should().Contain(i => i.ToString() == "Empty");
                args.ProgramPoint.Block.Instructions.Should().Contain(i => i.ToString() == "ref Empty");
                args.ProgramState.GetSymbolValue(identifierSymbol).Should().NotBeNull();
            };

            context.WalkWithInstructions(2);
        }
Esempio n. 7
0
        public void ExplodedGraph_SingleBranchVisited_If()
        {
            const string testInput = "var a = false; bool b; if (a) { b = true; } else { b = false; } a = b;";
            var          context   = new ExplodedGraphContext(testInput);
            var          aSymbol   = context.GetSymbol("a");
            var          bSymbol   = context.GetSymbol("b");
            var          numberOfLastInstructionVisits = 0;

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                if (args.Instruction.ToString() == "a = false")
                {
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.False);
                }
                if (args.Instruction.ToString() == "b = true")
                {
                    Execute.Assertion.FailWith("We should never get into this branch");
                }
                if (args.Instruction.ToString() == "b = false")
                {
                    args.ProgramState.GetSymbolValue(bSymbol).Should().Be(SymbolicValue.False);
                    args.ProgramState.GetSymbolValue(aSymbol)
                    .Should().BeNull("a is dead, so there should be no associated value to it.");
                }
                if (args.Instruction.ToString() == "a = b")
                {
                    numberOfLastInstructionVisits++;
                }
            };

            context.WalkWithInstructions(8);

            numberOfLastInstructionVisits.Should().Be(1);
        }
Esempio n. 8
0
        public void ExplodedGraph_TupleExpressionsWithDiscardDeconstruct()
        {
            const string testInput = "var (projectInstance, _) = loader;";

            var context = new ExplodedGraphContext(testInput);
            var projectInstanceSymbol = context.GetSymbol("projectInstance", ExplodedGraphContext.SymbolType.Declaration);

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

                switch (instruction)
                {
                case "var (projectInstance, _)":
                    args.ProgramState.GetSymbolValue(projectInstanceSymbol).Should().NotBeNull();
                    break;

                case "loader":
                    args.ProgramState.GetSymbolValue(projectInstanceSymbol).Should().NotBeNull();
                    break;

                case "var (projectInstance, _) = loader":
                    args.ProgramState.GetSymbolValue(projectInstanceSymbol).Should().NotBeNull();
                    args.ProgramState.HasValue.Should().BeFalse();
                    break;
                }
            };

            context.WalkWithInstructions(3);
        }
Esempio n. 9
0
        public void ExplodedGraph_BothBranchesVisited()
        {
            const string testInput                     = "var a = false; bool b; if (inParameter) { b = inParameter; } else { b = !inParameter; } a = b;";
            var          context                       = new ExplodedGraphContext(testInput);
            var          aSymbol                       = context.GetSymbol("a");
            var          bSymbol                       = context.GetSymbol("b");
            var          parameters                    = context.MainMethod.DescendantNodes().OfType <ParameterSyntax>();
            var          inParameterSymbol             = context.SemanticModel.GetDeclaredSymbol(parameters.First(d => d.Identifier.ToString() == "inParameter"));
            var          numberOfLastInstructionVisits = 0;
            var          visitedBlocks                 = new HashSet <Block>();
            var          branchesVisited               = 0;

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                visitedBlocks.Add(args.ProgramPoint.Block);

                if (args.Instruction.ToString() == "a = false")
                {
                    branchesVisited++;

                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.False);
                }
                if (args.Instruction.ToString() == "b = inParameter")
                {
                    branchesVisited++;

                    bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState).Should().BeTrue();
                    inParameterSymbol.HasConstraint(BoolConstraint.True, args.ProgramState).Should().BeTrue();
                }
                if (args.Instruction.ToString() == "b = !inParameter")
                {
                    branchesVisited++;

                    // b has value, but not true or false
                    args.ProgramState.GetSymbolValue(bSymbol).Should().NotBeNull();
                    bSymbol.HasConstraint(BoolConstraint.False, args.ProgramState).Should().BeFalse();
                    bSymbol.HasConstraint(BoolConstraint.True, args.ProgramState).Should().BeFalse();

                    inParameterSymbol.HasConstraint(BoolConstraint.False, args.ProgramState).Should().BeTrue();
                }
                if (args.Instruction.ToString() == "a = b")
                {
                    branchesVisited++;

                    args.ProgramState.GetSymbolValue(inParameterSymbol).Should().BeNull();     // not out/ref parameter and LVA says dead
                    numberOfLastInstructionVisits++;
                }
            };

            // Number of ExitBlocks is still 1 in this case:
            // All variables are dead at the ExitBlock, so whenever we get there,
            // the ExplodedGraph nodes should be the same, and thus should be processed only once.
            context.WalkWithInstructions(13);

            branchesVisited.Should().Be(4 + 1);
            numberOfLastInstructionVisits.Should().Be(2);
            visitedBlocks.Should().HaveCount(context.ControlFlowGraph.Blocks.Count() - 1 /* Exit block*/);
        }
Esempio n. 10
0
        public void ExplodedGraph_DeclarationStatementVisit()
        {
            const string testInput        = @"
using System.Collections.Generic;

namespace Namespace
{
  public class DeclarationStatement
  {
    public int Main(Dictionary<string, string> dictionary, string key)
    {
        dictionary.TryGetValue(key, out var value);
    }
  }
}";
            var          context          = new ExplodedGraphContext(TestHelper.Compile(testInput));
            var          dictionarySymbol = context.SemanticModel.GetDeclaredSymbol(context.MainMethod.ParameterList.Parameters.First());
            var          valueDeclaration = context.MainMethod.DescendantNodes().OfType <DeclarationExpressionSyntax>().First();
            var          valueSymbol      = context.SemanticModel.GetDeclaredSymbol(valueDeclaration);

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                var instruction = args.Instruction.ToString();
                switch (instruction)
                {
                case "dictionary":
                    args.ProgramState.GetSymbolValue(dictionarySymbol).Should().NotBeNull();
                    dictionarySymbol.HasConstraint(ObjectConstraint.NotNull, args.ProgramState).Should().BeFalse();
                    break;

                case "dictionary.TryGetValue":
                    args.ProgramState.GetSymbolValue(dictionarySymbol).Should().NotBeNull();
                    dictionarySymbol.HasConstraint(ObjectConstraint.NotNull, args.ProgramState).Should().BeTrue();
                    break;

                case "key":
                    args.ProgramState.GetSymbolValue(dictionarySymbol).Should().NotBeNull();
                    dictionarySymbol.HasConstraint(ObjectConstraint.NotNull, args.ProgramState).Should().BeTrue();
                    break;

                case "var value":
                    args.ProgramState.GetSymbolValue(dictionarySymbol).Should().NotBeNull();
                    dictionarySymbol.HasConstraint(ObjectConstraint.NotNull, args.ProgramState).Should().BeTrue();
                    break;

                case "dictionary.TryGetValue(key, out var value)":
                    args.ProgramState.GetSymbolValue(dictionarySymbol).Should().NotBeNull();
                    dictionarySymbol.HasConstraint(ObjectConstraint.NotNull, args.ProgramState).Should().BeTrue();

                    // Currently the DeclarationExpressionSyntax are ignored so the "value" variable is not
                    // https://github.com/SonarSource/sonar-dotnet/issues/2936
                    args.ProgramState.GetSymbolValue(valueSymbol).Should().BeNull();
                    break;
                }
            };

            context.WalkWithInstructions(5);
        }
Esempio n. 11
0
        public void ExplodedGraph_NonDecisionMakingAssignments()
        {
            const string  testInput       = "var a = true; a |= false; var b = 42; b++; ++b;";
            var           context         = new ExplodedGraphContext(testInput);
            var           aSymbol         = context.GetSymbol("a");
            var           bSymbol         = context.GetSymbol("b");
            var           branchesVisited = 0;
            SymbolicValue sv = null;

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                if (args.Instruction.ToString() == "a = true")
                {
                    branchesVisited++;
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "a |= false")
                {
                    branchesVisited++;
                    args.ProgramState.GetSymbolValue(aSymbol).Should().NotBeNull();
                    args.ProgramState.GetSymbolValue(aSymbol).Should().NotBe(SymbolicValue.False);
                    args.ProgramState.GetSymbolValue(aSymbol).Should().NotBe(SymbolicValue.True);
                }
                if (args.Instruction.ToString() == "b = 42")
                {
                    branchesVisited++;
                    sv = args.ProgramState.GetSymbolValue(bSymbol);
                    sv.Should().NotBeNull();
                }
                if (args.Instruction.ToString() == "b++")
                {
                    branchesVisited++;
                    var svNew = args.ProgramState.GetSymbolValue(bSymbol);
                    svNew.Should().NotBeNull();
                    svNew.Should().NotBe(sv);
                }
                if (args.Instruction.ToString() == "++b")
                {
                    branchesVisited++;
                    var svNew = args.ProgramState.GetSymbolValue(bSymbol);
                    svNew.Should().NotBeNull();
                    svNew.Should().NotBe(sv);
                }
            };

            context.WalkWithInstructions(11);

            branchesVisited.Should().Be(5);
        }
Esempio n. 12
0
        public void ExplodedGraph_StaticLocalFunctions()
        {
            const string testInput = @"static string Local(object o) {return o.ToString()} Local(null);";
            var          context   = new ExplodedGraphContext(testInput);
            var          numberOfValidatedInstructions = 0;

            context.ExplodedGraph.InstructionProcessed += (sender, args) =>
            {
                if (args.Instruction.ToString() == "o.ToString()")
                {
                    numberOfValidatedInstructions++;
                }
            };

            context.WalkWithInstructions(3);

            numberOfValidatedInstructions.Should().Be(0);   // Local functions are not supported by CFG (yet)
        }
Esempio n. 13
0
        public void ExplodedGraph_SequentialInput_OutParameter()
        {
            const string testInput          = "outParameter = true;";
            var          context            = new ExplodedGraphContext(testInput);
            var          parameters         = context.MainMethod.DescendantNodes().OfType <ParameterSyntax>();
            var          outParameterSymbol = context.SemanticModel.GetDeclaredSymbol(parameters.First(d => d.Identifier.ToString() == "outParameter"));

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                if (args.Instruction.ToString() == "outParameter = true")
                {
                    args.ProgramState.GetSymbolValue(outParameterSymbol)
                    .Should().Be(SymbolicValue.True);
                }
            };

            context.WalkWithInstructions(2);
        }
Esempio n. 14
0
        public void ExplodedGraph_BothBranchesVisited_NonCondition()
        {
            const string testInput               = "var str = this?.ToString();";
            var          context                 = new ExplodedGraphContext(testInput);
            var          visitedBlocks           = new HashSet <Block>();
            var          countConditionEvaluated = 0;

            context.ExplodedGraph.ConditionEvaluated   += (sender, args) => { countConditionEvaluated++; };
            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                visitedBlocks.Add(args.ProgramPoint.Block);
            };

            context.WalkWithInstructions(5);

            visitedBlocks.Should().HaveCount(context.ControlFlowGraph.Blocks.Count() - 1 /* Exit block */);
            countConditionEvaluated.Should().Be(0);
        }
Esempio n. 15
0
        public void ExplodedGraph_NonLocalNorFieldSymbolBranching()
        {
            const string testInput      = "if (Property) { cw(); }";
            var          context        = new ExplodedGraphContext(testInput);
            var          propertySymbol = context.SemanticModel.GetSymbolInfo(context.MainMethod.DescendantNodes()
                                                                              .OfType <IdentifierNameSyntax>().First(d => d.Identifier.ToString() == "Property")).Symbol;

            propertySymbol.Should().NotBeNull();
            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                if (args.Instruction.ToString() == "Property")
                {
                    args.ProgramState.GetSymbolValue(propertySymbol).Should().BeNull();
                }
            };

            context.WalkWithInstructions(3);
        }
Esempio n. 16
0
        public void ExplodedGraph_SwitchStatement()
        {
            const string testInput = @"string s=null; switch(s==null) {case true: s=""Value""; break; default : break;}; s.ToString();";
            var          context   = new ExplodedGraphContext(testInput);
            var          sSymbol   = context.GetSymbol("s");
            var          numberOfValidatedInstructions = 0;

            context.ExplodedGraph.InstructionProcessed += (sender, args) =>
            {
                if (args.Instruction.ToString() == "s.ToString()")
                {
                    numberOfValidatedInstructions++;
                    args.ProgramState.HasConstraint(args.ProgramState.GetSymbolValue(sSymbol), ObjectConstraint.NotNull).Should().BeTrue();
                }
            };

            context.WalkWithInstructions(14);

            numberOfValidatedInstructions.Should().Be(1);
        }
Esempio n. 17
0
        public void ExplodedGraph_BothBranchesVisited_StateMerge()
        {
            const string testInput = "var a = !true; bool b; if (inParameter) { b = false; } else { b = false; } a = b;";
            var          context   = new ExplodedGraphContext(testInput);
            var          aSymbol   = context.GetSymbol("a");
            var          numberOfLastInstructionVisits = 0;

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                if (args.Instruction.ToString() == "a = b")
                {
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.False);
                    numberOfLastInstructionVisits++;
                }
            };

            context.WalkWithInstructions(11);

            numberOfLastInstructionVisits.Should().Be(1);
        }
Esempio n. 18
0
        public void ExplodedGraph_DiscardDesignationAsFunctionArgument()
        {
            const string testInput = @"var result = obj.Read(out int _);";

            var context      = new ExplodedGraphContext(testInput);
            var resultSymbol = context.GetSymbol("result");

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

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

                case "obj.Read":
                    args.ProgramState.GetSymbolValue(resultSymbol).Should().BeNull();
                    break;

                case "int _":
                    args.ProgramState.GetSymbolValue(resultSymbol).Should().BeNull();
                    break;

                case "obj.Read(out int _)":
                    args.ProgramState.GetSymbolValue(resultSymbol).Should().BeNull();
                    break;

                case "result = obj.Read(out int _)":
                    args.ProgramState.GetSymbolValue(resultSymbol).Should().NotBeNull();
                    args.ProgramState.HasValue.Should().BeFalse();
                    break;
                }
            };

            context.WalkWithInstructions(5);
        }
Esempio n. 19
0
        public void ExplodedGraph_SingleBranchVisited_And()
        {
            const string testInput = "var a = false; if (a && !a) { a = !true; } else { a = true; }";
            var          context   = new ExplodedGraphContext(testInput);
            var          aSymbol   = context.GetSymbol("a");

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                switch (args.Instruction.ToString())
                {
                case "a = true":
                    args.ProgramState.GetSymbolValue(aSymbol).Should().Be(SymbolicValue.True);
                    break;

                case "a = !true":
                case "!a":
                    Execute.Assertion.FailWith("We should never get into this branch");
                    break;
                }
            };

            context.WalkWithInstructions(5);
        }
Esempio n. 20
0
        public void ExplodedGraph_DeclarationExpression()
        {
            const string testInput       = @"
namespace Namespace
{
    public class DeclarationExpression
    {
        public void Main(IDecoder decoder)
        {
            var result = decoder.Convert(out int bytesUsed, out int charsUsed);
        }
    }
    public interface IDecoder
    {
        bool Convert(out int bytesUsed, out int charsUsed);
    }
}";
            var          context         = new ExplodedGraphContext(TestHelper.Compile(testInput));
            var          bytesUsedSymbol = context.GetSymbol("bytesUsed", ExplodedGraphContext.SymbolType.Declaration);
            var          charsUsedSymbol = context.GetSymbol("charsUsed", ExplodedGraphContext.SymbolType.Declaration);

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

                switch (instruction)
                {
                case "decoder":
                    args.ProgramState.GetSymbolValue(bytesUsedSymbol).Should().BeNull();
                    args.ProgramState.GetSymbolValue(charsUsedSymbol).Should().BeNull();
                    break;

                case "decoder.Convert":
                    args.ProgramState.GetSymbolValue(bytesUsedSymbol).Should().BeNull();
                    args.ProgramState.GetSymbolValue(charsUsedSymbol).Should().BeNull();
                    break;

                case "int bytesUsed":
                    args.ProgramState.GetSymbolValue(bytesUsedSymbol).Should().NotBeNull();
                    args.ProgramState.GetSymbolValue(charsUsedSymbol).Should().BeNull();
                    break;

                case "int charsUsed":
                    args.ProgramState.GetSymbolValue(bytesUsedSymbol).Should().NotBeNull();
                    args.ProgramState.GetSymbolValue(charsUsedSymbol).Should().NotBeNull();
                    break;

                case "decoder.Convert(out int bytesUsed, out int charsUsed)":
                    args.ProgramState.GetSymbolValue(bytesUsedSymbol).Should().NotBeNull();
                    args.ProgramState.GetSymbolValue(charsUsedSymbol).Should().NotBeNull();
                    break;

                case "result = decoder.Convert(out int bytesUsed, out int charsUsed)":
                    args.ProgramState.GetSymbolValue(bytesUsedSymbol).Should().NotBeNull();
                    args.ProgramState.GetSymbolValue(charsUsedSymbol).Should().NotBeNull();
                    args.ProgramState.HasValue.Should().BeFalse();
                    break;
                }
            };

            context.WalkWithInstructions(6);
        }
Esempio n. 21
0
        public void ExplodedGraph_SwitchWithRecursivePatternVisit()
        {
            const string testInput             = @"
namespace Namespace
{
    public class Address
    {
        public string Name { get; }
        public string State { get; }
    }

    public class Person
    {
        public string Name { get; }
        public Address Address { get; }
    }

    public class DeclarationStatement
    {
        public string Main(Person person)
        {
            return person switch
                {
                    { Address: {State: ""WA"" } address } p => address.Name,
                    _ => string.Empty
                };
        }
    }
}";
            var          context               = new ExplodedGraphContext(TestHelper.Compile(testInput));
            var          personSymbol          = context.SemanticModel.GetDeclaredSymbol(context.MainMethod.ParameterList.Parameters.First());
            var          declarations          = context.MainMethod.DescendantNodes().OfType <SingleVariableDesignationSyntax>().ToList();
            var          addressSymbol         = context.SemanticModel.GetDeclaredSymbol(declarations[0]);
            var          pSymbol               = context.SemanticModel.GetDeclaredSymbol(declarations[1]);
            var          instructionsInspected = 0;

            context.ExplodedGraph.InstructionProcessed +=
                (sender, args) =>
            {
                var instruction = args.Instruction.ToString();
                switch (instruction)
                {
                case "person":
                    instructionsInspected++;
                    args.ProgramState.GetSymbolValue(personSymbol).Should().NotBeNull();
                    break;

                case "{ Address: {State: \"WA\" } address } p":
                    instructionsInspected++;
                    args.ProgramState.GetSymbolValue(personSymbol).Should().NotBeNull();

                    // Currently the recursive pattern is ignored and the values for "p" and "address" are not created.
                    // https://github.com/SonarSource/sonar-dotnet/issues/2937
                    args.ProgramState.GetSymbolValue(addressSymbol).Should().BeNull();
                    args.ProgramState.GetSymbolValue(pSymbol).Should().BeNull();
                    break;

                case "{State: \"WA\" } address":
                    instructionsInspected++;
                    args.ProgramState.GetSymbolValue(personSymbol).Should().NotBeNull();

                    // Currently the recursive pattern is ignored and the value for "address" is not created.
                    // https://github.com/SonarSource/sonar-dotnet/issues/2937
                    args.ProgramState.GetSymbolValue(addressSymbol).Should().BeNull();
                    break;

                case "\"WA\"":
                    instructionsInspected++;
                    args.ProgramState.GetSymbolValue(personSymbol).Should().NotBeNull();
                    break;
                }
            };

            context.WalkWithInstructions(8);

            instructionsInspected.Should().Be(4);
        }