/// <summary> /// Searches the tree down. Returns the found symbol or null. /// Only takes definitions into account. /// If you would like all symbols, not only definitions, use <c>GetSymbolAtPosition</c>. /// </summary> public ISymbolInformation TopDown(ISymbolInformation rootEntry, Uri file, int line, int character) { if (rootEntry == null) { return(null); } ISymbolInformation bestMatch = null; if (SymbolUtil.PositionIsWithinSymbolTotalRange(rootEntry, file, line, character)) { bestMatch = rootEntry; } foreach (var child in rootEntry.Children) { if (SymbolUtil.PositionIsWithinSymbolTotalRange(child, file, line, character)) { bestMatch = child; if (child.HasChildren) { var match = TopDown(child, file, line, character); bestMatch = match ?? bestMatch; } } // in case no better match was found, // check default scope too if ( (bestMatch == null || bestMatch.Equals(rootEntry)) && (child.Name == Resources.SymbolTableStrings.default_class || child.Name == Resources.SymbolTableStrings.default_module) && (child.Children?.Any() ?? false) ) { bestMatch = TopDown(child, file, line, character); } } return(bestMatch); }
/// <summary> /// Searches the tree downwards to match a specific location. /// Only symbols that wrap the location are searched. /// <returns> Returns the match oder null.</returns> /// This will find all symbols, not only definitions. /// If you would like to search for definitions only, use <c>TopDown</c> /// </summary> public ISymbolInformation GetSymbolAtPosition(ISymbolInformation rootEntry, Uri file, int line, int character) { if (rootEntry == null || (!SymbolUtil.PositionIsWithinSymbolTotalRange(rootEntry, file, line, character) && (rootEntry.Name != Resources.SymbolTableStrings.default_module))) { return(null); } var wrappingSymbol = TopDown(rootEntry, file, line, character); if (wrappingSymbol?.Descendants != null) { foreach (var symbol in wrappingSymbol.Descendants) { if (SymbolUtil.PositionIsWithinSymbolIdentifier(symbol, file, line, character)) { return(symbol); } } } if (line == wrappingSymbol?.Line && character <= wrappingSymbol.IdentifierEndColumn) { return(wrappingSymbol); } return(null); }