Exemplo n.º 1
0
        public void BuildCompletionData(IEditorData Editor,
                                        string EnteredText,
                                        out string lastResultPath)
        {
            lastResultPath = null;

            IStatement curStmt  = null;
            var        curBlock = DResolver.SearchBlockAt(Editor.SyntaxTree, Editor.CaretLocation, out curStmt);

            if (curBlock == null)
            {
                return;
            }

            IEnumerable <INode> listedItems = null;

            // Usually shows variable members
            #region DotCompletion
            if (EnteredText == ".")
            {
                alreadyAddedModuleNameParts.Clear();

                var resolveResults = DResolver.ResolveType(
                    Editor,
                    new ResolverContext
                {
                    ScopedBlock     = curBlock,
                    ParseCache      = Editor.ParseCache,
                    ImportCache     = Editor.ImportCache,
                    ScopedStatement = curStmt
                }
                    );

                if (resolveResults == null)                 //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope
                {
                    return;
                }

                /*
                 * Note: When having entered a module name stub only (e.g. "std." or "core.") it's needed to show all packages that belong to that root namespace
                 */

                foreach (var rr in resolveResults)
                {
                    lastResultPath = ResolveResult.GetResolveResultString(rr);
                    BuildCompletionData(rr, curBlock);
                }
            }
            #endregion

            else if (EnteredText == null || EnteredText == " " || EnteredText.Length < 1 || IsIdentifierChar(EnteredText[0]))
            {
                // 1) Get current context the caret is at.
                ParserTrackerVariables trackVars = null;

                var parsedBlock = DResolver.FindCurrentCaretContext(
                    Editor.ModuleCode,
                    curBlock,
                    Editor.CaretOffset,
                    Editor.CaretLocation,
                    out trackVars);

                bool CaretAfterLastParsedObject = false;

                if (trackVars != null && trackVars.LastParsedObject != null)
                {
                    if (trackVars.LastParsedObject is IExpression)
                    {
                        CaretAfterLastParsedObject = Editor.CaretLocation > (trackVars.LastParsedObject as IExpression).EndLocation;
                    }
                    else if (trackVars.LastParsedObject is INode)
                    {
                        CaretAfterLastParsedObject = Editor.CaretLocation > (trackVars.LastParsedObject as INode).EndLocation;
                    }
                }

                // 2) If in declaration and if node identifier is expected, do not show any data
                if (trackVars == null ||
                    (trackVars.LastParsedObject is INode &&
                     !CaretAfterLastParsedObject &&
                     trackVars.ExpectingIdentifier) ||
                    (trackVars.LastParsedObject is TokenExpression &&
                     !CaretAfterLastParsedObject &&
                     DTokens.BasicTypes[(trackVars.LastParsedObject as TokenExpression).Token] &&
                     !string.IsNullOrEmpty(EnteredText) &&
                     IsIdentifierChar(EnteredText[0]))
                    )
                {
                    return;
                }

                var visibleMembers = DResolver.MemberTypes.All;

                if (trackVars.LastParsedObject is ImportStatement && !CaretAfterLastParsedObject)
                {
                    visibleMembers = DResolver.MemberTypes.Imports;
                }
                else if (trackVars.LastParsedObject is NewExpression && (trackVars.IsParsingInitializer || !CaretAfterLastParsedObject))
                {
                    visibleMembers = DResolver.MemberTypes.Imports | DResolver.MemberTypes.Types;
                }
                else if (EnteredText == " ")
                {
                    return;
                }
                // In class bodies, do not show variables
                else if (!(parsedBlock is BlockStatement) && !trackVars.IsParsingInitializer)
                {
                    visibleMembers = DResolver.MemberTypes.Imports | DResolver.MemberTypes.Types | DResolver.MemberTypes.Keywords;
                }

                // In a method, parse from the method's start until the actual caret position to get an updated insight
                if (visibleMembers.HasFlag(DResolver.MemberTypes.Variables) && curBlock is DMethod)
                {
                    if (parsedBlock is BlockStatement)
                    {
                        var blockStmt = parsedBlock as BlockStatement;

                        // Insert the updated locals insight.
                        // Do not take the caret location anymore because of the limited parsing of our code.
                        var scopedStmt = blockStmt.SearchStatementDeeply(blockStmt.EndLocation /*Editor.CaretLocation*/);

                        var decls = BlockStatement.GetItemHierarchy(scopedStmt, Editor.CaretLocation);

                        foreach (var n in decls)
                        {
                            CompletionDataGenerator.Add(n);
                        }
                    }
                }

                if (visibleMembers != DResolver.MemberTypes.Imports)                 // Do not pass the curStmt because we already inserted all updated locals a few lines before!
                {
                    listedItems = DResolver.EnumAllAvailableMembers(curBlock, null /*, curStmt*/, Editor.CaretLocation, Editor.ParseCache, visibleMembers);
                }

                //TODO: Split the keywords into such that are allowed within block statements and non-block statements
                // Insert typable keywords
                if (visibleMembers.HasFlag(DResolver.MemberTypes.Keywords))
                {
                    foreach (var kv in DTokens.Keywords)
                    {
                        CompletionDataGenerator.Add(kv.Key);
                    }
                }

                #region Add module name stubs of importable modules
                if (visibleMembers.HasFlag(DResolver.MemberTypes.Imports))
                {
                    var nameStubs    = new Dictionary <string, string>();
                    var availModules = new List <IAbstractSyntaxTree>();
                    foreach (var mod in Editor.ParseCache)
                    {
                        if (string.IsNullOrEmpty(mod.ModuleName))
                        {
                            continue;
                        }

                        var parts = mod.ModuleName.Split('.');

                        if (!nameStubs.ContainsKey(parts[0]) && !availModules.Contains(mod))
                        {
                            if (parts[0] == mod.ModuleName)
                            {
                                availModules.Add(mod);
                            }
                            else
                            {
                                nameStubs.Add(parts[0], GetModulePath(mod.FileName, parts.Length, 1));
                            }
                        }
                    }

                    foreach (var kv in nameStubs)
                    {
                        CompletionDataGenerator.Add(kv.Key, PathOverride: kv.Value);
                    }

                    foreach (var mod in availModules)
                    {
                        CompletionDataGenerator.Add(mod.ModuleName, mod);
                    }
                }
                #endregion
            }

            // Add all found items to the referenced list
            if (listedItems != null)
            {
                foreach (var i in listedItems)
                {
                    if (CanItemBeShownGenerally(i) /* && dm.IsStatic*/)
                    {
                        CompletionDataGenerator.Add(i);
                    }
                }
            }
        }