public void TestGetFlowGraphNullArgument() { Assert.Throws <ArgumentNullException>(() => SemanticModel.GetControlFlowGraph((IBlockOperation)null)); Assert.Throws <ArgumentNullException>(() => SemanticModel.GetControlFlowGraph((IFieldInitializerOperation)null)); Assert.Throws <ArgumentNullException>(() => SemanticModel.GetControlFlowGraph((IPropertyInitializerOperation)null)); Assert.Throws <ArgumentNullException>(() => SemanticModel.GetControlFlowGraph((IParameterInitializerOperation)null)); Assert.Throws <ArgumentNullException>(() => SemanticModel.GetControlFlowGraph((IConstructorBodyOperation)null)); Assert.Throws <ArgumentNullException>(() => SemanticModel.GetControlFlowGraph((IMethodBodyOperation)null)); }
public static ControlFlowGraph GetTreeCFG(this Compilation compilation) { var tree = compilation.SyntaxTrees.Single(); var root = tree.GetRoot(); var semanticModel = compilation.GetSemanticModel(tree); var firstMethod = root.DescendantNodes().OfType <BaseMethodDeclarationSyntax>().First(); var firstMethodOper = semanticModel.GetOperation(firstMethod) as IMethodBodyOperation; return(SemanticModel.GetControlFlowGraph(firstMethodOper)); }
public static ControlFlowGraph GetControlFlowGraph(SyntaxNode syntaxNode, SemanticModel model) { IOperation operationRoot = model.GetOperation(syntaxNode); // Workaround for unit tests designed to work on IBlockOperation with ConstructorBodyOperation/MethodBodyOperation parent. operationRoot = operationRoot.Kind == OperationKind.Block && (operationRoot.Parent?.Kind == OperationKind.ConstructorBodyOperation || operationRoot.Parent?.Kind == OperationKind.MethodBodyOperation) ? operationRoot.Parent : operationRoot; TestOperationVisitor.VerifySubTree(operationRoot); ControlFlowGraph graph; switch (operationRoot) { case IBlockOperation blockOperation: graph = SemanticModel.GetControlFlowGraph(blockOperation); break; case IMethodBodyOperation methodBodyOperation: graph = SemanticModel.GetControlFlowGraph(methodBodyOperation); break; case IConstructorBodyOperation constructorBodyOperation: graph = SemanticModel.GetControlFlowGraph(constructorBodyOperation); break; case IFieldInitializerOperation fieldInitializerOperation: graph = SemanticModel.GetControlFlowGraph(fieldInitializerOperation); break; case IPropertyInitializerOperation propertyInitializerOperation: graph = SemanticModel.GetControlFlowGraph(propertyInitializerOperation); break; case IParameterInitializerOperation parameterInitializerOperation: graph = SemanticModel.GetControlFlowGraph(parameterInitializerOperation); break; default: return(null); } Assert.NotNull(graph); Assert.Same(operationRoot, graph.OriginalOperation); return(graph); }
public void LambdaFlow_04() { string source = @" struct C { void M(System.Action d1, System.Action<bool, bool> d2) /*<bind>*/{ d1 = () => { d2 = (bool result1, bool input1) => { result1 = input1; }; }; void local(bool result2, bool input2) => result2 = input2; }/*</bind>*/ } "; var compilation = CreateCompilation(source, parseOptions: TestOptions.Regular.WithFlowAnalysisFeature()); var tree = compilation.SyntaxTrees.Single(); var semanticModel = compilation.GetSemanticModel(tree); var graphM = SemanticModel.GetControlFlowGraph((IMethodBodyOperation)semanticModel.GetOperation(tree.GetRoot().DescendantNodes().OfType <MethodDeclarationSyntax>().Single())); Assert.NotNull(graphM); IFlowAnonymousFunctionOperation lambdaD1 = getLambda(graphM); Assert.Throws <ArgumentNullException>(() => graphM.GetLocalFunctionControlFlowGraph(null)); Assert.Throws <ArgumentOutOfRangeException>(() => graphM.GetLocalFunctionControlFlowGraph(lambdaD1.Symbol)); var graphD1 = graphM.GetAnonymousFunctionControlFlowGraph(lambdaD1); Assert.NotNull(graphD1); IFlowAnonymousFunctionOperation lambdaD2 = getLambda(graphD1); Assert.Throws <ArgumentNullException>(() => graphM.GetAnonymousFunctionControlFlowGraph(null)); Assert.Throws <ArgumentOutOfRangeException>(() => graphM.GetAnonymousFunctionControlFlowGraph(lambdaD2)); IFlowAnonymousFunctionOperation getLambda(ControlFlowGraph graph) { return(graph.Blocks.SelectMany(b => b.Operations.SelectMany(o => o.DescendantsAndSelf())).OfType <IFlowAnonymousFunctionOperation>().Single()); } }
public void TestFlowAnalysisFeatureFlag() { var source = @" class C { void M() { } }"; var tree = CSharpSyntaxTree.ParseText(source); void testFlowAnalysisFeatureFlagCore(bool expectException) { var compilation = CSharpCompilation.Create("c", new[] { tree }); var model = compilation.GetSemanticModel(tree, ignoreAccessibility: true); var methodBodySyntax = tree.GetCompilationUnitRoot().DescendantNodes().OfType <BaseMethodDeclarationSyntax>().Last(); var operation = (IMethodBodyOperation)model.GetOperation(methodBodySyntax); if (expectException) { Assert.Throws <InvalidOperationException>(() => SemanticModel.GetControlFlowGraph(operation)); } else { ControlFlowGraph graph = SemanticModel.GetControlFlowGraph(operation); Assert.NotNull(graph); Assert.NotEmpty(graph.Blocks); } } // Test without feature flag. testFlowAnalysisFeatureFlagCore(expectException: true); // Test with feature flag. tree = CSharpSyntaxTree.ParseText(source); var options = tree.Options.WithFeatures(new[] { new KeyValuePair <string, string>("flow-analysis", "true") }); tree = tree.WithRootAndOptions(tree.GetRoot(), options); testFlowAnalysisFeatureFlagCore(expectException: false); // Test with feature flag, case-insensitive. tree = CSharpSyntaxTree.ParseText(source); options = tree.Options.WithFeatures(new[] { new KeyValuePair <string, string>("Flow-Analysis", "true") }); tree = tree.WithRootAndOptions(tree.GetRoot(), options); testFlowAnalysisFeatureFlagCore(expectException: false); }