Example #1
0
        internal void AddRecord(DisplayNodeRecord record)
        {
            Contract.Requires <FrozenObjectModificationException>(!this.IsFrozen);

            this.MutableRecords.Add(record);
        }
Example #2
0
        // TODO: Consider changing the branching into assertions where possible
        private void FinishDisplayGraph()
        {
            foreach (var buildNode in this.BuildGraph.Nodes)
            {
                var flowNodeInfo = this.buildToFlowNodesMap[buildNode];
                if (flowNodeInfo.FlowNode != null)
                {
                    var displayNode = buildNode.DisplayNode;
                    if (displayNode == null)
                    {
                        continue;
                    }

                    if (buildNode.Operation?.Kind == SpecialOperationKind.Enter)
                    {
                        int valAssignOffset = 0;
                        int refAssignOffset = 0;

                        ParameterListSyntax parameterList = ((ParameterListSyntax)buildNode.Syntax);
                        var thisParam = this.BuildGraph.Variables.FirstOrDefault(v => v.Origin == VariableOrigin.This);
                        if (thisParam != null)
                        {
                            // Instance methods have the instance reference as the first parameter
                            var record = new DisplayNodeRecord(
                                flowNodeInfo.FlowNode,
                                new TextSpan(parameterList.OpenParenToken.Span.End, 0),
                                refAssignOffset,
                                this.BuildGraph.LocalInstanceModel.Type,
                                thisParam.DisplayName);
                            displayNode.AddRecord(record);

                            refAssignOffset++;
                        }

                        foreach (var parameterSyntax in parameterList.Parameters)
                        {
                            string parameterName  = parameterSyntax.Identifier.Text;
                            var    parameterModel =
                                (from kvp in this.BuildGraph.DefinedVariableModels
                                 where kvp.Key.Kind == SymbolKind.Parameter && kvp.Key.Name == parameterName
                                 select kvp.Value).FirstOrDefault();

                            if (parameterModel != null)
                            {
                                bool isRefModel = parameterModel.Factory.ValueKind == ValueModelKind.Reference;

                                var record = new DisplayNodeRecord(
                                    flowNodeInfo.FlowNode,
                                    parameterSyntax.Span,
                                    isRefModel ? valAssignOffset : refAssignOffset,
                                    parameterModel.Type,
                                    parameterSyntax.Identifier.Text);
                                displayNode.AddRecord(record);

                                if (isRefModel)
                                {
                                    refAssignOffset += parameterModel.AssignmentLeft.Count;
                                }
                                else
                                {
                                    valAssignOffset += parameterModel.AssignmentLeft.Count;
                                }
                            }
                        }
                    }
                    else
                    {
                        // Offset and type
                        int         assignmentOffset = -1;
                        int         operationOffset  = -1;
                        ITypeSymbol type             = null;
                        string      variableName     = null;
                        if (buildNode.VariableModel != null)
                        {
                            assignmentOffset = flowNodeInfo.AssignmentOffset;
                            operationOffset  = flowNodeInfo.OperationOffset;
                            type             = buildNode.VariableModel.Type;
                            if (buildNode.VariableModel.AssignmentLeft.FirstOrDefault() is BuildVariable buildVar &&
                                buildVar.Origin != VariableOrigin.Temporary)
                            {
                                variableName = buildVar.DisplayName;
                            }
                        }
                        else if (buildNode.Operation?.Kind == SpecialOperationKind.FieldWrite)
                        {
                            assignmentOffset = flowNodeInfo.AssignmentOffset;
                            operationOffset  = flowNodeInfo.OperationOffset;
                            type             = ((HeapOperation)buildNode.Operation).Reference.Type;
                        }

                        var record = new DisplayNodeRecord(flowNodeInfo.FlowNode, buildNode.Label.Span, assignmentOffset, type, variableName, operationOffset);
                        displayNode.AddRecord(record);
                    }

                    foreach (var buildEdge in buildNode.OutgoingEdges)
                    {
                        if (buildEdge.To.DisplayNode == null)
                        {
                            continue;
                        }

                        // Prevent self loops and multiple edges
                        var targetDisplayNode = buildEdge.To.DisplayNode;
                        if (displayNode != targetDisplayNode &&
                            !displayNode.OutgoingEdges.Any(displayEdge => displayEdge.To == targetDisplayNode))
                        {
                            // TODO: Edge label
                            this.DisplayGraph.AddEdge(displayNode, targetDisplayNode);
                        }

                        //var targetFlowNodeInfo = this.buildToFlowNodesMap[buildEdge.To];
                        //if (targetFlowNodeInfo.FlowNode != null)
                        //{
                        //    // We cannot step into the middle of the CFG node
                        //    Contract.Assert(targetFlowNodeInfo.AssignmentOffset == 0);


                        //}
                    }
                }
            }

            this.DisplayGraph.Freeze();
        }