コード例 #1
0
ファイル: ClassHierarchyJob.cpp プロジェクト: HackerFoo/rtags
int ClassHierarchyJob::execute()
{
    Symbol symbol = project()->findSymbol(location);
    if (symbol.isNull())
        return 1;
    if (!symbol.isClass() || !symbol.isDefinition())
        symbol = project()->findTarget(symbol.location);
    if (!symbol.isClass())
        return 1;

    typedef std::function<Set<Symbol>(const Symbol &)> FindFunc;
    std::function<void (const Symbol &, const char *title, int, FindFunc)> recurse = [&](const Symbol &symbol,
                                                                                         const char *title,
                                                                                         int indent,
                                                                                         FindFunc find)
    {
        auto classes = find(symbol);
        if (!indent) {
            if (classes.isEmpty()) {
                return;
            }
            write(title);
            indent = 2;
            write<256>("  %s\t%s",
                       symbol.symbolName.constData(),
                       symbol.location.key(keyFlags()).constData());
        } else {
            write<256>("%s%s\t%s",
                       String(indent, ' ').constData(),
                       symbol.symbolName.constData(),
                       symbol.location.key(keyFlags()).constData());
        }
        for (const Symbol &sym : classes) {
            recurse(sym, title, indent + 2, find);
        }
    };

    recurse(symbol, "Superclasses:", 0, [this](const Symbol &sym) {
            Set<Symbol> ret;
            for (const String &usr : sym.baseClasses) {
                for (const auto &s : project()->findByUsr(usr, sym.location.fileId(), Project::ArgDependsOn)) {
                    if (s.isDefinition()) {
                        ret.insert(s);
                        break;
                    }
                }
            }
            return ret;
        });
    recurse(symbol, "Subclasses:", 0, [this](const Symbol &sym) { return project()->findSubclasses(sym); });
    return 0;
}
コード例 #2
0
ファイル: QueryJob.cpp プロジェクト: martong/rtags
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);
}
コード例 #3
0
ファイル: QueryJob.cpp プロジェクト: martong/rtags
bool QueryJob::write(const Symbol &symbol,
                     Flags<Symbol::ToStringFlag> toStringFlags,
                     Flags<WriteFlag> writeFlags)
{
    if (symbol.isNull())
        return false;

    if (!filterLocation(symbol.location))
        return false;

    if (!filterKind(symbol.kind))
        return false;

    return write(symbol.toString(toStringFlags, keyFlags(), project()), writeFlags|Unfiltered);
}
コード例 #4
0
ファイル: ReferencesJob.cpp プロジェクト: LefterisJP/rtags
int ReferencesJob::execute()
{
    const bool rename = queryFlags() & QueryMessage::Rename;
    std::shared_ptr<Project> proj = project();
    if (!proj)
        return 1;
    Set<Symbol> refs;
    Map<Location, std::pair<bool, CXCursorKind> > references;
    if (!symbolName.isEmpty()) {
        const bool hasFilter = QueryJob::hasFilter();
        auto inserter = [this, hasFilter](Project::SymbolMatchType type, const String &string, const Set<Location> &locs) {
            if (type == Project::StartsWith) {
                const int paren = string.indexOf('(');
                if (paren == -1 || paren != symbolName.size() || RTags::isFunctionVariable(string))
                    return;
            }

            for (const auto &l : locs) {
                if (!hasFilter || filter(l.path())) {
                    locations.insert(l);
                }
            }
        };
        proj->findSymbols(symbolName, inserter, queryFlags());
    }
    const bool declarationOnly = queryFlags() & QueryMessage::DeclarationOnly;
    const bool definitionOnly = queryFlags() & QueryMessage::DefinitionOnly;
    Location startLocation;
    bool first = true;
    for (auto it = locations.begin(); it != locations.end(); ++it) {
        const Location pos = *it;
        Symbol sym = proj->findSymbol(pos);
        if (sym.isNull())
            continue;
        if (first && !(queryFlags() & QueryMessage::NoSortReferencesByInput)) {
            first = false;
            startLocation = sym.location;
        }

        if (sym.isReference())
            sym = proj->findTarget(sym);
        if (sym.isNull())
            continue;

        if (rename && sym.isConstructorOrDestructor()) {
            const Location loc = sym.location;
            sym.clear();
            const Set<String> usrs = proj->findTargetUsrs(loc);
            for (const String &usr : usrs) {
                for (const Symbol &s : proj->findByUsr(usr, loc.fileId(), Project::ArgDependsOn, loc)) {
                    if (s.isClass()) {
                        sym = s;
                        if (s.isDefinition())
                            break;
                    }
                }
            }

            if (sym.isNull())
                continue;
        }
        if (queryFlags() & QueryMessage::AllReferences) {
            const Set<Symbol> all = proj->findAllReferences(sym);
            for (const auto &symbol : all) {
                if (rename) {
                    if (symbol.kind == CXCursor_MacroExpansion && sym.kind != CXCursor_MacroDefinition)
                        continue;
                    if (symbol.flags & Symbol::AutoRef)
                        continue;
                } else if (sym.isClass() && symbol.isConstructorOrDestructor()) {
                    continue;
                }
                const bool def = symbol.isDefinition();
                if (def) {
                    if (declarationOnly)
                        continue;
                } else if (definitionOnly) {
                    continue;
                }
                references[symbol.location] = std::make_pair(def, symbol.kind);
            }
        } else if (queryFlags() & QueryMessage::FindVirtuals) {
            const Set<Symbol> virtuals = proj->findVirtuals(sym);
            for (const auto &symbol : virtuals) {
                const bool def = symbol.isDefinition();
                if (def) {
                    if (declarationOnly)
                        continue;
                } else if (definitionOnly) {
                    continue;
                }
                references[symbol.location] = std::make_pair(def, symbol.kind);
            }
        } else {
            const Set<Symbol> symbols = proj->findCallers(sym);
            for (const auto &symbol : symbols) {
                const bool def = symbol.isDefinition();
                if (def) {
                    if (declarationOnly)
                        continue;
                } else if (definitionOnly) {
                    continue;
                }
                references[symbol.location] = std::make_pair(false, CXCursor_FirstInvalid);
            }
        }
    }
    Flags<QueryJob::WriteFlag> writeFlags;
    Flags<Location::KeyFlag> kf = keyFlags();
    if (queryFlags() & QueryMessage::Elisp) {
        write("(list ", DontQuote);
        writeFlags |= QueryJob::NoContext;
    } else if (queryFlags() & QueryMessage::NoContext) {
        writeFlags |= QueryJob::NoContext;
    }

    auto writeCons = [this](const String &car, const String &cdr) {
        write("(cons ", DontQuote);
        write(car, DontQuote);
        write(cdr);
        write(")", DontQuote);
    };

    auto writeLoc = [this, writeCons, writeFlags, kf](const Location &loc) {
        if (queryFlags() & QueryMessage::Elisp) {
            if (!filterLocation(loc))
                return;
            write("(list ", DontQuote);
            locationToString(loc, [writeCons, this](LocationPiece piece, const String &string) {
                    switch (piece) {
                    case Piece_ContainingFunctionLocation:
                        if (queryFlags() & QueryMessage::ContainingFunctionLocation)
                            writeCons("'cfl", string);
                        break;
                    case Piece_ContainingFunctionName:
                        if (queryFlags() & QueryMessage::ContainingFunction)
                            writeCons("'cf", string);
                        break;
                    case Piece_Location:
                        writeCons("'loc", string);
                        break;
                    case Piece_Context:
                        if (!(queryFlags() & QueryMessage::NoContext))
                            writeCons("'ctx", string);
                        break;
                    case Piece_SymbolName:
                    case Piece_Kind:
                        break;
                    }
                });
            write(")", DontQuote);
        } else {
            write(loc, writeFlags);
        }
    };

    if (rename) {
        if (!references.isEmpty()) {
            if (queryFlags() & QueryMessage::ReverseSort) {
                Map<Location, std::pair<bool, CXCursorKind> >::const_iterator it = references.end();
                do {
                    --it;
                    writeLoc(it->first);
                } while (it != references.begin());
            } else {
                for (const auto &it : references) {
                    writeLoc(it.first);
                }
            }
        }
    } else {
        List<RTags::SortedSymbol> sorted;
        sorted.reserve(references.size());
        for (Map<Location, std::pair<bool, CXCursorKind> >::const_iterator it = references.begin();
             it != references.end(); ++it) {
            sorted.append(RTags::SortedSymbol(it->first, it->second.first, it->second.second));
        }
        if (queryFlags() & QueryMessage::ReverseSort) {
            std::sort(sorted.begin(), sorted.end(), std::greater<RTags::SortedSymbol>());
        } else {
            std::sort(sorted.begin(), sorted.end());
        }
        int startIndex = 0;
        const int count = sorted.size();
        if (!startLocation.isNull()) {
            for (int i=0; i<count; ++i) {
                if (sorted.at(i).location == startLocation) {
                    startIndex = i + 1;
                    break;
                }
            }
        }

        for (int i=0; i<count; ++i) {
            const Location &loc = sorted.at((startIndex + i) % count).location;
            writeLoc(loc);
        }
    }
    if (queryFlags() & QueryMessage::Elisp)
        write(")", DontQuote);

    return references.isEmpty() ? 1 : 0;
}