Commit d5d08529 authored by Peifeng Yu's avatar Peifeng Yu
Browse files

Merge remote-tracking branch 'origin/master' into peifeng/lldb-plugin

parents 6a09d5ea 2f758986
......@@ -34,7 +34,7 @@ include(KDECMakeSettings)
include(KDECompilerSettings NO_POLICY_SCOPE)
set(QT_MIN_VERSION "5.4.0")
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Widgets Concurrent Quick QuickWidgets WebKitWidgets Script Test)
find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Widgets Concurrent Quick QuickWidgets WebKitWidgets Test)
set(KF5_DEP_VERSION "5.15.0") # we need KCrash::initialize
find_package(KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS
Config
......@@ -145,6 +145,6 @@ install(EXPORT KDevelopTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" NAMESPAC
# in the KDE build system, this is the same as CMAKE_BINARY_DIR.
configure_file(${CMAKE_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_BINARY_DIR}/CTestCustom.cmake)
install(FILES org.kde.kdevelop.appdata.xml DESTINATION ${SHARE_INSTALL_PREFIX}/appdata/)
install(FILES org.kde.kdevelop.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
<kpartgui version="140" name="kdevelop" translationDomain="kdevelop">
<kpartgui version="141" name="kdevelop" translationDomain="kdevelop">
<MenuBar>
<Menu name="session" append="first_menu">
......@@ -146,6 +146,7 @@
<Menu name="settings">
<text context="@title:menu">Settings</text>
<Action name="colorscheme_menu"/>
<DefineGroup append="show_toolbar_merge" name="show_toolbar_merge"/>
<DefineGroup append="show_merge" name="show_merge" />
<DefineGroup append="configure_merge" name="configure_merge" />
......
......@@ -45,7 +45,6 @@
#include <QFileInfo>
#include <QDir>
#include <QProcess>
#include <QResource>
#include <QSessionManager>
#include <QTextStream>
#include <QDBusInterface>
......@@ -235,12 +234,12 @@ static qint64 getRunningSessionPid()
return KDevelop::SessionController::sessionRunInfo(sessionUuid).holderPid;
}
static QString findSessionId(const QString& session)
static QString findSessionId(const SessionInfos& availableSessionInfos, const QString& session)
{
//If there is a session and a project with the same name, always open the session
//regardless of the order encountered
QString projectAsSession;
foreach(const KDevelop::SessionInfo& si, KDevelop::SessionController::availableSessionInfos())
foreach(const KDevelop::SessionInfo& si, availableSessionInfos)
{
if ( session == si.name || session == si.uuid.toString() ) {
return si.uuid.toString();
......@@ -263,18 +262,6 @@ static QString findSessionId(const QString& session)
return projectAsSession;
}
static void tryLoadIconResources()
{
const QString breezeIcons = QStandardPaths::locate(QStandardPaths::DataLocation, QStringLiteral("icons/breeze/breeze-icons.rcc"));
if (!breezeIcons.isEmpty() && QFile::exists(breezeIcons)) {
qCDebug(APP) << "Loading icons rcc:" << breezeIcons;
// prepend /icons to the root to comply with KIcon* machinery
QResource::registerResource(breezeIcons, QStringLiteral("/icons/breeze"));
QIcon::setThemeSearchPaths(QStringList() << QStringLiteral(":/icons"));
}
}
static qint64 findSessionPid(const QString &sessionId)
{
KDevelop::SessionRunInfo sessionInfo = KDevelop::SessionController::sessionRunInfo( sessionId );
......@@ -414,8 +401,6 @@ int main( int argc, char *argv[] )
KCrash::initialize();
tryLoadIconResources();
Kdelibs4ConfigMigrator migrator(QStringLiteral("kdevelop"));
migrator.setConfigFiles({QStringLiteral("kdeveloprc")});
migrator.setUiFiles({QStringLiteral("kdevelopui.rc")});
......@@ -489,6 +474,8 @@ int main( int argc, char *argv[] )
initialFiles.append(UrlInfo(file));
}
const auto availableSessionInfos = KDevelop::SessionController::availableSessionInfos();
if (!initialFiles.isEmpty() && !parser.isSet("new-session")) {
#if KDEVELOP_SINGLE_APP
if (app.isRunning()) {
......@@ -500,7 +487,7 @@ int main( int argc, char *argv[] )
#else
qint64 pid = -1;
if (parser.isSet("open-session")) {
const QString session = findSessionId(parser.value("open-session"));
const QString session = findSessionId(availableSessionInfos, parser.value("open-session"));
if (session.isEmpty()) {
return 1;
} else if (KDevelop::SessionController::isSessionRunning(session)) {
......@@ -520,7 +507,7 @@ int main( int argc, char *argv[] )
QString session;
uint nRunningSessions = 0;
foreach(const KDevelop::SessionInfo& si, KDevelop::SessionController::availableSessionInfos())
foreach(const KDevelop::SessionInfo& si, availableSessionInfos)
if(KDevelop::SessionController::isSessionRunning(si.uuid.toString()))
++nRunningSessions;
......@@ -530,7 +517,7 @@ int main( int argc, char *argv[] )
{
QTextStream qerr(stderr);
SessionInfos candidates;
foreach(const KDevelop::SessionInfo& si, KDevelop::SessionController::availableSessionInfos())
foreach(const KDevelop::SessionInfo& si, availableSessionInfos)
if( (!si.name.isEmpty() || !si.projects.isEmpty() || parser.isSet("pid")) &&
(!parser.isSet("pid") || KDevelop::SessionController::isSessionRunning(si.uuid.toString())))
candidates << si;
......@@ -579,7 +566,7 @@ int main( int argc, char *argv[] )
} else if ( parser.isSet("new-session") )
{
session = parser.value("new-session");
foreach(const KDevelop::SessionInfo& si, KDevelop::SessionController::availableSessionInfos())
foreach(const KDevelop::SessionInfo& si, availableSessionInfos)
{
if ( session == si.name ) {
QTextStream qerr(stderr);
......@@ -589,14 +576,14 @@ int main( int argc, char *argv[] )
}
// session doesn't exist, we can create it
} else if ( parser.isSet("open-session") ) {
session = findSessionId(parser.value("open-session"));
session = findSessionId(availableSessionInfos, parser.value("open-session"));
if (session.isEmpty()) {
return 1;
}
} else if ( parser.isSet("remove-session") )
{
session = parser.value("remove-session");
auto si = findSessionInList(KDevelop::SessionController::availableSessionInfos(), session);
auto si = findSessionInList(availableSessionInfos, session);
if (!si) {
QTextStream qerr(stderr);
qerr << endl << i18n("No session with the name %1 exists.", session) << endl;
......@@ -618,12 +605,11 @@ int main( int argc, char *argv[] )
if(parser.isSet("pid")) {
if (session.isEmpty())
{ // just pick the first running session
foreach(const KDevelop::SessionInfo& si, KDevelop::SessionController::availableSessionInfos())
foreach(const KDevelop::SessionInfo& si, availableSessionInfos)
if(KDevelop::SessionController::isSessionRunning(si.uuid.toString()))
session = si.uuid.toString();
}
SessionInfos sessions = KDevelop::SessionController::availableSessionInfos();
const KDevelop::SessionInfo* sessionData = findSessionInList( sessions, session );
const KDevelop::SessionInfo* sessionData = findSessionInList(availableSessionInfos, session);
if( !sessionData ) {
qCritical() << "session not given or does not exist";
......
......@@ -29,7 +29,7 @@
#=============================================================================
set(KNOWN_VERSIONS 3.9 3.8 3.7 3.6 3.5)
set(KNOWN_VERSIONS 4.0 3.9 3.8 3.7 3.6 3.5)
foreach(version ${KNOWN_VERSIONS})
if (LLVM_DIR OR (DEFINED Clang_FIND_VERSION AND Clang_FIND_VERSION VERSION_GREATER version))
......
......@@ -26,6 +26,8 @@
#include <KLocalizedString>
#include <algorithm>
using namespace KDevelop;
using namespace KDevMI;
using namespace KDevMI::MI;
......@@ -70,25 +72,26 @@ void MIFrameStackModel::handleThreadInfo(const ResultRecord& r)
{
const Value& threads = r["threads"];
// Traverse GDB threads in backward order -- since GDB
// reports them in backward order. We want UI to
// show thread IDs in the natural order.
// FIXME: at least GDB 7.11 is reporting in the right order,
// consider sort the list afterwards.
QList<KDevelop::FrameStackModel::ThreadItem> threadsList;
int gidx = threads.size()-1;
for (; gidx >= 0; --gidx) {
KDevelop::FrameStackModel::ThreadItem i;
const Value & threadMI = threads[gidx];
i.nr = threadMI["id"].toInt();
QList<FrameStackModel::ThreadItem> threadsList;
for (int i = 0; i!= threads.size(); ++i) {
const auto &threadMI = threads[i];
FrameStackModel::ThreadItem threadItem;
threadItem.nr = threadMI["id"].toInt();
if (threadMI["state"].literal() == "stopped") {
i.name = getFunctionOrAddress(threads[gidx]["frame"]);
threadItem.name = getFunctionOrAddress(threadMI["frame"]);
} else {
i.name = i18n("(running)");
i18n("(running)");
}
threadsList << i;
threadsList << threadItem;
}
// Sort the list by id, some old version of GDB
// reports them in backward order. We want UI to
// show thread IDs in the natural order.
std::sort(threadsList.begin(), threadsList.end(),
[](const FrameStackModel::ThreadItem &a, const FrameStackModel::ThreadItem &b){
return a.nr < b.nr;
});
setThreads(threadsList);
if (r.hasField("current-thread-id")) {
int currentThreadId = r["current-thread-id"].toInt();
......
......@@ -60,6 +60,7 @@ DebugSession::DebugSession()
, m_breakpointController(nullptr)
, m_variableController(nullptr)
, m_frameStackModel(nullptr)
, m_autoDisableASLR(false)
{
m_breakpointController = new BreakpointController(this);
m_variableController = new VariableController(this);
......@@ -70,6 +71,11 @@ DebugSession::~DebugSession()
{
}
void DebugSession::setAutoDisableASLR(bool enable)
{
m_autoDisableASLR = enable;
}
BreakpointController *DebugSession::breakpointController() const
{
return m_breakpointController;
......@@ -122,6 +128,10 @@ void DebugSession::initializeDebugger()
addCommand(MI::NonMI, "source " + fileName);
}
// GDB can't disable ASLR on CI server.
addCommand(MI::GdbSet,
QStringLiteral("disable-randomization %1").arg(m_autoDisableASLR ? "on" : "off"));
qCDebug(DEBUGGERGDB) << "Initialized GDB";
}
......
......@@ -72,6 +72,11 @@ public:
VariableController * variableController() const override;
GdbFrameStackModel * frameStackModel() const override;
/// FIXME: only used in unit test currently, potentially could
/// be made a user configurable option.
/// Whether turn off auto-disable ASLR when starting inferiors
void setAutoDisableASLR(bool enable);
protected:
GdbDebugger *createDebugger() const override;
void initializeDebugger() override;
......@@ -90,6 +95,8 @@ private:
BreakpointController *m_breakpointController;
VariableController *m_variableController;
GdbFrameStackModel *m_frameStackModel;
bool m_autoDisableASLR;
};
} // end of namespace GDB
......
......@@ -35,7 +35,6 @@ public:
~GdbDebugger() override;
bool start(KConfigGroup& config, const QStringList& extraArguments = {}) override;
};
} // end of namespace GDB
......
......@@ -194,6 +194,7 @@ public:
TestDebugSession() : DebugSession()
{
setSourceInitFile(false);
setAutoDisableASLR(false);
m_frameStackModel = new TestFrameStackModel(this);
KDevelop::ICore::self()->debugController()->addSession(this);
}
......
......@@ -191,7 +191,9 @@ ClangParseJob::ClangParseJob(const IndexedString& url, ILanguageSupport* languag
foreach(auto document, ICore::self()->documentController()->openDocuments()) {
auto textDocument = document->textDocument();
if (!textDocument || !textDocument->isModified() || !textDocument->url().isLocalFile()
// TODO: Introduce a cache so we don't have to re-read all the open documents
// which were not changed since the last run
if (!textDocument || !textDocument->url().isLocalFile()
|| !DocumentFinderHelpers::mimeTypesList().contains(textDocument->mimeType()))
{
continue;
......
......@@ -299,7 +299,7 @@ CXChildVisitResult declVisitor(CXCursor cursor, CXCursor parent, CXClientData d)
DUChainReadLocker lock;
top = DUChain::self()->chainForDocument(ClangString(clang_getFileName(file)).toIndexed());
}
DeclarationPointer declaration = ClangHelpers::findDeclaration(clang_getCursorLocation(cursor), top);
DeclarationPointer declaration = ClangHelpers::findDeclaration(clang_getCursorLocation(cursor), QualifiedIdentifier(), top);
data->prototypes->append(FuncImplementInfo{kind == CXCursor_Constructor, kind == CXCursor_Destructor,
data->templatePrefix, returnType, rest, declaration});
......
......@@ -237,7 +237,7 @@ public:
QWidget* createExpandingWidget(const CodeCompletionModel* /*model*/) const override
{
return new ClangNavigationWidget(m_declaration);
return new ClangNavigationWidget(m_declaration, KDevelop::AbstractNavigationWidget::EmbeddableWidget);
}
int matchQuality() const
......
......@@ -75,6 +75,7 @@ QString AdaptSignatureAction::toolTip() const
void AdaptSignatureAction::execute()
{
Q_ASSERT(!DUChain::lock()->currentThreadHasReadLock() && !DUChain::lock()->currentThreadHasWriteLock());
DUChainReadLocker lock;
IndexedString url = m_otherSideTopContext->url();
lock.unlock();
......@@ -110,6 +111,7 @@ void AdaptSignatureAction::execute()
}
DocumentChange changeParameters(functionContext->url(), parameterRange, QString(), newText);
lock.unlock();
changeParameters.m_ignoreOldText = true;
changes.addChange(changeParameters);
changes.setReplacementPolicy(DocumentChangeSet::WarnOnFailedChange);
......
......@@ -30,7 +30,8 @@ using namespace KDevelop;
template<>
QWidget* ClangTopDUContext::createNavigationWidget(Declaration* decl, TopDUContext* topContext,
const QString& htmlPrefix, const QString& htmlSuffix) const
const QString& htmlPrefix, const QString& htmlSuffix,
KDevelop::AbstractNavigationWidget::DisplayHints hints) const
{
if (!decl) {
const QUrl u = url().toUrl();
......@@ -40,20 +41,21 @@ QWidget* ClangTopDUContext::createNavigationWidget(Declaration* decl, TopDUConte
item.isDirectory = false;
item.basePath = u.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash);
return new ClangNavigationWidget(item, TopDUContextPointer(topContext ? topContext : this->topContext()), htmlPrefix, htmlSuffix);
return new ClangNavigationWidget(item, TopDUContextPointer(topContext ? topContext : this->topContext()), htmlPrefix, htmlSuffix, hints);
}
return new ClangNavigationWidget(DeclarationPointer(decl));
return new ClangNavigationWidget(DeclarationPointer(decl), hints);
}
template<>
QWidget* ClangNormalDUContext::createNavigationWidget(Declaration* decl, TopDUContext* /*topContext*/,
const QString& /*htmlPrefix*/, const QString& /*htmlSuffix*/) const
const QString& /*htmlPrefix*/, const QString& /*htmlSuffix*/,
KDevelop::AbstractNavigationWidget::DisplayHints hints) const
{
if (!decl) {
clangDebug() << "no declaration, not returning navigationwidget";
return 0;
}
return new ClangNavigationWidget(DeclarationPointer(decl));
return new ClangNavigationWidget(DeclarationPointer(decl), hints);
}
DUCHAIN_DEFINE_TYPE_WITH_DATA(ClangNormalDUContext, DUContextData)
......
......@@ -40,7 +40,8 @@ public:
}
virtual QWidget* createNavigationWidget(KDevelop::Declaration* decl = 0, KDevelop::TopDUContext* topContext = 0,
const QString& htmlPrefix = QString(), const QString& htmlSuffix = QString()) const override;
const QString& htmlPrefix = QString(), const QString& htmlSuffix = QString(),
KDevelop::AbstractNavigationWidget::DisplayHints hints = KDevelop::AbstractNavigationWidget::NoHints) const override;
enum {
Identity = IdentityT
......
......@@ -193,7 +193,7 @@ ReferencedTopDUContext ClangHelpers::buildDUChain(CXFile file, const Imports& im
return context;
}
DeclarationPointer ClangHelpers::findDeclaration(CXSourceLocation location, const ReferencedTopDUContext& top)
DeclarationPointer ClangHelpers::findDeclaration(CXSourceLocation location, QualifiedIdentifier id, const ReferencedTopDUContext& top)
{
if (!top) {
// may happen for cyclic includes
......@@ -202,6 +202,24 @@ DeclarationPointer ClangHelpers::findDeclaration(CXSourceLocation location, cons
auto cursor = CursorInRevision(ClangLocation(location));
DUChainReadLocker lock;
QList<Declaration*> decls;
if (!id.isEmpty())
{
decls = top->findDeclarations(id);
foreach (Declaration* decl, decls)
{
if (decl->range().contains(cursor) ||
(decl->range().isEmpty() && decl->range().start == cursor))
{
return DeclarationPointer(decl);
}
}
}
// there was no match based on the IDs, try the classical
// range based search (very slow)
Q_ASSERT(top);
if (DUContext *local = top->findContextAt(cursor)) {
if (local->owner() && local->owner()->range().contains(cursor)) {
......@@ -221,7 +239,22 @@ DeclarationPointer ClangHelpers::findDeclaration(CXCursor cursor, const IncludeF
return {};
}
return findDeclaration(location, includes.value(file));
// build a qualified identifier by following the chain of semantic parents
QList<Identifier> ids;
CXCursor currentCursor = cursor;
while (currentCursor.kind != CXCursor_TranslationUnit &&
currentCursor.kind != CXCursor_InvalidFile)
{
ids << Identifier(ClangString(clang_getCursorSpelling(currentCursor)).toString());
currentCursor = clang_getCursorSemanticParent(currentCursor);
}
QualifiedIdentifier qid;
for (int i = ids.size()-1; i >= 0; --i)
{
qid.push(ids[i]);
}
return findDeclaration(location, qid, includes.value(file));
}
DeclarationPointer ClangHelpers::findDeclaration(CXType type, const IncludeFileContexts& includes)
......
......@@ -45,7 +45,7 @@ using IncludeFileContexts = QHash<CXFile, KDevelop::ReferencedTopDUContext>;
namespace ClangHelpers {
KDevelop::DeclarationPointer findDeclaration(CXSourceLocation cursor, const KDevelop::ReferencedTopDUContext& top);
KDevelop::DeclarationPointer findDeclaration(CXSourceLocation cursor, KDevelop::QualifiedIdentifier id, const KDevelop::ReferencedTopDUContext& top);
KDevelop::DeclarationPointer findDeclaration(CXCursor cursor, const IncludeFileContexts& includes);
KDevelop::DeclarationPointer findDeclaration(CXType type, const IncludeFileContexts& includes);
......
......@@ -29,6 +29,8 @@
#include <util/clangtypes.h>
#include <util/clangdebug.h>
#include <language/backgroundparser/urlparselock.h>
#include <language/duchain/duchainlock.h>
#include <language/duchain/duchain.h>
#include <clang-c/Index.h>
......@@ -94,6 +96,34 @@ IndexedString ClangIndex::translationUnitForUrl(const IndexedString& url)
return tu.value();
}
}
// if no explicit pin data is available, follow back the duchain import chain
{
KDevelop::DUChainReadLocker lock;
TopDUContext* top = DUChain::self()->chainForDocument(url);
if (top) {
TopDUContext* tuTop = top;
QSet<TopDUContext*> visited;
while(true) {
visited.insert(tuTop);
TopDUContext* next = NULL;
auto importers = tuTop->indexedImporters();
foreach(IndexedDUContext ctx, importers) {
if (ctx.data()) {
next = ctx.data()->topContext();
break;
}
}
if (!next || visited.contains(next)) {
break;
}
tuTop = next;
}
if (tuTop != top) {
return tuTop->url();
}
}
}
// otherwise, fallback to a simple buddy search for headers
if (ClangHelpers::isHeader(url.str())) {
foreach(const QUrl& buddy, DocumentFinderHelpers::getPotentialBuddies(url.toUrl(), false)) {
......
......@@ -78,12 +78,16 @@ CXChildVisitResult visitCursor(CXCursor cursor, CXCursor /*parent*/, CXClientDat
(*data->out) << "| display: \"" << displayName << "\" ";
}
ClangRange range(clang_getCursorExtent(cursor));
KTextEditor::Range simpleRange = range.toRange();
auto cursorExtent = ClangRange(clang_getCursorExtent(cursor)).toRange();
ClangString fileName(clang_getFileName(file));
(*data->out) << "| loc: " << fileName << '@' << '['
<< '(' << simpleRange.start().line()+1 << ',' << simpleRange.start().column()+1 << "),"
<< '(' << simpleRange.end().line()+1 << ',' << simpleRange.end().column()+1 << ")] ";
<< '(' << cursorExtent.start().line()+1 << ',' << cursorExtent.start().column()+1 << "),"
<< '(' << cursorExtent.end().line()+1 << ',' << cursorExtent.end().column()+1 << ")] ";
auto spellingNameRange = ClangRange(clang_Cursor_getSpellingNameRange(cursor, 0, 0)).toRange();
(*data->out) << "| sp-name-range: ["
<< '(' << spellingNameRange.start().line()+1 << ',' << spellingNameRange.start().column()+1 << "),"
<< '(' << spellingNameRange.end().line()+1 << ',' << spellingNameRange.end().column()+1 << ")] ";
if (clang_isDeclaration(kind)) {
(*data->out) << "| isDecl";
......
......@@ -83,9 +83,9 @@ QString MacroNavigationContext::html(bool shorten)
modifyHtml() += QStringLiteral(" "); //The action name _must_ stay "show_uses", since that is also used from outside
makeLink(i18n("Show uses"), QStringLiteral("show_uses"), NavigationAction(m_macro.dynamicCast<Declaration>(), NavigationAction::NavigateUses));
auto code = m_macro->definition().str().replace(QStringLiteral("\n"), QStringLiteral("<br/>"));
auto code = m_macro->definition().str();
modifyHtml() += QLatin1String("<p>") + i18n("Body: ");
modifyHtml() += QLatin1String("<tt>") + code + QLatin1String("</tt>");
modifyHtml() += QLatin1String("<tt>") + code.toHtmlEscaped().replace(QStringLiteral("\n"), QStringLiteral("<br/>")) + QLatin1String("</tt>");
modifyHtml() += QLatin1String("</p>");
modifyHtml() += fontSizeSuffix(shorten) + QLatin1String("</p></body></html>");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment