Ejemplo n.º 1
0
bool QueryJob::write(Location location, Flags<WriteFlag> flags)
{
    if (location.isNull())
        return false;
    if (!(flags & Unfiltered)) {
        if (!filterLocation(location))
            return false;
        flags |= Unfiltered;
    }

    String out;
    if (!locationToString(location, [&out](LocationPiece piece, const String &string) {
                switch (piece) {
                case Piece_Location:
                    break;
                case Piece_SymbolName:
                case Piece_Kind:
                case Piece_Context:
                    out << '\t';
                    break;
                case Piece_ContainingFunctionName:
                case Piece_ContainingFunctionLocation:
                    out << "\tfunction: ";
                    break;
                }
                out << string;
            }, flags))
        return false;
    return write(out, flags);
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
bool QueryJob::write(const Symbol &symbol, Flags<WriteFlag> writeFlags)
{
    Flags<Symbol::ToStringFlag> toStringFlags;
    if (queryFlags() & QueryMessage::SymbolInfoIncludeTargets)
        toStringFlags |= Symbol::IncludeTargets;
    if (queryFlags() & QueryMessage::SymbolInfoIncludeReferences)
        toStringFlags |= Symbol::IncludeReferences;
    if (queryFlags() & QueryMessage::SymbolInfoIncludeParents)
        toStringFlags |= Symbol::IncludeParents;
    if (queryFlags() & QueryMessage::SymbolInfoIncludeBaseClasses)
        toStringFlags |= Symbol::IncludeBaseClasses;
    if (queryFlags() & (QueryMessage::ContainingFunction|QueryMessage::JSON|QueryMessage::Elisp))
        toStringFlags |= Symbol::IncludeContainingFunction;
    if (queryFlags() & (QueryMessage::ContainingFunctionLocation|QueryMessage::JSON|QueryMessage::Elisp))
        toStringFlags |= Symbol::IncludeContainingFunctionLocation;

    if (symbol.isNull())
        return false;

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

    if (!mKindFilters.filter(symbol))
        return false;

    String out;
    if (queryFlags() & (QueryMessage::Elisp|QueryMessage::JSON)) {
        Value val = symbol.toValue(project(), toStringFlags, locationToStringFlags() | Location::NoColor, mPieceFilters);
        if (queryFlags() & QueryMessage::Elisp) {
            out = RTags::toElisp(val);
        } else {
            out = val.toJSON();
        }
    } else {
        out = symbol.toString(project(), toStringFlags, locationToStringFlags(), mPieceFilters);
    }
    return write(out, writeFlags|Unfiltered);
}
Ejemplo n.º 5
0
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 size_t paren = string.indexOf('(');
                if (paren == String::npos || 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()) {
            const Symbol target = proj->findTarget(sym);
            if (!target.isNull() && target.kind != CXCursor_MacroExpansion)
                sym = target;
        }
        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::ToStringFlag> kf = locationToStringFlags();
    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](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) {
            Location loc = sorted.at((startIndex + i) % count).location;
            writeLoc(loc);
        }
    }
    if (queryFlags() & QueryMessage::Elisp)
        write(")", DontQuote);

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