Beispiel #1
0
        private static bool AddPrototypes(ref StringBuilder outputMessage, ParsedImplementation function)
        {
            var protoStr = Npp.GetTextByRange(function.Position, function.EndPosition);

            // ensure that the file was correctly parsed
            if (ParserHandler.AblParser.ParserErrors.Count == 0)
            {
                // get the best position to insert the prototype
                bool insertBefore;
                int  insertPos = GetCaretPositionForInsertion <ParsedPrototype>(function.Name, ProInsertPosition.Last, out insertBefore);

                // if we didn't find a good position, then let's assume the user doesn't need one
                if (insertPos > 0)
                {
                    // replace the end ":" or "." by a " FOWARD."
                    protoStr = FormatInsertion(protoStr.Substring(0, protoStr.Length - 1).TrimEnd(' ') + " FORWARD.", "_FUNCTION-FORWARD " + function.Name + " Procedure", insertBefore);

                    Npp.SetTextByRange(insertPos, insertPos, protoStr);

                    //outputMessage.Append("<br> - <a href='" + function.FilePath + "#" + insertPos + "'>" + function.Name + "</a>");
                    outputMessage.Append("<br> - " + function.Name);

                    return(true);
                }
            }

            return(false);
        }
Beispiel #2
0
        /// <summary>
        /// This method checks if the current document contains function prototypes that are not updated
        /// and correct them if needed
        /// </summary>
        private bool UpdatePrototypes(ref StringBuilder outputMessage, ParsedImplementation function)
        {
            var protoStr = Sci.GetTextByRange(function.Position, function.EndPosition);

            // replace the end ":" or "." by a " FOWARD."
            protoStr = protoStr.Substring(0, protoStr.Length - 1).TrimEnd(' ') + " FORWARD.";
            Sci.SetTextByRange(function.PrototypePosition, function.PrototypeEndPosition, protoStr);

            outputMessage.Append("<br> - <a href='" + function.FilePath + "#" + (function.PrototypePosition) + "'>" + function.Name + "</a>");

            return(true);
        }
Beispiel #3
0
        public void Visit(ParsedImplementation pars)
        {
            pars.ReturnType = ConvertStringToParsedPrimitiveType(pars.TempReturnType, false);

            // to code explorer
            PushToCodeExplorer(
                GetExplorerListNode("Functions", CodeExplorerIconType.Function),
                new FunctionCodeItem {
                DisplayText   = pars.Name,
                Flags         = pars.Flags,
                SubText       = null,
                DocumentOwner = pars.FilePath,
                GoToLine      = pars.Line,
                GoToColumn    = pars.Column
            });

            // to completion data
            PushToAutoCompletion(new FunctionCompletionItem {
                DisplayText = pars.Name,
                SubText     = pars.ReturnType.ToString(),
                Flags       = pars.Flags,
            }, pars);
        }
Beispiel #4
0
 public void Visit(ParsedImplementation pars)
 {
     AppendEverything(pars);
 }
Beispiel #5
0
        /// <summary>
        /// returns the best caret position for inserting a new IProNew
        /// </summary>
        private int GetCaretPositionForInsertion <T>(string codeName, ProInsertPosition insertPos, out bool insertBefore) where T : ParsedScopeBlock
        {
            insertBefore = false;

            // at caret position
            if (insertPos == ProInsertPosition.CaretPosition)
            {
                return(Sci.GetPosFromLineColumn(Sci.Line.CurrentLine, 0));
            }

            T refItem = null;

            #region set insertBefore and refItem

            // the following is a little annoying to code and understand...
            // the idea is to get (or dont get if it doesn't exist) the previous or the next item
            // of type T in the existing list of said types so we can "anchor" on it to insert
            // our new stuff...
            if (typeof(ParsedPrototype) == typeof(T))
            {
                // find the previous/next function implementation with a prototype
                bool found = false;
                ParsedImplementation foundImplement = null;
                foreach (var impl in _parsedItems.Where(item => item is ParsedImplementation).Cast <ParsedImplementation>())
                {
                    if (impl != null)
                    {
                        // we didn't match our current function implementation yet
                        if (!found)
                        {
                            // we just did
                            if (impl.Name.Equals(codeName))
                            {
                                found = true;
                                continue;
                            }
                            // set previous item
                            if (impl.HasPrototype)
                            {
                                foundImplement = impl;
                            }
                        }
                        else
                        {
                            // match first item after we found our implementation
                            if (impl.HasPrototype)
                            {
                                insertBefore   = true;
                                foundImplement = impl;
                                break;
                            }
                        }
                    }
                }

                // now we need its proto
                if (foundImplement != null)
                {
                    refItem = _parsedItems.FirstOrDefault(fun => {
                        var proto = fun as ParsedPrototype;
                        return(proto != null && proto.Name.Equals(foundImplement.Name) && proto.SimpleForward);
                    }) as T;
                }
            }
            else
            {
                // list of existing items of the same type
                var existingList = _parsedItems.Where(item => item.GetType() == typeof(T)).Select(item => (T)item).ToList();
                if (existingList.Count > 0)
                {
                    // alphabetical order
                    if (insertPos == ProInsertPosition.AlphabeticalOrder)
                    {
                        // find the position that would take our new code
                        int index = existingList.Select(item => item.Name).ToList().BinarySearch(codeName);
                        if (index < 0)
                        {
                            index = ~index - 1; // we get the index in which it should be inserted - 1
                            if (index == -1)
                            {
                                insertBefore = true;
                                refItem      = existingList[0];
                            }
                            else
                            {
                                refItem = existingList[index];
                            }
                        }

                        // first of its kind
                    }
                    else if (insertPos == ProInsertPosition.First)
                    {
                        refItem      = existingList.FirstOrDefault();
                        insertBefore = true;
                    }
                    else if (insertPos == ProInsertPosition.Last)
                    {
                        refItem = existingList.LastOrDefault();
                    }
                }
            }

            #endregion

            string preProcBlockType = null;
            string typeComment      = null;
            if (typeof(ParsedImplementation) == typeof(T))
            {
                preProcBlockType = @"_FUNCTION";
                typeComment      = @"Function\s+Implementations";
            }
            else if (typeof(ParsedPrototype) == typeof(T))
            {
                preProcBlockType = @"_FUNCTION-FORWARD";
                typeComment      = @"Function\s+Prototypes";
            }
            else if (typeof(ParsedProcedure) == typeof(T))
            {
                preProcBlockType = @"_PROCEDURE";
                typeComment      = @"Internal\s+Procedures";
            }

            // is there already an item existing?
            if (refItem != null && preProcBlockType != null)
            {
                // try to find a &IF DEFINED(EXCLUDE- block or a _UIB_BLOCK that surrounds the prototype
                var surroundingScope = GetPreProcBlock(refItem, preProcBlockType);
                if (surroundingScope != null)
                {
                    return(insertBefore ? surroundingScope.Position : surroundingScope.EndBlockPosition);
                }

                // otherwise return the position of the function itself
                return(insertBefore ? refItem.Position : refItem.EndBlockPosition);
            }

            // can we find a comment indicating where the proc should be inserted?
            if (typeComment != null)
            {
                Sci.TargetWholeDocument();
                var previousFlags = Sci.SearchFlags;
                Sci.SearchFlags = SearchFlags.Regex;
                var streg    = @"\/\*\s+[\*]+\s+" + typeComment + @"\s+[\*]+";
                var foundPos = Sci.SearchInTarget(streg);
                Sci.SearchFlags = previousFlags;
                if (foundPos == -1)
                {
                    foundPos = new Regex(@"\/\*\s+[\*]+\s+" + typeComment + @"\s+[\*]+").Match(Sci.Text).Index;
                    if (foundPos == 0)
                    {
                        foundPos = -1;
                    }
                }
                if (foundPos > -1)
                {
                    return(Sci.GetPosFromLineColumn(Sci.LineFromPosition(foundPos) + 1, 0));
                }
            }

            // At last, we find the best position considering the appbuilder blocks

            if (typeof(ParsedImplementation) == typeof(T))
            {
                // function implementation goes all the way bottom
                return(Sci.TextLength);
            }
            if (typeof(ParsedPrototype) == typeof(T))
            {
                // prototypes go after &ANALYZE-SUSPEND _UIB-PREPROCESSOR-BLOCK
                var preprocessorBlock = _parsedItems.FirstOrDefault(item => item is ParsedScopePreProcBlock && ((ParsedScopePreProcBlock)item).Type == ParsedPreProcBlockType.UibPreprocessorBlock);
                if (preprocessorBlock != null)
                {
                    insertBefore = false;
                    return(((ParsedScopePreProcBlock)preprocessorBlock).EndBlockPosition);
                }
            }
            if (typeof(ParsedProcedure) == typeof(T))
            {
                // new procedure goes before the first function implementation of last
                var firstFunc = _parsedItems.FirstOrDefault(item => item is ParsedImplementation) as ParsedImplementation;
                if (firstFunc != null)
                {
                    insertBefore = true;

                    // try to find a &IF DEFINED(EXCLUDE- block that surrounds the func
                    var surroundingScope = GetPreProcBlock(firstFunc, @"_FUNCTION");
                    if (surroundingScope != null)
                    {
                        return(surroundingScope.Position);
                    }

                    return(firstFunc.Position);
                }
                // otherwise it goes at the end
                return(Sci.TextLength);
            }

            return(-1);
        }
Beispiel #6
0
        /// <summary>
        /// Matches a function definition (not the FORWARD prototype)
        /// </summary>
        private ParsedFunction CreateParsedFunction(Token functionToken)
        {
            // info we will extract from the current statement :
            string               name             = null;
            string               parsedReturnType = null;
            int                  extent           = 0;
            ParseFlag            flags            = 0;
            StringBuilder        parameters       = new StringBuilder();
            List <ParsedDefine>  parametersList   = null;
            ParsedImplementation createdImp       = null;

            _lastTokenWasSpace = true;

            Token token;
            int   state = 0;

            do
            {
                token = PeekAt(1); // next token
                if (token is TokenEos)
                {
                    break;
                }
                if (token is TokenComment)
                {
                    continue;
                }
                switch (state)
                {
                case 0:
                    // matching name
                    if (!(token is TokenWord))
                    {
                        break;
                    }
                    name = token.Value;
                    state++;
                    break;

                case 1:
                    // matching return type
                    if (!(token is TokenWord))
                    {
                        break;
                    }
                    if (token.Value.EqualsCi("returns") || token.Value.EqualsCi("class"))
                    {
                        continue;
                    }

                    parsedReturnType = token.Value;

                    state++;
                    break;

                case 2:
                    // matching parameters (start)
                    if (token is TokenWord)
                    {
                        if (token.Value.EqualsCi("private"))
                        {
                            flags |= ParseFlag.Private;
                        }
                        if (token.Value.EqualsCi("extent"))
                        {
                            extent = GetExtentNumber(2);
                        }

                        // we didn't match any opening (, but we found a forward
                        if (token.Value.EqualsCi("forward"))
                        {
                            state = 99;
                        }
                        else if (token.Value.EqualsCi("in"))
                        {
                            state = 100;
                        }
                    }
                    else if (token is TokenSymbol && token.Value.Equals("("))
                    {
                        state = 3;
                    }
                    break;

                case 3:
                    // read parameters, define a ParsedDefineItem for each
                    parametersList = GetParsedParameters(functionToken, parameters);
                    state          = 10;
                    break;

                case 10:
                    // matching prototype, we dont want to create a ParsedItem for prototype
                    if (token is TokenWord)
                    {
                        if (token.Value.EqualsCi("forward"))
                        {
                            state = 99;
                        }
                        else if (token.Value.EqualsCi("in"))
                        {
                            state = 100;
                        }
                    }
                    break;
                }
            } while (MoveNext());
            if (name == null || parsedReturnType == null)
            {
                return(null);
            }

            // otherwise it needs to ends with : or .
            if (!(token is TokenEos))
            {
                return(null);
            }



            // New prototype, we matched a forward or a IN
            if (state >= 99)
            {
                ParsedPrototype createdProto = new ParsedPrototype(name, functionToken, parsedReturnType)
                {
                    Scope            = GetCurrentBlock <ParsedScopeBlock>(),
                    FilePath         = FilePathBeingParsed,
                    SimpleForward    = state == 99, // allows us to know if we expect an implementation in this .p or not
                    EndPosition      = token.EndPosition,
                    EndBlockLine     = token.Line,
                    EndBlockPosition = token.EndPosition,
                    Flags            = flags,
                    Extent           = extent,
                    ParametersString = parameters.ToString()
                };
                if (!_functionPrototype.ContainsKey(name))
                {
                    _functionPrototype.Add(name, createdProto);
                }

                AddParsedItem(createdProto, functionToken.OwnerNumber);

                // case of a IN
                if (!createdProto.SimpleForward)
                {
                    // add the parameters to the list
                    if (parametersList != null)
                    {
                        createdProto.Parameters = new List <ParsedDefine>();
                        foreach (var parsedItem in parametersList)
                        {
                            createdProto.Parameters.Add(parsedItem);
                        }
                    }
                }
            }
            else
            {
                // New function
                createdImp = new ParsedImplementation(name, functionToken, parsedReturnType)
                {
                    EndPosition      = token.EndPosition,
                    Flags            = flags,
                    Extent           = extent,
                    ParametersString = parameters.ToString()
                };

                // it has a prototype?
                if (_functionPrototype.ContainsKey(name))
                {
                    // make sure it was a prototype!
                    var proto = _functionPrototype[name] as ParsedPrototype;
                    if (proto != null && proto.SimpleForward)
                    {
                        createdImp.HasPrototype         = true;
                        createdImp.PrototypeLine        = proto.Line;
                        createdImp.PrototypeColumn      = proto.Column;
                        createdImp.PrototypePosition    = proto.Position;
                        createdImp.PrototypeEndPosition = proto.EndPosition;

                        // boolean to know if the implementation matches the prototype
                        createdImp.PrototypeUpdated = (
                            createdImp.Flags == proto.Flags &&
                            createdImp.Extent.Equals(proto.Extent) &&
                            createdImp.TempReturnType.EqualsCi(proto.TempReturnType) &&
                            createdImp.ParametersString.EqualsCi(proto.ParametersString));
                    }
                }
                else
                {
                    _functionPrototype.Add(name, createdImp);
                }

                // add the parameters to the list
                if (parametersList != null)
                {
                    createdImp.Parameters = new List <ParsedDefine>();
                    foreach (var parsedItem in parametersList)
                    {
                        createdImp.Parameters.Add(parsedItem);
                    }
                }

                AddParsedItem(createdImp, functionToken.OwnerNumber);
            }

            return(createdImp);
        }