bool QueryJob::locationToString(Location location, const std::function<void(LocationPiece, const String &)> &cb, Flags<WriteFlag> writeFlags) { if (location.isNull()) return false; Flags<Location::ToStringFlag> kf = locationToStringFlags(); kf &= ~Location::ShowContext; cb(Piece_Location, location.toString(kf, &mContextCache)); if (!(writeFlags & NoContext) && !(queryFlags() & QueryMessage::NoContext)) cb(Piece_Context, location.context(kf, &mContextCache)); const bool containingFunction = queryFlags() & QueryMessage::ContainingFunction; const bool containingFunctionLocation = queryFlags() & QueryMessage::ContainingFunctionLocation; const bool cursorKind = queryFlags() & QueryMessage::CursorKind; const bool displayName = queryFlags() & QueryMessage::DisplayName; if (containingFunction || containingFunctionLocation || cursorKind || displayName || !mKindFilters.isEmpty()) { int idx; Symbol symbol = project()->findSymbol(location, &idx); if (symbol.isNull()) { error() << "Somehow can't find" << location << "in symbols"; } else { if (!mKindFilters.filter(symbol)) return false; if (displayName) cb(Piece_SymbolName, symbol.displayName()); if (cursorKind) cb(Piece_Kind, symbol.kindSpelling()); if (containingFunction || containingFunctionLocation) { const uint32_t fileId = location.fileId(); const unsigned int line = location.line(); const unsigned int column = location.column(); auto fileMap = project()->openSymbols(location.fileId()); if (fileMap) { while (idx > 0) { symbol = fileMap->valueAt(--idx); if (symbol.location.fileId() != fileId) break; if (symbol.isDefinition() && RTags::isContainer(symbol.kind) && comparePosition(line, column, symbol.startLine, symbol.startColumn) >= 0 && comparePosition(line, column, symbol.endLine, symbol.endColumn) <= 0) { if (containingFunction) cb(Piece_ContainingFunctionName, symbol.symbolName); if (containingFunctionLocation) cb(Piece_ContainingFunctionLocation, symbol.location.toString(locationToStringFlags() & ~Location::ShowContext)); break; } } } } } } return true; }
bool QueryJob::write(const Location &location, Flags<WriteFlag> flags) { if (location.isNull()) return false; if (!(flags & Unfiltered)) { if (!filterLocation(location)) return false; flags |= Unfiltered; } String out = location.key(keyFlags()); const bool containingFunction = queryFlags() & QueryMessage::ContainingFunction; const bool cursorKind = queryFlags() & QueryMessage::CursorKind; const bool displayName = queryFlags() & QueryMessage::DisplayName; if (containingFunction || cursorKind || displayName || !mKindFilters.isEmpty()) { int idx; Symbol symbol = project()->findSymbol(location, &idx); if (symbol.isNull()) { error() << "Somehow can't find" << location << "in symbols"; } else { if (!filterKind(symbol.kind)) return false; if (displayName) out += '\t' + symbol.displayName(); if (cursorKind) out += '\t' + symbol.kindSpelling(); if (containingFunction) { const uint32_t fileId = location.fileId(); const unsigned int line = location.line(); const unsigned int column = location.column(); auto fileMap = project()->openSymbols(location.fileId()); if (fileMap) { while (idx > 0) { symbol = fileMap->valueAt(--idx); if (symbol.location.fileId() != fileId) break; if (symbol.isDefinition() && RTags::isContainer(symbol.kind) && comparePosition(line, column, symbol.startLine, symbol.startColumn) >= 0 && comparePosition(line, column, symbol.endLine, symbol.endColumn) <= 0) { out += "\tfunction: " + symbol.symbolName; break; } } } } } } return write(out, flags); }