Esempio n. 1
0
 /// <summary>
 /// Check if the given commented text is one of a Function declaration Header, if so the text is added to the
 /// Function Data commented header string buffer.
 /// </summary>
 /// <param name="nodes">The nodes indices that can correspond to afUnction Declaration node</param>
 /// <param name="text">The Commented Text</param>
 private void CheckFunctionDeclCommentedheader(LinearNodeSourceCodeMapper mapper, List <int> nodes, string text)
 {
     if (nodes == null)
     {
         return;
     }
     if (text == null)
     {
         return;
     }
     if (text.Length == 0)
     {
         return;
     }
     foreach (int node in nodes)
     {
         if (node >= 0 && mapper.Nodes[node] is LinearNodeSourceCodeMapper.NodeFunctionData)
         {
             LinearNodeSourceCodeMapper.NodeFunctionData fundata = (LinearNodeSourceCodeMapper.NodeFunctionData)mapper.Nodes[node];
             if (fundata.CommentedHeader.Length == 0)
             {//Add a first empty comment line
                 TextLineSnapshot h    = new TextLineSnapshot(-1, "*", null);
                 string           crlf = "";
                 foreach (var hl in Indent(h, null))
                 {
                     fundata.CommentedHeader.Append(crlf);
                     fundata.CommentedHeader.Append(hl.Text.TrimEnd());
                     crlf = Environment.NewLine;
                 }
                 fundata.CommentedHeader.Append(crlf);
             }
             fundata.CommentedHeader.Append(text);
             fundata.CommentedHeader.Append(Environment.NewLine);
         }
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Perform a linear Generation
        /// //1) A Non commented line with no Associated nodes is generated without any change.
        /// //2) If the line is commented then first comment all following lines that have the same intersection with the corresponding target Nodes.
        /// //3) For each node related to a line, and not already generated the corresponding code.
        /// //4) Flush of Function declations.
        /// <param name="mapper">The linearization representation</param>
        /// <param name="Input">Input source lines</param>
        /// <returns>The Generated Source Document</returns>
        /// </summary>
        private SourceText LinearGeneration <A>(LinearNodeSourceCodeMapper mapper, IReadOnlyList <A> Input) where A : ITextLine
        {
            SourceText targetSourceText = new GapSourceText();
            //Stack Used to save current generation buffer when switching in a function declaration generation.
            //Beacuse a function declartion has its own buffer.
            Stack <SourceText> stackOuterBuffer = new Stack <SourceText>();
            Stack <SourceText> stackLocalBuffer = new Stack <SourceText>();
            //Bit Array of Generated Nodes.
            BitArray generated_node = new BitArray(mapper.NodeCount);

            //For detecting line having characters in columns [73-80]
            Lines_73_80_Flags = new HashSet <int>();
            //The previous line generation buffer
            StringSourceText previousBuffer = null;

            for (int i = 0; i < mapper.LineData.Length; i++)
            {
                //--------------------------------------------------------------------------------------------------------------
                //1) A Non commented line with no Associated nodes is generated without any change.
                if (!mapper.CommentedLines[i] && mapper.LineData[i].LineNodes == null)
                {
                    //If there was a previous buffer ==> Flush it
                    if (previousBuffer != null)
                    {
                        if (!mapper.IsGeneratedEmptyBuffer(previousBuffer))
                        {
                            AppendBufferContent(targetSourceText, previousBuffer);
                        }
                        previousBuffer = null;
                    }
                    string text = Input[i].Text;
                    if (mapper.LineData[i].Buffer != null)
                    {//This line has been assigned a target Buffer
                        mapper.LineData[i].Buffer.Insert(text, targetSourceText.Size, targetSourceText.Size);
                        mapper.LineData[i].Buffer.Insert(Environment.NewLine, targetSourceText.Size, targetSourceText.Size);
                    }
                    else
                    {
                        targetSourceText.Insert(text, targetSourceText.Size, targetSourceText.Size);
                        targetSourceText.Insert(Environment.NewLine, targetSourceText.Size, targetSourceText.Size);
                    }
                    continue;
                }
                //--------------------------------------------------------------------------------------------------------------
                //2) If the line is commented then first comment all following lines that have the same intersection with
                // the corresponding target Nodes.
                List <int> line_nodes = mapper.LineData[i].LineNodes;
                //If there was a previous buffer ==> Flush it
                if (previousBuffer != null && mapper.CommentedLines[i])
                {
                    if (!mapper.IsGeneratedEmptyBuffer(previousBuffer))
                    {
                        AppendBufferContent(targetSourceText, previousBuffer);
                    }
                    previousBuffer = null;
                }
                for (int j = i; mapper.CommentedLines[j]; j++)
                {
                    List <int> current_nodes = mapper.LineData[j].LineNodes;
                    if (!LinearNodeSourceCodeMapper.HasIntersection(line_nodes, current_nodes))
                    {
                        break;//This commented line has no nodes which intersect with the previous line.
                    }
                    IEnumerable <ITextLine> lines = Indent(Input[j], true);
                    foreach (var line in lines)
                    {
                        string text = line.Text.TrimEnd();
                        targetSourceText.Insert(text, targetSourceText.Size, targetSourceText.Size);
                        targetSourceText.Insert(Environment.NewLine, targetSourceText.Size, targetSourceText.Size);
                        CheckFunctionDeclCommentedheader(mapper, current_nodes, text);
                    }
                    mapper.CommentedLines[j] = false;//This commented line has been generated now
                    line_nodes = current_nodes;
                }
                //--------------------------------------------------------------------------------------------------------------
                //3)For each node related to this line, and not already generated.
                line_nodes = mapper.LineData[i].LineNodes;
                foreach (int node_index in line_nodes)
                {
                    if (node_index == -1 || mapper.Nodes[node_index].node.IsFlagSet(Node.Flag.GeneratorCanIgnoreIt))
                    {//bad Node
                        continue;
                    }
                    if (generated_node[node_index])
                    {
                        continue;                                                                           //Already Generated.
                    }
                    bool             bFunctionBodyNode = mapper.Nodes[node_index].FunctionBodyNode != null; //Is this node in a function body ?
                    StringSourceText curSourceText     = mapper.Nodes[node_index].Buffer;
                    if (curSourceText != previousBuffer && previousBuffer != null)
                    {//Flush previous buffer
                        if (!mapper.IsGeneratedEmptyBuffer(previousBuffer))
                        {
                            AppendBufferContent(targetSourceText, previousBuffer);
                        }
                        previousBuffer = null;
                    }
                    Node node                = mapper.Nodes[node_index].node;
                    bool bGenerated          = node is Generated;
                    bool bForceGenerateLines = true;
                    if (!bGenerated)
                    {   //This Node is not Generated: If it removed then remove its source code otherwise do Nothing it is already in the source buffer.
                        bForceGenerateLines = false;
                        if (mapper.Nodes[node_index].Removed)
                        {//If this node is removed
                            //var sourceLine = TargetDocument[i];
                            Position from = mapper.Nodes[node_index].From;
                            Position to   = mapper.Nodes[node_index].To;
                            //Delete <==> Replace with blanks
                            ReplaceByBlanks(curSourceText, from.Pos, to.Pos);
                        }
                        else if (mapper.Nodes[node_index].node.IsFlagSet(Node.Flag.ForceGetGeneratedLines))
                        {//As lines to generate and replace
                            bForceGenerateLines = true;
                        }
                    }
                    if (bForceGenerateLines)
                    {
                        bool     bIsFunctionDecl = mapper.Nodes[node_index] is LinearNodeSourceCodeMapper.NodeFunctionData;
                        bool     bFirst          = true;
                        Position from            = mapper.Nodes[node_index].From;
                        Position to = mapper.Nodes[node_index].To;
                        bool     bIsGenerateAndReplace = node is GeneratedAndReplace;
                        if (bIsGenerateAndReplace)
                        {//The node has a source code that must be replaced
                            string code = (node as GeneratedAndReplace).ReplaceCode;
                            GenerateIntoBufferCheckLineExceed(from, to, curSourceText, code, i + 1);
                        }
                        else
                        {
                            foreach (var line in NodeLines(node, generated_node))
                            {
                                bool         bInsertSplit = false;
                                StringWriter sw           = new StringWriter();
                                if (bFirst && !bIsFunctionDecl && curSourceText != null)
                                {//The first element don't ident it just insert it a the right position
                                 //issue #892 => Anyway Handle splitting
                                    sw.WriteLine(line.Text);
                                    bFirst       = false;
                                    bInsertSplit = true;
                                }
                                else
                                {
                                    foreach (var l in Indent(line, null))
                                    {
                                        sw.WriteLine(l.Text.TrimEnd());
                                    }
                                }
                                sw.Flush();
                                string text = sw.ToString();
                                if (bIsFunctionDecl)
                                { //This the Function Header output.
                                    LinearNodeSourceCodeMapper.NodeFunctionData funData = mapper.Nodes[node_index] as LinearNodeSourceCodeMapper.NodeFunctionData;
                                    int f = Math.Min(from.Pos, curSourceText.Size);
                                    int t = Math.Min(to.Pos, curSourceText.Size);
                                    if (f != t)
                                    {
                                        //Create a the erase string to erase in the original source code
                                        //The Function header.
                                        //Erase in the original source code the Function header?
                                        ReplaceByBlanks(curSourceText, f, t);
                                        //Output the pre-stored comment header
                                        InsertLineMaybeSplit(funData.FunctionDeclBuffer, funData.CommentedHeader.ToString(), funData.FunctionDeclBuffer.Size, funData.FunctionDeclBuffer.Size, bInsertSplit);
                                    }
                                    //Insert the sequence
                                    InsertLineMaybeSplit(funData.FunctionDeclBuffer, text, funData.FunctionDeclBuffer.Size, funData.FunctionDeclBuffer.Size, bInsertSplit);
                                }
                                else
                                {
                                    if (curSourceText == null)
                                    {
                                        InsertLineMaybeSplit(targetSourceText, text, targetSourceText.Size, targetSourceText.Size, bInsertSplit);
                                    }
                                    else
                                    {
                                        InsertLineMaybeSplit(curSourceText, text, Math.Min(from.Pos, curSourceText.Size), Math.Min(to.Pos, curSourceText.Size), bInsertSplit);
                                    }
                                }
                                from = to;
                                sw.Close();
                            }
                        }
                        //Don't pad in case of replacement or insertion in a function declaration
                        if (!bIsGenerateAndReplace && !bIsFunctionDecl)
                        {
                            //Pad a splitted segment
                            if (mapper.Nodes[node_index].Positions != null)
                            {
                                int    span = mapper.Nodes[node_index].Positions.Item3;
                                string pad  = new string(' ', span);
                                curSourceText.Insert(pad, to.Pos, to.Pos);
                            }
                        }
                        if (bIsFunctionDecl)
                        {   //Switch in function declaration -> push the current buffers
                            LinearNodeSourceCodeMapper.NodeFunctionData funData = mapper.Nodes[node_index] as LinearNodeSourceCodeMapper.NodeFunctionData;
                            stackLocalBuffer.Push(curSourceText);
                            stackOuterBuffer.Push(targetSourceText);
                            //Now Generate in Function Declaration Buffer.
                            targetSourceText = funData.FunctionDeclBuffer;
                            curSourceText    = null;
                        }
                    }
                    //This node is now generated.
                    generated_node[node_index] = true;
                    if (mapper.Nodes[node_index].node.IsFlagSet(Node.Flag.EndFunctionDeclarationNode))
                    {   //Leaving function declaration --> Pop saved buffers.
                        if (previousBuffer != null)
                        {
                            if (!mapper.IsGeneratedEmptyBuffer(previousBuffer))
                            {
                                AppendBufferContent(targetSourceText, previousBuffer);
                            }
                            previousBuffer = null;
                        }
                        System.Diagnostics.Debug.Assert(stackOuterBuffer.Count > 0 && stackLocalBuffer.Count > 0);
                        if (stackOuterBuffer.Count > 0 && stackLocalBuffer.Count > 0)
                        {
                            targetSourceText = stackOuterBuffer.Pop();
                            curSourceText    = (StringSourceText)stackLocalBuffer.Pop();
                        }
                        previousBuffer = curSourceText;
                    }
                    else
                    {
                        previousBuffer = curSourceText;
                    }
                }
                //--------------------------------------------------------------------------------------------------------------
            }
            //If there was a previous buffer ==> Flush it
            if (previousBuffer != null)
            {
                if (!mapper.IsGeneratedEmptyBuffer(previousBuffer))
                {
                    AppendBufferContent(targetSourceText, previousBuffer);
                }
                previousBuffer = null;
            }
            //--------------------------------------------------------------------------------------------------------------
            //4)//Flush of Function declation body
            foreach (int fun_index in mapper.FunctionDeclarationNodeIndices)
            {
                LinearNodeSourceCodeMapper.NodeFunctionData funData = mapper.Nodes[fun_index] as LinearNodeSourceCodeMapper.NodeFunctionData;
                AppendBufferContent(targetSourceText, funData.FunctionDeclBuffer);
            }
            //5)//Generate Line Exceed Diagnostics
            GenerateExceedLineDiagnostics();
            return(targetSourceText);
        }