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); } } } }