diff --git a/CMakeLists.txt b/CMakeLists.txt index fa2e5032..a0384e59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,16 +2,30 @@ PROJECT(kdevpython) # write the plugin version to a file set(KDEVPYTHON_VERSION_MAJOR 1) -set(KDEVPYTHON_VERSION_MINOR 7) -set(KDEVPYTHON_VERSION_PATCH 60) +set(KDEVPYTHON_VERSION_MINOR 90) +set(KDEVPYTHON_VERSION_PATCH 90) # KDevplatform dependency version set( KDEVPLATFORM_VERSION "${KDEVPYTHON_VERSION_MAJOR}.${KDEVPYTHON_VERSION_MINOR}.${KDEVPYTHON_VERSION_PATCH}" ) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${kdevpython_SOURCE_DIR}/cmake/) +find_package(ECM 0.0.9 REQUIRED NO_MODULE) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${kdevpython_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH}) -cmake_minimum_required(VERSION 2.8.9) +set(REQUIRED QT_VERSION 5.2.0) -find_package(KDE4 REQUIRED) +cmake_minimum_required(VERSION 2.8.12) + +include(CMakePackageConfigHelpers) + +include(ECMAddTests) +include(ECMOptionalAddSubdirectory) +include(ECMSetupVersion) + +include(KDEInstallDirs) +include(KDECMakeSettings) +include(KDECompilerSettings) + +find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Widgets Test WebKitWidgets) +find_package(KF5 REQUIRED I18n NewStuff ItemModels ThreadWeaver KDELibs4Support TextEditor KCMUtils) find_package(KDevPlatform ${KDEVPLATFORM_VERSION} REQUIRED) @@ -29,19 +43,17 @@ endif ( NOT WIN32 ) # then, build the plugin include_directories( ${KDEVPLATFORM_INCLUDE_DIR} - ${KDE4_INCLUDES} - ${KDE4_INCLUDE_DIR}/threadweaver + +# ${KDE4_INCLUDE_DIR}/threadweaver ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/duchain ${CMAKE_CURRENT_SOURCE_DIR}/parser ${CMAKE_CURRENT_BINARY_DIR}/parser - ${KDEVPGQT_INCLUDE_DIR} + ${KDEVELOP_INCLUDE_DIR} ) -add_definitions( -DKDE_DEFAULT_DEBUG_AREA=9011 ) - if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Intel") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") endif() @@ -62,25 +74,27 @@ add_subdirectory(checks) set(kdevpythonlanguagesupport_PART_SRCS codegen/correctionfilegenerator.cpp codegen/refactoring.cpp + codegen/codegendebug.cpp pythonlanguagesupport.cpp pythonparsejob.cpp pythonhighlighting.cpp + pythondebug.cpp checks/basiccheck.cpp checks/controlflowgraphbuilder.cpp checks/dataaccessvisitor.cpp ) -kde4_add_ui_files(kdevpythonlanguagesupport_PART_SRCS codegen/correctionwidget.ui) +ki18n_wrap_ui(kdevpythonlanguagesupport_PART_SRCS codegen/correctionwidget.ui) -kde4_add_plugin(kdevpythonlanguagesupport ${kdevpythonlanguagesupport_PART_SRCS}) +add_library(kdevpythonlanguagesupport MODULE ${kdevpythonlanguagesupport_PART_SRCS}) target_link_libraries(kdevpythonlanguagesupport - ${KDE4_KDEUI_LIBS} - ${KDEVPLATFORM_INTERFACES_LIBRARIES} - ${KDEVPLATFORM_LANGUAGE_LIBRARIES} - ${KDE4_THREADWEAVER_LIBRARIES} - ${KDE4_KTEXTEDITOR_LIBS} + KDev::Interfaces + KDev::Language + KF5::ThreadWeaver + KF5::TextEditor + KF5::KDELibs4Support kdev4pythoncompletion kdev4pythonparser kdev4pythonduchain @@ -88,7 +102,8 @@ target_link_libraries(kdevpythonlanguagesupport install(TARGETS kdevpythonlanguagesupport DESTINATION ${PLUGIN_INSTALL_DIR}) -install(FILES kdevpythonsupport.desktop DESTINATION ${SERVICES_INSTALL_DIR}) +configure_file(kdevpythonsupport.desktop.cmake ${CMAKE_CURRENT_BINARY_DIR}/kdevpythonsupport.desktop) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kdevpythonsupport.desktop DESTINATION ${SERVICES_INSTALL_DIR}) install(DIRECTORY documentation_files DESTINATION ${DATA_INSTALL_DIR}/kdevpythonsupport) install(DIRECTORY correction_files DESTINATION ${DATA_INSTALL_DIR}/kdevpythonsupport) diff --git a/DESIGN b/DESIGN index a86130dc..957138d5 100644 --- a/DESIGN +++ b/DESIGN @@ -20,23 +20,7 @@ It should be obvious from the large amount of examples what those rules look lik This class returns a CodeAst, which is then passed back to the parse job, which then calls the DUChain classes to analyze the tree. If an error occurs, parsing is aborted and the error is reported to the user. -As the standard python AST library obfuscates some ranges (like, in foo.bar.baz, all of foo, bar and baz are -said to start at column 0, while we need to know bar starts at 4 and baz at 8), we had no choice than to fork -the python parser and make those changes ourselves. The python source code can be found in the python-src -directory. The patches which were applied to the parser are in the patches/ subdirectory in git patch format; -those can be used if we want to switch the python version one day (from python 2.7 to 3.x, for example). The DUChain Library ------------------- -This library builds a Definition-Use-Chain from the AST, which is then used to -support code completion, syntax highlighting and other language features in -KDevelop. The design of the DUChain is described at: -http://api.kde.org/4.x-api/kdevplatform-apidocs/language/html/duchain-design.html - -The following language elements create a new Context: -- a class definition -- a function definition -- a compound statement, that includes for, while, if, with statements <- this has been removed, -as those do not really create a new context in the python language (i.e. variable declarations -inside such "contexts" still exist outside, unlike C++) - +See http://api.kde.org/4.x-api/kdevplatform-apidocs/language/html/duchain-design.html \ No newline at end of file diff --git a/INSTALL b/INSTALL index 489a7ddb..2b1585f4 100644 --- a/INSTALL +++ b/INSTALL @@ -6,13 +6,6 @@ make install If you run into crashes, please rebuild with the -DCMAKE_BUILD_TYPE=debug flag passed to cmake and report a bug with the backtrace attached. -IMPORTANT: If you're using Arch Linux: Arch breaks the standard of having "python" point to a python2 implementation. This breaks stuff. -So if you're using arch, either make "python" call some python2 interpreter instead of python3 while compiling (only while compiling, doesn't matter afterwards) -or edit the file python-src/Parser/asdl_c.py and change the first line to point to your python2 implementation, so usually replace -#! /usr/bin/env python -with -#! /usr/bin/env python2 - Running test suite: To enable test building, run cmake .. -DKDE4_BUILD_TESTS=true diff --git a/README.packagers b/README.packagers index af01c73d..a2d8fc04 100644 --- a/README.packagers +++ b/README.packagers @@ -29,3 +29,12 @@ It MUST be packaged together with the program, as it contains runtime data which is necessary for the program to work correctly (such as representations of python's built-in data types, which are then read by the parser etc.). + +Licensing notes +--------------- +The following files are not copyrighted: +Everything in duchain/tests/data/ +Everything in documentation_files/ +Everything in correction_files/ +Everything in app_templates/ +example_ast.py diff --git a/TODO b/TODO deleted file mode 100644 index 85fbe08c..00000000 --- a/TODO +++ /dev/null @@ -1,15 +0,0 @@ -- Support "from ... import *" -- fix function argument calltip (currently implemented incorrectly) -- write debugger interface -- use PYTHONPATH for searching includes -- add C module template -- add a lot of error reporting -- support unsure types in autocompletion / highlighting - - -A note from David Nolden(one of the authors of C++ Language support): -[2007-09-04 23:38] apaku: Btw. I have thought a bit about python code-completion. I think to make it really good, you need the following: -[2007-09-04 23:38] 1. An expression-parser, that is able to determine the type of any python expression (maybe could be integrated in type-builder) -[2007-09-04 23:39] 2. A specialized PythonDeclaration class that can hold an arbitrarily sized list of types -[2007-09-04 23:39] 3. Whenever assigning something to a value, evaluate that somethings type, and add it to the declarations type-list -[2007-09-04 23:40] However expression-parsing was a lot of work for c++, I don't know how much it would be for python diff --git a/checks/basiccheck.cpp b/checks/basiccheck.cpp index 6ec4a47a..dbc47787 100644 --- a/checks/basiccheck.cpp +++ b/checks/basiccheck.cpp @@ -26,8 +26,6 @@ #include #include -#include - using namespace KDevelop; QString BasicCheck::name() const diff --git a/checks/controlflowgraphbuilder.h b/checks/controlflowgraphbuilder.h index 1edcb52d..1a93e08c 100644 --- a/checks/controlflowgraphbuilder.h +++ b/checks/controlflowgraphbuilder.h @@ -28,6 +28,7 @@ #include #include +#include namespace Python { diff --git a/checks/dataaccessvisitor.cpp b/checks/dataaccessvisitor.cpp index 73129b89..7cffecc4 100644 --- a/checks/dataaccessvisitor.cpp +++ b/checks/dataaccessvisitor.cpp @@ -37,7 +37,7 @@ DataAccessVisitor::Access DataAccessVisitor::transformFlag(ExpressionAst::Contex if ( context == ExpressionAst::AugStore || context == ExpressionAst::Store ) { return DataAccess::Write; } - if ( context == ExpressionAst::ExpressionAst::Parameter ) { + if ( context == ExpressionAst::Parameter ) { // TODO return DataAccess::Read; } diff --git a/checks/dataaccessvisitor.h b/checks/dataaccessvisitor.h index d8aaa5f4..d309832d 100644 --- a/checks/dataaccessvisitor.h +++ b/checks/dataaccessvisitor.h @@ -24,6 +24,7 @@ #include #include +#include #include namespace Python { diff --git a/codecompletion/CMakeLists.txt b/codecompletion/CMakeLists.txt index 8a569da2..a2df2e15 100644 --- a/codecompletion/CMakeLists.txt +++ b/codecompletion/CMakeLists.txt @@ -8,6 +8,7 @@ set(completion_SRCS model.cpp worker.cpp helpers.cpp + codecompletiondebug.cpp items/missingincludeitem.cpp items/declaration.cpp @@ -18,7 +19,11 @@ set(completion_SRCS items/replacementvariable.cpp ) -kde4_add_library(kdev4pythoncompletion SHARED ${completion_SRCS}) +add_library(kdev4pythoncompletion SHARED ${completion_SRCS}) + +generate_export_header(kdev4pythoncompletion EXPORT_MACRO_NAME KDEVPYTHONCOMPLETION_EXPORT + EXPORT_FILE_NAME pythoncompletionexport.h +) add_dependencies(kdev4pythoncompletion kdev4pythonparser @@ -26,10 +31,10 @@ add_dependencies(kdev4pythoncompletion ) target_link_libraries(kdev4pythoncompletion LINK_PRIVATE - ${KDE4_KDECORE_LIBS} - ${KDEVPLATFORM_LANGUAGE_LIBRARIES} - ${KDEVPLATFORM_INTERFACES_LIBRARIES} - ${KDEVPLATFORM_PROJECT_LIBRARIES} + KF5::KDELibs4Support + KDev::Language + KDev::Interfaces + KDev::Project kdev4pythonduchain kdev4pythonparser ) diff --git a/codecompletion/codecompletiondebug.cpp b/codecompletion/codecompletiondebug.cpp new file mode 100644 index 00000000..3f089c18 --- /dev/null +++ b/codecompletion/codecompletiondebug.cpp @@ -0,0 +1,23 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "codecompletiondebug.h" +Q_LOGGING_CATEGORY(KDEV_PYTHON_CODECOMPLETION, "kdev.python.codecompletion") + + diff --git a/codecompletion/codecompletiondebug.h b/codecompletion/codecompletiondebug.h new file mode 100644 index 00000000..e3a78893 --- /dev/null +++ b/codecompletion/codecompletiondebug.h @@ -0,0 +1,27 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef CODECOMPLETIONDEBUG_H +#define CODECOMPLETIONDEBUG_H + +#include +Q_DECLARE_LOGGING_CATEGORY(KDEV_PYTHON_CODECOMPLETION) + +#endif + diff --git a/codecompletion/context.cpp b/codecompletion/context.cpp index 7d942065..6dc19d9a 100644 --- a/codecompletion/context.cpp +++ b/codecompletion/context.cpp @@ -55,6 +55,9 @@ #include #include +#include +#include "codecompletiondebug.h" + using namespace KTextEditor; using namespace KDevelop; @@ -107,7 +110,7 @@ QList< CompletionTreeElementPointer > PythonCodeCompletionContext::ungroupedElem static QList setOmitParentheses(QList items) { for ( auto current: items ) { - if ( auto func = KSharedPtr::dynamicCast(current) ) { + if ( auto func = dynamic_cast(current.data()) ) { func->setDoNotCall(true); } } @@ -144,8 +147,8 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::functionCallI auto v = visitorForString(m_guessTypeOfExpression, m_duContext.data()); DUChainReadLocker lock; if ( ! v || ! v->lastDeclaration() ) { - kWarning() << "Did not receive a function declaration from expression visitor! Not offering call tips."; - kWarning() << "Tried: " << m_guessTypeOfExpression; + qCWarning(KDEV_PYTHON_CODECOMPLETION) << "Did not receive a function declaration from expression visitor! Not offering call tips."; + qCWarning(KDEV_PYTHON_CODECOMPLETION) << "Tried: " << m_guessTypeOfExpression; return resultingItems; } functionCalled = Helper::functionDeclarationForCalledDeclaration(v->lastDeclaration()).first.data(); @@ -158,7 +161,7 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::functionCallI auto calltipItems = declarationListToItemList(calltips); foreach ( CompletionTreeItemPointer current, calltipItems ) { - kDebug() << "Adding calltip item, at argument:" << m_alreadyGivenParametersCount+1; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Adding calltip item, at argument:" << m_alreadyGivenParametersCount+1; FunctionDeclarationCompletionItem* item = static_cast(current.data()); item->setAtArgument(m_alreadyGivenParametersCount + 1); item->setDepth(depth()); @@ -175,7 +178,7 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::functionCallI if ( DUContext* args = DUChainUtils::getArgumentContext(functionCalled) ) { int normalParameters = args->localDeclarations().count() - functionCalled->defaultParametersSize(); if ( normalParameters > m_alreadyGivenParametersCount ) { - kDebug() << "Not at default arguments yet"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Not at default arguments yet"; return resultingItems; } for ( unsigned int i = 0; i < functionCalled->defaultParametersSize(); i++ ) { @@ -184,7 +187,7 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::functionCallI paramName + "=", i18n("specify default parameter"), KeywordItem::ImportantItem)); } - kDebug() << "adding " << functionCalled->defaultParametersSize() << "default args"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "adding " << functionCalled->defaultParametersSize() << "default args"; } return resultingItems; @@ -196,7 +199,7 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::defineItems() ItemList resultingItems; // Find all base classes of the current class context if ( m_duContext->type() != DUContext::Class ) { - kWarning() << "current context is not a class context, not offering define completion"; + qCWarning(KDEV_PYTHON_CODECOMPLETION) << "current context is not a class context, not offering define completion"; return resultingItems; } ClassDeclaration* klass = dynamic_cast(m_duContext->owner()); @@ -232,12 +235,14 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::defineItems() existingIdentifiers << identifier; QStringList argumentNames; DUContext* argumentsContext = DUChainUtils::getArgumentContext(funcDecl); - foreach ( Declaration* argument, argumentsContext->localDeclarations() ) { - argumentNames << argument->identifier().toString(); + if ( argumentsContext ) { + foreach ( Declaration* argument, argumentsContext->localDeclarations() ) { + argumentNames << argument->identifier().toString(); + } + resultingItems << CompletionTreeItemPointer(new ImplementFunctionCompletionItem( + funcDecl->identifier().toString(), argumentNames, m_indent) + ); } - resultingItems << CompletionTreeItemPointer(new ImplementFunctionCompletionItem( - funcDecl->identifier().toString(), argumentNames, m_indent) - ); } } isOwnContext = false; @@ -247,13 +252,13 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::defineItems() PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::raiseItems() { - kDebug() << "Finding items for raise statement"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Finding items for raise statement"; DUChainReadLocker lock; ItemList resultingItems; ReferencedTopDUContext ctx = Helper::getDocumentationFileContext(); QList< Declaration* > declarations = ctx->findDeclarations(QualifiedIdentifier("BaseException")); if ( declarations.isEmpty() || ! declarations.first()->abstractType() ) { - kDebug() << "No valid exception classes found, aborting"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "No valid exception classes found, aborting"; return resultingItems; } Declaration* base = declarations.first(); @@ -286,7 +291,7 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::importFileIte { DUChainReadLocker lock; ItemList resultingItems; - kDebug() << "Preparing to do autocompletion for import..."; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Preparing to do autocompletion for import..."; m_maxFolderScanDepth = 1; resultingItems << includeItemsForSubmodule(""); return resultingItems; @@ -296,7 +301,7 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::inheritanceIt { ItemList resultingItems; DUChainReadLocker lock; - kDebug() << "InheritanceCompletion"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "InheritanceCompletion"; QList declarations; if ( ! m_guessTypeOfExpression.isEmpty() ) { // The class completion is a member access @@ -336,15 +341,15 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::memberAccessI DUChainReadLocker lock; if ( v ) { if ( v->lastType() ) { - kDebug() << v->lastType()->toString(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << v->lastType()->toString(); resultingItems << getCompletionItemsForType(v->lastType()); } else { - kWarning() << "Did not receive a type from expression visitor! Not offering autocompletion."; + qCWarning(KDEV_PYTHON_CODECOMPLETION) << "Did not receive a type from expression visitor! Not offering autocompletion."; } } else { - kWarning() << "Completion requested for syntactically invalid expression, not offering anything"; + qCWarning(KDEV_PYTHON_CODECOMPLETION) << "Completion requested for syntactically invalid expression, not offering anything"; } // append eventually stripped postfix, for e.g. os.chdir| @@ -373,12 +378,12 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::stringFormatt ItemList resultingItems; int cursorPosition; StringFormatter stringFormatter(CodeHelpers::extractStringUnderCursor(m_text, - m_duContext->range().castToSimpleRange().textRange(), - m_position.castToSimpleCursor().textCursor(), + m_duContext->range().castToSimpleRange(), + m_position.castToSimpleCursor(), &cursorPosition)); - kDebug() << "Next identifier id: " << stringFormatter.nextIdentifierId(); - kDebug() << "Cursor position in string: " << cursorPosition; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Next identifier id: " << stringFormatter.nextIdentifierId(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Cursor position in string: " << cursorPosition; bool insideReplacementVariable = stringFormatter.isInsideReplacementVariable(cursorPosition); RangeInString variablePosition = stringFormatter.getVariablePosition(cursorPosition); @@ -407,11 +412,10 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::stringFormatt // in the document. We can safely assume that the replacement variable is on one line, // because the regex does not allow newlines inside replacement variables. KTextEditor::Range range; - range.setBothLines(m_position.line); - range.start().setColumn(m_position.column - (cursorPosition - variablePosition.beginIndex)); - range.end().setColumn(m_position.column + (variablePosition.endIndex - cursorPosition)); + range.setStart({m_position.line, m_position.column - (cursorPosition - variablePosition.beginIndex)}); + range.setEnd({m_position.line, m_position.column + (variablePosition.endIndex - cursorPosition)}); - kDebug() << "Variable under cursor: " << variable->toString(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Variable under cursor: " << variable->toString(); bool hasNumericOnlyOption = variable->hasPrecision() || (variable->hasType() && variable->type() != 's') || variable->align() == '='; @@ -434,7 +438,7 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::stringFormatt } if ( ! variable->hasFormatSpec() ) { - auto addFormatSpec = [&](const QString& format, const QString& title, bool useTemplateEngine=false) + auto addFormatSpec = [&](const QString& format, const QString& title, bool useTemplateEngine) { resultingItems.append(makeFormattingItem(variable->conversion(), format, title, useTemplateEngine)); }; @@ -445,17 +449,17 @@ PythonCodeCompletionContext::ItemList PythonCodeCompletionContext::stringFormatt // These options don't make sense if we've set conversion using str() or repr() if ( ! variable->hasConversion() ) { addFormatSpec(".${precision}", i18n("Specify precision"), true); - addFormatSpec("%", i18n("Format as percentage")); - addFormatSpec("c", i18n("Format as character")); - addFormatSpec("b", i18n("Format as binary number")); - addFormatSpec("o", i18n("Format as octal number")); - addFormatSpec("x", i18n("Format as hexadecimal number")); - addFormatSpec("e", i18n("Format in scientific (exponent) notation")); - addFormatSpec("f", i18n("Format as fixed point number")); + addFormatSpec("%", i18n("Format as percentage"), false); + addFormatSpec("c", i18n("Format as character"), false); + addFormatSpec("b", i18n("Format as binary number"), false); + addFormatSpec("o", i18n("Format as octal number"), false); + addFormatSpec("x", i18n("Format as hexadecimal number"), false); + addFormatSpec("e", i18n("Format in scientific (exponent) notation"), false); + addFormatSpec("f", i18n("Format as fixed point number"), false); } } - kDebug() << "Resulting items size: " << resultingItems.size(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Resulting items size: " << resultingItems.size(); return resultingItems; } @@ -551,8 +555,8 @@ QList PythonCodeCompletionContext::completionItems(bo m_fullCompletion = fullCompletion; ItemList resultingItems; - kDebug() << "Line: " << m_position.line; - kDebug() << "Completion type:" << m_operation; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Line: " << m_position.line; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Completion type:" << m_operation; if ( m_operation != FunctionCallCompletion ) { resultingItems.append(shebangItems()); @@ -564,7 +568,7 @@ QList PythonCodeCompletionContext::completionItems(bo } if ( m_operation == PythonCodeCompletionContext::NoCompletion ) { - kDebug() << "no code completion"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "no code completion"; } else if ( m_operation == PythonCodeCompletionContext::GeneratorVariableCompletion ) { resultingItems.append(generatorItems()); @@ -609,7 +613,7 @@ QList PythonCodeCompletionContext::completionItems(bo DUChainReadLocker lock; QList declarations = m_duContext->allDeclarations(m_position, m_duContext->topContext()); foreach ( const DeclarationDepthPair& d, declarations ) { - if ( d.first and d.first->context()->type() == DUContext::Class ) { + if ( d.first && d.first->context()->type() == DUContext::Class ) { declarations.removeAll(d); } } @@ -681,7 +685,7 @@ QList PythonCodeCompletionContext::declarationListToI int count = declarations.length(); for ( int i = 0; i < count; i++ ) { if ( maxDepth && maxDepth > declarations.at(i).second ) { - kDebug() << "Skipped completion item because of its depth"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Skipped completion item because of its depth"; continue; } currentDeclaration = DeclarationPointer(declarations.at(i).first); @@ -725,7 +729,6 @@ QList< CompletionTreeItemPointer > PythonCodeCompletionContext::getCompletionIte QList result; UnsureType::Ptr unsure = type.cast(); int count = unsure->typesSize(); - kDebug() << "Getting completion items for " << count << "types of unsure type " << unsure; for ( int i = 0; i < count; i++ ) { result.append(getCompletionItemsForOneType(unsure->types()[i].abstractType())); } @@ -770,20 +773,20 @@ QList PythonCodeCompletionContext::getCompletionItems } // find properties of class declaration TypePtr cls = StructureType::Ptr::dynamicCast(type); - kDebug() << "Finding completion items for class type"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Finding completion items for class type"; if ( ! cls || ! cls->internalContext(m_duContext->topContext()) ) { - kWarning() << "No class type available, no completion offered"; + qCWarning(KDEV_PYTHON_CODECOMPLETION) << "No class type available, no completion offered"; return QList(); } // the PublicOnly will filter out non-explictly defined __get__ etc. functions inherited from object QList searchContexts = Helper::internalContextsForClass(cls, m_duContext->topContext(), Helper::PublicOnly); QList keepDeclarations; foreach ( const DUContext* currentlySearchedContext, searchContexts ) { - kDebug() << "searching context " << currentlySearchedContext->scopeIdentifier() << "for autocompletion items"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "searching context " << currentlySearchedContext->scopeIdentifier() << "for autocompletion items"; QList declarations = currentlySearchedContext->allDeclarations(CursorInRevision::invalid(), m_duContext->topContext(), false); - kDebug() << "found" << declarations.length() << "declarations"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "found" << declarations.length() << "declarations"; // filter out those which are builtin functions, and those which were imported; we don't want those here // also, discard all magic functions from autocompletion @@ -794,7 +797,7 @@ QList PythonCodeCompletionContext::getCompletionItems keepDeclarations.append(current); } else { - kDebug() << "Discarding declaration " << current.first->toString(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Discarding declaration " << current.first->toString(); } } } @@ -803,7 +806,7 @@ QList PythonCodeCompletionContext::getCompletionItems QList PythonCodeCompletionContext::findIncludeItems(IncludeSearchTarget item) { - kDebug() << "TARGET:" << item.directory.pathOrUrl() << item.remainingIdentifiers << item.directory.path(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "TARGET:" << item.directory.pathOrUrl() << item.remainingIdentifiers << item.directory.path(); QDir currentDirectory(item.directory.path()); QFileInfoList contents = currentDirectory.entryInfoList(QStringList(), QDir::Files | QDir::Dirs); bool atBottom = item.remainingIdentifiers.isEmpty(); @@ -832,7 +835,7 @@ QList PythonCodeCompletionContext::findIncludeItems(I else { QFileInfo file(item.directory.path(), item.remainingIdentifiers.first() + ".py"); item.remainingIdentifiers.removeFirst(); - kDebug() << " CHECK:" << file.absoluteFilePath(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << " CHECK:" << file.absoluteFilePath(); if ( file.exists() ) { sourceFile = file.absoluteFilePath(); } @@ -841,9 +844,9 @@ QList PythonCodeCompletionContext::findIncludeItems(I if ( ! sourceFile.isEmpty() ) { IndexedString filename(sourceFile); TopDUContext* top = DUChain::self()->chainForDocument(filename); - kDebug() << top; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << top; DUContext* c = internalContextForDeclaration(top, item.remainingIdentifiers); - kDebug() << " GOT:" << c; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << " GOT:" << c; if ( c ) { // tell function declaration items not to add brackets items << setOmitParentheses(declarationListToItemList(c->localDeclarations().toList())); @@ -861,7 +864,7 @@ QList PythonCodeCompletionContext::findIncludeItems(I if ( file.fileName().startsWith('.') ) { continue; } - kDebug() << " > CONTENT:" << file.absolutePath() << file.fileName(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << " > CONTENT:" << file.absolutePath() << file.fileName(); if ( file.isFile() ) { if ( file.fileName().endsWith(".py") || file.fileName().endsWith(".so") ) { IncludeItem fileInclude; @@ -926,7 +929,7 @@ DUContext* PythonCodeCompletionContext::internalContextForDeclaration(TopDUConte QList PythonCodeCompletionContext::includeItemsForSubmodule(QString submodule) { - QList searchPaths = Helper::getSearchPaths(m_workingOnDocument); + QList searchPaths = Helper::getSearchPaths(m_workingOnDocument); QStringList subdirs; if ( ! submodule.isEmpty() ) { @@ -943,23 +946,20 @@ QList PythonCodeCompletionContext::includeItemsForSub // Thus, we first generate a list of possible paths, then match them against those which actually exist // and then gather all the items in those paths. - foreach ( KUrl currentPath, searchPaths ) { - kDebug() << "Searching: " << currentPath << subdirs; + foreach ( QUrl currentPath, searchPaths ) { + auto d = QDir(currentPath.path()); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Searching: " << currentPath << subdirs; int identifiersUsed = 0; foreach ( const QString& subdir, subdirs ) { - currentPath.cd(subdir); - QFileInfo d(currentPath.path()); - kDebug() << currentPath << d.exists() << d.isDir(); - if ( ! d.exists() || ! d.isDir() ) { - currentPath.cd(".."); - currentPath.cleanPath(); + if ( ! d.cd(subdir) ) { break; } + qCDebug(KDEV_PYTHON_CODECOMPLETION) << currentPath << d.exists(); identifiersUsed++; } QStringList remainingIdentifiers = subdirs.mid(identifiersUsed, -1); foundPaths.append(IncludeSearchTarget(currentPath, remainingIdentifiers)); - kDebug() << "Found path:" << currentPath << remainingIdentifiers << subdirs; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Found path:" << currentPath << remainingIdentifiers << subdirs; } return findIncludeItems(foundPaths); } @@ -986,8 +986,8 @@ void PythonCodeCompletionContext::summonParentForEventualCall(TokenList allExpre int offset = 0; while ( true ) { QPair nextCall = allExpressions.nextIndexOfStatus(ExpressionParser::EventualCallFound, offset); - kDebug() << "next call:" << nextCall; - kDebug() << allExpressions.toString(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "next call:" << nextCall; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << allExpressions.toString(); if ( nextCall.first == -1 ) { // no more eventual calls break; @@ -995,12 +995,12 @@ void PythonCodeCompletionContext::summonParentForEventualCall(TokenList allExpre offset = nextCall.first; allExpressions.reset(offset); TokenListEntry eventualFunction = allExpressions.weakPop(); - kDebug() << eventualFunction.expression << eventualFunction.status; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << eventualFunction.expression << eventualFunction.status; // it's only a call if a "(" bracket is followed (<- direction) by an expression. if ( eventualFunction.status != ExpressionParser::ExpressionFound ) { continue; // not a call, try the next opening "(" bracket } - kDebug() << "Call found! Creating parent-context."; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Call found! Creating parent-context."; // determine the amount of "free" commas in between allExpressions.reset(); int atParameter = 0; @@ -1039,11 +1039,11 @@ PythonCodeCompletionContext::PythonCodeCompletionContext(DUContextPointer contex m_workingOnDocument = context->topContext()->url().toUrl(); QString textWithoutStrings = CodeHelpers::killStrings(text); - kDebug() << text << position << context->localScopeIdentifier().toString() << context->range(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << text << position << context->localScopeIdentifier().toString() << context->range(); QPair beforeAndAfterCursor = CodeHelpers::splitCodeByCursor(text, - context->range().castToSimpleRange().textRange(), - position.castToSimpleCursor().textCursor()); + context->range().castToSimpleRange(), + position.castToSimpleCursor()); // check if the current position is inside a multi-line comment -> no completion if this is the case CodeHelpers::EndLocation location = CodeHelpers::endsInside(beforeAndAfterCursor.first); @@ -1086,7 +1086,7 @@ PythonCodeCompletionContext::PythonCodeCompletionContext(DUContextPointer contex currentlyCheckedLine -= 1; } while ( currentlyChecked && context->parentContextOf(currentlyChecked) ) { - kDebug() << "checking:" << currentlyChecked->range() << currentlyChecked->type(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "checking:" << currentlyChecked->range() << currentlyChecked->type(); // FIXME: "<=" is not really good, it must be exactly one indent-level less int offset = position.line-currentlyChecked->range().start.line; // If the check leaves the current context, abort. @@ -1096,7 +1096,7 @@ PythonCodeCompletionContext::PythonCodeCompletionContext(DUContextPointer contex if ( indents.indentForLine(indents.linesCount()-1-offset) <= indents.indentForLine(indents.linesCount()-1) ) { - kDebug() << "changing context to" << currentlyChecked->range() + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "changing context to" << currentlyChecked->range() << ( currentlyChecked->type() == DUContext::Class ); context = currentlyChecked; break; @@ -1169,7 +1169,7 @@ PythonCodeCompletionContext::PythonCodeCompletionContext(DUContextPointer contex m_operation = DefineCompletion; } else { - kDebug() << "def outside class context"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "def outside class context"; m_operation = NoCompletion; } return; @@ -1262,8 +1262,8 @@ PythonCodeCompletionContext::PythonCodeCompletionContext(DUContextPointer contex else { m_searchImportItemsInModule = firstPiece + "." + secondPiece; } - kDebug() << firstPiece << secondPiece; - kDebug() << "Got submodule to search:" << m_searchImportItemsInModule << "from text" << textWithoutStrings; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << firstPiece << secondPiece; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "Got submodule to search:" << m_searchImportItemsInModule << "from text" << textWithoutStrings; m_operation = ImportSubCompletion; return; } diff --git a/codecompletion/helpers.cpp b/codecompletion/helpers.cpp index e92223b3..6c608eed 100644 --- a/codecompletion/helpers.cpp +++ b/codecompletion/helpers.cpp @@ -33,6 +33,9 @@ #include #include +#include +#include "codecompletiondebug.h" + #include "duchain/declarations/functiondeclaration.h" #include "parser/codehelpers.h" @@ -177,7 +180,7 @@ QString ExpressionParser::skipUntilStatus(ExpressionParser::Status requestedStat Status currentStatus = InvalidStatus; while ( currentStatus != requestedStatus ) { lastExpression = popExpression(¤tStatus); - kDebug() << lastExpression << currentStatus; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << lastExpression << currentStatus; if ( currentStatus == NothingFound ) { *ok = ( requestedStatus == NothingFound ); // ok exactly if the caller requested NothingFound as end status return QString(); @@ -238,7 +241,7 @@ QString ExpressionParser::popExpression(ExpressionParser::Status* status) bool lastCharIsSpace = getRemainingCode().right(1).at(0).isSpace(); m_cursorPositionInString -= trailingWhitespace(); if ( operatingOn.endsWith('(') ) { - kDebug() << "eventual call found"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "eventual call found"; m_cursorPositionInString -= 1; *status = EventualCallFound; return QString(); @@ -409,7 +412,7 @@ void createArgumentList(Declaration* dec_, QString& ret, QList< QVariant >* high StringFormatter::StringFormatter(const QString &string) : m_string(string) { - kDebug() << "String being parsed: " << string; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "String being parsed: " << string; QRegExp regex("\\{(\\w+)(?:!([rs]))?(?:\\:(.*))?\\}"); regex.setMinimal(true); int pos = 0; @@ -419,7 +422,7 @@ StringFormatter::StringFormatter(const QString &string) QChar conversion = (conversionStr.isNull() || conversionStr.isEmpty()) ? QChar() : conversionStr.at(0); QString formatSpec = regex.cap(3); - kDebug() << "variable: " << regex.cap(0); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "variable: " << regex.cap(0); // The regex guarantees that conversion is only a single character ReplacementVariable variable(identifier, conversion, formatSpec); diff --git a/codecompletion/items/declaration.cpp b/codecompletion/items/declaration.cpp index 7df09403..ecd537a5 100644 --- a/codecompletion/items/declaration.cpp +++ b/codecompletion/items/declaration.cpp @@ -34,7 +34,9 @@ using namespace KDevelop; namespace Python { -PythonDeclarationCompletionItem::PythonDeclarationCompletionItem(DeclarationPointer decl, KSharedPtr< CodeCompletionContext > context, int inheritanceDepth) +PythonDeclarationCompletionItem::PythonDeclarationCompletionItem(DeclarationPointer decl, + QExplicitlySharedDataPointer context, + int inheritanceDepth) : NormalDeclarationCompletionItem(decl, context, inheritanceDepth) , m_typeHint(PythonCodeCompletionContext::NoHint) , m_addMatchQuality(0) @@ -68,7 +70,7 @@ QVariant PythonDeclarationCompletionItem::data(const QModelIndex& index, int rol return 0; } if ( m_typeHint == PythonCodeCompletionContext::IterableRequested - && dynamic_cast(declaration()->abstractType().unsafeData()) ) + && dynamic_cast(declaration()->abstractType().data()) ) { return 10; } diff --git a/codecompletion/items/declaration.h b/codecompletion/items/declaration.h index 5277ea23..0259b494 100644 --- a/codecompletion/items/declaration.h +++ b/codecompletion/items/declaration.h @@ -29,7 +29,7 @@ namespace Python { class PythonDeclarationCompletionItem : public KDevelop::NormalDeclarationCompletionItem { public: PythonDeclarationCompletionItem(KDevelop::DeclarationPointer decl = KDevelop::DeclarationPointer(), - KSharedPtr context = KSharedPtr(), + QExplicitlySharedDataPointer context = QExplicitlySharedDataPointer(), int inheritanceDepth = 0); virtual QVariant data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const; void setTypeHint(PythonCodeCompletionContext::ItemTypeHint type); diff --git a/codecompletion/items/functiondeclaration.cpp b/codecompletion/items/functiondeclaration.cpp index b23f8ee5..b807a2fb 100644 --- a/codecompletion/items/functiondeclaration.cpp +++ b/codecompletion/items/functiondeclaration.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,8 @@ #include "declarations/functiondeclaration.h" #include "duchain/helpers.h" +#include +#include "../codecompletiondebug.h" using namespace KDevelop; using namespace KTextEditor; @@ -115,7 +118,7 @@ QVariant FunctionDeclarationCompletionItem::data(const QModelIndex& index, int r case KDevelop::CodeCompletionModel::MatchQuality: { if ( m_typeHint == PythonCodeCompletionContext::IterableRequested && dec && dec->type() - && dynamic_cast(dec->type()->returnType().unsafeData()) ) + && dynamic_cast(dec->type()->returnType().data()) ) { return 2 + PythonDeclarationCompletionItem::data(index, role, model).toInt(); } @@ -130,16 +133,17 @@ void FunctionDeclarationCompletionItem::setDoNotCall(bool doNotCall) m_doNotCall = doNotCall; } -void FunctionDeclarationCompletionItem::executed(KTextEditor::Document* document, const KTextEditor::Range& word) +void FunctionDeclarationCompletionItem::executed(KTextEditor::View* view, const KTextEditor::Range& word) { - kDebug() << "FunctionDeclarationCompletionItem executed"; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "FunctionDeclarationCompletionItem executed"; + KTextEditor::Document* document = view->document(); DeclarationPointer resolvedDecl(Helper::resolveAliasDeclaration(declaration().data())); DUChainReadLocker lock; QPair fdecl = Helper::functionDeclarationForCalledDeclaration(resolvedDecl); lock.unlock(); if ( ! fdecl.first && (! resolvedDecl || ! resolvedDecl->abstractType() || resolvedDecl->abstractType()->whichType() != AbstractType::TypeStructure) ) { - kError() << "ERROR: could not get declaration data, not executing completion item!"; + qCritical(KDEV_PYTHON_CODECOMPLETION) << "ERROR: could not get declaration data, not executing completion item!"; return; } QString suffix = "()"; @@ -151,7 +155,7 @@ void FunctionDeclarationCompletionItem::executed(KTextEditor::Document* document { // don't insert brackets if they're already there, // the item is a decorator, or if it's an import item. - suffix = ""; + suffix.clear(); } // place cursor behind bracktes by default int skip = 2; @@ -173,9 +177,7 @@ void FunctionDeclarationCompletionItem::executed(KTextEditor::Document* document } } document->replaceText(word, declaration()->identifier().toString() + suffix); - if ( View* view = document->activeView() ) { - view->setCursorPosition( Cursor(word.end().line(), word.end().column() + skip) ); - } + view->setCursorPosition( Cursor(word.end().line(), word.end().column() + skip) ); } FunctionDeclarationCompletionItem::~FunctionDeclarationCompletionItem() { } diff --git a/codecompletion/items/functiondeclaration.h b/codecompletion/items/functiondeclaration.h index bd571c1a..2e301a57 100644 --- a/codecompletion/items/functiondeclaration.h +++ b/codecompletion/items/functiondeclaration.h @@ -41,7 +41,7 @@ class FunctionDeclarationCompletionItem : public Python::PythonDeclarationComple virtual QVariant data(const QModelIndex& index, int role, const CodeCompletionModel* model) const; - virtual void executed(KTextEditor::Document* document, const KTextEditor::Range& word); + virtual void executed(KTextEditor::View* view, const KTextEditor::Range& word) override; private: int m_atArgument; int m_depth; diff --git a/codecompletion/items/implementfunction.cpp b/codecompletion/items/implementfunction.cpp index 8b51fa99..5c619b43 100644 --- a/codecompletion/items/implementfunction.cpp +++ b/codecompletion/items/implementfunction.cpp @@ -22,10 +22,14 @@ #include #include +#include + #include #include #include +#include + using namespace KDevelop; using namespace KTextEditor; @@ -37,14 +41,15 @@ ImplementFunctionCompletionItem::ImplementFunctionCompletionItem(const QString& } -void ImplementFunctionCompletionItem::execute(KTextEditor::Document* document, const KTextEditor::Range& word) +void ImplementFunctionCompletionItem::execute(KTextEditor::View* view, const KTextEditor::Range& word) { + auto document = view->document(); const QString finalText = m_name + "(" + m_arguments.join(", ") + "):"; document->replaceText(word, finalText); // 4 spaces is indentation for python. everyone does it like this. you must, too. // TODO use kate settings document->insertLine(word.start().line() + 1, m_previousIndent + " "); - if ( View* view = document->activeView() ) { + if ( View* view = static_cast(ICore::self()->partController())->activeView() ) { view->setCursorPosition(Cursor(word.end().line() + 1, m_previousIndent.length() + 4)); } } diff --git a/codecompletion/items/implementfunction.h b/codecompletion/items/implementfunction.h index 42891cae..dfd838ef 100644 --- a/codecompletion/items/implementfunction.h +++ b/codecompletion/items/implementfunction.h @@ -29,7 +29,7 @@ class ImplementFunctionCompletionItem : public CompletionTreeItem { public: ImplementFunctionCompletionItem(const QString& name, const QStringList& arguments, const QString& previousIndent); - virtual void execute(KTextEditor::Document* document, const KTextEditor::Range& word); + virtual void execute(KTextEditor::View* view, const KTextEditor::Range& word) override; virtual QVariant data(const QModelIndex& index, int role, const CodeCompletionModel* model) const; private: diff --git a/codecompletion/items/importfile.cpp b/codecompletion/items/importfile.cpp index 56d027d0..bbc9de49 100644 --- a/codecompletion/items/importfile.cpp +++ b/codecompletion/items/importfile.cpp @@ -19,10 +19,14 @@ #include "importfile.h" #include +#include #include #include "duchain/navigation/navigationwidget.h" +#include +#include "codecompletiondebug.h" + using namespace KDevelop; namespace Python { @@ -37,11 +41,11 @@ ImportFileItem::~ImportFileItem() } -void ImportFileItem::execute(KTextEditor::Document* document, const KTextEditor::Range& word) +void ImportFileItem::execute(KTextEditor::View* view, const KTextEditor::Range& word) { - kDebug() << "ImportFileItem executed"; - document->replaceText(word, moduleName); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "ImportFileItem executed"; + view->document()->replaceText(word, moduleName); } -} \ No newline at end of file +} diff --git a/codecompletion/items/importfile.h b/codecompletion/items/importfile.h index 76c61ebf..a7077fd3 100644 --- a/codecompletion/items/importfile.h +++ b/codecompletion/items/importfile.h @@ -35,7 +35,7 @@ class ImportFileItem : public IncludeFileItemBase ImportFileItem(const KDevelop::IncludeItem& include); virtual ~ImportFileItem(); - virtual void execute(KTextEditor::Document* document, const KTextEditor::Range& word); + virtual void execute(KTextEditor::View* view, const KTextEditor::Range& word) override; QString moduleName; KDevelop::IProject* fromProject; }; diff --git a/codecompletion/items/keyword.cpp b/codecompletion/items/keyword.cpp index 834ea70b..81393780 100644 --- a/codecompletion/items/keyword.cpp +++ b/codecompletion/items/keyword.cpp @@ -1,16 +1,16 @@ /***************************************************************************** - * Copyright (c) 2011 Sven Brauch * + * Copyright (c) 2011-2014 Sven Brauch * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * * published by the Free Software Foundation; either version 2 of * * the License, or (at your option) any later version. * - * * + * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * - * * + * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************** @@ -21,6 +21,7 @@ #include #include #include + #include #include @@ -37,14 +38,14 @@ KeywordItem::KeywordItem(KDevelop::CodeCompletionContext::Ptr context, QString k m_keyword = keyword; } -void KeywordItem::execute(Document* document, const Range& word) +void KeywordItem::execute(View* view, const Range& word) { if ( m_flags & ForceLineBeginning ) { Range newRange(Cursor(word.start().line(), 0), word.end()); - document->replaceText(newRange, m_keyword); + view->document()->replaceText(newRange, m_keyword); } else { - document->replaceText(word, m_keyword); + view->document()->replaceText(word, m_keyword); } } diff --git a/codecompletion/items/keyword.h b/codecompletion/items/keyword.h index 21cc2dc4..5ec224f5 100644 --- a/codecompletion/items/keyword.h +++ b/codecompletion/items/keyword.h @@ -35,8 +35,8 @@ class KeywordItem : public NormalDeclarationCompletionItem ImportantItem = 0x2 }; KeywordItem(CodeCompletionContext::Ptr context, QString keyword, QString descr, Python::KeywordItem::Flags flags = NoFlags); - virtual void execute(KTextEditor::Document* document, const KTextEditor::Range& word); - virtual QVariant data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const; + virtual void execute(KTextEditor::View* view, const KTextEditor::Range& word) override; + virtual QVariant data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const override; private: QString m_keyword; QString m_description; diff --git a/codecompletion/items/missingincludeitem.cpp b/codecompletion/items/missingincludeitem.cpp index 49a11107..db5189ae 100644 --- a/codecompletion/items/missingincludeitem.cpp +++ b/codecompletion/items/missingincludeitem.cpp @@ -16,9 +16,15 @@ *****************************************************************************/ #include "missingincludeitem.h" + #include + #include +#include + #include +#include +#include "codecompletiondebug.h" namespace Python { @@ -48,14 +54,14 @@ QVariant MissingIncludeItem::data(const QModelIndex& index, int role, const KDev return QVariant(); } -void MissingIncludeItem::execute(KTextEditor::Document* document, const KTextEditor::Range& word) +void MissingIncludeItem::execute(KTextEditor::View* view, const KTextEditor::Range& word) { - kDebug() << "executed with text" << m_text; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "executed with text" << m_text; // First, add the import statement to the top of the file // FIXME: deal with multi-line comments int insertAt = 0; - for ( int i = 0; i < document->lines(); i++ ) { - const QString& line = document->line(i); + for ( int i = 0; i < view->document()->lines(); i++ ) { + const QString& line = view->document()->line(i); if ( line.trimmed().startsWith('#') || line.trimmed().isEmpty() ) { continue; } @@ -79,11 +85,11 @@ void MissingIncludeItem::execute(KTextEditor::Document* document, const KTextEdi if ( ! m_removeComponents.isEmpty() ) { const KTextEditor::Cursor end = word.end(); const KTextEditor::Cursor start = end - KTextEditor::Cursor(0, m_removeComponents.length()); - document->replaceText(KTextEditor::Range(start, end), m_matchText); + view->document()->replaceText(KTextEditor::Range(start, end), m_matchText); } // Do this only later, otherwise ranges change - document->insertLine(qMax(0, insertAt - 1), m_text); + view->document()->insertLine(qMax(0, insertAt - 1), m_text); } } diff --git a/codecompletion/items/missingincludeitem.h b/codecompletion/items/missingincludeitem.h index 17d646cd..963cede6 100644 --- a/codecompletion/items/missingincludeitem.h +++ b/codecompletion/items/missingincludeitem.h @@ -27,8 +27,8 @@ namespace Python { class MissingIncludeItem : public KDevelop::CompletionTreeItem { public: MissingIncludeItem(const QString& insertText, const QString& matchText, const QString& removeComponents=QString()); - virtual void execute(KTextEditor::Document* document, const KTextEditor::Range& word); - virtual QVariant data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const; + virtual void execute(KTextEditor::View* view, const KTextEditor::Range& word) override; + virtual QVariant data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const override; private: const QString m_text; diff --git a/codecompletion/items/replacementvariable.cpp b/codecompletion/items/replacementvariable.cpp index edfc3f62..e188983e 100644 --- a/codecompletion/items/replacementvariable.cpp +++ b/codecompletion/items/replacementvariable.cpp @@ -21,7 +21,7 @@ #include #include #include -#include +// #include not currently supported #include #include @@ -38,8 +38,9 @@ ReplacementVariableItem::ReplacementVariableItem(const ReplacementVariable &vari { } -void ReplacementVariableItem::execute(Document *document, const Range &word) +void ReplacementVariableItem::execute(View* view, const Range &word) { + auto document = view->document(); if ( ! m_position.isValid() ) { m_position = word; } @@ -48,26 +49,28 @@ void ReplacementVariableItem::execute(Document *document, const Range &word) Range removeRange(m_position.start(), removeUntil); if ( document->text(m_position).lastIndexOf('{') != -1 ) { // remove the whole existing expression - removeRange.end().setColumn(m_position.end().column()); + removeRange.setEnd({removeRange.end().line(), m_position.end().column()}); } else { // remove nothing unless there is an opening { already, in that case remove that - removeRange.start() = m_position.end(); - removeRange.end() = m_position.end(); + removeRange= {m_position.end(), m_position.end()}; - Range previousCharacter(word.start(), word.start()); - previousCharacter.start().setColumn(word.start().column() - 1); + Range previousCharacter(word.start() - Cursor(0, 1), word.start()); if ( document->text(previousCharacter) == "{" ) { - removeRange.start().setColumn(removeRange.start().column() - 1); + removeRange.setStart(removeRange.start() - Cursor(0, 1)); } } if ( m_hasEditableFields ) { - TemplateInterface2 *templateInterface = qobject_cast(document->activeView()); - if ( templateInterface ) { + qWarning() << "template interface not supported by editor"; +#if 0 + TODO: re-enable once the template interface exists again + auto iface = qobject_cast(ICore::self()->partController()->activeView()); + if ( iface ) { document->removeText(removeRange); - templateInterface->insertTemplateText(removeRange.start(), m_variable.toString(), QMap(), NULL); + iface->insertTemplateText(removeRange.start(), m_variable.toString(), QMap(), NULL); } +#endif } else { document->removeText(removeRange); diff --git a/codecompletion/items/replacementvariable.h b/codecompletion/items/replacementvariable.h index ab4f1181..5f22cb69 100644 --- a/codecompletion/items/replacementvariable.h +++ b/codecompletion/items/replacementvariable.h @@ -31,7 +31,7 @@ class ReplacementVariableItem : public CompletionTreeItem { public: ReplacementVariableItem(const ReplacementVariable &variable, const QString &description, bool hasEditableFields, KTextEditor::Range position = KTextEditor::Range::invalid()); - virtual void execute(KTextEditor::Document* document, const KTextEditor::Range& word); + virtual void execute(KTextEditor::View* view, const KTextEditor::Range& word) override; virtual QVariant data(const QModelIndex& index, int role, const KDevelop::CodeCompletionModel* model) const; private: diff --git a/codecompletion/model.cpp b/codecompletion/model.cpp index 07a29521..b60b14e0 100644 --- a/codecompletion/model.cpp +++ b/codecompletion/model.cpp @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (c) 2010-2011 Sven Brauch * + * Copyright (c) 2010-2014 Sven Brauch * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License as * @@ -20,6 +20,10 @@ #include #include +#include + +#include +#include "codecompletiondebug.h" #include "context.h" #include "worker.h" @@ -65,27 +69,23 @@ bool PythonCodeCompletionModel::shouldAbortCompletion(KTextEditor::View* view, c { const QString text = view->document()->text(range); if ( completionContext() ) { - KSharedPtr context = KSharedPtr::staticCast( - completionContext() - ); + auto context = static_cast(completionContext().data()); if ( context->completionContextType() == PythonCodeCompletionContext::StringFormattingCompletion ) { if ( text.endsWith('"') || text.endsWith("'") || text.endsWith(' ') ) { return true; } } } - return KTextEditor::CodeCompletionModelControllerInterface3::shouldAbortCompletion(view, range, currentCompletion); + return KTextEditor::CodeCompletionModelControllerInterface::shouldAbortCompletion(view, range, currentCompletion); } QString PythonCodeCompletionModel::filterString(KTextEditor::View *view, const KTextEditor::Range &range, const KTextEditor::Cursor &position) { // TODO The completion context may be null, so we need to check it first. This might a bug. if ( completionContext() ) { - KSharedPtr context = KSharedPtr::staticCast( - completionContext() - ); + auto context = static_cast(completionContext().data()); if (context->completionContextType() == PythonCodeCompletionContext::StringFormattingCompletion) { - return QString(); + return QString(); } } return CodeCompletionModel::filterString(view, range, position); @@ -94,8 +94,8 @@ QString PythonCodeCompletionModel::filterString(KTextEditor::View *view, const K KTextEditor::Range PythonCodeCompletionModel::completionRange(KTextEditor::View* view, const KTextEditor::Cursor& position) { m_currentDocument = view->document()->url(); - kWarning() << "Current document: " << m_currentDocument; - return KTextEditor::CodeCompletionModelControllerInterface3::completionRange(view, position); + qCWarning(KDEV_PYTHON_CODECOMPLETION) << "Current document: " << m_currentDocument; + return KTextEditor::CodeCompletionModelControllerInterface::completionRange(view, position); } KDevelop::CodeCompletionWorker* PythonCodeCompletionModel::createCompletionWorker() diff --git a/codecompletion/pythoncompletionexport.h b/codecompletion/pythoncompletionexport.h deleted file mode 100644 index f607003c..00000000 --- a/codecompletion/pythoncompletionexport.h +++ /dev/null @@ -1,34 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2012 Sven Brauch * - * * - * This program is free software; you can redistribute it and/or * - * modify it under the terms of the GNU General Public License as * - * published by the Free Software Foundation; either version 2 of * - * the License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * - ***************************************************************************** - */ - -#ifndef PYTHONCOMPLETIONEXPORT_H -#define PYTHONCOMPLETIONEXPORT_H - -/* needed for KDE_EXPORT macros */ -#include - - -#ifndef KDEVPYTHONCOMPLETION_EXPORT -# ifdef MAKE_KDEV4PYTHONCOMPLETION_LIB -# define KDEVPYTHONCOMPLETION_EXPORT KDE_EXPORT -# else -# define KDEVPYTHONCOMPLETION_EXPORT KDE_IMPORT -# endif -#endif - -#endif \ No newline at end of file diff --git a/codecompletion/tests/CMakeLists.txt b/codecompletion/tests/CMakeLists.txt index c7416d7c..c0a26f2d 100644 --- a/codecompletion/tests/CMakeLists.txt +++ b/codecompletion/tests/CMakeLists.txt @@ -1,10 +1,15 @@ -kde4_add_unit_test(pycompletiontest pycompletiontest.cpp) +set(pycompletiontest_SRCS + pycompletiontest.cpp + ../codecompletiondebug.cpp) -target_link_libraries(pycompletiontest - kdev4pythonduchain - kdev4pythoncompletion - kdev4pythonparser - ${kdev4pythonparser_LIBRARIES} - ${QT_QTTEST_LIBRARY} - ${KDEVPLATFORM_TESTS_LIBRARIES} +ecm_add_test(${pycompletiontest_SRCS} + TEST_NAME pycompletiontest + LINK_LIBRARIES + kdev4pythonduchain + kdev4pythoncompletion + kdev4pythonparser + ${kdev4pythonparser_LIBRARIES} + Qt5::Test + KDev::Tests + KF5::KDELibs4Support ) diff --git a/codecompletion/tests/pycompletiontest.cpp b/codecompletion/tests/pycompletiontest.cpp index eed29d17..d55430f9 100644 --- a/codecompletion/tests/pycompletiontest.cpp +++ b/codecompletion/tests/pycompletiontest.cpp @@ -36,6 +36,9 @@ #include "codecompletion/context.h" #include "codecompletion/helpers.h" +#include +#include "codecompletiondebug.h" + using namespace KDevelop; QTEST_MAIN(Python::PyCompletionTest) @@ -45,7 +48,6 @@ Q_DECLARE_METATYPE(KTextEditor::Range) static int testId = 0; static QString basepath = "/tmp/__kdevpythoncompletiontest.dir/"; -static QFSFileEngine fileEngine; namespace Python { @@ -78,7 +80,7 @@ void makefile(QString filename, QString contents) { fileptr.close(); KUrl url = KUrl(basepath + filename); url.cleanPath(); - kDebug() << "updating duchain for " << url.url() << basepath; + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "updating duchain for " << url.url() << basepath; const IndexedString urlstring(url); DUChain::self()->updateContextForUrl(urlstring, KDevelop::TopDUContext::ForceUpdate); ICore::self()->languageController()->backgroundParser()->parseDocuments(); @@ -90,7 +92,8 @@ void PyCompletionTest::initShell() AutoTestShell::init(); TestCore* core = new TestCore(); core->initialize(KDevelop::Core::NoUi); - fileEngine.mkdir(basepath, false); + QDir d; + d.mkpath(basepath); KUrl doc_url = KUrl(KStandardDirs::locate("data", "kdevpythonsupport/documentation_files/builtindocumentation.py")); doc_url.cleanPath(KUrl::SimplifyDirSeparators); @@ -103,8 +106,8 @@ void PyCompletionTest::initShell() KDevelop::CodeRepresentation::setDiskChangesForbidden(true); // now, create a nice little completion hierarchy - fileEngine.mkdir(basepath + "submoduledir", false); - fileEngine.mkdir(basepath + "submoduledir/anothersubdir", false); + d.mkpath(basepath + "submoduledir"); + d.mkpath(basepath + "submoduledir/anothersubdir"); makefile("toplevelmodule.py", "some_var = 3\ndef some_function(): pass\nclass some_class():\n def method(): pass"); makefile("submoduledir/__init__.py", "var_in_sub_init = 5"); makefile("submoduledir/subfile.py", "var_in_subfile = 5\nclass some_subfile_class():\n def method2(): pass"); @@ -467,8 +470,9 @@ void PyCompletionTest::testAutoBrackets() KService::Ptr documentService = KService::serviceByDesktopPath("katepart.desktop"); QVERIFY(documentService); KTextEditor::Document* document = documentService->createInstance(this); + auto view = document->createView(nullptr); QVERIFY(document); - item->execute(document, KTextEditor::Range(0, 0, 0, 0)); + item->execute(view, KTextEditor::Range(0, 0, 0, 0)); QCOMPARE(document->text(), QLatin1String("myprop")); } @@ -543,8 +547,10 @@ void PyCompletionTest::testFunctionDeclarationCompletion() KTextEditor::Document* document = documentService->createInstance(this); QVERIFY(document); document->setText(documentCode); + + auto view = document->createView(nullptr); - completionItems.first()->execute(document, executeRange); + completionItems.first()->execute(view, executeRange); QCOMPARE(document->text(), expectedCode); } @@ -567,7 +573,7 @@ void PyCompletionTest::testFunctionDeclarationCompletion_data() QTest::newRow("class_name_no_constructor_parens") << "class Foo:\n pass\nbar = %INVOKE" << "Foo%CURSOR" << KTextEditor::Range(2, 6, 2, 9) << "Foo()"; - QTest::newRow("class_name_explicit_constructor_parens") << "class Foo:\n def __init__(self):\n pass\nbar = %INVOKE" << "Foo%CURSOR" + QTest::newRow("class_name_explicit_constructor_parens") << "class Foo:\n def __init__(self):\n pass\nbar = %INVOKE" << "Fo%CURSOR" << KTextEditor::Range(3, 6, 3, 9) << "Foo()"; } diff --git a/codecompletion/worker.cpp b/codecompletion/worker.cpp index 8aa73b57..2b1d31e6 100644 --- a/codecompletion/worker.cpp +++ b/codecompletion/worker.cpp @@ -24,6 +24,9 @@ #include "codehelpers.h" #include +#include +#include "codecompletiondebug.h" + namespace Python { PythonCodeCompletionWorker::PythonCodeCompletionWorker(PythonCodeCompletionModel *parent, KUrl /*document*/) @@ -48,8 +51,8 @@ KDevelop::CodeCompletionContext* PythonCodeCompletionWorker::createCompletionCon void PythonCodeCompletionWorker::updateContextRange(KTextEditor::Range &contextRange, KTextEditor::View *view, KDevelop::DUContextPointer context) const { if ( CodeHelpers::endsInside(view->document()->text(contextRange)) == CodeHelpers::String ) { - kDebug() << "we're dealing with string completion. extend the range"; - contextRange = context->rangeInCurrentRevision().textRange(); + qCDebug(KDEV_PYTHON_CODECOMPLETION) << "we're dealing with string completion. extend the range"; + contextRange = context->rangeInCurrentRevision(); } } diff --git a/codegen/codegendebug.cpp b/codegen/codegendebug.cpp new file mode 100644 index 00000000..67f6334b --- /dev/null +++ b/codegen/codegendebug.cpp @@ -0,0 +1,23 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "codegendebug.h" +Q_LOGGING_CATEGORY(KDEV_PYTHON_CODEGEN, "kdev.python.codegen") + + diff --git a/codegen/codegendebug.h b/codegen/codegendebug.h new file mode 100644 index 00000000..41bd55ef --- /dev/null +++ b/codegen/codegendebug.h @@ -0,0 +1,27 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef CODEGENDEBUG_H +#define CODEGENDEBUG_H + +#include +Q_DECLARE_LOGGING_CATEGORY(KDEV_PYTHON_CODEGEN) + +#endif + diff --git a/codegen/correctionfilegenerator.cpp b/codegen/correctionfilegenerator.cpp index 0a980a91..c9258f9e 100644 --- a/codegen/correctionfilegenerator.cpp +++ b/codegen/correctionfilegenerator.cpp @@ -21,7 +21,6 @@ #include "correctionfilegenerator.h" #include -#include #include #include @@ -38,6 +37,9 @@ #include "duchain/helpers.h" #include "parser/codehelpers.h" +#include +#include "codegendebug.h" + using namespace KDevelop; namespace Python { @@ -67,7 +69,7 @@ void TypeCorrection::doContextMenu(ContextMenuExtension &extension, Context *con && declaration->abstractType()->whichType() == AbstractType::TypeFunction)) ) { QAction* action = new QAction(i18n("Specify type for \"%1\"...", declaration->qualifiedIdentifier().toString()), 0); action->setData(QVariant::fromValue(IndexedDeclaration(declaration))); - action->setIcon(KIcon("code-class")); + action->setIcon(QIcon::fromTheme("code-class")); connect(action, SIGNAL(triggered(bool)), this, SLOT(executeSpecifyTypeAction())); extension.addAction(ContextMenuExtension::ExtensionGroup, action); @@ -79,7 +81,7 @@ void TypeCorrection::executeSpecifyTypeAction() { QAction* action = qobject_cast(sender()); if ( ! action ) { - kWarning() << "slot not invoked by triggering a QAction, should not happen"; // :) + qCWarning(KDEV_PYTHON_CODEGEN) << "slot not invoked by triggering a QAction, should not happen"; // :) return; } @@ -90,7 +92,7 @@ void TypeCorrection::executeSpecifyTypeAction() } if ( ! decl.isValid() ) { - kWarning() << "No declaration found!"; + qCWarning(KDEV_PYTHON_CODEGEN) << "No declaration found!"; return; } @@ -102,7 +104,7 @@ void TypeCorrection::executeSpecifyTypeAction() hintType = CorrectionFileGenerator::LocalVariableHint; } else { - kWarning() << "Correction requested for something that's not a local variable or function."; + qCWarning(KDEV_PYTHON_CODEGEN) << "Correction requested for something that's not a local variable or function."; return; } @@ -133,7 +135,7 @@ void TypeCorrection::accepted() CorrectionAssistant *dialog = qobject_cast(sender()); Q_ASSERT(dialog); if ( ! dialog ) { - kWarning() << "accepted() called without a sender"; + qCWarning(KDEV_PYTHON_CODEGEN) << "accepted() called without a sender"; return; } @@ -147,7 +149,7 @@ void TypeCorrection::accepted() } if ( ! decl.isValid() ) { - kWarning() << "No declaration found!"; + qCWarning(KDEV_PYTHON_CODEGEN) << "No declaration found!"; return; } @@ -162,7 +164,7 @@ void TypeCorrection::accepted() generator.addHint(m_ui->typeText->text(), m_ui->importsText->text().split(',', QString::SkipEmptyParts), decl.data(), hintType); - kDebug() << "Forcing a reparse on " << decl.data()->topContext()->url(); + qCDebug(KDEV_PYTHON_CODEGEN) << "Forcing a reparse on " << decl.data()->topContext()->url(); ICore::self()->languageController()->backgroundParser()->addDocument(IndexedString(decl.data()->topContext()->url()), TopDUContext::ForceUpdate); ICore::self()->languageController()->backgroundParser()->addDocument(IndexedString(correctionFile), @@ -173,11 +175,11 @@ CorrectionFileGenerator::CorrectionFileGenerator(const QString &filePath) : m_file(filePath) { Q_ASSERT(! filePath.isEmpty()); - kDebug() << "Correction file path: " << filePath; + qCDebug(KDEV_PYTHON_CODEGEN) << "Correction file path: " << filePath; QFileInfo info(m_file); if ( ! info.absoluteDir().exists() ) { - kDebug() << "Directory does not exist. Creating..."; + qCDebug(KDEV_PYTHON_CODEGEN) << "Directory does not exist. Creating..."; info.absoluteDir().mkpath(info.absolutePath()); } @@ -192,7 +194,7 @@ void CorrectionFileGenerator::addHint(const QString &typeCode, const QStringList CorrectionFileGenerator::HintType hintType) { if ( ! forDeclaration || ! forDeclaration->context() ) { - kWarning() << "Declaration does not have context!" << (forDeclaration ? forDeclaration->toString() : ""); + qCWarning(KDEV_PYTHON_CODEGEN) << "Declaration does not have context!" << (forDeclaration ? forDeclaration->toString() : ""); return; } @@ -216,8 +218,8 @@ void CorrectionFileGenerator::addHint(const QString &typeCode, const QStringList bool inFunction = context->type() == DUContext::Function || (context->owner() && context->owner()->abstractType()->whichType() == AbstractType::TypeFunction); - kDebug() << "Are we in a class: " << inClass; - kDebug() << "Are we in a function: " << inFunction; + qCDebug(KDEV_PYTHON_CODEGEN) << "Are we in a class: " << inClass; + qCDebug(KDEV_PYTHON_CODEGEN) << "Are we in a function: " << inFunction; QString enclosingClassIdentifier, enclosingFunctionIdentifier; @@ -236,8 +238,8 @@ void CorrectionFileGenerator::addHint(const QString &typeCode, const QStringList } } - kDebug() << "Enclosing class: " << enclosingClassIdentifier; - kDebug() << "Enclosing function: " << enclosingFunctionIdentifier; + qCDebug(KDEV_PYTHON_CODEGEN) << "Enclosing class: " << enclosingClassIdentifier; + qCDebug(KDEV_PYTHON_CODEGEN) << "Enclosing function: " << enclosingFunctionIdentifier; QString declarationIdentifier = forDeclaration->identifier().identifier().str(); @@ -269,9 +271,9 @@ void CorrectionFileGenerator::addHint(const QString &typeCode, const QStringList foundClassDeclaration = true; } - kDebug() << "Found class declaration: " << foundClassDeclaration << enclosingClassIdentifier; - kDebug() << "Found function declaration: " << foundFunctionDeclaration << functionIdentifier; - kDebug() << "Line: " << line; + qCDebug(KDEV_PYTHON_CODEGEN) << "Found class declaration: " << foundClassDeclaration << enclosingClassIdentifier; + qCDebug(KDEV_PYTHON_CODEGEN) << "Found function declaration: " << foundFunctionDeclaration << functionIdentifier; + qCDebug(KDEV_PYTHON_CODEGEN) << "Line: " << line; int indentsForNextStatement = m_fileIndents->indentForLine(line); @@ -322,7 +324,7 @@ void CorrectionFileGenerator::addHint(const QString &typeCode, const QStringList else if ( hintType == LocalVariableHint ) { hintCode = "l_" + declarationIdentifier + " = " + typeCode; } - kDebug() << "Hint code: " << hintCode; + qCDebug(KDEV_PYTHON_CODEGEN) << "Hint code: " << hintCode; hintCode.prepend(QString(indentsForNextStatement, ' ')); newCode.append(hintCode); @@ -351,8 +353,8 @@ void CorrectionFileGenerator::addHint(const QString &typeCode, const QStringList QTemporaryFile temp; if ( checkForValidSyntax() && temp.open() ) { - kDebug() << "File path: " << m_file.fileName(); - kDebug() << "Temporary file path: " << temp.fileName(); + qCDebug(KDEV_PYTHON_CODEGEN) << "File path: " << m_file.fileName(); + qCDebug(KDEV_PYTHON_CODEGEN) << "Temporary file path: " << temp.fileName(); QTextStream stream(&temp); stream << m_code.join("\n"); m_fileIndents.reset(new FileIndentInformation(m_code)); @@ -362,7 +364,7 @@ void CorrectionFileGenerator::addHint(const QString &typeCode, const QStringList success = success ? QFile::rename(temp.fileName(), m_file.fileName()) : false; if ( success && m_file.open(QFile::ReadWrite) ) { - kDebug() << "Successfully saved correction file."; + qCDebug(KDEV_PYTHON_CODEGEN) << "Successfully saved correction file."; m_oldContents = m_code; } @@ -371,7 +373,7 @@ void CorrectionFileGenerator::addHint(const QString &typeCode, const QStringList } } else { - kDebug() << "Something went wrong, reverting changes to correction file"; + qCDebug(KDEV_PYTHON_CODEGEN) << "Something went wrong, reverting changes to correction file"; m_code = m_oldContents; } } diff --git a/codegen/refactoring.cpp b/codegen/refactoring.cpp index 7ab341cf..c2345b5c 100644 --- a/codegen/refactoring.cpp +++ b/codegen/refactoring.cpp @@ -23,6 +23,8 @@ #include "refactoring.h" #include "duchain/helpers.h" +#include +#include "codegendebug.h" namespace Python { @@ -47,7 +49,7 @@ Refactoring::Refactoring(QObject *parent) bool Refactoring::acceptForContextMenu(const KDevelop::Declaration* decl) { if (decl->topContext() == Helper::getDocumentationFileContext()) { - kDebug() << "in doc file, not offering rename action"; + qCDebug(KDEV_PYTHON_CODEGEN) << "in doc file, not offering rename action"; return false; } return true; diff --git a/debugger/CMakeLists.txt b/debugger/CMakeLists.txt index df2b2dc2..169b1a6a 100644 --- a/debugger/CMakeLists.txt +++ b/debugger/CMakeLists.txt @@ -18,20 +18,20 @@ set(kdevpdb_PART_SRCS debugjob.cpp debugsession.cpp pdbdebuggerplugin.cpp + debuggerdebug.cpp ) -kde4_add_plugin(kdevpdb ${kdevpdb_PART_SRCS}) +add_library(kdevpdb MODULE ${kdevpdb_PART_SRCS}) target_link_libraries(kdevpdb - sublime kdev4pythonparser - ${KDEVPLATFORM_INTERFACES_LIBRARIES} - ${KDEVPLATFORM_LANGUAGE_LIBRARIES} - ${KDEVPLATFORM_DEBUGGER_LIBRARIES} - ${KDEVPLATFORM_OUTPUTVIEW_LIBRARIES} - ${KDEVPLATFORM_PROJECT_LIBRARIES} - ${KDE4_KDEUI_LIBS} - ${KDEVPLATFORM_UTIL_LIBRARIES} - ${KDE4_KTEXTEDITOR_LIBS} + KDev::Interfaces + KDev::Language + KDev::Debugger + KDev::OutputView + KDev::Project + KDev::Util + KF5::TextEditor + KF5::KDELibs4Support ${KDE4WORKSPACE_PROCESSUI_LIBS} ) diff --git a/debugger/__kdevpython_debugger_utils.py b/debugger/__kdevpython_debugger_utils.py index 04917a39..1c538fc7 100644 --- a/debugger/__kdevpython_debugger_utils.py +++ b/debugger/__kdevpython_debugger_utils.py @@ -1,5 +1,8 @@ # This file is imported from within the debugger +# Copyright 2014 Sven Brauch +# License: GPL v2+ + from kdevpdb import kdevOutputFormatter __kdevpython_builtin_locals = locals diff --git a/debugger/breakpointcontroller.cpp b/debugger/breakpointcontroller.cpp index 05f3e5b9..580e0508 100644 --- a/debugger/breakpointcontroller.cpp +++ b/debugger/breakpointcontroller.cpp @@ -20,11 +20,14 @@ #include "breakpointcontroller.h" #include +#include +#include "debuggerdebug.h" + namespace Python { BreakpointController::BreakpointController(IDebugSession* parent): IBreakpointController(parent) { - kDebug() << "constructing breakpoint controller"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "constructing breakpoint controller"; connect(debugSession(), SIGNAL(event(IDebugSession::event_t)), this, SLOT(slotEvent(IDebugSession::event_t))); } @@ -35,7 +38,7 @@ DebugSession* BreakpointController::session() void BreakpointController::slotEvent(IDebugSession::event_t evt) { - kDebug() << evt; + qCDebug(KDEV_PYTHON_DEBUGGER) << evt; if ( evt == IDebugSession::connected_to_program ) { foreach ( Breakpoint* bp, breakpointModel()->breakpoints() ) { if ( bp->deleted() ) { @@ -48,7 +51,7 @@ void BreakpointController::slotEvent(IDebugSession::event_t evt) void BreakpointController::sendMaybe(KDevelop::Breakpoint* breakpoint) { - kDebug() << "sending breakpoint: " << breakpoint << "( deleted:" << breakpoint->deleted() << ")"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "sending breakpoint: " << breakpoint << "( deleted:" << breakpoint->deleted() << ")"; if ( breakpoint->deleted() ) { session()->removeBreakpoint(breakpoint); } @@ -59,4 +62,4 @@ void BreakpointController::sendMaybe(KDevelop::Breakpoint* breakpoint) } -#include "breakpointcontroller.moc" \ No newline at end of file +#include "breakpointcontroller.moc" diff --git a/debugger/debuggerdebug.cpp b/debugger/debuggerdebug.cpp new file mode 100644 index 00000000..057f1895 --- /dev/null +++ b/debugger/debuggerdebug.cpp @@ -0,0 +1,23 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "debuggerdebug.h" +Q_LOGGING_CATEGORY(KDEV_PYTHON_DEBUGGER, "kdev.python.debugger") + + diff --git a/debugger/debuggerdebug.h b/debugger/debuggerdebug.h new file mode 100644 index 00000000..fc0318e5 --- /dev/null +++ b/debugger/debuggerdebug.h @@ -0,0 +1,27 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef DEBUGGERDEBUG_H +#define DEBUGGERDEBUG_H + +#include +Q_DECLARE_LOGGING_CATEGORY(KDEV_PYTHON_DEBUGGER) + +#endif + diff --git a/debugger/debugjob.cpp b/debugger/debugjob.cpp index 0d581e24..504971fb 100644 --- a/debugger/debugjob.cpp +++ b/debugger/debugjob.cpp @@ -18,7 +18,6 @@ #include "debugjob.h" -#include #include #include @@ -28,6 +27,9 @@ #include #include +#include +#include "debuggerdebug.h" + namespace Python { @@ -49,13 +51,13 @@ void DebugJob::start() startOutput(); - kDebug() << "connecting standardOutputReceived"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "connecting standardOutputReceived"; connect(m_session, SIGNAL(realDataReceived(QStringList)), this, SLOT(standardOutputReceived(QStringList))); connect(m_session, SIGNAL(stderrReceived(QStringList)), this, SLOT(standardErrorReceived(QStringList))); connect(m_session, SIGNAL(finished()), this, SLOT(sessionFinished())); KDevelop::ICore::self()->debugController()->addSession(m_session); m_session->start(); - kDebug() << "starting program:" << program; + qCDebug(KDEV_PYTHON_DEBUGGER) << "starting program:" << program; } void DebugJob::sessionFinished() @@ -72,7 +74,7 @@ void DebugJob::standardErrorReceived(QStringList lines) void DebugJob::standardOutputReceived(QStringList lines) { - kDebug() << "standard output received:" << lines << outputModel(); + qCDebug(KDEV_PYTHON_DEBUGGER) << "standard output received:" << lines << outputModel(); if ( OutputModel* m = outputModel() ) { m->appendLines(lines); } @@ -85,7 +87,7 @@ OutputModel* DebugJob::outputModel() bool DebugJob::doKill() { - kDebug() << "kill signal received"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "kill signal received"; m_session->stopDebugger(); return true; } diff --git a/debugger/debugsession.cpp b/debugger/debugsession.cpp index 68eb2d70..56bc119b 100644 --- a/debugger/debugsession.cpp +++ b/debugger/debugsession.cpp @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -34,6 +33,9 @@ #include "variable.h" #include "breakpointcontroller.h" +#include +#include "debuggerdebug.h" + using namespace KDevelop; static QByteArray debuggerPrompt = "__KDEVPYTHON_DEBUGGER_PROMPT"; @@ -47,13 +49,13 @@ KDevelop::IFrameStackModel* DebugSession::createFrameStackModel() return new PdbFrameStackModel(this); } -DebugSession::DebugSession(QStringList program, const KUrl &workingDirectory) : +DebugSession::DebugSession(QStringList program, const QUrl &workingDirectory) : IDebugSession() , m_workingDirectory(workingDirectory) , m_nextNotifyMethod(0) , m_inDebuggerData(0) { - kDebug() << "creating debug session"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "creating debug session"; m_variableController = new Python::VariableController(this); m_breakpointController = new Python::BreakpointController(this); m_program = program; @@ -107,7 +109,7 @@ QStringList byteArrayToStringList(const QByteArray& r) { void DebugSession::dataAvailable() { QByteArray data = m_debuggerProcess->readAllStandardOutput(); - kDebug() << data.length() << "bytes of data available"; + qCDebug(KDEV_PYTHON_DEBUGGER) << data.length() << "bytes of data available"; // remove pointless state changes data.replace(debuggerOutputBegin+debuggerOutputEnd, ""); @@ -131,7 +133,7 @@ void DebugSession::dataAvailable() nextChangeAt = atLastChange ? len : qMin(nextChangeAt, len); - kDebug() << data; + qCDebug(KDEV_PYTHON_DEBUGGER) << data; Q_ASSERT(m_inDebuggerData == 0 || m_inDebuggerData == 1); if ( m_inDebuggerData == 1 ) { @@ -181,7 +183,7 @@ void DebugSession::dataAvailable() else { notifyNext(); if ( m_commandQueue.isEmpty() ) { - kDebug() << "Changing state to PausedState"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "Changing state to PausedState"; setState(PausedState); } } @@ -197,7 +199,7 @@ void DebugSession::dataAvailable() void DebugSession::setNotifyNext(QWeakPointer object, const char* method) { - kDebug() << "set notify next:" << object << method; + qCDebug(KDEV_PYTHON_DEBUGGER) << "set notify next:" << object << method; m_nextNotifyObject = object; m_nextNotifyMethod = method; } @@ -205,12 +207,12 @@ void DebugSession::setNotifyNext(QWeakPointer object, const char* metho void DebugSession::notifyNext() { QSharedPointer lock = m_nextNotifyObject.toStrongRef(); - kDebug() << "notify next:" << m_nextNotifyObject << m_nextNotifyObject.data() << this; - if ( m_nextNotifyMethod and m_nextNotifyObject ) { + qCDebug(KDEV_PYTHON_DEBUGGER) << "notify next:" << m_nextNotifyObject << m_nextNotifyObject.data() << this; + if ( m_nextNotifyMethod && m_nextNotifyObject ) { QMetaObject::invokeMethod(m_nextNotifyObject.data(), m_nextNotifyMethod, Qt::DirectConnection, Q_ARG(QByteArray, m_buffer)); } else { - kDebug() << "notify called, but nothing to notify!"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "notify called, but nothing to notify!"; } m_buffer.clear(); m_nextNotifyMethod = 0; @@ -219,9 +221,9 @@ void DebugSession::notifyNext() void DebugSession::processNextCommand() { - kDebug() << "processing next debugger command in queue"; - if ( m_processBusy or m_state == EndedState ) { - kDebug() << "process is busy or ended, aborting"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "processing next debugger command in queue"; + if ( m_processBusy || m_state == EndedState ) { + qCDebug(KDEV_PYTHON_DEBUGGER) << "process is busy or ended, aborting"; return; } m_processBusy = true; @@ -233,7 +235,7 @@ void DebugSession::processNextCommand() m_commandQueue.removeFirst(); setNotifyNext(cmd->notifyObject(), cmd->notifyMethod()); cmd->run(this); - kDebug() << "command executed, deleting it."; + qCDebug(KDEV_PYTHON_DEBUGGER) << "command executed, deleting it."; delete cmd; if ( ! m_commandQueue.isEmpty() ) { processNextCommand(); @@ -242,7 +244,7 @@ void DebugSession::processNextCommand() void DebugSession::setState(DebuggerState state) { - kDebug() << "Setting state to" << state; + qCDebug(KDEV_PYTHON_DEBUGGER) << "Setting state to" << state; if ( state == m_state ) { return; @@ -262,14 +264,14 @@ void DebugSession::setState(DebuggerState state) } } - kDebug() << "debugger state changed to" << m_state; + qCDebug(KDEV_PYTHON_DEBUGGER) << "debugger state changed to" << m_state; raiseEvent(program_state_changed); emit stateChanged(m_state); } void DebugSession::write(const QByteArray& cmd) { - kDebug() << " >>> WRITE:" << cmd; + qCDebug(KDEV_PYTHON_DEBUGGER) << " >>> WRITE:" << cmd; m_debuggerProcess->write(cmd); } @@ -342,7 +344,7 @@ void DebugSession::addCommand(PdbCommand* cmd) if ( m_state == EndedState || m_state == StoppingState ) { return; } - kDebug() << " +++ adding command to queue:" << cmd; + qCDebug(KDEV_PYTHON_DEBUGGER) << " +++ adding command to queue:" << cmd; m_commandQueue.append(cmd); if ( cmd->type() == PdbCommand::UserType ) { // this is queued and will run after the command is executed. @@ -353,7 +355,7 @@ void DebugSession::addCommand(PdbCommand* cmd) void DebugSession::checkCommandQueue() { - kDebug() << "items in queue:" << m_commandQueue.length(); + qCDebug(KDEV_PYTHON_DEBUGGER) << "items in queue:" << m_commandQueue.length(); if ( m_commandQueue.isEmpty() ) { return; } @@ -386,7 +388,7 @@ void DebugSession::runImmediately(const QString& cmd) if ( state() == ActiveState ) { m_nextNotifyMethod = 0; m_nextNotifyObject.clear(); // TODO is this correct? - kDebug() << "interrupting debugger"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "interrupting debugger"; kill(m_debuggerProcess->pid(), SIGINT); write(cmd.toAscii()); write("continue\n"); @@ -400,20 +402,20 @@ void DebugSession::runImmediately(const QString& cmd) void DebugSession::addBreakpoint(Breakpoint* bp) { QString location = bp->url().path() + ":" + QString::number(bp->line() + 1); - kDebug() << "adding breakpoint" << location; + qCDebug(KDEV_PYTHON_DEBUGGER) << "adding breakpoint" << location; runImmediately("break " + location + '\n'); } void DebugSession::removeBreakpoint(Breakpoint* bp) { QString location = bp->url().path() + ":" + QString::number(bp->line() + 1); - kDebug() << "deleting breakpoint" << location; + qCDebug(KDEV_PYTHON_DEBUGGER) << "deleting breakpoint" << location; runImmediately("clear " + location + '\n'); } void DebugSession::createVariable(Python::Variable* variable, QObject* callback, const char* callbackMethod) { - kDebug() << "asked to create variable"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "asked to create variable"; InternalPdbCommand* cmd = new InternalPdbCommand(variable, "dataFetched", ("print(" + variable->expression() + ")\n").toAscii()); variable->m_notifyCreated = callback; @@ -428,13 +430,13 @@ void DebugSession::clearOutputBuffer() void DebugSession::updateLocation() { - kDebug() << "updating location"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "updating location"; InternalPdbCommand* cmd = new InternalPdbCommand(this, "locationUpdateReady", "where\n"); addCommand(cmd); } void DebugSession::locationUpdateReady(QByteArray data) { - kDebug() << "Got where information: " << data; + qCDebug(KDEV_PYTHON_DEBUGGER) << "Got where information: " << data; QList lines = data.split('\n'); if ( lines.length() >= 3 ) { lines.removeLast(); // prompt @@ -444,8 +446,8 @@ void DebugSession::locationUpdateReady(QByteArray data) { QRegExp m("^> (/.*\\.py)\\((\\d*)\\).*$"); m.setMinimal(true); m.exactMatch(where); - setCurrentPosition(KUrl(m.capturedTexts().at(1)), m.capturedTexts().at(2).toInt() - 1 , ""); - kDebug() << "New position: " << m.capturedTexts().at(1) << m.capturedTexts().at(2).toInt() - 1 << m.capturedTexts() << where; + setCurrentPosition(QUrl::fromLocalFile(m.capturedTexts().at(1)), m.capturedTexts().at(2).toInt() - 1 , ""); + qCDebug(KDEV_PYTHON_DEBUGGER) << "New position: " << m.capturedTexts().at(1) << m.capturedTexts().at(2).toInt() - 1 << m.capturedTexts() << where; } } @@ -461,7 +463,7 @@ void DebugSession::stopDebugger() m_commandQueue.clear(); m_nextNotifyMethod = 0; m_nextNotifyObject.clear(); - kDebug() << "killed debugger"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "killed debugger"; setState(IDebugSession::EndedState); } diff --git a/debugger/debugsession.h b/debugger/debugsession.h index f45b87f7..410ef4a3 100644 --- a/debugger/debugsession.h +++ b/debugger/debugsession.h @@ -23,6 +23,9 @@ #include #include +#include +#include "debuggerdebug.h" + #include #include #include @@ -41,7 +44,7 @@ Q_OBJECT virtual KDevelop::IFrameStackModel* createFrameStackModel(); public: - DebugSession(QStringList program, const KUrl& workingDirectory); + DebugSession(QStringList program, const QUrl& workingDirectory); virtual ~DebugSession(); /** * @brief Start the debugger. @@ -212,7 +215,7 @@ public slots: QByteArray m_buffer; QStringList m_program; QList m_commandQueue; - const KUrl& m_workingDirectory; + const QUrl& m_workingDirectory; private: /// objects to notify next QWeakPointer m_nextNotifyObject; @@ -307,7 +310,7 @@ struct SimplePdbCommand : public PdbCommand { }; void run(DebugSession* session) { Q_ASSERT(m_command.endsWith('\n') && "command must end with a newline"); - kDebug() << "running command:" << m_command.toAscii() << m_notifyMethod; + qCDebug(KDEV_PYTHON_DEBUGGER) << "running command:" << m_command.toAscii() << m_notifyMethod; session->write(m_command.toAscii()); } private: diff --git a/debugger/kdevpdb.desktop b/debugger/kdevpdb.desktop index 4e219e9f..51492e85 100644 --- a/debugger/kdevpdb.desktop +++ b/debugger/kdevpdb.desktop @@ -9,6 +9,7 @@ Comment[ca@valencia]=Este connector proveeix d'un frontal pel PDB Comment[da]=Dette plugin er en brugerflade til PDB Comment[de]=Dieses Modul stellt eine Oberfläche für PDB zur Verfügung. Comment[el]=Αυτό το πρόσθετο παρέχει ένα περιβάλλον για το PDB +Comment[en_GB]=This plugin provides a frontend for PDB Comment[es]=Este complemento proporciona una interfaz para PDB Comment[et]=PDB kasutajaliidese plugin Comment[fi]=Tämä liitännäinen tarjoaa PDB-käyttöliittymän @@ -18,6 +19,7 @@ Comment[gl]=Este complemento fornece unha interface para PDB. Comment[hu]=Ez a bővítmény egy felületet biztosít a PDB-hez Comment[it]=Questa estensione fornisce un'interfaccia per PDB Comment[kk]=Бұл плагин PDB-ге интерфейс жасайды +Comment[ko]=이 플러그인은 PDB 프론트엔드를 제공합니다 Comment[mr]=हे प्लगइन पीडीबी करिता फ्रंटएन्ड पुरविते Comment[nb]=Dette programtillegget er et forstykke til PDB Comment[nds]=Dit Moduul stellt en Böversiet för PDB praat. @@ -42,6 +44,7 @@ Name[ca@valencia]=kdevpdb Name[da]=kdevpdb Name[de]=kdevpdb Name[el]=kdevpdb +Name[en_GB]=kdevpdb Name[es]=kdevpdb Name[et]=kdevpdb Name[fi]=kdevpdb @@ -51,6 +54,7 @@ Name[gl]=kdevpdb Name[hu]=kdevpdb Name[it]=kdevpdb Name[kk]=kdevpdb +Name[ko]=kdevpdb Name[mr]=के-डेव्ह-पीडीबी Name[nb]=kdevpdb Name[nl]=kdevpdb @@ -74,6 +78,7 @@ GenericName[ca@valencia]=Frontal del depurador de Python GenericName[da]=Brugerflade til Python-fejlsøgeren GenericName[de]=Oberfläche für Python-Debugger GenericName[el]=Python Debugger Frontend +GenericName[en_GB]=Python Debugger Frontend GenericName[es]=Interfaz de depurador para Python GenericName[et]=Pythoni siluri kasutajaliides GenericName[fi]=Python Debugger -käyttöliittymä @@ -83,6 +88,7 @@ GenericName[gl]=Interface de depuración de Python GenericName[hu]=Python hibakövetési felület GenericName[it]=Interfaccia debugger Python GenericName[kk]=Python жөндегіш интерфейсі +GenericName[ko]=파이썬 디버거 프론트엔드 GenericName[mr]=पायथोन डिबगर फ्रंटएन्ड GenericName[nb]=Grensesnitt for Python-feilsøker GenericName[nl]=Frontend voor Python-debugger @@ -102,7 +108,7 @@ GenericName[zh_TW]=Python 除錯器前端介面 Icon=text-x-python X-KDE-Library=kdevpdb X-KDevelop-Category=Global -X-KDevelop-Version=18 +X-KDevelop-Version=19 X-KDE-PluginInfo-Name=kdevpdb X-KDE-PluginInfo-License=GPL X-KDE-PluginInfo-Category=Debugging diff --git a/debugger/kdevpdb.py b/debugger/kdevpdb.py index cf432e43..3d0ba281 100644 --- a/debugger/kdevpdb.py +++ b/debugger/kdevpdb.py @@ -1,3 +1,6 @@ +# Copyright 2014 Sven Brauch +# License: GPL v2+ + from pdb import * import sys @@ -40,4 +43,4 @@ def _runscript(self, filename): if __name__ == '__main__': import pdb pdb.Pdb = kdevPdb - pdb.main() \ No newline at end of file + pdb.main() diff --git a/debugger/pdbdebuggerplugin.cpp b/debugger/pdbdebuggerplugin.cpp index bd843476..6ad9f2e2 100644 --- a/debugger/pdbdebuggerplugin.cpp +++ b/debugger/pdbdebuggerplugin.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include "pdbdebuggerplugin.h" #include "pdblauncher.h" @@ -37,12 +37,12 @@ namespace Python { K_PLUGIN_FACTORY(PdbDebuggerPluginFactory, registerPlugin(); ) K_EXPORT_PLUGIN(PdbDebuggerPluginFactory( KAboutData("kdevpdbsupport", "kdevpython", ki18n("Python Debugger (pdb) Support"), - KDEVPYTHON_VERSION_STR, ki18n("Support for the Python Debugger"), KAboutData::License_GPL) + KDEVPYTHON_VERSION_STR, ki18n("Support for the Python Debugger"), K4AboutData::License_GPL) .addAuthor(ki18n("Sven Brauch"), ki18n("Author"), "svenbrauch@googlemail.com", "") )) PdbDebuggerPlugin::PdbDebuggerPlugin(QObject* parent, const QVariantList&) - : IPlugin(PdbDebuggerPluginFactory::componentData(), parent) + : IPlugin("kdevpdbsupport", parent) { IExecuteScriptPlugin* iface = KDevelop::ICore::self()->pluginController() ->pluginForExtension("org.kdevelop.IExecuteScriptPlugin")->extension(); diff --git a/debugger/pdbframestackmodel.cpp b/debugger/pdbframestackmodel.cpp index 67609340..93659379 100644 --- a/debugger/pdbframestackmodel.cpp +++ b/debugger/pdbframestackmodel.cpp @@ -19,9 +19,11 @@ #include "pdbframestackmodel.h" #include "debugsession.h" -#include #include +#include +#include "debuggerdebug.h" + using namespace KDevelop; namespace Python { @@ -44,7 +46,7 @@ void PdbFrameStackModel::setDebuggerAtFrame(int newFrame) void PdbFrameStackModel::framesFetched(QByteArray framelist) { - kDebug() << "frames fetched:" << framelist; + qCDebug(KDEV_PYTHON_DEBUGGER) << "frames fetched:" << framelist; QList lines = framelist.split('\n'); QList frames; bool parsingLocation = false; @@ -65,7 +67,7 @@ void PdbFrameStackModel::framesFetched(QByteArray framelist) // version 1 has some *really* weird "greedy" ruleset which makes no sense at all for me location.setPatternSyntax(QRegExp::RegExp2); if ( location.exactMatch(line) ) { - kDebug() << location.capturedTexts(); + qCDebug(KDEV_PYTHON_DEBUGGER) << location.capturedTexts(); if ( ! location.capturedTexts().at(1).isEmpty() ) { m_debuggerAtFrame = framesCount; } @@ -74,12 +76,12 @@ void PdbFrameStackModel::framesFetched(QByteArray framelist) currentFrame->name = location.capturedTexts().at(4); } else { - kDebug() << "regular expression mismatches" << line; + qCDebug(KDEV_PYTHON_DEBUGGER) << "regular expression mismatches" << line; } } } m_debuggerAtFrame = framesCount - m_debuggerAtFrame - 1; - kDebug() << "at frame:" << m_debuggerAtFrame; + qCDebug(KDEV_PYTHON_DEBUGGER) << "at frame:" << m_debuggerAtFrame; QList framesReversed; for ( int i = frames.length() - 1; i >= 0; i-- ) { framesReversed.append(frames.at(i)); @@ -90,8 +92,8 @@ void PdbFrameStackModel::framesFetched(QByteArray framelist) void PdbFrameStackModel::threadsFetched(QByteArray threadsData) { - kDebug() << "threads fetched" << threadsData; - kDebug() << "Implement me: Thread debugging is not supported by pdb."; + qCDebug(KDEV_PYTHON_DEBUGGER) << "threads fetched" << threadsData; + qCDebug(KDEV_PYTHON_DEBUGGER) << "Implement me: Thread debugging is not supported by pdb."; QList threads; ThreadItem mainThread; mainThread.nr = 0; @@ -103,14 +105,14 @@ void PdbFrameStackModel::threadsFetched(QByteArray threadsData) void PdbFrameStackModel::fetchFrames(int /*threadNumber*/, int /*from*/, int /*to*/) { - kDebug() << "frames requested"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "frames requested"; InternalPdbCommand* cmd = new InternalPdbCommand(this, "framesFetched", "where\n"); static_cast(session())->addCommand(cmd); } void PdbFrameStackModel::fetchThreads() { - kDebug() << "threads requested"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "threads requested"; // pdb doesn't support threads. InternalPdbCommand* cmd = new InternalPdbCommand(this, "threadsFetched", "pass\n"); static_cast(session())->addCommand(cmd); @@ -118,4 +120,4 @@ void PdbFrameStackModel::fetchThreads() } -#include "pdbframestackmodel.moc" \ No newline at end of file +#include "pdbframestackmodel.moc" diff --git a/debugger/pdblauncher.cpp b/debugger/pdblauncher.cpp index 03a6a8d3..59dc4117 100644 --- a/debugger/pdblauncher.cpp +++ b/debugger/pdblauncher.cpp @@ -31,9 +31,11 @@ #include #include #include -#include #include +#include +#include "debuggerdebug.h" + namespace Python { @@ -64,7 +66,7 @@ QString PdbLauncher::name() const KJob* PdbLauncher::start(const QString& launchMode, KDevelop::ILaunchConfiguration* cfg) { - kDebug() << "start of debugger process requested"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "start of debugger process requested"; if ( launchMode == "debug" ) { IExecuteScriptPlugin* iface = KDevelop::ICore::self()->pluginController() ->pluginForExtension("org.kdevelop.IExecuteScriptPlugin")->extension(); @@ -78,7 +80,7 @@ KJob* PdbLauncher::start(const QString& launchMode, KDevelop::ILaunchConfigurati p.start(interpreter, QStringList() << "--version"); p.waitForFinished(500); QByteArray version = p.readAll(); - kDebug() << "interpreter version:" << version; + qCDebug(KDEV_PYTHON_DEBUGGER) << "interpreter version:" << version; if ( ! version.startsWith("Python 3.") ) { KMessageBox::error(ICore::self()->uiController()->activeMainWindow(), i18n("Sorry, debugging is only supported for Python 3.x applications."), @@ -96,7 +98,7 @@ KJob* PdbLauncher::start(const QString& launchMode, KDevelop::ILaunchConfigurati l << job; return new KDevelop::ExecuteCompositeJob( KDevelop::ICore::self()->runController(), l ); } - kDebug() << "unknown launch mode"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "unknown launch mode"; return 0; } diff --git a/debugger/variable.cpp b/debugger/variable.cpp index 54073a8e..65598506 100644 --- a/debugger/variable.cpp +++ b/debugger/variable.cpp @@ -21,6 +21,9 @@ #include "debugsession.h" #include +#include +#include "debuggerdebug.h" + namespace Python { Variable::Variable(KDevelop::TreeModel* model, KDevelop::TreeItem* parent, const QString& expression, const QString& display): @@ -39,7 +42,7 @@ void Variable::dataFetched(QByteArray rawData) } setValue(value); setHasMore(true); - kDebug() << "value set to" << value << ", calling update method"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "value set to" << value << ", calling update method"; QMetaObject::invokeMethod(m_notifyCreated, m_notifyCreatedMethod, Qt::QueuedConnection, Q_ARG(bool, true)); } @@ -80,7 +83,7 @@ void Variable::moreChildrenFetched(QByteArray rawData) while ( i < data.length() ) { QByteArray d = data.at(i); // sort magic functions at the end of the list, they're not too interesting usually - if ( d.startsWith('_') and i < initialLength ) { + if ( d.startsWith('_') && i < initialLength ) { data.append(d); i++; continue; @@ -104,7 +107,7 @@ void Variable::moreChildrenFetched(QByteArray rawData) } Variable* v = new Variable(model_, this, childName, prettyName); appendChild(v); - kDebug() << "adding child:" << expression() << i << d; + qCDebug(KDEV_PYTHON_DEBUGGER) << "adding child:" << expression() << i << d; v->setValue(realValue); v->setId(pythonId); v->setHasMoreInitial(true); diff --git a/debugger/variablecontroller.cpp b/debugger/variablecontroller.cpp index 4c3b7725..dfceed92 100644 --- a/debugger/variablecontroller.cpp +++ b/debugger/variablecontroller.cpp @@ -34,6 +34,9 @@ #include #include +#include +#include "debuggerdebug.h" + using namespace KDevelop; namespace Python { @@ -50,7 +53,7 @@ void VariableController::addWatch(KDevelop::Variable* variable) void VariableController::addWatchpoint(KDevelop::Variable* /*variable*/) { - kWarning() << "addWatchpoint requested (not implemented)"; + qCWarning(KDEV_PYTHON_DEBUGGER) << "addWatchpoint requested (not implemented)"; } void VariableController::handleEvent(IDebugSession::event_t event) @@ -61,9 +64,9 @@ void VariableController::handleEvent(IDebugSession::event_t event) int delta = model->currentFrame() - model->debuggerAtFrame(); model->setDebuggerAtFrame(model->currentFrame()); bool positive = delta > 0; - kDebug() << "changing frame by" << delta; + qCDebug(KDEV_PYTHON_DEBUGGER) << "changing frame by" << delta; for ( int i = delta; i != 0; i += ( positive ? -1 : 1 ) ) { - kDebug() << ( positive ? "up" : "down" ) << model->currentFrame() << model->debuggerAtFrame(); + qCDebug(KDEV_PYTHON_DEBUGGER) << ( positive ? "up" : "down" ) << model->currentFrame() << model->debuggerAtFrame(); s->addSimpleInternalCommand(positive ? "up" : "down"); } } @@ -82,15 +85,15 @@ QString VariableController::expressionUnderCursor(KTextEditor::Document* doc, co if ( ! doc->isModified() ) { if ( TopDUContext* context = DUChain::self()->chainForDocument(doc->url()) ) { DUContext* contextAtCursor = context->findContextAt(CursorInRevision(cursor.line(), cursor.column())); - if ( contextAtCursor and contextAtCursor->type() == DUContext::Class ) { - if ( contextAtCursor->owner() and ! contextAtCursor->owner()->identifier().isEmpty() ) { + if ( contextAtCursor && contextAtCursor->type() == DUContext::Class ) { + if ( contextAtCursor->owner() && ! contextAtCursor->owner()->identifier().isEmpty() ) { prefix = contextAtCursor->owner()->identifier().toString() + "."; } } } } else { - kDebug() << "duchain unavailable for document" << doc->url() << "or document out of date"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "duchain unavailable for document" << doc->url() << "or document out of date"; } TextDocumentLazyLineFetcher linefetcher(doc); @@ -101,7 +104,7 @@ void VariableController::localsUpdateReady(QByteArray rawData) { QRegExp formatExtract("([a-zA-Z0-9_]+) \\=\\> (.*)"); QList data = rawData.split('\n'); - kDebug() << "locals update:" << data; + qCDebug(KDEV_PYTHON_DEBUGGER) << "locals update:" << data; int i = 0; QStringList vars; @@ -113,7 +116,7 @@ void VariableController::localsUpdateReady(QByteArray rawData) vars << key; values[key] = formatExtract.capturedTexts().at(2); } - else kWarning() << "mismatch:" << d; + else qCWarning(KDEV_PYTHON_DEBUGGER) << "mismatch:" << d; i++; } QList variableObjects = KDevelop::ICore::self()->debugController()->variableCollection() @@ -127,7 +130,7 @@ void VariableController::localsUpdateReady(QByteArray rawData) void VariableController::update() { - kDebug() << "update requested"; + qCDebug(KDEV_PYTHON_DEBUGGER) << "update requested"; DebugSession* d = static_cast(parent()); if (autoUpdate() & UpdateWatches) { variableCollection()->watches()->reinstall(); diff --git a/docfilekcm/CMakeLists.txt b/docfilekcm/CMakeLists.txt index 7779380d..84e584cb 100644 --- a/docfilekcm/CMakeLists.txt +++ b/docfilekcm/CMakeLists.txt @@ -4,16 +4,19 @@ set(kcm_docfiles_SRCS kcm_docfiles.cpp ) -kde4_add_plugin(kcm_docfiles ${kcm_docfiles_SRCS}) +add_library(kcm_docfiles MODULE ${kcm_docfiles_SRCS}) target_link_libraries(kcm_docfiles - ${KDE4_KIO_LIBS} - ${KDEVPLATFORM_INTERFACES_LIBRARIES} - ${KDEVPLATFORM_LANGUAGE_LIBRARIES} - ${KDEVPLATFORM_PROJECT_LIBRARIES} - ${KDEVPLATFORM_UTIL_LIBRARIES} - ${KDE4_KNEWSTUFF3_LIBS} - ${KDEVPLATFORM_INTERFACES_LIBRARIES} + KF5::KIOCore + KF5::Archive + KF5::KCMUtils + KF5::NewStuff + KF5::KDELibs4Support + KDev::Interfaces + KDev::Language + KDev::Project + KDev::Util + KDev::Interfaces ) install(TARGETS kcm_docfiles @@ -26,4 +29,4 @@ install(FILES kdev_python_docfiles.knsrc DESTINATION ${CONFIG_INSTALL_DIR}) install(FILES ../documentation_src/introspection/introspect.py - DESTINATION ${DATA_INSTALL_DIR}/kdevpythonsupport/scripts) \ No newline at end of file + DESTINATION ${DATA_INSTALL_DIR}/kdevpythonsupport/scripts) diff --git a/docfilekcm/docfilemanagerwidget.cpp b/docfilekcm/docfilemanagerwidget.cpp index 2c50c352..e9818df5 100644 --- a/docfilekcm/docfilemanagerwidget.cpp +++ b/docfilekcm/docfilemanagerwidget.cpp @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include @@ -47,6 +49,7 @@ #include #include #include +#include DocfileManagerWidget::DocfileManagerWidget(QWidget* parent) : QWidget(parent) @@ -68,15 +71,15 @@ DocfileManagerWidget::DocfileManagerWidget(QWidget* parent) // construct the buttons for up/download QVBoxLayout* buttonsLayout = new QVBoxLayout; QPushButton* ghnsButton = new QPushButton(i18n("Download new")); - ghnsButton->setIcon(KIcon("get-hot-new-stuff")); + ghnsButton->setIcon(QIcon::fromTheme("get-hot-new-stuff")); QPushButton* generateButton = new QPushButton(i18n("Generate...")); - generateButton->setIcon(KIcon("tools-wizard")); + generateButton->setIcon(QIcon::fromTheme("tools-wizard")); QPushButton* uploadButton = new QPushButton(i18n("Share selected")); - uploadButton->setIcon(KIcon("applications-internet")); // TODO better icon semantically + uploadButton->setIcon(QIcon::fromTheme("applications-internet")); // TODO better icon semantically QPushButton* importButton = new QPushButton(i18n("Import from editor")); importButton->setToolTip(i18n("Copy the contents of the active editor window " "to a new file in the documentation directory")); - importButton->setIcon(KIcon("edit-copy")); + importButton->setIcon(QIcon::fromTheme("edit-copy")); buttonsLayout->addWidget(ghnsButton); buttonsLayout->addWidget(uploadButton); buttonsLayout->addWidget(generateButton); @@ -92,11 +95,11 @@ DocfileManagerWidget::DocfileManagerWidget(QWidget* parent) QFrame* separator2 = new QFrame(); separator2->setFrameShape(QFrame::HLine); QPushButton* openFileManagerButton = new QPushButton(i18n("Open file manager")); - openFileManagerButton->setIcon(KIcon("system-file-manager")); + openFileManagerButton->setIcon(QIcon::fromTheme("system-file-manager")); QPushButton* openTextEditorButton = new QPushButton(i18nc("Edit selected files", "Edit selected")); - openTextEditorButton->setIcon(KIcon("kate")); + openTextEditorButton->setIcon(QIcon::fromTheme("kate")); QPushButton* searchPathsButton = new QPushButton(i18n("Search paths...")); - searchPathsButton->setIcon(KIcon("folder")); + searchPathsButton->setIcon(QIcon::fromTheme("folder")); buttonsLayout->addWidget(separator); buttonsLayout->addWidget(openFileManagerButton); buttonsLayout->addWidget(openTextEditorButton); @@ -149,7 +152,7 @@ void DocfileManagerWidget::showSearchPaths() void DocfileManagerWidget::openDocfilePath() { - KUrl docfileDirectory(docfilePath()); + auto docfileDirectory = QUrl::fromLocalFile(docfilePath()); KRun::runUrl(docfileDirectory, KMimeType::findByUrl(docfileDirectory)->name(), this); } @@ -158,7 +161,7 @@ void DocfileManagerWidget::copyEditorContents() KDevelop::IDocumentController* documentController = KDevelop::ICore::self()->documentController(); if ( documentController->activeDocument() ) { if ( KTextEditor::Document* doc = documentController->activeDocument()->textDocument() ) { - KDialog* dialog = new KDialog(this); + auto dialog = new KDialog(this); dialog->setButtons(KDialog::Ok | KDialog::Cancel); QWidget* contents = new QWidget; contents->setLayout(new QVBoxLayout); @@ -171,11 +174,11 @@ void DocfileManagerWidget::copyEditorContents() contents->layout()->addWidget(new QLabel(i18n("After copying, you will be editing the new document."))); dialog->setMainWidget(contents); if ( dialog->exec() == KDialog::Accepted ) { - KUrl target = KUrl(docfilePath() + "/" + lineEdit->text()); - target.cleanPath(KUrl::SimplifyDirSeparators); - QDir d(target.directory()); + auto target = QUrl::fromLocalFile(docfilePath() + "/" + lineEdit->text()); + // TODO QUrl: cleanPath? + QDir d(target.url()); if ( ! d.exists() ) { - d.mkpath(target.directory()); + d.mkpath(d.absolutePath()); } doc->saveAs(target); } @@ -190,9 +193,7 @@ void DocfileManagerWidget::openSelectedInTextEditor() KMessageBox::information(this, i18n("Please select at least one file from the list for editing.")); } foreach ( const QUrl& item, selected ) { - KUrl fullUrl(item); - fullUrl.setProtocol("file"); // TODO isn't there a more elegant solution for this? - KDevelop::ICore::self()->documentController()->openDocument(fullUrl); + KDevelop::ICore::self()->documentController()->openDocument(item); } } diff --git a/docfilekcm/docfilewizard.cpp b/docfilekcm/docfilewizard.cpp index ec609fd9..da104c50 100644 --- a/docfilekcm/docfilewizard.cpp +++ b/docfilekcm/docfilewizard.cpp @@ -35,11 +35,11 @@ #include #include -#include #include #include #include #include +#include DocfileWizard::DocfileWizard(const QString& workingDirectory, QWidget* parent) : QDialog(parent) @@ -92,13 +92,13 @@ DocfileWizard::DocfileWizard(const QString& workingDirectory, QWidget* parent) QHBoxLayout* buttonsLayout = new QHBoxLayout; buttonsLayout->setDirection(QBoxLayout::RightToLeft); QPushButton* closeButton = new QPushButton(i18n("Close")); - closeButton->setIcon(KIcon("dialog-close")); + closeButton->setIcon(QIcon::fromTheme("dialog-close")); saveButton = new QPushButton(i18n("Save and close")); saveButton->setEnabled(false); - saveButton->setIcon(KIcon("dialog-ok-apply")); + saveButton->setIcon(QIcon::fromTheme("dialog-ok-apply")); runButton = new QPushButton(i18n("Generate")); runButton->setDefault(true); - runButton->setIcon(KIcon("tools-wizard")); + runButton->setIcon(QIcon::fromTheme("tools-wizard")); buttonsLayout->addWidget(closeButton); buttonsLayout->addWidget(runButton); buttonsLayout->addWidget(saveButton); diff --git a/docfilekcm/kcm_docfiles.cpp b/docfilekcm/kcm_docfiles.cpp index 2a2bbc5c..60da38de 100644 --- a/docfilekcm/kcm_docfiles.cpp +++ b/docfilekcm/kcm_docfiles.cpp @@ -24,15 +24,12 @@ #include #include -#include - #include "docfilemanagerwidget.h" -K_PLUGIN_FACTORY(DocfilesKCModuleFactory, registerPlugin(); ) -K_EXPORT_PLUGIN(DocfilesKCModuleFactory("kcm_docfiles", "kdevpythonsupport")) +K_PLUGIN_FACTORY(DocfilesKCModuleFactory, registerPlugin();) DocfilesKCModule::DocfilesKCModule(QWidget* parent, const QVariantList& args) - : KCModule(DocfilesKCModuleFactory::componentData(), parent, args) + : KCModule(parent, args) { managerWidget = new DocfileManagerWidget(parent); parent->layout()->addWidget(managerWidget); @@ -43,3 +40,4 @@ DocfilesKCModule::~DocfilesKCModule() } +#include "kcm_docfiles.moc" diff --git a/docfilekcm/kcm_docfiles.h b/docfilekcm/kcm_docfiles.h index 47537bd1..317885e8 100644 --- a/docfilekcm/kcm_docfiles.h +++ b/docfilekcm/kcm_docfiles.h @@ -17,15 +17,18 @@ * along with this program; if not, see . * ************************************************************************/ -#ifndef KCM_CUSTOMBUILDSYSTEM_H -#define KCM_CUSTOMBUILDSYSTEM_H +#ifndef KCM_PY_DOCFILES_H +#define KCM_PY_DOCFILES_H #include #include +#include + class DocfileManagerWidget; class DocfilesKCModule : public KCModule { +Q_OBJECT public: DocfilesKCModule( QWidget* parent, const QVariantList& args = QVariantList() ); virtual ~DocfilesKCModule(); diff --git a/docfilekcm/kcm_kdevpythondocfiles.desktop b/docfilekcm/kcm_kdevpythondocfiles.desktop index 984f060d..947f550a 100644 --- a/docfilekcm/kcm_kdevpythondocfiles.desktop +++ b/docfilekcm/kcm_kdevpythondocfiles.desktop @@ -16,6 +16,7 @@ Name[ca@valencia]=Dades de la documentació de Python Name[da]=Python dokumentationsdata Name[de]=Python-Dokumentationsdaten Name[el]=Δεδομένα τεκμηρίωσης Python +Name[en_GB]=Python documentation data Name[es]=Datos de documentación para Python Name[fi]=Python-dokumentaatiodata Name[fr]=Données de documentation pour Python @@ -23,6 +24,7 @@ Name[gl]=Datos da documentación de Python Name[hu]=Python dokumentációs adatok Name[it]=Dati della documentazione di Python Name[kk]=Python құжаттама дерегі +Name[ko]=파이썬 문서 데이터 Name[mr]=पायथोन दस्तऐवजीकरण डेटा Name[nb]=Python dokumentasjonsdata Name[nl]=Gegevens voor Python-documentatie @@ -44,6 +46,7 @@ Comment[ca@valencia]=Gestiona els fitxers de documentació usats pel connector d Comment[da]=Håndtér dokumentationsfiler som bruges af Python-pluginet Comment[de]=Verwaltet Dokumentationsdateien, die vom Pythonmodul verwendet werden Comment[el]=Διαχείριση αρχείων τεκμηρίωσης που χρησιμεύουν στο πρόσθετο Python +Comment[en_GB]=Manage documentation files used by the Python plugin Comment[es]=Gestionar archivos de documentación usados por el complemento de Python Comment[fi]=Hallitse Python-liitännäisen käyttämiä dokumentaatiotiedostoja Comment[fr]=Gère les fichiers de documentation utilisés par le module externe Python @@ -51,6 +54,7 @@ Comment[gl]=Xestiona os ficheiros de documentación usados por complemento de Py Comment[hu]=Dokumentációs fájlok kezelése a Python bővítmény használatával Comment[it]=Gestisce i file della documentazione usati dall'estensione Python Comment[kk]=Python плагині қолданатын құжаттама файлдарды басқару +Comment[ko]=파이썬 플러그인에서 사용하는 문서 파일 관리 Comment[mr]=पायथोन प्लगइन द्वारे वापरल्या जाणारे दस्तऐवजीकरण व्यवस्थापीत करा Comment[nb]=Håndtere dokumentasjonsfiler som Python-programtillegget bruker Comment[nl]=Documentatiebestanden beheren gebruikt door de plug-in van Python diff --git a/documentation_files/COPYING b/documentation_files/COPYING new file mode 100644 index 00000000..dfd08b5d --- /dev/null +++ b/documentation_files/COPYING @@ -0,0 +1,2 @@ +All files in this subdirectory tree are generated automatically and are not +subject to copyright, unless the file header says something different. diff --git a/documentation_src/introspection/introspect.py b/documentation_src/introspection/introspect.py index 2df2adf0..540685a4 100644 --- a/documentation_src/introspection/introspect.py +++ b/documentation_src/introspection/introspect.py @@ -2,7 +2,7 @@ # -*- Coding:utf-8 -*- # Copyright 2013 by Sven Brauch -# License: GNU GPL v3 or later +# License: GNU GPL v2 or later # The script output is not copyrighted, use it for whatever you want. # WARNING: This script does things which can cause bad stuff to happen diff --git a/documentation_src/numpy/generate_numpy_doc.py b/documentation_src/numpy/generate_numpy_doc.py index 786453ed..d861e1fa 100644 --- a/documentation_src/numpy/generate_numpy_doc.py +++ b/documentation_src/numpy/generate_numpy_doc.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Copyright 2014 Sven Brauch +# License: GPL v2+ + import importlib modules = ["numpy", "numpy.ctypeslib", diff --git a/documentation_src/pyqt/generate.sh b/documentation_src/pyqt/generate.sh index 70b1c5b6..b6d0ee9e 100644 --- a/documentation_src/pyqt/generate.sh +++ b/documentation_src/pyqt/generate.sh @@ -1,3 +1,6 @@ +# Copyright 2014 Sven Brauch +# License: GPL v2+ + pyqt=($(ls /usr/share/sip/PyQt4)) element_count=${#pyqt[@]} for index in $(seq $element_count); do diff --git a/duchain/CMakeLists.txt b/duchain/CMakeLists.txt index 1c1720c8..6cfb0c05 100644 --- a/duchain/CMakeLists.txt +++ b/duchain/CMakeLists.txt @@ -19,6 +19,7 @@ set(duchain_SRCS declarationbuilder.cpp usebuilder.cpp dumpchain.cpp + duchaindebug.cpp navigation/navigationwidget.cpp navigation/declarationnavigationcontext.cpp @@ -30,14 +31,19 @@ set(duchain_SRCS ) -kde4_add_library( kdev4pythonduchain SHARED ${duchain_SRCS} ) +add_library( kdev4pythonduchain SHARED ${duchain_SRCS} ) + +generate_export_header( kdev4pythonduchain EXPORT_MACRO_NAME KDEVPYTHONDUCHAIN_EXPORT + EXPORT_FILE_NAME pythonduchainexport.h +) + target_link_libraries( kdev4pythonduchain LINK_PRIVATE - ${KDE4_KDECORE_LIBS} - ${KDEVPLATFORM_LANGUAGE_LIBRARIES} - ${KDEVPLATFORM_PROJECT_LIBRARIES} - ${KDE4_KTEXTEDITOR_LIBS} - ${KDEVPLATFORM_INTERFACES_LIBRARIES} - ${QT_QTWEBKIT_LIBRARY} + Qt5::WebKitWidgets + KF5::KDELibs4Support + KF5::TextEditor + KDev::Interfaces + KDev::Language + KDev::Project kdev4pythonparser ) diff --git a/duchain/assistants/missingincludeassistant.cpp b/duchain/assistants/missingincludeassistant.cpp index 2883043e..5fb3377e 100644 --- a/duchain/assistants/missingincludeassistant.cpp +++ b/duchain/assistants/missingincludeassistant.cpp @@ -1,6 +1,6 @@ /* - * - * Copyright 2013 + * This file is part of kdev-python, the Python language support plugin for KDevelop + * Copyright 2013 Sven Brauch * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -29,7 +29,9 @@ #include -#include +#include +#include "../duchaindebug.h" + #include #include #include @@ -46,9 +48,9 @@ MissingIncludeProblem::MissingIncludeProblem(const QString &moduleName, IndexedS } -KSharedPtr MissingIncludeProblem::solutionAssistant() const +QExplicitlySharedDataPointer MissingIncludeProblem::solutionAssistant() const { - return KSharedPtr(new MissingIncludeAssistant(m_moduleName, m_currentDocument)); + return QExplicitlySharedDataPointer(new MissingIncludeAssistant(m_moduleName, m_currentDocument)); } DocumentationGeneratorAction::DocumentationGeneratorAction(const QString& module, const IndexedString& document) @@ -73,7 +75,7 @@ void DocumentationGeneratorAction::execute() wizard.setModuleName(module); wizard.exec(); if ( ! wizard.wasSavedAs().isNull() ) { - ICore::self()->documentController()->openDocument(KUrl(wizard.wasSavedAs())); + ICore::self()->documentController()->openDocument(QUrl::fromLocalFile(wizard.wasSavedAs())); // force a recursive update of the context, so that all the imports are reparsed too // (since they potentially have changed through this action) ICore::self()->languageController()->backgroundParser()->addDocument(document, TopDUContext::ForceUpdateRecursive); @@ -83,7 +85,7 @@ void DocumentationGeneratorAction::execute() void MissingIncludeAssistant::createActions() { - KSharedPtr action(new DocumentationGeneratorAction(module, document)); + QExplicitlySharedDataPointer action(new DocumentationGeneratorAction(module, document)); addAction(action); } @@ -96,4 +98,4 @@ MissingIncludeAssistant::MissingIncludeAssistant(const QString& module, const In } -#include "missingincludeassistant.moc" \ No newline at end of file +#include "missingincludeassistant.moc" diff --git a/duchain/assistants/missingincludeassistant.h b/duchain/assistants/missingincludeassistant.h index c3bb2e0d..576f2dd5 100644 --- a/duchain/assistants/missingincludeassistant.h +++ b/duchain/assistants/missingincludeassistant.h @@ -24,11 +24,11 @@ #define PYTHON_MISSINGINCLUDEASSISTANT_H #include -#include +#include #include #include -#include +#include namespace Python { @@ -36,7 +36,7 @@ namespace Python { class MissingIncludeProblem : public KDevelop::Problem { public: MissingIncludeProblem(const QString& moduleName, KDevelop::IndexedString currentDocument); - virtual KSharedPtr< KDevelop::IAssistant > solutionAssistant() const; + virtual QExplicitlySharedDataPointer solutionAssistant() const override; private: QString m_moduleName; diff --git a/duchain/contextbuilder.cpp b/duchain/contextbuilder.cpp index 40e344b5..4193b209 100644 --- a/duchain/contextbuilder.cpp +++ b/duchain/contextbuilder.cpp @@ -160,7 +160,7 @@ RangeInRevision ContextBuilder::editorFindRange(Ast* fromNode, Ast* toNode) } CursorInRevision ContextBuilder::editorFindPositionSafe(Ast* node) { - if ( not node ) { + if ( !node ) { return CursorInRevision::invalid(); } return editor()->findPosition(node); @@ -321,17 +321,17 @@ void ContextBuilder::visitCode(CodeAst* node) { AstDefaultVisitor::visitCode(node); } -QPair ContextBuilder::findModulePath(const QString& name, const KUrl& currentDocument) +QPair ContextBuilder::findModulePath(const QString& name, const QUrl& currentDocument) { QStringList nameComponents = name.split("."); - QList searchPaths; + QList searchPaths; if ( name.startsWith('.') ) { /* To take care for imports like "from ....xxxx.yyy import zzz" * we need to take current doc path and run "cd .." enough times */ nameComponents.removeFirst(); QString tname = name.mid(1); // remove first dot - QDir curPathDir = QDir(currentDocument.directory()); + QDir curPathDir = QDir(currentDocument.adjusted(QUrl::RemoveFilename).toLocalFile()); foreach(QString c, tname) { if (c != ".") break; @@ -347,10 +347,10 @@ QPair ContextBuilder::findModulePath(const QString& name, con searchPaths = Helper::getSearchPaths(currentDocument); } // Loop over all the name components, and find matching folders or files. - KUrl tmp; + QDir tmp; QStringList leftNameComponents; - foreach ( KUrl currentPath, searchPaths ) { - tmp = currentPath; + foreach ( QUrl currentPath, searchPaths ) { + tmp.setPath(currentPath.path()); leftNameComponents = nameComponents; foreach ( QString component, nameComponents ) { if ( component == "*" ) { @@ -361,7 +361,7 @@ QPair ContextBuilder::findModulePath(const QString& name, con // only empty the list if not importing *, this is convenient later on leftNameComponents.removeFirst(); } - QString testFilename = tmp.path(KUrl::AddTrailingSlash) + component; + QString testFilename = tmp.path() + "/" + component; tmp.cd(component); QFileInfo sourcedir(testFilename); @@ -375,13 +375,13 @@ QPair ContextBuilder::findModulePath(const QString& name, con // the file matching the next name component will be returned, // toegether with a list of names which must be resolved inside that file. if ( sourcefile.exists() ) { - KUrl sourceUrl = testFilename + extension; - sourceUrl.cleanPath(); + auto sourceUrl = QUrl::fromLocalFile(testFilename + extension); + // TODO QUrl: cleanPath? return qMakePair(sourceUrl, leftNameComponents); } else if ( sourcedir.exists() && sourcedir.isDir() ) { - KUrl path(testFilename + "/__init__.py"); - path.cleanPath(); + auto path = QUrl::fromLocalFile(testFilename + "/__init__.py"); + // TODO QUrl: cleanPath? return qMakePair(path, leftNameComponents); } } @@ -393,28 +393,28 @@ QPair ContextBuilder::findModulePath(const QString& name, con RangeInRevision ContextBuilder::rangeForArgumentsContext(FunctionDefinitionAst* node) { - SimpleCursor start = node->name->range().end; - SimpleCursor end = start; + auto start = node->name->range().end(); + auto end = start; if ( node->arguments->kwarg ) { - end = node->arguments->kwarg->range().end; + end = node->arguments->kwarg->range().end(); } else if ( node->arguments->vararg ) { - end = node->arguments->vararg->range().end; + end = node->arguments->vararg->range().end(); } if ( ! node->arguments->arguments.isEmpty() && node->arguments->vararg ) { if ( node->arguments->vararg->appearsBefore(node->arguments->arguments.last()) ) { - end = node->arguments->arguments.last()->range().end; + end = node->arguments->arguments.last()->range().end(); } } else if ( ! node->arguments->arguments.isEmpty() ) { - end = node->arguments->arguments.last()->range().end; + end = node->arguments->arguments.last()->range().end(); } if ( ! node->arguments->defaultValues.isEmpty() ) { - end = qMax(node->arguments->defaultValues.last()->range().end, end); + end = qMax(node->arguments->defaultValues.last()->range().end(), end); } - RangeInRevision range(start.line, start.column, end.line, end.column); + RangeInRevision range(start.line(), start.column(), end.line(), end.column()); // make the range contain the closing and opening parentheses range.start.column -= 1; range.end.column += 1; diff --git a/duchain/contextbuilder.h b/duchain/contextbuilder.h index db8ed69c..5c42bee2 100644 --- a/duchain/contextbuilder.h +++ b/duchain/contextbuilder.h @@ -75,10 +75,10 @@ class KDEVPYTHONDUCHAIN_EXPORT ContextBuilder: public ContextBuilderBase, public * * @param name a dotted name, such as PyQt4.QtCore.QWidget * @param currentDocument the current document, for resolving relative imports - * @return QPair< KUrl, QStringList > the URL if found, and a list of components from + * @return QPair< QUrl, QStringList > the URL if found, and a list of components from * the end of the name which were not yet consumed */ - static QPair findModulePath(const QString& name, const KUrl& currentDocument); + static QPair findModulePath(const QString& name, const QUrl& currentDocument); /** * @brief Get the range which encompasses the given @p node. diff --git a/duchain/correctionhelper.cpp b/duchain/correctionhelper.cpp index 3b28158d..04eb329b 100644 --- a/duchain/correctionhelper.cpp +++ b/duchain/correctionhelper.cpp @@ -28,6 +28,9 @@ #include #include +#include +#include "duchaindebug.h" + #include #include @@ -43,12 +46,12 @@ CorrectionHelper::CorrectionHelper(const IndexedString& _url, DeclarationBuilder if ( !absolutePath.isValid() || absolutePath.isEmpty() || ! QFile::exists(absolutePath.path()) ) { return; } - kDebug() << "Found correction file for " << _url.str() << ": " << absolutePath.path(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "Found correction file for " << _url.str() << ": " << absolutePath.path(); const IndexedString indexedPath(absolutePath); DUChainReadLocker lock; m_hintTopContext = DUChain::self()->chainForDocument(indexedPath); - kDebug() << "got top context for" << absolutePath << m_hintTopContext; + qCDebug(KDEV_PYTHON_DUCHAIN) << "got top context for" << absolutePath << m_hintTopContext; m_contextStack.top() = m_hintTopContext.data(); if ( ! m_hintTopContext ) { // The file exists, but was not parsed yet. Schedule it, and re-schedule the current one too. @@ -80,7 +83,7 @@ void CorrectionHelper::enter(const KDevelop::Identifier& identifier) return; } - kDebug() << "Looking in " << identifier.toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "Looking in " << identifier.toString(); // there's a hint declaration for this object, put it on the stack DUContext* internal = decls.first()->internalContext(); m_contextStack.push(internal); @@ -109,7 +112,7 @@ AbstractType::Ptr CorrectionHelper::hintFor(const KDevelop::Identifier &identifi return hint; } - kDebug() << "Found specified correct type for " << identifier.toString() << decls.first()->abstractType()->toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "Found specified correct type for " << identifier.toString() << decls.first()->abstractType()->toString(); return decls.first()->abstractType(); } diff --git a/duchain/declarationbuilder.cpp b/duchain/declarationbuilder.cpp index 06cb9d4b..19b8de68 100644 --- a/duchain/declarationbuilder.cpp +++ b/duchain/declarationbuilder.cpp @@ -48,6 +48,10 @@ #include #include + +#include +#include "duchaindebug.h" + #include #include @@ -63,7 +67,7 @@ DeclarationBuilder::DeclarationBuilder(Python::PythonEditorIntegrator* editor, i , m_ownPriority(ownPriority) { setEditor(editor); - kDebug() << "Building Declarations"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Building Declarations"; } DeclarationBuilder:: ~DeclarationBuilder() @@ -89,18 +93,18 @@ ReferencedTopDUContext DeclarationBuilder::build(const IndexedString& url, Ast* // The declaration builder needs to run twice, so it can resolve uses of e.g. functions // which are called before they are defined (which is easily possible, due to python's dynamic nature). if ( ! m_prebuilding ) { - kDebug() << "building, but running pre-builder first"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "building, but running pre-builder first"; DeclarationBuilder* prebuilder = new DeclarationBuilder(editor()); prebuilder->m_ownPriority = m_ownPriority; prebuilder->m_currentlyParsedDocument = currentlyParsedDocument(); prebuilder->setPrebuilding(true); prebuilder->m_futureModificationRevision = m_futureModificationRevision; updateContext = prebuilder->build(url, node, updateContext); - kDebug() << "pre-builder finished"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "pre-builder finished"; delete prebuilder; } else { - kDebug() << "prebuilding"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "prebuilding"; } return DeclarationBuilderBase::build(url, node, updateContext); } @@ -158,7 +162,7 @@ template T* DeclarationBuilder::visitVariableDeclaration(Ast* node, return visitVariableDeclaration(static_cast(node), 0, previous, type); } else { - kWarning() << "cannot create variable declaration for non-(name|identifier) AST, this is a programming error"; + qCWarning(KDEV_PYTHON_DUCHAIN) << "cannot create variable declaration for non-(name|identifier) AST, this is a programming error"; return static_cast(0); } } @@ -213,7 +217,7 @@ template QList DeclarationBuilder::reopenFittingDeclar Declaration* fitting = dynamic_cast(d); if ( ! fitting ) { // Only use a declaration if the type matches - kDebug() << "skipping" << d->toString() << "which could not be cast to the requested type"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "skipping" << d->toString() << "which could not be cast to the requested type"; continue; } // Do not use declarations which have been encountered previously; @@ -236,7 +240,7 @@ template QList DeclarationBuilder::reopenFittingDeclar break; } else { - kDebug() << "Not opening previously existing declaration because it's in another top context"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Not opening previously existing declaration because it's in another top context"; } } else if ( ! invalidType ) { @@ -282,10 +286,10 @@ template T* DeclarationBuilder::visitVariableDeclaration(Identifier* // tells whether there's fitting declarations to update (update is not the same as re-open! one is for // code which uses the same variable twice, the other is for multiple passes of the parser) bool haveFittingDeclaration = false; - if ( ! existingDeclarations.isEmpty() and existingDeclarations.last() ) { + if ( ! existingDeclarations.isEmpty() && existingDeclarations.last() ) { Declaration* d = Helper::resolveAliasDeclaration(existingDeclarations.last()); DUChainReadLocker lock; - if ( d and d->topContext() != topContext() ) { + if ( d && d->topContext() != topContext() ) { inSameTopContext = false; } if ( dynamic_cast(existingDeclarations.last()) ) { @@ -320,7 +324,7 @@ template T* DeclarationBuilder::visitVariableDeclaration(Identifier* if ( currentContext()->type() == DUContext::Function ) { // check for argument type hints (those are created when calling functions) AbstractType::Ptr hints = Helper::extractTypeHints(dec->abstractType(), topContext()); - kDebug() << hints->toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << hints->toString(); if ( hints.cast() || hints.cast() ) { // This only happens when the type hint is a tuple, which means the vararg/kwarg of a function is being processed. newType = hints; @@ -354,7 +358,7 @@ template T* DeclarationBuilder::visitVariableDeclaration(Identifier* } T* result = dynamic_cast(dec); - if ( ! result ) kWarning() << "variable declaration does not have the expected type"; + if ( ! result ) qCWarning(KDEV_PYTHON_DUCHAIN) << "variable declaration does not have the expected type"; return result; } @@ -477,8 +481,8 @@ Declaration* DeclarationBuilder::findDeclarationInContext(QStringList dottedName CursorInRevision::invalid(), 0, DUContext::NoFiltering); // break if the list of identifiers is not yet totally worked through and no // declaration with an internal context was found - if ( declarations.isEmpty() or ( not declarations.last()->internalContext() and identifierCount != i ) ) { - kDebug() << "Declaration not found: " << dottedNameIdentifier << "in top context" << ctx->url().toUrl().path(); + if ( declarations.isEmpty() || ( !declarations.last()->internalContext() && identifierCount != i ) ) { + qCDebug(KDEV_PYTHON_DUCHAIN) << "Declaration not found: " << dottedNameIdentifier << "in top context" << ctx->url().toUrl().path(); return 0; } else { @@ -620,7 +624,7 @@ Declaration* DeclarationBuilder::createDeclarationTree(const QStringList& nameCo Q_ASSERT( ( innerCtx.data() || aliasDeclaration ) && "exactly one of innerCtx or aliasDeclaration must be provided"); Q_ASSERT( ( !innerCtx.data() || !aliasDeclaration ) && "exactly one of innerCtx or aliasDeclaration must be provided"); - kDebug() << "creating declaration tree for" << nameComponents; + qCDebug(KDEV_PYTHON_DUCHAIN) << "creating declaration tree for" << nameComponents; Declaration* lastDeclaration = 0; int depth = 0; @@ -632,7 +636,7 @@ Declaration* DeclarationBuilder::createDeclarationTree(const QStringList& nameCo currentName.append(nameComponents.at(j)); } lastDeclaration = findDeclarationInContext(currentName, topContext()); - if ( lastDeclaration and lastDeclaration->range() < range ) { + if ( lastDeclaration && lastDeclaration->range() < range ) { depth = i; break; } @@ -641,15 +645,15 @@ Declaration* DeclarationBuilder::createDeclarationTree(const QStringList& nameCo DUContext* extendingPreviousImportCtx = 0; QStringList remainingNameComponents; bool injectingContext = false; - if ( lastDeclaration and lastDeclaration->internalContext() ) { - kDebug() << "Found existing import statement while creating declaration for " << declarationIdentifier->value; + if ( lastDeclaration && lastDeclaration->internalContext() ) { + qCDebug(KDEV_PYTHON_DUCHAIN) << "Found existing import statement while creating declaration for " << declarationIdentifier->value; for ( int i = depth; i < nameComponents.length(); i++ ) { remainingNameComponents.append(nameComponents.at(i)); } extendingPreviousImportCtx = lastDeclaration->internalContext(); injectContext(extendingPreviousImportCtx); injectingContext = true; - kDebug() << "remaining identifiers:" << remainingNameComponents; + qCDebug(KDEV_PYTHON_DUCHAIN) << "remaining identifiers:" << remainingNameComponents; } else { remainingNameComponents = nameComponents; @@ -712,14 +716,14 @@ Declaration* DeclarationBuilder::createDeclarationTree(const QStringList& nameCo } d->setAutoDeclaration(true); currentContext()->createUse(d->ownIndex(), displayRange); - kDebug() << "really encountered:" << d << "; scheduled:" << m_scheduledForDeletion; - kDebug() << d->toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "really encountered:" << d << "; scheduled:" << m_scheduledForDeletion; + qCDebug(KDEV_PYTHON_DUCHAIN) << d->toString(); scheduleForDeletion(d, false); - kDebug() << "scheduled:" << m_scheduledForDeletion; + qCDebug(KDEV_PYTHON_DUCHAIN) << "scheduled:" << m_scheduledForDeletion; } if ( done ) break; - kDebug() << "creating context for " << component; + qCDebug(KDEV_PYTHON_DUCHAIN) << "creating context for " << component; // otherwise, create a new "level" entry (a pseudo type + context + declaration which contains all imported items) StructureType::Ptr moduleType = StructureType::Ptr(new StructureType()); openType(moduleType); @@ -739,17 +743,17 @@ Declaration* DeclarationBuilder::createDeclarationTree(const QStringList& nameCo openedTypes.append(moduleType); if ( i == remainingNameComponents.length() - 1 ) { if ( innerCtx ) { - kDebug() << "adding imported context to inner declaration"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "adding imported context to inner declaration"; currentContext()->addImportedParentContext(innerCtx); } else if ( aliasDeclaration ) { - kDebug() << "setting alias declaration on inner declaration"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "setting alias declaration on inner declaration"; } } } for ( int i = openedContexts.length() - 1; i >= 0; i-- ) { // Close all the declarations and contexts opened previosly, and assign the types. - kDebug() << "closing context"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "closing context"; closeType(); closeContext(); Declaration* d = openedDeclarations.at(i); @@ -787,8 +791,8 @@ Declaration* DeclarationBuilder::createModuleImportDeclaration(QString moduleNam } Q_ASSERT(range.isValid()); - kDebug() << "Found module path [path/path in file]: " << moduleInfo; - kDebug() << "Declaration identifier:" << declarationIdentifier->value; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Found module path [path/path in file]: " << moduleInfo; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Declaration identifier:" << declarationIdentifier->value; DUChainWriteLocker lock; const IndexedString modulePath = IndexedString(moduleInfo.first); ReferencedTopDUContext moduleContext = DUChain::self()->chainForDocument(modulePath); @@ -798,18 +802,18 @@ Declaration* DeclarationBuilder::createModuleImportDeclaration(QString moduleNam // The file was not found -- this is either an error in the user's code, // a missing module, or a C module (.so) which is unreadable for kdevelop // TODO imrpove error handling in case the module exists as a shared object or .pyc file only - kDebug() << "invalid or non-existent URL:" << moduleInfo; + qCDebug(KDEV_PYTHON_DUCHAIN) << "invalid or non-existent URL:" << moduleInfo; KDevelop::Problem *p = new Python::MissingIncludeProblem(moduleName, currentlyParsedDocument()); p->setFinalLocation(DocumentRange(currentlyParsedDocument(), range.castToSimpleRange())); p->setSource(KDevelop::ProblemData::SemanticAnalysis); p->setSeverity(KDevelop::ProblemData::Warning); p->setDescription(i18n("Module \"%1\" not found", moduleName)); - problemEncountered.attach(p); + problemEncountered = p; return 0; } if ( ! moduleContext ) { // schedule the include file for parsing, and schedule the current one for reparsing after that is done - kDebug() << "No module context, recompiling"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "No module context, recompiling"; m_unresolvedImports.append(modulePath); Helper::scheduleDependency(modulePath, m_ownPriority); // parseDocuments() must *not* be called from a background thread! @@ -825,11 +829,11 @@ Declaration* DeclarationBuilder::createModuleImportDeclaration(QString moduleNam // import a specific declaration from the given file lock.lock(); if ( declarationIdentifier->value == "*" ) { - kDebug() << "Importing * from module"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Importing * from module"; currentContext()->addImportedParentContext(moduleContext); } else { - kDebug() << "Got module, importing declaration: " << moduleInfo.second; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Got module, importing declaration: " << moduleInfo.second; Declaration* originalDeclaration = findDeclarationInContext(moduleInfo.second, moduleContext); if ( originalDeclaration ) { DUChainWriteLocker lock(DUChain::lock()); @@ -843,7 +847,7 @@ Declaration* DeclarationBuilder::createModuleImportDeclaration(QString moduleNam p->setSource(KDevelop::ProblemData::SemanticAnalysis); p->setSeverity(KDevelop::ProblemData::Warning); p->setDescription(i18n("Declaration for \"%1\" not found in specified module", moduleInfo.second.join("."))); - problemEncountered.attach(p); + problemEncountered = p; } } } @@ -933,7 +937,7 @@ void DeclarationBuilder::applyDocstringHints(CallAst* node, FunctionDeclaration: return; } DUChainWriteLocker wlock; - kDebug() << "Adding content type: " << argVisitor.lastType()->toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "Adding content type: " << argVisitor.lastType()->toString(); container->addContentType(argVisitor.lastType()); v.lastDeclaration()->setType(container); }; @@ -1022,7 +1026,7 @@ void DeclarationBuilder::addArgumentTypeHints(CallAst* node, DeclarationPointer atVararg = true; } - kDebug() << currentParamIndex << currentArgumentIndex << atVararg << lastFunctionDeclaration->vararg(); + qCDebug(KDEV_PYTHON_DUCHAIN) << currentParamIndex << currentArgumentIndex << atVararg << lastFunctionDeclaration->vararg(); ExpressionAst* arg = node->arguments.at(currentArgumentIndex); @@ -1045,8 +1049,7 @@ void DeclarationBuilder::addArgumentTypeHints(CallAst* node, DeclarationPointer indexInVararg++; Declaration* parameter = parameters.at(lastFunctionDeclaration->vararg()+hasSelfArgument); IndexedContainer::Ptr varargContainer = parameter->type(); - kDebug() << "vararg container:" << varargContainer; - kDebug() << "adding" << addType->toString() << "at position" << indexInVararg; + qCDebug(KDEV_PYTHON_DUCHAIN) << "adding" << addType->toString() << "at position" << indexInVararg; if ( ! varargContainer ) continue; if ( varargContainer->typesCount() > indexInVararg ) { AbstractType::Ptr oldType = varargContainer->typeAt(indexInVararg).abstractType(); @@ -1059,7 +1062,6 @@ void DeclarationBuilder::addArgumentTypeHints(CallAst* node, DeclarationPointer parameter->setAbstractType(varargContainer.cast()); } else { - kDebug() << "adding" << argumentType << "at position" << currentArgumentIndex << "/" << currentParamIndex; if ( ! argumentType ) continue; AbstractType::Ptr newType = Helper::mergeTypes(parameters.at(currentParamIndex)->abstractType(), addType.cast()); @@ -1316,7 +1318,7 @@ void DeclarationBuilder::assignToAttribute(AttributeAst* attrib, const Declarati DeclarationPointer parentObjectDeclaration = checkPreviousAttributes.lastDeclaration(); if ( ! parentObjectDeclaration ) { - kDebug() << "No declaration for attribute base, aborting creation of attribute"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "No declaration for attribute base, aborting creation of attribute"; return; } // if foo is a class, this is like foo.bar = 3 @@ -1333,7 +1335,7 @@ void DeclarationBuilder::assignToAttribute(AttributeAst* attrib, const Declarati internal = parentObjectDeclaration->internalContext(); } if ( ! internal ) { - kDebug() << "No internal context for structure type, aborting creation of attribute declaration"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "No internal context for structure type, aborting creation of attribute declaration"; return; } @@ -1358,7 +1360,7 @@ void DeclarationBuilder::assignToAttribute(AttributeAst* attrib, const Declarati DUChainWriteLocker lock; previousContext->createUse(dec->ownIndex(), editorFindRange(attrib, attrib)); } - else kWarning() << "No declaration created for " << attrib->attribute << "as parent is not a class"; + else qCWarning(KDEV_PYTHON_DUCHAIN) << "No declaration created for " << attrib->attribute << "as parent is not a class"; closeInjectedContext(); } @@ -1446,7 +1448,7 @@ void DeclarationBuilder::visitClassDefinition( ClassDefinitionAst* node ) lock.lock(); // every python class inherits from "object". // We use this to add all the __str__, __get__, ... methods. - if ( dec->baseClassesSize() == 0 and node->name->value != "object" ) { + if ( dec->baseClassesSize() == 0 && node->name->value != "object" ) { DUChainWriteLocker wlock; ReferencedTopDUContext docContext = Helper::getDocumentationFileContext(); if ( docContext ) { @@ -1476,8 +1478,8 @@ void DeclarationBuilder::visitClassDefinition( ClassDefinitionAst* node ) dec->setInternalContext(currentContext()); lock.unlock(); - foreach ( Ast* node, node->body ) { - AstDefaultVisitor::visitNode(node); + foreach ( Ast* _node, node->body ) { + AstDefaultVisitor::visitNode(_node); } lock.lock(); @@ -1624,7 +1626,7 @@ void DeclarationBuilder::visitFunctionDefinition( FunctionDefinitionAst* node ) DUChainWriteLocker lock; KDevelop::Problem *p = new KDevelop::Problem(); // only mark first line - p->setFinalLocation(DocumentRange(currentlyParsedDocument(), SimpleRange(node->startLine, node->startCol, node->startLine, 10000))); + p->setFinalLocation(DocumentRange(currentlyParsedDocument(), KTextEditor::Range(node->startLine, node->startCol, node->startLine, 10000))); p->setSource(KDevelop::ProblemData::SemanticAnalysis); p->setSeverity(KDevelop::ProblemData::Warning); p->setDescription(i18n("Non-static class method without arguments, must have at least one (self)")); @@ -1650,11 +1652,11 @@ void DeclarationBuilder::visitFunctionDefinition( FunctionDefinitionAst* node ) lock.lock(); if ( v.lastType() && v.isAlias() ) { type->setReturnType(Helper::mergeTypes(type->returnType(), v.lastType())); - kDebug() << "updated function return type to " << type->toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "updated function return type to " << type->toString(); dec->setType(type); } else if ( ! v.isAlias()) { - kDebug() << "not updating function return type because expression is not a type object"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "not updating function return type because expression is not a type object"; } } @@ -1814,7 +1816,7 @@ void DeclarationBuilder::visitArguments( ArgumentsAst* node ) int parametersCount = node->arguments.length(); int firstDefaultParameterOffset = parametersCount - defaultParametersCount; int currentIndex = 0; - kDebug() << "arguments:" << node->arguments.size(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "arguments:" << node->arguments.size(); foreach ( ArgAst* arg, node->arguments ) { // Iterate over all the function's arguments, create declarations, and add the arguments // to the functions FunctionType. @@ -1824,12 +1826,12 @@ void DeclarationBuilder::visitArguments( ArgumentsAst* node ) continue; } - kDebug() << "visiting argument:" << arg->argumentName->value; + qCDebug(KDEV_PYTHON_DUCHAIN) << "visiting argument:" << arg->argumentName->value; // Create a variable declaration for the parameter, to be used in the function body. Declaration* paramDeclaration = visitVariableDeclaration(arg->argumentName); if ( ! paramDeclaration ) { - kDebug() << "could not create parameter declaration!"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "could not create parameter declaration!"; continue; } @@ -1854,7 +1856,7 @@ void DeclarationBuilder::visitArguments( ArgumentsAst* node ) workingOnDeclaration->addDefaultParameter(IndexedString("...")); } - kDebug() << "is first:" << isFirst << hasCurrentDeclaration() << currentDeclaration(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "is first:" << isFirst << hasCurrentDeclaration() << currentDeclaration(); if ( isFirst && hasCurrentDeclaration() && currentContext() && currentContext()->parentContext() ) { DUChainReadLocker lock; if ( currentContext()->parentContext()->type() == DUContext::Class ) { @@ -1867,7 +1869,7 @@ void DeclarationBuilder::visitArguments( ArgumentsAst* node ) paramDeclaration->setAbstractType(Helper::mergeTypes(paramDeclaration->abstractType(), argumentType)); type->addArgument(argumentType); if ( argumentType ) { - kDebug() << "creating argument with type" << argumentType->toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "creating argument with type" << argumentType->toString(); } } // Handle *args, **kwargs, and assign them a list / dictionary type. diff --git a/duchain/declarations/classdeclaration.h b/duchain/declarations/classdeclaration.h index 52684f6c..d93367cb 100644 --- a/duchain/declarations/classdeclaration.h +++ b/duchain/declarations/classdeclaration.h @@ -21,7 +21,7 @@ #define PYTHONCLASSDECLARATION_H #include -#include +#include #include "pythonduchainexport.h" #include "decorator.h" diff --git a/duchain/declarations/decorator.h b/duchain/declarations/decorator.h index 1f4f11a0..32ca761c 100644 --- a/duchain/declarations/decorator.h +++ b/duchain/declarations/decorator.h @@ -22,7 +22,7 @@ #define DECORATOR_H #include -#include +#include using namespace KDevelop; diff --git a/duchain/declarations/functiondeclaration.h b/duchain/declarations/functiondeclaration.h index 39082e2d..ba0ce2fb 100644 --- a/duchain/declarations/functiondeclaration.h +++ b/duchain/declarations/functiondeclaration.h @@ -21,7 +21,7 @@ #define PYTHONFUNCTIONDECLARATION_H #include -#include +#include #include "pythonduchainexport.h" #include "decorator.h" diff --git a/duchain/duchaindebug.cpp b/duchain/duchaindebug.cpp new file mode 100644 index 00000000..f31df9ae --- /dev/null +++ b/duchain/duchaindebug.cpp @@ -0,0 +1,23 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "duchaindebug.h" +Q_LOGGING_CATEGORY(KDEV_PYTHON_DUCHAIN, "kdev.python.duchain") + + diff --git a/duchain/duchaindebug.h b/duchain/duchaindebug.h new file mode 100644 index 00000000..d407a614 --- /dev/null +++ b/duchain/duchaindebug.h @@ -0,0 +1,27 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef DUCHAINDEBUG_H +#define DUCHAINDEBUG_H + +#include +Q_DECLARE_LOGGING_CATEGORY(KDEV_PYTHON_DUCHAIN) + +#endif + diff --git a/duchain/dumpchain.cpp b/duchain/dumpchain.cpp index 230b84d0..a378bde5 100644 --- a/duchain/dumpchain.cpp +++ b/duchain/dumpchain.cpp @@ -30,6 +30,9 @@ #include #include +#include +#include "duchaindebug.h" + using namespace KDevelop; namespace Python { @@ -44,18 +47,18 @@ void DumpChain::dump( DUContext * context, bool imported ) { if( !context ) return; - kDebug() << QString( indent*2, ' ' ) << (imported ? "==import==> Context " : "New Context ") << context->scopeIdentifier(true) << context->transformFromLocalRevision(context->range()).textRange() << " " << context << " " << (dynamic_cast(context) ? "top-context" : ""); + qCDebug(KDEV_PYTHON_DUCHAIN) << QString( indent*2, ' ' ) << (imported ? "==import==> Context " : "New Context ") << context->scopeIdentifier(true) << context->transformFromLocalRevision(context->range()) << " " << context << " " << (dynamic_cast(context) ? "top-context" : ""); if (!imported) { foreach (Declaration* dec, context->localDeclarations()) { - kDebug() << QString( (indent+1)*2, ' ' ) << "Declaration: " << dec->toString() << " [" << dec->qualifiedIdentifier() << "] "<< dec << "(internal ctx" << dec->internalContext() << ")" << context->transformFromLocalRevision(dec->range()).textRange() << ", "<< ( dec->isDefinition() ? "definition, " : "declaration, " ) << dec->uses().count() << "use(s)"; + qCDebug(KDEV_PYTHON_DUCHAIN) << QString( (indent+1)*2, ' ' ) << "Declaration: " << dec->toString() << " [" << dec->qualifiedIdentifier() << "] "<< dec << "(internal ctx" << dec->internalContext() << ")" << context->transformFromLocalRevision(dec->range()) << ", "<< ( dec->isDefinition() ? "definition, " : "declaration, " ) << dec->uses().count() << "use(s)"; for( QMap >::const_iterator it = dec->uses().constBegin(); it != dec->uses().constEnd(); ++it ) { - kDebug() << QString((indent+1)*2, ' ') << "File:" << it.key().str(); + qCDebug(KDEV_PYTHON_DUCHAIN) << QString((indent+1)*2, ' ') << "File:" << it.key().str(); foreach(const RangeInRevision& r, it.value()) { - kDebug() << QString((indent+2)*2, ' ') << "Use:" << context->transformFromLocalRevision(r).textRange(); + qCDebug(KDEV_PYTHON_DUCHAIN) << QString((indent+2)*2, ' ') << "Use:" << context->transformFromLocalRevision(r); } } } diff --git a/duchain/expressionvisitor.cpp b/duchain/expressionvisitor.cpp index 86b8d122..cd825f7b 100644 --- a/duchain/expressionvisitor.cpp +++ b/duchain/expressionvisitor.cpp @@ -37,6 +37,9 @@ #include #include +#include +#include "duchaindebug.h" + #include #include @@ -184,7 +187,7 @@ void ExpressionVisitor::visitCall(CallAst* node) } else { if ( actualDeclaration ) { - kDebug() << "Declaraton is not a class or function declaration"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Declaraton is not a class or function declaration"; } return encounterUnknown(); } @@ -194,7 +197,7 @@ void ExpressionVisitor::checkForDecorators(CallAst* node, FunctionDeclaration* f { AbstractType::Ptr type; Declaration* useDeclaration = nullptr; - if ( isConstructor and classDecl ) { + if ( isConstructor && classDecl ) { type = classDecl->abstractType(); useDeclaration = classDecl; } @@ -223,7 +226,7 @@ void ExpressionVisitor::checkForDecorators(CallAst* node, FunctionDeclaration* f }; QHash< QString, std::function > knownDecoratorHints; - kDebug() << "Got function declaration with decorators, checking for list content type..."; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Got function declaration with decorators, checking for list content type..."; knownDecoratorHints["getsType"] = [&](QStringList /*arguments*/, QString /*currentHint*/) { if ( node->function->astType != Ast::AttributeAstType ) { return false; @@ -232,7 +235,7 @@ void ExpressionVisitor::checkForDecorators(CallAst* node, FunctionDeclaration* f // when calling foo.bar[3].baz.iteritems(), find the type of "foo.bar[3].baz" baseTypeVisitor.visitNode(static_cast(node->function)->value); if ( auto t = baseTypeVisitor.lastType().cast() ) { - kDebug() << "Found container, using type"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Found container, using type"; AbstractType::Ptr newType = t->contentType().abstractType(); encounter(newType, DeclarationPointer(useDeclaration)); return true; @@ -249,7 +252,7 @@ void ExpressionVisitor::checkForDecorators(CallAst* node, FunctionDeclaration* f baseTypeVisitor.visitNode(static_cast(node->function)->value); DUChainWriteLocker lock; if ( auto t = baseTypeVisitor.lastType().cast() ) { - kDebug() << "Got container:" << t->toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "Got container:" << t->toString(); auto newType = typeObjectForIntegralType("list", context()); if ( ! newType ) { return false; @@ -286,7 +289,7 @@ void ExpressionVisitor::checkForDecorators(CallAst* node, FunctionDeclaration* f }; knownDecoratorHints["getsListOfBoth"] = [&](QStringList /*arguments*/, QString /*currentHint*/) { - kDebug() << "Got getsListOfBoth decorator, checking container"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Got getsListOfBoth decorator, checking container"; if ( node->function->astType != Ast::AttributeAstType ) { return false; } @@ -295,7 +298,7 @@ void ExpressionVisitor::checkForDecorators(CallAst* node, FunctionDeclaration* f baseTypeVisitor.visitNode(static_cast(node->function)->value); DUChainWriteLocker lock; if ( auto t = baseTypeVisitor.lastType().cast() ) { - kDebug() << "Got container:" << t->toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "Got container:" << t->toString(); auto resultingType = listOfTuples(t->keyType().abstractType(), t->contentType().abstractType()); encounter(resultingType, DeclarationPointer(useDeclaration)); return true; @@ -305,7 +308,7 @@ void ExpressionVisitor::checkForDecorators(CallAst* node, FunctionDeclaration* f knownDecoratorHints["returnContentEqualsContentOf"] = [&](QStringList arguments, QString /*currentHint*/) { int argNum = ! arguments.isEmpty() ? arguments.at(0).toInt() : 0; - kDebug() << "Found argument dependent decorator, checking argument type" << argNum; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Found argument dependent decorator, checking argument type" << argNum; if ( argNum >= node->arguments.length() ) { return false; } @@ -436,7 +439,7 @@ void ExpressionVisitor::visitList(ListAst* node) } else { encounterUnknown(); - kWarning() << " [ !!! ] did not get a typetrack container object when expecting one! Fix code / setup."; + qCWarning(KDEV_PYTHON_DUCHAIN) << " [ !!! ] did not get a typetrack container object when expecting one! Fix code / setup."; } encounter(AbstractType::Ptr::staticCast(type)); } @@ -525,7 +528,7 @@ void ExpressionVisitor::visitTuple(TupleAst* node) { encounter(AbstractType::Ptr::staticCast(type)); } else { - kWarning() << "tuple type object is not available"; + qCWarning(KDEV_PYTHON_DUCHAIN) << "tuple type object is not available"; return encounterUnknown(); } } diff --git a/duchain/helpers.cpp b/duchain/helpers.cpp index 4461cdb9..6a64e2f6 100644 --- a/duchain/helpers.cpp +++ b/duchain/helpers.cpp @@ -21,10 +21,12 @@ #include #include -#include #include #include +#include +#include "duchaindebug.h" + #include #include #include @@ -39,6 +41,9 @@ #include #include #include +#include + +#include #include @@ -53,7 +58,7 @@ using namespace KDevelop; namespace Python { -QList Helper::cachedSearchPaths; +QList Helper::cachedSearchPaths; QStringList Helper::dataDirs; QString Helper::documentationFile; DUChainPointer Helper::documentationFileContext = DUChainPointer(0); @@ -87,13 +92,15 @@ void Helper::scheduleDependency(const IndexedString& dependency, int betterThanP IndexedDeclaration Helper::declarationUnderCursor(bool allowUse) { KDevelop::IDocument* doc = ICore::self()->documentController()->activeDocument(); - if ( doc && doc->textDocument() && doc->textDocument()->activeView() ) { + const auto view = static_cast(ICore::self()->partController())->activeView(); + if ( doc && doc->textDocument() && view ) { DUChainReadLocker lock; + const auto cursor = view->cursorPosition(); if ( allowUse ) { - return DUChainUtils::itemUnderCursor(doc->url(), SimpleCursor(doc->textDocument()->activeView()->cursorPosition())); + return DUChainUtils::itemUnderCursor(doc->url(), cursor); } else { - return DUChainUtils::declarationInLine(SimpleCursor(doc->textDocument()->activeView()->cursorPosition()), DUChainUtils::standardContextForUrl(doc->url())); + return DUChainUtils::declarationInLine(cursor, DUChainUtils::standardContextForUrl(doc->url())); } } @@ -142,14 +149,14 @@ AbstractType::Ptr Helper::extractTypeHints(AbstractType::Ptr type, TopDUContext* } else if ( UnsureType::Ptr unsure = type.cast() ) { int len = unsure->typesSize(); - for ( int i = 0; i < len and i < maxHints; i++ ) { + for ( int i = 0; i < len && i < maxHints; i++ ) { if ( HintedType::Ptr hinted = unsure->types()[i].abstractType().cast() ) { if ( hinted->isValid(current) ) { - kDebug() << "Adding type hint (multi): " << hinted->toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "Adding type hint (multi): " << hinted->toString(); result->addType(hinted->indexed()); } else { - kDebug() << "Discarding type hint (multi): " << hinted->toString(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "Discarding type hint (multi): " << hinted->toString(); maxHints += 1; } } @@ -247,7 +254,7 @@ Declaration* Helper::declarationForName(const QualifiedIdentifier& identifier, c QList importedLocalDeclarations; { DUChainReadLocker lock(DUChain::lock()); - if ( context.data() == context->topContext() and nodeRange.isValid() ) { + if ( context.data() == context->topContext() && nodeRange.isValid() ) { declarations = context->topContext()->findDeclarations(identifier, nodeRange.end); } else { @@ -266,7 +273,7 @@ Declaration* Helper::declarationForName(const QualifiedIdentifier& identifier, c do { declaration = importedLocalDeclarations.last(); importedLocalDeclarations.pop_back(); - if ( not declaration or declaration->context()->type() == DUContext::Class ) { + if ( !declaration || declaration->context()->type() == DUContext::Class ) { declaration = 0; } if ( importedLocalDeclarations.isEmpty() ) { @@ -294,7 +301,7 @@ QList< DUContext* > Helper::internalContextsForClass(StructureType::Ptr klassTyp ClassDeclaration* klass = dynamic_cast(decl); if ( klass ) { FOREACH_FUNCTION ( const BaseClassInstance& base, klass->baseClasses ) { - if ( flags == PublicOnly and base.access == KDevelop::Declaration::Private ) { + if ( flags == PublicOnly && base.access == KDevelop::Declaration::Private ) { continue; } StructureType::Ptr baseClassType = base.baseClass.type(); @@ -355,13 +362,13 @@ KUrl Helper::getCorrectionFile(KUrl document) } foreach (QString correctionFileDir, correctionFileDirs) { - foreach ( const KUrl& basePath, Helper::getSearchPaths(KUrl()) ) { + foreach ( const QUrl& basePath, Helper::getSearchPaths(QUrl()) ) { if ( ! basePath.isParentOf(document) ) { continue; } - QString path = KUrl::relativePath(basePath.path(), document.path()); - KUrl absolutePath(correctionFileDir + path); - absolutePath.cleanPath(); + QString path = basePath.resolved(document).path(); + auto absolutePath = QUrl::fromLocalFile(correctionFileDir + path); + // TODO QUrl: cleanPath? if ( QFile::exists(absolutePath.path()) ) { return absolutePath; @@ -391,21 +398,21 @@ KUrl Helper::getLocalCorrectionFile(KUrl document) return absolutePath; } -QList Helper::getSearchPaths(KUrl workingOnDocument) +QList Helper::getSearchPaths(QUrl workingOnDocument) { - QList searchPaths; + QList searchPaths; // search in the projects, as they're packages and likely to be installed or added to PYTHONPATH later foreach (IProject* project, ICore::self()->projectController()->projects() ) { - searchPaths.append(KUrl(project->folder().url())); + searchPaths.append(project->folder()); } foreach ( const QString& path, getDataDirs() ) { - searchPaths.append(KUrl(path)); + searchPaths.append(QUrl::fromLocalFile(path)); } if ( cachedSearchPaths.isEmpty() ) { KStandardDirs d; - kDebug() << "*** Gathering search paths..."; + qCDebug(KDEV_PYTHON_DUCHAIN) << "*** Gathering search paths..."; QStringList getpath; getpath << "-c" << "import sys; sys.stdout.write(':'.join(sys.path))"; @@ -422,27 +429,27 @@ QList Helper::getSearchPaths(KUrl workingOnDocument) } } else { - kWarning() << "Could not get search paths! Defaulting to stupid stuff."; - searchPaths.append(KUrl("/usr/lib/python2.7")); - searchPaths.append(KUrl("/usr/lib/python2.7/site-packages")); + qCWarning(KDEV_PYTHON_DUCHAIN) << "Could not get search paths! Defaulting to stupid stuff."; + searchPaths.append(QUrl::fromLocalFile("/usr/lib/python2.7")); + searchPaths.append(QUrl::fromLocalFile("/usr/lib/python2.7/site-packages")); QString path = qgetenv("PYTHONPATH"); QStringList paths = path.split(':'); foreach ( const QString& path, paths ) { cachedSearchPaths.append(path); } } - kDebug() << " *** Done. Got search paths: " << cachedSearchPaths; + qCDebug(KDEV_PYTHON_DUCHAIN) << " *** Done. Got search paths: " << cachedSearchPaths; } else { - kDebug() << " --- Search paths from cache: " << cachedSearchPaths; + qCDebug(KDEV_PYTHON_DUCHAIN) << " --- Search paths from cache: " << cachedSearchPaths; } searchPaths.append(cachedSearchPaths); - const QString& currentDir = workingOnDocument.directory(KUrl::IgnoreTrailingSlash); - if ( ! currentDir.isEmpty() ) { + auto currentDir = QDir(workingOnDocument.path()); + if ( ! currentDir.path().isEmpty() ) { // search in the current packages - searchPaths.append(KUrl(currentDir)); + searchPaths.append(QUrl::fromLocalFile(currentDir.path())); } return searchPaths; @@ -483,7 +490,6 @@ AbstractType::Ptr Helper::contentOfIterable(const AbstractType::Ptr iterable) AbstractType::Ptr Helper::mergeTypes(AbstractType::Ptr type, const AbstractType::Ptr newType) { UnsureType::Ptr ret; - ret.count(); return TypeUtils::mergeTypes(type, newType); } diff --git a/duchain/helpers.h b/duchain/helpers.h index d93af3ed..e4f94a35 100644 --- a/duchain/helpers.h +++ b/duchain/helpers.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -37,7 +36,6 @@ #include #include -#include #include @@ -53,7 +51,7 @@ namespace Python { class KDEVPYTHONDUCHAIN_EXPORT Helper { public: /** get search paths for python files **/ - static QList getSearchPaths(KUrl workingOnDocument); + static QList getSearchPaths(QUrl workingOnDocument); static QStringList dataDirs; static QString documentationFile; static QStringList correctionFileDirs; @@ -67,7 +65,7 @@ class KDEVPYTHONDUCHAIN_EXPORT Helper { static KUrl getCorrectionFile(KUrl document); static KUrl getLocalCorrectionFile(KUrl document); - static QList cachedSearchPaths; + static QList cachedSearchPaths; static AbstractType::Ptr extractTypeHints(AbstractType::Ptr type, TopDUContext* current); diff --git a/duchain/navigation/declarationnavigationcontext.cpp b/duchain/navigation/declarationnavigationcontext.cpp index 980436b9..24660c3f 100644 --- a/duchain/navigation/declarationnavigationcontext.cpp +++ b/duchain/navigation/declarationnavigationcontext.cpp @@ -57,7 +57,7 @@ void DeclarationNavigationContext::htmlIdentifiedType(AbstractType::Ptr type, co QString contentType; if ( map ) { if ( auto key = map->keyType().abstractType() ) { - IdentifiedType* identifiedKey = dynamic_cast(key.unsafeData()); + IdentifiedType* identifiedKey = dynamic_cast(key.data()); if ( identifiedKey ) { contentType.append(getLink(key->toString(), DeclarationPointer( identifiedKey->declaration(m_topContext.data())), @@ -71,7 +71,7 @@ void DeclarationNavigationContext::htmlIdentifiedType(AbstractType::Ptr type, co } } if ( AbstractType::Ptr contents = t->contentType().abstractType() ) { - IdentifiedType* identifiedContent = dynamic_cast(contents.unsafeData()); + IdentifiedType* identifiedContent = dynamic_cast(contents.data()); if ( identifiedContent ) { contentType.append(getLink(contents->toString(), DeclarationPointer( identifiedContent->declaration(m_topContext.data())), diff --git a/duchain/pythonduchainexport.h b/duchain/pythonduchainexport.h deleted file mode 100644 index 1dc33dca..00000000 --- a/duchain/pythonduchainexport.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * This file is part of KDevelop * - * Copyright 2007 Andreas Pakulat * - * Copyright 2006 Matt Rogers * - * Copyright 2004 Jaroslaw Staniek * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU Library General Public License as * - * published by the Free Software Foundation; either version 2 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - ***************************************************************************/ - -#ifndef PYTHONDUCHAINEXPORT_H -#define PYTHONDUCHAINEXPORT_H - -/* needed for KDE_EXPORT macros */ -#include - - -#ifndef KDEVPYTHONDUCHAIN_EXPORT -# ifdef MAKE_KDEV4PYTHONDUCHAIN_LIB -# define KDEVPYTHONDUCHAIN_EXPORT KDE_EXPORT -# else -# define KDEVPYTHONDUCHAIN_EXPORT KDE_IMPORT -# endif -#endif - -#endif - -//kate: space-indent on; indent-width 4; replace-tabs on; auto-insert-doxygen on; indent-mode cstyle; diff --git a/duchain/pythonducontext.cpp b/duchain/pythonducontext.cpp index 23ec0a24..dfceb453 100644 --- a/duchain/pythonducontext.cpp +++ b/duchain/pythonducontext.cpp @@ -26,6 +26,9 @@ #include "navigation/navigationwidget.h" +#include +#include "duchaindebug.h" + using namespace KDevelop; namespace Python { @@ -37,7 +40,7 @@ REGISTER_DUCHAIN_ITEM_WITH_DATA(PythonNormalDUContext, DUContextData); template<> QWidget* PythonTopDUContext::createNavigationWidget(Declaration* decl, TopDUContext* topContext, const QString& htmlPrefix, const QString& htmlSuffix) const { if ( ! decl ) { - kDebug() << "no declaration, not returning navigationwidget"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "no declaration, not returning navigationwidget"; return 0; } return new NavigationWidget(DeclarationPointer(decl), TopDUContextPointer(topContext), htmlPrefix, htmlSuffix); @@ -46,7 +49,7 @@ QWidget* PythonTopDUContext::createNavigationWidget(Declaration* decl, TopDUCont template<> QWidget* PythonNormalDUContext::createNavigationWidget(Declaration* decl, TopDUContext* topContext, const QString& htmlPrefix, const QString& htmlSuffix) const { if ( ! decl ) { - kDebug() << "no declaration, not returning navigationwidget"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "no declaration, not returning navigationwidget"; return 0; } return new NavigationWidget(DeclarationPointer(decl), TopDUContextPointer(topContext), htmlPrefix, htmlSuffix); diff --git a/duchain/tests/CMakeLists.txt b/duchain/tests/CMakeLists.txt index 7d892d0c..20ef11aa 100644 --- a/duchain/tests/CMakeLists.txt +++ b/duchain/tests/CMakeLists.txt @@ -1,6 +1,16 @@ -automoc4(pyduchaintest waitforupdate.cpp) -kde4_add_unit_test(pyduchaintest pyduchaintest.cpp) -kde4_add_unit_test(duchainbench duchainbench.cpp) +set(pyduchaintest_SRCS + pyduchaintest.cpp + ../duchaindebug.cpp) + +ecm_add_test(${pyduchaintest_SRCS} + TEST_NAME pyduchaintest) + +set(duchainbench_SRCS + duchainbench.cpp + ../duchaindebug.cpp) + +ecm_add_test(${duchainbench_SRCS} + TEST_NAME duchainbench) add_definitions(-DDUCHAIN_PY_DATA_DIR="${CMAKE_CURRENT_SOURCE_DIR}") @@ -8,14 +18,16 @@ target_link_libraries(pyduchaintest kdev4pythonduchain kdev4pythonparser ${kdev4pythonparser_LIBRARIES} - ${QT_QTTEST_LIBRARY} - ${KDEVPLATFORM_TESTS_LIBRARIES} + Qt5::Test + KDev::Tests + KF5::KDELibs4Support ) target_link_libraries(duchainbench kdev4pythonduchain kdev4pythonparser ${kdev4pythonparser_LIBRARIES} - ${QT_QTTEST_LIBRARY} - ${KDEVPLATFORM_TESTS_LIBRARIES} + Qt5::Test + KDev::Tests + KF5::KDELibs4Support ) diff --git a/duchain/tests/duchainbench.cpp b/duchain/tests/duchainbench.cpp index 813614f5..4c717e93 100644 --- a/duchain/tests/duchainbench.cpp +++ b/duchain/tests/duchainbench.cpp @@ -21,6 +21,9 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * *****************************************************************************/ +#include +#include "duchaindebug.h" + #include "duchainbench.h" #include @@ -48,7 +51,7 @@ DUChainBench::DUChainBench(QObject* parent): QObject(parent) qFatal("Failed to create temp directory, Aboring"); } testDir = QDir(QString(tempdirname)); - kDebug() << "tempdirname" << tempdirname; + qCDebug(KDEV_PYTHON_DUCHAIN) << "tempdirname" << tempdirname; initShell(); } @@ -63,7 +66,7 @@ void DUChainBench::initShell() KUrl doc_url = KUrl(KStandardDirs::locate("data", "kdevpythonsupport/documentation_files/builtindocumentation.py")); doc_url.cleanPath(KUrl::SimplifyDirSeparators); - kDebug() << doc_url; + qCDebug(KDEV_PYTHON_DUCHAIN) << doc_url; DUChain::self()->updateContextForUrl(IndexedString(doc_url), KDevelop::TopDUContext::AllDeclarationsContextsAndUses); ICore::self()->languageController()->backgroundParser()->parseDocuments(); @@ -78,7 +81,7 @@ ReferencedTopDUContext DUChainBench::parse(const QString& code) TestFile* testfile = new TestFile(code + "\n", "py", 0, testDir.absolutePath().append("/")); createdFiles << testfile; testfile->parse((TopDUContext::Features) (TopDUContext::ForceUpdate | TopDUContext::AST) ); - testfile->waitForParsed(500); + testfile->waitForParsed(2000); if ( testfile->isReady() ) { m_ast = static_cast(testfile->topContext()->ast().data())->ast; @@ -135,4 +138,4 @@ void DUChainBench::benchSimpleStatements() QBENCHMARK { parse(code); } -} \ No newline at end of file +} diff --git a/duchain/tests/duchainbench.h b/duchain/tests/duchainbench.h index 1a2e6a99..730a694c 100644 --- a/duchain/tests/duchainbench.h +++ b/duchain/tests/duchainbench.h @@ -21,12 +21,12 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * *****************************************************************************/ -#ifndef DUCHAINBENCH_H -#define DUCHAINBENCH_H +#ifndef PY_DUCHAINBENCH_H +#define PY_DUCHAINBENCH_H #include #include "ast.h" -#include +#include #include #include diff --git a/duchain/tests/pyduchaintest.cpp b/duchain/tests/pyduchaintest.cpp index 173a5cbd..6d770196 100644 --- a/duchain/tests/pyduchaintest.cpp +++ b/duchain/tests/pyduchaintest.cpp @@ -22,6 +22,9 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * *****************************************************************************/ +#include +#include "duchaindebug.h" + #include "pyduchaintest.h" #include @@ -33,7 +36,7 @@ #include #include #include -#include +#include #include #include #include @@ -42,6 +45,8 @@ #include #include +#include + #include "parsesession.h" #include "pythoneditorintegrator.h" #include "declarationbuilder.h" @@ -71,7 +76,7 @@ PyDUChainTest::PyDUChainTest(QObject* parent): QObject(parent) qFatal("Failed to create temp directory, Aboring"); } testDir = QDir(QString(tempdirname)); - kDebug() << "tempdirname" << tempdirname; + qCDebug(KDEV_PYTHON_DUCHAIN) << "tempdirname" << tempdirname; QByteArray pythonpath = qgetenv("PYTHONPATH"); pythonpath.prepend(":").prepend(assetsDir.absolutePath().toAscii()); @@ -97,22 +102,22 @@ void PyDUChainTest::init() { QString currentTest = QString(QTest::currentTestFunction()); if (lastTest == currentTest) { - kDebug() << "Already prepared assets for " << currentTest << ", skipping"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Already prepared assets for " << currentTest << ", skipping"; return; } else { lastTest = currentTest; } - kDebug() << "Preparing assets for test " << currentTest; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Preparing assets for test " << currentTest; QDir assetModuleDir = QDir(assetsDir.absolutePath()); if (!assetModuleDir.cd(currentTest)) { - kDebug() << "Asset directory " << currentTest + qCDebug(KDEV_PYTHON_DUCHAIN) << "Asset directory " << currentTest << " does not exist under " << assetModuleDir.absolutePath() << ". Skipping it."; return; } - kDebug() << "Searching for python files in " << assetModuleDir.absolutePath(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "Searching for python files in " << assetModuleDir.absolutePath(); QList foundfiles = FindPyFiles(assetModuleDir); @@ -125,7 +130,7 @@ void PyDUChainTest::init() // Parse each file twice, to ensure no parsing-order related bugs appear. // Such bugs will need separate unit tests and should not influence these. foreach(const QString filename, foundfiles) { - kDebug() << "Parsing asset: " << filename; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Parsing asset: " << filename; DUChain::self()->updateContextForUrl(IndexedString(filename), KDevelop::TopDUContext::AllDeclarationsContextsAndUses); ICore::self()->languageController()->backgroundParser()->parseDocuments(); } @@ -149,7 +154,7 @@ void PyDUChainTest::initShell() KUrl doc_url = KUrl(KStandardDirs::locate("data", "kdevpythonsupport/documentation_files/builtindocumentation.py")); doc_url.cleanPath(KUrl::SimplifyDirSeparators); - kDebug() << doc_url; + qCDebug(KDEV_PYTHON_DUCHAIN) << doc_url; DUChain::self()->updateContextForUrl(IndexedString(doc_url), KDevelop::TopDUContext::AllDeclarationsContextsAndUses); ICore::self()->languageController()->backgroundParser()->parseDocuments(); @@ -168,6 +173,7 @@ ReferencedTopDUContext PyDUChainTest::parse(const QString& code) testfile->waitForParsed(500); if ( testfile->isReady() ) { + Q_ASSERT(testfile->topContext()); m_ast = static_cast(testfile->topContext()->ast().data())->ast; return testfile->topContext(); } @@ -402,7 +408,7 @@ void PyDUChainTest::testClassVariables() if ( useIndex != -1 ) { QVERIFY(useIndex < c->usesCount()); const Use* u = &(c->uses()[useIndex]); - QVERIFY(not u->usedDeclaration(c->topContext())); + QVERIFY(!u->usedDeclaration(c->topContext())); } } @@ -566,7 +572,7 @@ void PyDUChainTest::testSimple() foreach(Declaration* d, declarations) { usesCount += d->uses().size(); - QVERIFY(!d->abstractType().isNull()); + QVERIFY(d->abstractType()); } QCOMPARE(usesCount, uses); @@ -588,10 +594,10 @@ void PyDUChainTest::testSimple_data() class AttributeRangeTestVisitor : public AstDefaultVisitor { public: bool found; - SimpleRange searchingForRange; + KTextEditor::Range searchingForRange; QString searchingForIdentifier; virtual void visitAttribute(AttributeAst* node) { - SimpleRange r(0, node->startCol, 0, node->endCol); + auto r = KTextEditor::Range(0, node->startCol, 0, node->endCol); qDebug() << "Found attr: " << r << node->attribute->value << ", looking for: " << searchingForRange << searchingForIdentifier; if ( r == searchingForRange && node->attribute->value == searchingForIdentifier ) { found = true; @@ -600,7 +606,7 @@ class AttributeRangeTestVisitor : public AstDefaultVisitor { AstDefaultVisitor::visitAttribute(node); } virtual void visitFunctionDefinition(FunctionDefinitionAst* node) { - SimpleRange r(0, node->name->startCol, 0, node->name->endCol); + auto r = KTextEditor::Range(0, node->name->startCol, 0, node->name->endCol); qDebug() << "Found func: " << r << node->name->value << ", looking for: " << searchingForRange << searchingForIdentifier; qDebug() << node->arguments->vararg << node->arguments->kwarg; if ( r == searchingForRange && node->name->value == searchingForIdentifier ) { @@ -608,7 +614,7 @@ class AttributeRangeTestVisitor : public AstDefaultVisitor { return; } if ( node->arguments->vararg ) { - SimpleRange r(0, node->arguments->vararg->startCol, 0, node->arguments->vararg->startCol+node->arguments->vararg->argumentName->value.length()); + auto r = KTextEditor::Range(0, node->arguments->vararg->startCol, 0, node->arguments->vararg->startCol+node->arguments->vararg->argumentName->value.length()); qDebug() << "Found vararg: " << node->arguments->vararg->argumentName->value << r; if ( r == searchingForRange && node->arguments->vararg->argumentName->value == searchingForIdentifier ) { found = true; @@ -616,7 +622,7 @@ class AttributeRangeTestVisitor : public AstDefaultVisitor { } } if ( node->arguments->kwarg ) { - SimpleRange r(0, node->arguments->kwarg->startCol, 0, node->arguments->kwarg->startCol+node->arguments->kwarg->argumentName->value.length()); + auto r = KTextEditor::Range(0, node->arguments->kwarg->startCol, 0, node->arguments->kwarg->startCol+node->arguments->kwarg->argumentName->value.length()); qDebug() << "Found kwarg: " << node->arguments->kwarg->argumentName->value << r; if ( r == searchingForRange && node->arguments->kwarg->argumentName->value == searchingForIdentifier ) { found = true; @@ -626,7 +632,7 @@ class AttributeRangeTestVisitor : public AstDefaultVisitor { AstDefaultVisitor::visitFunctionDefinition(node); } virtual void visitClassDefinition(ClassDefinitionAst* node) { - SimpleRange r(0, node->name->startCol, 0, node->name->endCol); + auto r = KTextEditor::Range(0, node->name->startCol, 0, node->name->endCol); qDebug() << "Found cls: " << r << node->name->value << ", looking for: " << searchingForRange << searchingForIdentifier; if ( r == searchingForRange && node->name->value == searchingForIdentifier ) { found = true; @@ -669,7 +675,7 @@ void PyDUChainTest::testRanges() int scol = column_ranges.at(i).split(",")[0].toInt(); int ecol = column_ranges.at(i).split(",")[1].toInt(); QString identifier = column_ranges.at(i).split(",")[2]; - SimpleRange r(0, scol, 0, ecol); + auto r = KTextEditor::Range(0, scol, 0, ecol); AttributeRangeTestVisitor* visitor = new AttributeRangeTestVisitor(); visitor->searchingForRange = r; @@ -714,13 +720,12 @@ class TypeTestVisitor : public AstDefaultVisitor { if ( node->identifier->value != "checkme" ) return; QList decls = ctx->findDeclarations(QualifiedIdentifier(node->identifier->value)); if ( ! decls.length() ) { - kDebug() << "No declaration found for " << node->identifier->value; + qCDebug(KDEV_PYTHON_DUCHAIN) << "No declaration found for " << node->identifier->value; return; } Declaration* d = decls.last(); - kDebug() << "Declaration: " << node->identifier->value << d->type(); QVERIFY(d->abstractType()); - kDebug() << "found: " << node->identifier->value << "is" << d->abstractType()->toString() << "should be" << searchingForType; + qCDebug(KDEV_PYTHON_DUCHAIN) << "found: " << node->identifier->value << "is" << d->abstractType()->toString() << "should be" << searchingForType; if ( d->abstractType()->toString().replace("__kdevpythondocumentation_builtin_", "").startsWith(searchingForType) ) { found = true; return; @@ -920,13 +925,13 @@ void PyDUChainTest::testImportDeclarations() { bool found = false; QString name = expected; QList decls = ctx->allDeclarations(CursorInRevision::invalid(), ctx->topContext(), false); - kDebug() << "FOUND DECLARATIONS:"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "FOUND DECLARATIONS:"; foreach ( const pair& current, decls ) { - kDebug() << current.first->toString() << current.first->identifier().identifier().byteArray() << name; + qCDebug(KDEV_PYTHON_DUCHAIN) << current.first->toString() << current.first->identifier().identifier().byteArray() << name; } foreach ( const pair& current, decls ) { if ( ! ( current.first->identifier().identifier().byteArray() == name ) ) continue; - kDebug() << "Found: " << current.first->toString() << " for " << name; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Found: " << current.first->toString() << " for " << name; AliasDeclaration* isAliased = dynamic_cast(current.first); if ( isAliased && shouldBeAliased ) { found = true; // TODO fixme @@ -1007,7 +1012,7 @@ void PyDUChainTest::testAutocompletionFlickering() lock.lock(); QList

decls2 = ctx2->allDeclarations(CursorInRevision::invalid(), ctx2->topContext()); foreach ( p d2, decls2 ) { - kDebug() << "@1: " << d2.first->toString() << "::" << d2.first->id().hash() << "<>" << declIds.first().hash(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "@1: " << d2.first->toString() << "::" << d2.first->id().hash() << "<>" << declIds.first().hash(); QVERIFY(d2.first->id() == declIds.first()); declIds.removeFirst(); } @@ -1040,7 +1045,7 @@ void PyDUChainTest::testAutocompletionFlickering() decls2 = ctx2->allDeclarations(CursorInRevision::invalid(), ctx2->topContext(), false).first().first->internalContext() ->allDeclarations(CursorInRevision::invalid(), ctx2->topContext()); foreach ( p d2, decls2 ) { - kDebug() << "@2: " << d2.first->toString() << "::" << d2.first->id().hash() << "<>" << declIds.first().hash(); + qCDebug(KDEV_PYTHON_DUCHAIN) << "@2: " << d2.first->toString() << "::" << d2.first->id().hash() << "<>" << declIds.first().hash(); QVERIFY(d2.first->id() == declIds.first()); declIds.removeFirst(); } @@ -1244,7 +1249,6 @@ void PyDUChainTest::testContainerTypes() QList decls = ctx->findDeclarations(QualifiedIdentifier("checkme")); QVERIFY(decls.length() > 0); QVERIFY(decls.first()->abstractType()); - kDebug() << "TEST type is: " << decls.first()->abstractType().unsafeData()->toString(); if ( ! use_type ) { auto type = ListType::Ptr::dynamicCast(decls.first()->abstractType()); QVERIFY(type); diff --git a/duchain/tests/pyduchaintest.h b/duchain/tests/pyduchaintest.h index 1a2ecdff..4b9110d4 100644 --- a/duchain/tests/pyduchaintest.h +++ b/duchain/tests/pyduchaintest.h @@ -27,7 +27,7 @@ #include #include "ast.h" -#include +#include #include #include diff --git a/duchain/types/hintedtype.cpp b/duchain/types/hintedtype.cpp index bd1b859f..b2c24b37 100644 --- a/duchain/types/hintedtype.cpp +++ b/duchain/types/hintedtype.cpp @@ -4,7 +4,7 @@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -26,6 +26,9 @@ #include #include +#include +#include "../duchaindebug.h" + #include using namespace KDevelop; @@ -56,17 +59,17 @@ bool HintedType::isValid(TopDUContext* /*current*/) if ( ! creator ) { return false; } - KDEBUG_BLOCK +// KDEBUG_BLOCK ModificationRevision rev(creator->parsingEnvironmentFile()->modificationRevision()); - kDebug() << "current: " << rev.revision << "; created:" << d_func()->m_modificationRevision.revision; - kDebug() << "current: " << rev.modificationTime << "; created:" << d_func()->m_modificationRevision.modificationTime; + qCDebug(KDEV_PYTHON_DUCHAIN) << "current: " << rev.revision << "; created:" << d_func()->m_modificationRevision.revision; + qCDebug(KDEV_PYTHON_DUCHAIN) << "current: " << rev.modificationTime << "; created:" << d_func()->m_modificationRevision.modificationTime; if ( d_func()->m_modificationRevision < rev ) { - kDebug() << "modification revision mismatch, invalidating"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "modification revision mismatch, invalidating"; return false; } /// This should not be needed any more since 193f52027fb7 // if ( creator == current && d_func()->m_modificationRevision == rev && rev.revision != 0 ) { -// kDebug() << "modification revision exact match, but same context, invalidating"; +// qCDebug(KDEV_PYTHON_DUCHAIN) << "modification revision exact match, but same context, invalidating"; // return false; // } return true; @@ -76,7 +79,7 @@ void HintedType::setCreatedBy(TopDUContext* context, const ModificationRevision& { d_func_dynamic()->m_createdByContext = context->indexed(); d_func_dynamic()->m_modificationRevision = revision; - kDebug() << "new HintedType with modification time: " << d_func()->m_modificationRevision.modificationTime + qCDebug(KDEV_PYTHON_DUCHAIN) << "new HintedType with modification time: " << d_func()->m_modificationRevision.modificationTime << "; " << d_func()->m_modificationRevision.revision; } diff --git a/duchain/types/hintedtype.h b/duchain/types/hintedtype.h index 9e43d97c..75ebb109 100644 --- a/duchain/types/hintedtype.h +++ b/duchain/types/hintedtype.h @@ -4,7 +4,7 @@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/duchain/types/indexedcontainer.cpp b/duchain/types/indexedcontainer.cpp index 6589e2f6..5759de40 100644 --- a/duchain/types/indexedcontainer.cpp +++ b/duchain/types/indexedcontainer.cpp @@ -4,7 +4,7 @@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/duchain/types/indexedcontainer.h b/duchain/types/indexedcontainer.h index bb7fe1a0..ad56cf86 100644 --- a/duchain/types/indexedcontainer.h +++ b/duchain/types/indexedcontainer.h @@ -4,7 +4,7 @@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/duchain/types/unsuretype.cpp b/duchain/types/unsuretype.cpp index 2042d412..3b76a30e 100644 --- a/duchain/types/unsuretype.cpp +++ b/duchain/types/unsuretype.cpp @@ -4,7 +4,7 @@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -27,6 +27,8 @@ #include #include #include +#include +#include "../duchaindebug.h" namespace Python { @@ -70,7 +72,7 @@ QString UnsureType::toString() const QList encountered; foreach ( AbstractType::Ptr type, typesRecursive() ) { if ( ! type ) { - kWarning() << "Invalid type: " << type.unsafeData(); + qCWarning(KDEV_PYTHON_DUCHAIN) << "Invalid type: " << type.data(); continue; } diff --git a/duchain/types/unsuretype.h b/duchain/types/unsuretype.h index b5562613..0a2d15de 100644 --- a/duchain/types/unsuretype.h +++ b/duchain/types/unsuretype.h @@ -4,7 +4,7 @@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -32,13 +32,14 @@ #include #include #include +#include namespace Python { class KDEVPYTHONDUCHAIN_EXPORT UnsureType : public KDevelop::UnsureType { public: - typedef TypePtr Ptr; + typedef KDevelop::TypePtr Ptr; UnsureType(); UnsureType(const UnsureType& rhs); diff --git a/duchain/usebuilder.cpp b/duchain/usebuilder.cpp index d2eb9fa6..1906e619 100644 --- a/duchain/usebuilder.cpp +++ b/duchain/usebuilder.cpp @@ -18,6 +18,9 @@ */ #include "usebuilder.h" +#include +#include "duchaindebug.h" + #include #include @@ -108,9 +111,9 @@ void UseBuilder::visitName(NameAst* node) void UseBuilder::visitAttribute(AttributeAst* node) { - kDebug() << "VisitAttribute start"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "VisitAttribute start"; UseBuilderBase::visitAttribute(node); - kDebug() << "Visit Attribute base end"; + qCDebug(KDEV_PYTHON_DUCHAIN) << "Visit Attribute base end"; DUContext* context = contextAtOrCurrent(editorFindPositionSafe(node)); ExpressionVisitor v(context); @@ -124,7 +127,7 @@ void UseBuilder::visitAttribute(AttributeAst* node) // this is the declaration, don't build a use for it return; } - if ( ! declaration && v.isConfident() && ( ! v.lastType() or Helper::isUsefulType(v.lastType()) ) ) { + if ( ! declaration && v.isConfident() && ( ! v.lastType() || Helper::isUsefulType(v.lastType()) ) ) { KDevelop::Problem *p = new KDevelop::Problem(); p->setFinalLocation(DocumentRange(currentlyParsedDocument(), useRange.castToSimpleRange())); p->setSource(KDevelop::ProblemData::SemanticAnalysis); diff --git a/kdevpythonsupport.desktop b/kdevpythonsupport.desktop deleted file mode 100644 index bb45aeed..00000000 --- a/kdevpythonsupport.desktop +++ /dev/null @@ -1,128 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Type=Service -Exec=blubb -Comment=Python Language Support (Python 3 version) -Comment[bg]=Поддръжка на езика Python -Comment[bs]=Podrška za Python jezik -Comment[ca]=Implementació del llenguatge Python -Comment[ca@valencia]=Implementació del llenguatge Python -Comment[da]=Sprogunderstøttelse for Python -Comment[de]=Sprachunterstützung für Python -Comment[el]=Υποστήριξη γλώσσας Python -Comment[en_GB]=Python Language Support -Comment[es]=Implementación del lenguaje Python -Comment[et]=Pythoni keele toetus -Comment[fi]=Python-kielituki -Comment[fr]=Prise en charge du langage Python -Comment[ga]=Tacaíocht Python -Comment[gl]=Compatibilidade coa linguaxe Python. -Comment[hne]=पायथन भाखा समर्थन -Comment[hu]=Python nyelvi támogatás -Comment[it]=Supporto per il linguaggio Python -Comment[kk]=Python тілін қолдауы -Comment[mr]=पायथोन भाषा समर्थन -Comment[nb]=Støtte for Python-språket -Comment[nds]=Ünnerstütten för Python -Comment[nl]=Ondersteuning voor de taal Python -Comment[pa]=ਪਾਈਥਨ ਲੈਗੂਇਜ਼ ਸਹਿਯੋਗ -Comment[pl]=Obsługa języka Python -Comment[pt]=Suporte para a Linguagem Python -Comment[pt_BR]=Suporte à linguagem Python -Comment[ro]=Suport pentru limbajul Python -Comment[ru]=Поддержка языка Python -Comment[sk]=Podpora jazyka Python -Comment[sl]=Podpora jeziku Python -Comment[sv]=Stöd för språket Python -Comment[tr]=Python Dil Desteği -Comment[uk]=Підтримка мови Python -Comment[x-test]=xxPython Language Supportxx -Comment[zh_CN]=Python 语言支持 -Comment[zh_TW]=Python 語言支援 -Name=Python Support (Python 3 version) -Name[bg]=Поддръжка на Python -Name[bs]=Python podrška -Name[ca]=Implementació de Python -Name[ca@valencia]=Implementació de Python -Name[cs]=Podpora Pythonu -Name[da]=Understøttelse af Python -Name[de]=Unterstützung für Python -Name[el]=Υποστήριξη Python -Name[en_GB]=Python Support -Name[es]=Implementación de Python -Name[et]=Pythoni toetus -Name[fi]=Python-tuki -Name[fr]=Prise en charge de Python -Name[ga]=Tacaíocht Python -Name[gl]=Compatibilidade con Python -Name[hu]=Python-támogatás -Name[it]=Supporto per Python -Name[kk]=Python қолдауы -Name[mr]=पायथोन समर्थन -Name[nb]=Støtte for Python -Name[nds]=Python-Ünnerstütten -Name[nl]=Ondersteuning voor Python -Name[pl]=Obsługa Python -Name[pt]=Suporte para Python -Name[pt_BR]=Suporte à Python -Name[ro]=Suport pentru Python -Name[ru]=Поддержка Python -Name[sk]=Podpora Pythonu -Name[sl]=Podpora Pythonu -Name[sv]=Python-stöd -Name[tr]=Python Desteği -Name[ug]=Python قوللىشى -Name[uk]=Підтримка Python -Name[x-test]=xxPython Supportxx -Name[zh_CN]=Python 支持 -Name[zh_TW]=Python 支援 -GenericName=Python Support (Python 3 version) -GenericName[bg]=Поддръжка на Python -GenericName[bs]=Python podrška -GenericName[ca]=Implementació de Python -GenericName[ca@valencia]=Implementació de Python -GenericName[cs]=Podpora Pythonu -GenericName[da]=Understøttelse af Python -GenericName[de]=Unterstützung für Python -GenericName[el]=Υποστήριξη Python -GenericName[en_GB]=Python Support -GenericName[es]=Implementación de Python -GenericName[et]=Pythoni toetus -GenericName[fi]=Python-tuki -GenericName[fr]=Prise en charge de Python -GenericName[ga]=Tacaíocht Python -GenericName[gl]=Compatibilidade con Python -GenericName[hne]=पायथन समर्थन -GenericName[hu]=Python-támogatás -GenericName[it]=Supporto per Python -GenericName[kk]=Python қолдауы -GenericName[mr]=पायथोन समर्थन -GenericName[nb]=Støtte for Python -GenericName[nds]=Python-Ünnerstütten -GenericName[nl]=Ondersteuning voor Python -GenericName[pa]=ਪਾਈਥਨ ਸਹਿਯੋਗ -GenericName[pl]=Obsługa Python -GenericName[pt]=Suporte para Python -GenericName[pt_BR]=Suporte à Python -GenericName[ro]=Suport pentru Python -GenericName[ru]=Поддержка Python -GenericName[sk]=Podpora Pythonu -GenericName[sl]=Podpora Pythonu -GenericName[sv]=Python-stöd -GenericName[tr]=Python Desteği -GenericName[ug]=Python قوللىشى -GenericName[uk]=Підтримка Python -GenericName[x-test]=xxPython Supportxx -GenericName[zh_CN]=Python 支持 -GenericName[zh_TW]=Python 支援 -ServiceTypes=KDevelop/Plugin -Icon=text-x-python -X-KDE-Library=kdevpythonlanguagesupport -X-KDevelop-Version=18 -X-KDevelop-Language=Python -X-KDevelop-Args=PYTHON -X-KDevelop-Interfaces=ILanguageSupport,org.kdevelop.ILanguageCheckProvider -X-KDevelop-SupportedMimeTypes=text/x-python -X-KDE-PluginInfo-Name=kdevpythonsupport -X-KDevelop-Mode=NoGUI -X-KDE-PluginInfo-Category=Language Support diff --git a/kdevpythonsupport.desktop.cmake b/kdevpythonsupport.desktop.cmake new file mode 100644 index 00000000..6e5d289c --- /dev/null +++ b/kdevpythonsupport.desktop.cmake @@ -0,0 +1,60 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Service +Exec=blubb +Comment=Python Language Support (Python 3 version) +Comment[ca]=Implementació del llenguatge Python (versió 3 del Python) +Comment[de]=Sprachunterstützung für Python Version 3 +Comment[en_GB]=Python Language Support (Python 3 version) +Comment[es]=Implementación del lenguaje Python (versión 3 de Python) +Comment[fi]=Python-kielituki (Python 3) +Comment[it]=Supporto per il linguaggio Python (Python 3) +Comment[nl]=Ondersteuning voor de taal Python (Python versie 3) +Comment[pl]=Obsługa języka Python (Python w wersji 3) +Comment[pt]=Suporte para a Linguagem Python (versão 3) +Comment[pt_BR]=Suporte à linguagem Python (versão Python 3) +Comment[sk]=Podpora jazyka Python (verzia Python 3) +Comment[sl]=Podpora jeziku Python (različica Python 3) +Comment[uk]=Підтримка мови Python (версія Python 3) +Comment[x-test]=xxPython Language Support (Python 3 version)xx +Name=Python Support (Python 3 version) +Name[ca]=Implementació de Python (versió 3 del Python) +Name[de]=Unterstützung für Python Version 3 +Name[en_GB]=Python Support (Python 3 version) +Name[es]=Implementación de Python (versión 3 de Python) +Name[fi]=Python-tuki (Python 3) +Name[it]=Supporto per Python (Python 3) +Name[nl]=Ondersteuning voor Python (Python versie 3) +Name[pl]=Obsługa Pythona (Python w wersji 3) +Name[pt]=Suporte para Python (versão 3) +Name[pt_BR]=Suporte à Python (versão Python 3) +Name[sk]=Podpora Pythonu (verzia Python 3) +Name[sl]=Podpora za Python (različica Python 3) +Name[uk]=Підтримка Python (версія Python 3) +Name[x-test]=xxPython Support (Python 3 version)xx +GenericName=Python Support (Python 3 version) +GenericName[ca]=Implementació de Python (versió 3 del Python) +GenericName[de]=Unterstützung für Python Version 3 +GenericName[en_GB]=Python Support (Python 3 version) +GenericName[es]=Implementación de Python (versión 3 de Python) +GenericName[fi]=Python-tuki (Python 3) +GenericName[it]=Supporto per Python (Python 3) +GenericName[nl]=Ondersteuning voor Python (Python versie 3) +GenericName[pl]=Obsługa Pythona (Python w wersji 3) +GenericName[pt]=Suporte para Python (versão 3) +GenericName[pt_BR]=Suporte à Python (versão Python 3) +GenericName[sk]=Podpora Pythonu (verzia Python 3) +GenericName[sl]=Podpora za Python (različica Python 3) +GenericName[uk]=Підтримка Python (версія Python 3) +GenericName[x-test]=xxPython Support (Python 3 version)xx +ServiceTypes=KDevelop/Plugin +Icon=text-x-python +X-KDE-Library=kdevpythonlanguagesupport +X-KDevelop-Version=@KDEV_PLUGIN_VERSION@ +X-KDevelop-Language=Python +X-KDevelop-Args=PYTHON +X-KDevelop-Interfaces=ILanguageSupport,org.kdevelop.ILanguageCheckProvider +X-KDevelop-SupportedMimeTypes=text/x-python +X-KDE-PluginInfo-Name=kdevpythonsupport +X-KDevelop-Mode=NoGUI +X-KDE-PluginInfo-Category=Language Support diff --git a/parser/CMakeLists.txt b/parser/CMakeLists.txt index 1058d76f..774718e3 100644 --- a/parser/CMakeLists.txt +++ b/parser/CMakeLists.txt @@ -11,6 +11,7 @@ set(parser_STAT_SRCS astvisitor.cpp astbuilder.cpp cythonsyntaxremover.cpp + parserdebug.cpp ) find_package(PythonLibs 3.4 REQUIRED) @@ -20,15 +21,18 @@ endif() include_directories(kdev4pythonparser ${PYTHON_INCLUDE_DIRS}) -kde4_add_library( kdev4pythonparser SHARED ${parser_SRCS} ${parser_STAT_SRCS} ) +add_library( kdev4pythonparser SHARED ${parser_STAT_SRCS} ) + +generate_export_header(kdev4pythonparser EXPORT_MACRO_NAME KDEVPYTHONPARSER_EXPORT + EXPORT_FILE_NAME parserexport.h) + target_link_libraries(kdev4pythonparser LINK_PRIVATE - ${KDE4_KDECORE_LIBS} - ${KDEVPLATFORM_LANGUAGE_LIBRARIES} - ${QT_QTCORE_LIBRARY} + KF5::KDELibs4Support + KDev::Language + Qt5::Core ${PYTHON_LIBRARY} ) -add_dependencies(kdev4pythonparser parser) install(TARGETS kdev4pythonparser DESTINATION ${INSTALL_TARGETS_DEFAULT_ARGS}) add_subdirectory(tests) diff --git a/parser/ast.h b/parser/ast.h index 01294d8e..cf8ce3a7 100644 --- a/parser/ast.h +++ b/parser/ast.h @@ -25,14 +25,9 @@ #define PYTHON_AST_H #include -#include #include -#include -#include #include - -#include - +#include #include "parserexport.h" namespace KDevelop @@ -203,8 +198,8 @@ class KDEVPYTHONPARSER_EXPORT Ast return startLine < other->startLine || ( startLine == other->startLine && startCol < other->startCol ); }; - const KDevelop::SimpleRange range() const { - return KDevelop::SimpleRange(startLine, startCol, endLine, endCol); + const KTextEditor::Range range() const { + return KTextEditor::Range(startLine, startCol, endLine, endCol); }; int startCol; diff --git a/parser/astbuilder.cpp b/parser/astbuilder.cpp index e914877f..9b4ae622 100644 --- a/parser/astbuilder.cpp +++ b/parser/astbuilder.cpp @@ -25,12 +25,7 @@ #include #include -#include -#include #include -#include -#include -#include #include #include #include @@ -44,6 +39,9 @@ #include #include +#include +#include "parserdebug.h" + using namespace KDevelop; extern grammar _PyParser_Grammar; @@ -303,14 +301,14 @@ QPair fileHeaderHack(QString& contents, const KUrl& filename) if ( ! proj ) { return QPair(contents, 0); } - const KUrl headerFileUrl = proj->folder().path(KUrl::AddTrailingSlash) + ".kdev_python_header"; + const QUrl headerFileUrl = proj->folder().path() + "/.kdev_python_header"; QFile headerFile(headerFileUrl.path()); QString headerFileContents; if ( headerFile.exists() ) { headerFile.open(QIODevice::ReadOnly); headerFileContents = headerFile.readAll(); headerFile.close(); - kDebug() << "Found header file, applying hack"; + qCDebug(KDEV_PYTHON_PARSER) << "Found header file, applying hack"; int insertAt = 0; bool endOfCommentsReached = false; bool commentSignEncountered = false; @@ -320,15 +318,15 @@ QPair fileHeaderHack(QString& contents, const KUrl& filename) int l = contents.length(); do { if ( insertAt >= l ) { - kDebug() << "File consist only of comments, not applying hack"; + qCDebug(KDEV_PYTHON_PARSER) << "File consist only of comments, not applying hack"; return QPair(contents, 0); } if ( contents.at(insertAt) == '#' ) { commentSignEncountered = true; } - if ( not contents.at(insertAt).isSpace() ) { + if ( !contents.at(insertAt).isSpace() ) { // atLineBeginning = false; - if ( not commentSignEncountered ) { + if ( !commentSignEncountered ) { endOfCommentsReached = true; } } @@ -342,12 +340,12 @@ QPair fileHeaderHack(QString& contents, const KUrl& filename) endOfCommentsReached = true; } insertAt += 1; - } while ( not endOfCommentsReached ); - kDebug() << "Inserting contents at char" << lastLineBeginning << "of file"; + } while ( !endOfCommentsReached ); + qCDebug(KDEV_PYTHON_PARSER) << "Inserting contents at char" << lastLineBeginning << "of file"; contents = contents.left(lastLineBeginning) + "\n" + headerFileContents + "\n#\n" + contents.right(contents.length() - lastLineBeginning); - kDebug() << contents; + qCDebug(KDEV_PYTHON_PARSER) << contents; return QPair(contents, - ( headerFileContents.count('\n') + 3 )); } else { @@ -400,7 +398,7 @@ CodeAst::Ptr AstBuilder::parse(KUrl filename, QString &contents) CythonSyntaxRemover cythonSyntaxRemover; if (filename.fileName().endsWith(".pyx", Qt::CaseInsensitive)) { - kDebug() << filename.fileName() << "is probably Cython file."; + qCDebug(KDEV_PYTHON_PARSER) << filename.fileName() << "is probably Cython file."; contents = cythonSyntaxRemover.stripCythonSyntax(contents); } @@ -410,7 +408,7 @@ CodeAst::Ptr AstBuilder::parse(KUrl filename, QString &contents) qDebug() << " ====< parse error, trying to fix"; PyErr_Fetch(&exception, &value, &backtrace); - kDebug() << "Error objects: " << exception << value << backtrace; + qCDebug(KDEV_PYTHON_PARSER) << "Error objects: " << exception << value << backtrace; PyObject_Print(value, stderr, Py_PRINT_RAW); PyObject* errorMessage_str = PyTuple_GetItem(value, 0); @@ -419,7 +417,7 @@ CodeAst::Ptr AstBuilder::parse(KUrl filename, QString &contents) PyObject_Print(errorMessage_str, stderr, Py_PRINT_RAW); if ( ! errorDetails_tuple ) { - kWarning() << "Error retrieving error message, not displaying, and not doing anything"; + qCWarning(KDEV_PYTHON_PARSER) << "Error retrieving error message, not displaying, and not doing anything"; return CodeAst::Ptr(); } PyObject* linenoobj = PyTuple_GetItem(errorDetails_tuple, 1); @@ -432,10 +430,10 @@ CodeAst::Ptr AstBuilder::parse(KUrl filename, QString &contents) int colno = PyLong_AsLong(colnoobj); ProblemPointer p(new Problem()); - SimpleCursor start(lineno + lineOffset, (colno-4 > 0 ? colno-4 : 0)); - SimpleCursor end(lineno + lineOffset, (colno+4 > 4 ? colno+4 : 4)); - SimpleRange range(start, end); - kDebug() << "Problem range: " << range; + KTextEditor::Cursor start(lineno + lineOffset, (colno-4 > 0 ? colno-4 : 0)); + KTextEditor::Cursor end(lineno + lineOffset, (colno+4 > 4 ? colno+4 : 4)); + KTextEditor::Range range(start, end); + qCDebug(KDEV_PYTHON_PARSER) << "Problem range: " << range; DocumentRange location(IndexedString(filename.path()), range); p->setFinalLocation(location); p->setDescription(PyUnicodeObjectToQString(errorMessage_str)); @@ -494,9 +492,9 @@ CodeAst::Ptr AstBuilder::parse(KUrl filename, QString &contents) // we can easily fix that by adding in a "pass" statement. However, we want to add that in the next line, if possible // so context ranges for autocompletion stay intact. if ( contents[emptySince] == QChar(':') ) { - kDebug() << indents.length() << emptySinceLine + 1 << indents; + qCDebug(KDEV_PYTHON_PARSER) << indents.length() << emptySinceLine + 1 << indents; if ( indents.length() > emptySinceLine + 1 && indents.at(emptySinceLine) < indents.at(emptySinceLine + 1) ) { - kDebug() << indents.at(emptySinceLine) << indents.at(emptySinceLine + 1); + qCDebug(KDEV_PYTHON_PARSER) << indents.at(emptySinceLine) << indents.at(emptySinceLine + 1); contents.insert(emptyLinesSince + 1 + indents.at(emptyLinesSinceLine), "\tpass#"); } else { @@ -504,7 +502,7 @@ CodeAst::Ptr AstBuilder::parse(KUrl filename, QString &contents) } } else if ( indents.length() >= currentLine && currentLine > 0 ) { - kDebug() << indents << currentLine; + qCDebug(KDEV_PYTHON_PARSER) << indents << currentLine; contents[i+1+indents.at(currentLine - 1)] = QChar('#'); contents.insert(i+1+indents.at(currentLine - 1), "pass"); } @@ -517,8 +515,8 @@ CodeAst::Ptr AstBuilder::parse(KUrl filename, QString &contents) currentLineBeginning = qMin(contents.length() - 1, currentLineBeginning); errline = qMax(0, qMin(indents.length()-1, errline)); if ( ! syntaxtree ) { - kWarning() << "Discarding parts of the code to be parsed because of previous errors"; - kDebug() << indents; + qCWarning(KDEV_PYTHON_PARSER) << "Discarding parts of the code to be parsed because of previous errors"; + qCDebug(KDEV_PYTHON_PARSER) << indents; int indentAtError = indents.at(errline); QChar c; bool atLineBeginning = true; @@ -527,13 +525,13 @@ CodeAst::Ptr AstBuilder::parse(KUrl filename, QString &contents) int currentLineContentBeginning = currentLineBeginning; for ( int i = currentLineBeginning; i < len; i++ ) { c = contents.at(i); - kDebug() << c; + qCDebug(KDEV_PYTHON_PARSER) << c; if ( c == '\n' ) { if ( currentIndent <= indentAtError && currentIndent != -1 ) { - kDebug() << "Start of error code: " << currentLineBeginning; - kDebug() << "End of error block (current position): " << currentLineBeginning_end; - kDebug() << "Length: " << currentLineBeginning_end - currentLineBeginning; - kDebug() << "indent at error <> current indent:" << indentAtError << "<>" << currentIndent; + qCDebug(KDEV_PYTHON_PARSER) << "Start of error code: " << currentLineBeginning; + qCDebug(KDEV_PYTHON_PARSER) << "End of error block (current position): " << currentLineBeginning_end; + qCDebug(KDEV_PYTHON_PARSER) << "Length: " << currentLineBeginning_end - currentLineBeginning; + qCDebug(KDEV_PYTHON_PARSER) << "indent at error <> current indent:" << indentAtError << "<>" << currentIndent; // contents.remove(currentLineBeginning, currentLineBeginning_end-currentLineBeginning); break; } @@ -553,14 +551,14 @@ CodeAst::Ptr AstBuilder::parse(KUrl filename, QString &contents) } if ( c.isSpace() && atLineBeginning ) currentIndent += 1; } - kDebug() << "This is what is left: " << contents; + qCDebug(KDEV_PYTHON_PARSER) << "This is what is left: " << contents; syntaxtree = PyParser_ASTFromString(contents.toUtf8(), "", file_input, &flags, arena); } if ( ! syntaxtree ) { return CodeAst::Ptr(); // everything fails, so we abort. } } - kDebug() << "Got syntax tree from python parser:" << syntaxtree->kind << Module_kind; + qCDebug(KDEV_PYTHON_PARSER) << "Got syntax tree from python parser:" << syntaxtree->kind << Module_kind; PythonAstTransformer t(lineOffset); t.run(syntaxtree, filename.fileName().replace(".py", "")); diff --git a/parser/astbuilder.h b/parser/astbuilder.h index 21adc81d..86a15d4e 100644 --- a/parser/astbuilder.h +++ b/parser/astbuilder.h @@ -25,7 +25,6 @@ #include "ast.h" #include "parserexport.h" -#include #include #include "astdefaultvisitor.h" diff --git a/parser/astdefaultvisitor.cpp b/parser/astdefaultvisitor.cpp index 63b01c45..94355e53 100644 --- a/parser/astdefaultvisitor.cpp +++ b/parser/astdefaultvisitor.cpp @@ -22,7 +22,6 @@ #include "astdefaultvisitor.h" #include "ast.h" -#include namespace Python { diff --git a/parser/codehelpers.cpp b/parser/codehelpers.cpp index f9be2954..4b11dbfd 100644 --- a/parser/codehelpers.cpp +++ b/parser/codehelpers.cpp @@ -109,7 +109,7 @@ CodeHelpers::EndLocation CodeHelpers::endsInside(const QString &code) stringDelimiters << "\"\"\"" << "\'\'\'" << "'" << "\""; QStack stringStack; const int max_len = code.length(); - kDebug() << "Checking for comment line:" << code; + qDebug() << "Checking for comment line:" << code; for ( int atChar = 0; atChar < max_len; atChar++ ) { const QChar c = code.at(atChar); if ( c == ' ' || c.isLetterOrNumber() ) { @@ -208,7 +208,7 @@ QString CodeHelpers::expressionUnderCursor(Python::LazyLineFetcher& lineFetcher, while ( start >= 0 ) { QChar c = line[start]; int bracket = closingBrackets.indexOf(c); - kDebug() << bracket << c; + qDebug() << bracket << c; if ( ! brackets.isEmpty() && brackets.top() == c ) { brackets.pop(); } @@ -265,13 +265,13 @@ QString CodeHelpers::expressionUnderCursor(Python::LazyLineFetcher& lineFetcher, linePart = QString(); } else { - kDebug() << line << start << end << end-start << line.length(); + qDebug() << line << start << end << end-start << line.length(); linePart = line.mid(start, end-start + 1); } QString expression(linePart + text); expression = expression.trimmed(); - kDebug() << "expression found:" << expression; + qDebug() << "expression found:" << expression; return expression; } @@ -296,7 +296,7 @@ QString CodeHelpers::extractStringUnderCursor(const QString &code, KTextEditor:: while ( start >= 0 ) { QChar c = beforeAndAfter.first.at(start); int quote = quoteCharacters.indexOf(c); -// kDebug() << quote << c; +// qDebug() << quote << c; // if we've found a quote character and we're either at the beginning of the code or the previous char is not a backslash if ( quote != -1 && (start == 0 || (start != 0 && beforeAndAfter.first.at(start - 1) != '\\')) ) { @@ -337,7 +337,7 @@ QString CodeHelpers::extractStringUnderCursor(const QString &code, KTextEditor:: *cursorPositionInString = beforeAndAfter.first.size() - start; } - kDebug() << "string found:" << string; + qDebug() << "string found:" << string; return string; } diff --git a/parser/codehelpers.h b/parser/codehelpers.h index 414eef44..1ee7ac1d 100644 --- a/parser/codehelpers.h +++ b/parser/codehelpers.h @@ -20,6 +20,7 @@ #ifndef CODEHELPERS_H #define CODEHELPERS_H #include +#include #include #include "parserexport.h" diff --git a/parser/conversionGenerator.py b/parser/conversionGenerator.py index 06fe43c3..e35c4fcc 100644 --- a/parser/conversionGenerator.py +++ b/parser/conversionGenerator.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +# Copyright 2014 by Sven Brauch +# License: GPL v2+ + # Transforms a conversion definition file (.sdef) into C++ code. To be copied over manually. :) # sdef example line: # RULE_FOR _stmt;KIND Expr_kind;ACTIONS create|ExpressionAst set|value->ExpressionAst,value;CODE;; diff --git a/parser/cythonsyntaxremover.cpp b/parser/cythonsyntaxremover.cpp index e9d8ce85..dd547586 100644 --- a/parser/cythonsyntaxremover.cpp +++ b/parser/cythonsyntaxremover.cpp @@ -23,7 +23,11 @@ #include "astdefaultvisitor.h" #include "codehelpers.h" #include -#include + +#include + +#include +#include "parserdebug.h" using namespace KDevelop; @@ -35,10 +39,11 @@ class CythonDeletionFixVisitor : public AstDefaultVisitor { public: CythonDeletionFixVisitor(const QVector& deletedRanges) : m_deletedRanges() { + for (const auto& del: deletedRanges) { // TODO: Multi-line deletes, handle them, possible? - if (del.range.start.line == del.range.end.line) { - m_deletedRanges[del.range.start.line].append(del.range); + if (del.range.start().line() == del.range.end().line()) { + m_deletedRanges[del.range.start().line()].append(del.range); } } // sort by column for faster access @@ -60,10 +65,10 @@ class CythonDeletionFixVisitor : public AstDefaultVisitor { return; } for (auto range: m_deletedRanges[name->startLine]) { - if (name->startCol >= range.start.column) { - name->startCol += range.end.column-range.start.column; + if (name->startCol >= range.start().column()) { + name->startCol += range.end().column() - range.start().column(); if (name->startLine == name->endLine) { - name->endCol += range.end.column-range.start.column; + name->endCol += range.end().column() - range.start().column(); } } else { @@ -75,7 +80,7 @@ class CythonDeletionFixVisitor : public AstDefaultVisitor { private: // Key is the line number of the ranges to delete. - QMap> m_deletedRanges; + QMap> m_deletedRanges; }; @@ -92,10 +97,10 @@ QString CythonSyntaxRemover::stripCythonSyntax(const QString& code) // Check every line quickly for hints that Cython syntax // is used and then find the correct replacement via // regular expressions. - for (m_offset.column = m_offset.line = 0; - m_offset.line < m_code.length(); - m_offset.line++, m_offset.column = 0) { - QString& line = m_code[m_offset.line]; + for (m_offset.setPosition(0, 0); + m_offset.line() < m_code.length(); + m_offset.setLine(m_offset.line()+1), m_offset.setColumn(0)) { + QString& line = m_code[m_offset.line()]; if (fixFunctionDefinitions(line)) continue; if (fixExtensionClasses(line)) continue; if (fixVariableTypes(line)) continue; @@ -125,41 +130,41 @@ bool CythonSyntaxRemover::fixFunctionDefinitions(QString& line) // a class definition for a derived class. return false; } - kDebug() << "Function, replace" << definition + qCDebug(KDEV_PYTHON_PARSER) << "Function, replace" << definition << "and remove return type: " << returnType; // from the beginning of the argument list (open paren), // replace type specifiers (if available). - m_offset.column = wholeMatch.length(); - kDebug() << "Regex ended at offset" << m_offset; + m_offset.setColumn(wholeMatch.length()); + qCDebug(KDEV_PYTHON_PARSER) << "Regex ended at offset" << m_offset; auto types = getArgumentListTypes(); for (int i = types.size()-1; i >= 0; i--) { auto range = types[i]; - kDebug() << "Replace" << range.start.line << ":" << range.start.column << " to " << range.end.line << ":" << range.end.column << m_code[range.start.line].mid(range.start.column, range.end.column - range.start.column); - QString white = QString(" ").repeated(range.end.column - range.start.column); - m_code[range.start.line].replace(range.start.column, white.length(), white); + qCDebug(KDEV_PYTHON_PARSER) << "Replace" << range.start().line() << ":" << range.start().column() << " to " << range.end().line() << ":" << range.end().column() << m_code[range.start().line()].mid(range.start().column(), range.end().column() - range.start().column()); + QString white = QString(" ").repeated(range.end().column() - range.start().column()); + m_code[range.start().line()].replace(range.start().column(), white.length(), white); } // Find range of syntax for return values in case an exception occurs // Syntax: "cdef foo(bar) except (EXPRESSION,*):" - SimpleCursor start = m_offset; - while (m_code[m_offset.line][m_offset.column] != ':') { - m_offset.column++; - if (m_offset.column >= m_code[m_offset.line].length()) { - m_offset.line++; - m_offset.column = 0; - if(m_offset.line >= m_code.length()) { - m_offset.line = m_code.length() - 1; - m_offset.column = m_code[m_offset.line].length() - 1; + auto start = m_offset; + while (m_code[m_offset.line()][m_offset.column()] != ':') { + m_offset.setColumn(m_offset.column() + 1); + if (m_offset.column() >= m_code.at(m_offset.line()).length()) { + m_offset.setLine(m_offset.line()+1); + m_offset.setColumn(0); + if(m_offset.line() >= m_code.length()) { + m_offset.setLine(m_code.length() - 1); + m_offset.setColumn(m_code[m_offset.line()].length() - 1); break; } } } // replace the exception definition - if (start.line == m_offset.line && start.column < m_offset.column) { - auto exceptionDefLen = m_offset.column-start.column; - auto exceptionDef = m_code[m_offset.line].mid(start.column, exceptionDefLen); + if (start.line() == m_offset.line() && start.column() < m_offset.column()) { + auto exceptionDefLen = m_offset.column() - start.column(); + auto exceptionDef = m_code.at(m_offset.line()).mid(start.column(), exceptionDefLen); if(exceptionDef.indexOf(QString("except")) != -1) { - m_deletions.append(DeletedCode{exceptionDef, SimpleRange(start, m_offset)}); - m_code[start.line].remove(start.column, exceptionDefLen); + m_deletions.append(DeletedCode{exceptionDef, {start, m_offset}}); + m_code[start.line()].remove(start.column(), exceptionDefLen); } else { // probably the closing ":" was not typed yet, recover m_offset @@ -167,20 +172,20 @@ bool CythonSyntaxRemover::fixFunctionDefinitions(QString& line) } } // replace multiline expression... - else if (start.line < m_offset.line) { + else if (start.line() < m_offset.line()) { auto pos = start; QString exceptionDef; bool foundExceptKeyword = false; - for (; pos.line < m_offset.line && pos.line < m_code.length(); pos.line++, pos.column = 0) { - QString& curLine = m_code[pos.line]; - exceptionDef.append(curLine.mid(pos.column, curLine.length()-pos.column)); + for (; pos.line() < m_offset.line() && pos.line() < m_code.length(); pos.setLine(pos.line()+1), pos.setColumn(0)) { + QString& curLine = m_code[pos.line()]; + exceptionDef.append(curLine.mid(pos.column(), curLine.length() - pos.column())); // replace with ":" if there is an offset to start of line. This is the // case for the first line - kDebug() << "foundExceptKeyword?" << foundExceptKeyword << "curLine.indexOf(\"except\")" << curLine.indexOf("except"); + qCDebug(KDEV_PYTHON_PARSER) << "foundExceptKeyword?" << foundExceptKeyword << "curLine.indexOf(\"except\")" << curLine.indexOf("except"); if(foundExceptKeyword || curLine.indexOf("except") != -1) { foundExceptKeyword = true; - curLine.replace(pos.column, curLine.length()-pos.column, - pos.column ? QString(":") : QString()); + curLine.replace(pos.column(), curLine.length() - pos.column(), + pos.column() ? QStringLiteral(":") : QString()); } else { // first line of "exception def" did not contain except @@ -191,27 +196,27 @@ bool CythonSyntaxRemover::fixFunctionDefinitions(QString& line) } } if(foundExceptKeyword) { - QString& curLine = m_code[m_offset.line]; + QString& curLine = m_code[m_offset.line()]; // remove one more char than offset points to, we don't want to keep // the : in the multiline case - m_offset.column++; - exceptionDef.append(curLine.mid(0, m_offset.column)); - curLine.remove(0, m_offset.column); - m_deletions.append(DeletedCode{exceptionDef, SimpleRange(start, m_offset)}); + m_offset.setColumn(m_offset.column() + 1); + exceptionDef.append(curLine.mid(0, m_offset.column())); + curLine.remove(0, m_offset.column()); + m_deletions.append(DeletedCode{exceptionDef, {start, m_offset}}); } } // if a return type was specified, delete it from code if (returnTypePos != -1) { - SimpleRange delrange(start.line, returnTypePos, - start.line, returnTypePos + returnType.length()); + auto delrange = KTextEditor::Range(start.line(), returnTypePos, + start.line(), returnTypePos + returnType.length()); m_deletions.append(DeletedCode{returnType, delrange}); line.remove(returnTypePos, returnType.length()); } // if the keyword is not def (but cdef, cpdef ...), replace it if (definition != QString("def")) { - SimpleRange delrange(start.line, definitionPos, - start.line, definitionPos + definition.length()-3); + auto delrange = KTextEditor::Range(start.line(), definitionPos, + start.line(), definitionPos + definition.length()-3); m_deletions.append(DeletedCode{definition, delrange}); line.replace(definitionPos, definition.length(), @@ -231,9 +236,9 @@ bool CythonSyntaxRemover::fixExtensionClasses(QString& line) if (regexp_cdef_class.indexIn(line) != -1) { auto definition = regexp_cdef_class.cap(1); auto definition_pos = regexp_cdef_class.pos(1); - kDebug() << "Extension class, remove " << definition; - SimpleRange delrange(m_offset.line, definition_pos, - m_offset.line, definition_pos+definition.length()); + qCDebug(KDEV_PYTHON_PARSER) << "Extension class, remove " << definition; + auto delrange = KTextEditor::Range(m_offset.line(), definition_pos, + m_offset.line(), definition_pos+definition.length()); m_deletions.append(DeletedCode{regexp_cdef_class.cap(1), delrange}); line.remove(definition_pos, definition.length()); @@ -252,9 +257,9 @@ bool CythonSyntaxRemover::fixVariableTypes(QString& line) // cdef TYPE Var1=0, Var2=4 static QRegExp regexp_cdef_variable("^(\\s*)cdef\\s+[\\.a-zA-Z0-9_]+(\\[[^\\]]+\\])?\\s*\\**\\s*[a-zA-Z0-9_]+\\s*(,\\s*[a-zA-Z0-9_]+\\s*)*"); if (regexp_cdef_variable.indexIn(line) != -1) { - kDebug() << "Variable cdef -> pass"; - SimpleRange delrange(m_offset.line, 0, - m_offset.line, line.length()-regexp_cdef_variable.cap(1).length()-4); + qCDebug(KDEV_PYTHON_PARSER) << "Variable cdef -> pass"; + auto delrange = KTextEditor::Range(m_offset.line(), 0, + m_offset.line(), line.length()-regexp_cdef_variable.cap(1).length()-4); m_deletions.append(DeletedCode{line, delrange}); line = regexp_cdef_variable.cap(1); line += QString("pass"); @@ -272,9 +277,9 @@ bool CythonSyntaxRemover::fixCimports(QString& line) regexp_cimport_a.setMinimal(true); if (regexp_cimport_a.indexIn(line) != -1 || regexp_cimport_b.indexIn(line) != -1) { - SimpleRange delrange(m_offset.line, 0, m_offset.line, line.length()); + auto delrange = KTextEditor::Range(m_offset.line(), 0, m_offset.line(), line.length()); m_deletions.append(DeletedCode{line, delrange}); - line = QString(); + line.clear(); return true; } return false; @@ -292,17 +297,17 @@ bool CythonSyntaxRemover::fixCtypedefs(QString& line) regexp_ctypedef.cap(1).length()); auto typeDef = regexp_ctypedef.cap(1); auto typeDefPos = regexp_ctypedef.pos(1); - SimpleRange delrange(m_offset.line, typeDefPos, - m_offset.line, regexp_ctypedef.pos(1) + typeDef.length()); + auto delrange = KTextEditor::Range(m_offset.line(), typeDefPos, + m_offset.line(), regexp_ctypedef.pos(1) + typeDef.length()); m_deletions.append(DeletedCode{typeDef, delrange}); return true; } return false; } -QVector CythonSyntaxRemover::getArgumentListTypes() +QVector CythonSyntaxRemover::getArgumentListTypes() { - QVector type_specifiers; + QVector type_specifiers; auto token_list(getArgumentListTokens()); // if there are consecutive IDs, the first ID is the type specifier for (int i = 0; i < token_list.size()-1; i++) { @@ -314,51 +319,54 @@ QVector CythonSyntaxRemover::getArgumentListTypes() return type_specifiers; } -QVector< CythonSyntaxRemover::Token > CythonSyntaxRemover::getArgumentListTokens() +QVector CythonSyntaxRemover::getArgumentListTokens() { - SimpleRange range(m_offset, m_offset); + auto range = KTextEditor::Range(m_offset, m_offset); QVector token_list; bool stop_tokenizer = false; while (!stop_tokenizer) { // did we reach end of line? // continue to next line until we hit non-empty line - while (m_offset.column >= m_code[m_offset.line].length()) { - if (m_offset.line >= m_code.length()-1) + while (m_offset.column() >= m_code[m_offset.line()].length()) { + if (m_offset.line() >= m_code.length()-1) { break; - m_offset.column = 0; - m_offset.line++; - range.start = m_offset; - range.end = m_offset; + } + m_offset.setColumn(0); + m_offset.setLine(m_offset.line() + 1); + range.setStart(m_offset); + range.setEnd(m_offset); } - QChar c = m_code[m_offset.line][m_offset.column++]; + QChar c = m_code.at(m_offset.line()).at(m_offset.column()); + m_offset.setColumn(m_offset.column() + 1); if (c.isSpace()) { - range.start = m_offset; - range.end = m_offset; + range.setStart(m_offset); + range.setEnd(m_offset); } else if (c == '=') { - range.end.column++; + range.setEnd(range.end() + KTextEditor::Cursor(0, 1)); int open_paren_count = 0; bool in_string = false; // while there are open parenthesis or if we are in // string mode and the current character does not terminate // the token, consume! - c = m_code[m_offset.line][m_offset.column++]; + c = m_code.at(m_offset.line()).at(m_offset.column()); + m_offset.setColumn(m_offset.column() + 1); while (open_paren_count > 0 || in_string || !(c == ',' || c == ')')) { - if (m_offset.column >= m_code[m_offset.line].length()) { - if (m_offset.line >= m_code.length()) { - m_offset.column--; + if (m_offset.column() >= m_code.at(m_offset.line()).length()) { + if (m_offset.line() >= m_code.length()) { + m_offset.setColumn(m_offset.column() - 1); break; } - m_offset.line++; - m_offset.column = 0; + m_offset.setLine(m_offset.line() + 1); + m_offset.setColumn(0); } - range.end = m_offset; + range.setEnd(m_offset); // TODO: Support for """ """ multiline strings. // Maybe implicitly contained? if (c == '"') { - if (in_string && m_offset.column >= 2) - in_string = (m_code[m_offset.line][m_offset.column-2] == '\\'); + if (in_string && m_offset.column() >= 2) + in_string = (m_code.at(m_offset.line()).at(m_offset.column()-2) == '\\'); else in_string = !in_string; } @@ -366,43 +374,48 @@ QVector< CythonSyntaxRemover::Token > CythonSyntaxRemover::getArgumentListTokens open_paren_count++; else if (!in_string && c == ')') open_paren_count--; - c = m_code[m_offset.line][m_offset.column++]; + c = m_code.at(m_offset.line()).at(m_offset.column()); + m_offset.setColumn(m_offset.column() + 1); } - m_offset.column--; - range.end = m_offset; + m_offset.setColumn(m_offset.column() - 1); + range.setEnd(m_offset); token_list.append({TOKEN_DEFAULT_ARGUMENT, range}); - range.start = range.end; + range.setStart(range.end()); } else if (c == ',') { - range.end = m_offset; + range.setEnd(m_offset); token_list.append({TOKEN_COMMA, range}); - range.start = range.end; + range.setStart(range.end()); } else if (c == ')') { stop_tokenizer = true; - range.end = m_offset; + range.setEnd(m_offset); token_list.append({TOKEN_END, range}); - range.start = range.end; + range.setStart(range.end()); } else { int open_bracket_count = 0; - c = m_code[m_offset.line][m_offset.column++]; + c = m_code.at(m_offset.line()).at(m_offset.column()); + m_offset.setColumn(m_offset.column()+1); // stop consuming the input if there are no closing // square brackets left and the current character is // whitespace, =, ,, ) or the end of line. while ((!c.isSpace() - && m_offset.column < m_code[m_offset.line].length() + && m_offset.column() < m_code.at(m_offset.line()).length() && c != ')' && c != ',' && c != '=') || open_bracket_count > 0) { - if (c == '[') + if (c == '[') { open_bracket_count++; - else if (c == ']') + } + else if (c == ']') { open_bracket_count--; - c = m_code[m_offset.line][m_offset.column++]; + } + c = m_code.at(m_offset.line()).at(m_offset.column()); + m_offset.setColumn(m_offset.column() + 1); } - m_offset.column--; - range.end = m_offset; + m_offset.setColumn(m_offset.column() - 1); + range.setEnd(m_offset); token_list.append({TOKEN_ID, range}); - range.start = range.end; + range.setStart(range.end()); } } return token_list; diff --git a/parser/cythonsyntaxremover.h b/parser/cythonsyntaxremover.h index 4183f385..b0369829 100644 --- a/parser/cythonsyntaxremover.h +++ b/parser/cythonsyntaxremover.h @@ -26,8 +26,7 @@ #include "parserexport.h" #include #include -#include - +#include namespace Python { @@ -50,12 +49,12 @@ class KDEVPYTHONPARSER_EXPORT CythonSyntaxRemover { struct Token { TOKEN_TYPE type; - KDevelop::SimpleRange range; + KTextEditor::Range range; }; struct DeletedCode { QString code; - KDevelop::SimpleRange range; + KTextEditor::Range range; }; QString stripCythonSyntax(const QString& code); @@ -68,12 +67,12 @@ class KDEVPYTHONPARSER_EXPORT CythonSyntaxRemover { bool fixCimports(QString& line); bool fixCtypedefs(QString& line); - QVector getArgumentListTypes(); + QVector getArgumentListTypes(); QVector getArgumentListTokens(); QStringList m_code; QString m_strippedCode; - KDevelop::SimpleCursor m_offset; + KTextEditor::Cursor m_offset; QVector m_deletions; }; diff --git a/parser/generated.h b/parser/generated.h index 128d2b18..bc3a31f7 100644 --- a/parser/generated.h +++ b/parser/generated.h @@ -251,7 +251,7 @@ class PythonAstTransformer { break; } default: - kWarning() << "Unsupported statement AST type: " << node->kind; + qCWarning(KDEV_PYTHON_PARSER) << "Unsupported statement AST type: " << node->kind; Q_ASSERT(false); } @@ -315,7 +315,7 @@ class PythonAstTransformer { break; } default: - kWarning() << "Unsupported statement AST type: " << node->kind; + qCWarning(KDEV_PYTHON_PARSER) << "Unsupported statement AST type: " << node->kind; Q_ASSERT(false); } @@ -574,7 +574,7 @@ class PythonAstTransformer { break; } default: - kWarning() << "Unsupported statement AST type: " << node->kind; + qCWarning(KDEV_PYTHON_PARSER) << "Unsupported statement AST type: " << node->kind; Q_ASSERT(false); } @@ -643,7 +643,7 @@ class PythonAstTransformer { break; } default: - kWarning() << "Unsupported statement AST type: " << node->kind; + qCWarning(KDEV_PYTHON_PARSER) << "Unsupported statement AST type: " << node->kind; Q_ASSERT(false); } diff --git a/parser/parserdebug.cpp b/parser/parserdebug.cpp new file mode 100644 index 00000000..429fca3d --- /dev/null +++ b/parser/parserdebug.cpp @@ -0,0 +1,23 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "parserdebug.h" +Q_LOGGING_CATEGORY(KDEV_PYTHON_PARSER, "kdev.python.parser") + + diff --git a/parser/parserdebug.h b/parser/parserdebug.h new file mode 100644 index 00000000..13839069 --- /dev/null +++ b/parser/parserdebug.h @@ -0,0 +1,27 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef PARSERDEBUG_H +#define PARSERDEBUG_H + +#include +Q_DECLARE_LOGGING_CATEGORY(KDEV_PYTHON_PARSER) + +#endif + diff --git a/parser/parserexport.h b/parser/parserexport.h deleted file mode 100644 index 12b139a3..00000000 --- a/parser/parserexport.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * This file is part of KDevelop * - * Copyright 2007 Andreas Pakulat * - * Copyright 2006 Matt Rogers * - * Copyright 2004 Jaroslaw Staniek * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU Library General Public License as * - * published by the Free Software Foundation; either version 2 of the * - * License, or (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - ***************************************************************************/ - -#ifndef PARSEREXPORT_H -#define PARSEREXPORT_H - -/* needed for KDE_EXPORT macros */ -#include - - -#ifndef KDEVPYTHONPARSER_EXPORT -# ifdef MAKE_KDEV4PYTHONPARSER_LIB -# define KDEVPYTHONPARSER_EXPORT KDE_EXPORT -# else -# define KDEVPYTHONPARSER_EXPORT KDE_IMPORT -# endif -#endif - -#endif - -//kate: space-indent on; indent-width 4; replace-tabs on; auto-insert-doxygen on; indent-mode cstyle; diff --git a/parser/parsesession.cpp b/parser/parsesession.cpp index 12615762..2ab9418d 100644 --- a/parser/parsesession.cpp +++ b/parser/parsesession.cpp @@ -18,12 +18,11 @@ ***************************************************************************** */ #include "parsesession.h" - -#include -#include - #include "astbuilder.h" +#include +#include "parserdebug.h" + using namespace KDevelop; namespace Python @@ -81,11 +80,11 @@ QPair ParseSession::parse() if( matched.second ) { - kDebug() << "Sucessfully parsed"; + qCDebug(KDEV_PYTHON_PARSER) << "Sucessfully parsed"; }else { matched.first.clear(); - kDebug() << "Couldn't parse content"; + qCDebug(KDEV_PYTHON_PARSER) << "Couldn't parse content"; } return matched; } diff --git a/parser/parsesession.h b/parser/parsesession.h index d5afae61..f6cd75df 100644 --- a/parser/parsesession.h +++ b/parser/parsesession.h @@ -20,10 +20,8 @@ #define PYTHON_PARSESESSION_H #include #include "parserexport.h" -#include #include #include -#include #include #include "ast.h" #include "kurl.h" diff --git a/parser/tests/CMakeLists.txt b/parser/tests/CMakeLists.txt index 7b24f98f..c47cfb2b 100644 --- a/parser/tests/CMakeLists.txt +++ b/parser/tests/CMakeLists.txt @@ -1,5 +1,11 @@ -kde4_add_unit_test(pyasttest pyasttest.cpp) -target_link_libraries(pyasttest kdev4pythonparser ${QT_QTTEST_LIBRARY} ${KDEVPLATFORM_TESTS_LIBRARIES}) +set(pyasttest_SRCS pyasttest.cpp ../parserdebug.cpp) -kde4_add_unit_test(pycythontest pycythontest.cpp) -target_link_libraries(pycythontest kdev4pythonparser ${QT_QTTEST_LIBRARY} ${KDEVPLATFORM_TESTS_LIBRARIES}) \ No newline at end of file +include_directories(${CMAKE_BINARY_DIR}/duchain) +ecm_add_test(${pyasttest_SRCS} + TEST_NAME pyasttest + LINK_LIBRARIES kdev4pythonparser Qt5::Test KDev::Tests KF5::KDELibs4Support) + +set(pycythontest_SRCS pycythontest.cpp ../parserdebug.cpp) +ecm_add_test(${pycythontest_SRCS} + TEST_NAME pycythontest + LINK_LIBRARIES kdev4pythonparser Qt5::Test KDev::Tests KF5::KDELibs4Support) diff --git a/parser/tests/pyasttest.cpp b/parser/tests/pyasttest.cpp index f8929f8e..578ac75e 100644 --- a/parser/tests/pyasttest.cpp +++ b/parser/tests/pyasttest.cpp @@ -4,7 +4,7 @@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -40,6 +39,9 @@ #include "pyasttest.h" #include "../astbuilder.h" +#include +#include "../parserdebug.h" + using namespace Python; QTEST_MAIN(PyAstTest) @@ -211,12 +213,12 @@ void PyAstTest::testExpressions_data() QTest::newRow("True") << "True"; } -Q_DECLARE_METATYPE(SimpleRange); +Q_DECLARE_METATYPE(KTextEditor::Range); void PyAstTest::testCorrectedFuncRanges() { QFETCH(QString, code); - QFETCH(SimpleRange, range); + QFETCH(KTextEditor::Range, range); CodeAst::Ptr ast = getAst(code); QVERIFY(ast); @@ -226,7 +228,7 @@ void PyAstTest::testCorrectedFuncRanges() } FunctionDefinitionAst* func = static_cast(node); QVERIFY(func->name); - kDebug() << func->name->range() << range; + qCDebug(KDEV_PYTHON_PARSER) << func->name->range() << range; QCOMPARE(func->name->range(), range); } } @@ -234,12 +236,12 @@ void PyAstTest::testCorrectedFuncRanges() void PyAstTest::testCorrectedFuncRanges_data() { QTest::addColumn("code"); - QTest::addColumn("range"); + QTest::addColumn("range"); - QTest::newRow("decorator") << "@decorate\ndef func(arg): pass" << SimpleRange(1, 4, 1, 7); - QTest::newRow("decorator_arg") << "@decorate(yomama=3)\ndef func(arg): pass" << SimpleRange(1, 4, 1, 7); - QTest::newRow("two_decorators") << "@decorate2\n@decorate\ndef func(arg): pass" << SimpleRange(2, 4, 2, 7); - QTest::newRow("decorate_class") << "class foo:\n @decorate2\n @decorate\n def func(arg): pass" << SimpleRange(3, 5, 3, 8); + QTest::newRow("decorator") << "@decorate\ndef func(arg): pass" << KTextEditor::Range(1, 4, 1, 7); + QTest::newRow("decorator_arg") << "@decorate(yomama=3)\ndef func(arg): pass" << KTextEditor::Range(1, 4, 1, 7); + QTest::newRow("two_decorators") << "@decorate2\n@decorate\ndef func(arg): pass" << KTextEditor::Range(2, 4, 2, 7); + QTest::newRow("decorate_class") << "class foo:\n @decorate2\n @decorate\n def func(arg): pass" << KTextEditor::Range(3, 5, 3, 8); } void PyAstTest::testNewPython3() diff --git a/parser/tests/pyasttest.h b/parser/tests/pyasttest.h index 560d5b5a..a7cf5c9c 100644 --- a/parser/tests/pyasttest.h +++ b/parser/tests/pyasttest.h @@ -4,7 +4,7 @@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, diff --git a/parser/tests/pycythontest.cpp b/parser/tests/pycythontest.cpp index ea83a8bd..dd0e2218 100644 --- a/parser/tests/pycythontest.cpp +++ b/parser/tests/pycythontest.cpp @@ -4,7 +4,7 @@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -18,12 +18,10 @@ #include #include -#include #include #include #include #include -#include #include #include "pythoneditorintegrator.h" @@ -34,10 +32,13 @@ #include "../cythonsyntaxremover.h" #include "../astbuilder.h" +#include +#include "../parserdebug.h" + using namespace Python; QTEST_MAIN(PyCythonTest) -Q_DECLARE_METATYPE(KDevelop::SimpleRange); +Q_DECLARE_METATYPE(KTextEditor::Range); PyCythonTest::PyCythonTest(QObject* parent): QObject(parent) { @@ -132,7 +133,7 @@ void PyCythonTest::testCythonReplacement_data() void PyCythonTest::testCythonRanges() { QFETCH(QString, code); - QFETCH(SimpleRange, range); + QFETCH(KTextEditor::Range, range); CodeAst::Ptr ast = getAst(code, KUrl("test.pyx")); QVERIFY(ast); @@ -142,7 +143,7 @@ void PyCythonTest::testCythonRanges() { } FunctionDefinitionAst* func = static_cast(node); QVERIFY(func->name); - kDebug() << func->name->range() << range; + qCDebug(KDEV_PYTHON_PARSER) << func->name->range() << range; QCOMPARE(func->name->range(), range); } } @@ -150,11 +151,11 @@ void PyCythonTest::testCythonRanges() { void PyCythonTest::testCythonRanges_data() { QTest::addColumn("code"); - QTest::addColumn("range"); + QTest::addColumn("range"); - QTest::newRow("cdef") << "cdef foobar(arg): pass" << SimpleRange(0, 5, 0, 10); - QTest::newRow("cdef_return") << "cdef float* foobar(arg): pass" << SimpleRange(0, 12, 0, 17); - QTest::newRow("normal_def") << "def foobar(arg): pass" << SimpleRange(0, 4, 0, 9); + QTest::newRow("cdef") << "cdef foobar(arg): pass" << KTextEditor::Range(0, 5, 0, 10); + QTest::newRow("cdef_return") << "cdef float* foobar(arg): pass" << KTextEditor::Range(0, 12, 0, 17); + QTest::newRow("normal_def") << "def foobar(arg): pass" << KTextEditor::Range(0, 4, 0, 9); } diff --git a/parser/tests/pycythontest.h b/parser/tests/pycythontest.h index 5bb46ae0..3ebb6b2a 100644 --- a/parser/tests/pycythontest.h +++ b/parser/tests/pycythontest.h @@ -5,7 +5,7 @@ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or + the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -24,6 +24,8 @@ #include #include "ast.h" +#include + namespace KDevelop { class TopDUContext; class ReferencedTopDUContext; diff --git a/pep8kcm/CMakeLists.txt b/pep8kcm/CMakeLists.txt index cc438845..807a7509 100644 --- a/pep8kcm/CMakeLists.txt +++ b/pep8kcm/CMakeLists.txt @@ -2,16 +2,16 @@ set(kcm_pep8_SRCS kcm_pep8.cpp ) -kde4_add_plugin(kcm_pep8 ${kcm_pep8_SRCS}) +add_library(kcm_pep8 MODULE ${kcm_pep8_SRCS}) target_link_libraries(kcm_pep8 - ${KDE4_KIO_LIBS} - ${KDEVPLATFORM_INTERFACES_LIBRARIES} - ${KDEVPLATFORM_LANGUAGE_LIBRARIES} - ${KDEVPLATFORM_PROJECT_LIBRARIES} - ${KDEVPLATFORM_UTIL_LIBRARIES} - ${KDE4_KNEWSTUFF3_LIBS} - ${KDEVPLATFORM_INTERFACES_LIBRARIES} + KF5::KIOCore + KDev::Interfaces + KDev::Language + KDev::Project + KDev::Util + KF5::NewStuff + KF5::KCMUtils ) install(TARGETS kcm_pep8 diff --git a/pep8kcm/kcm_kdevpythonpep8.desktop b/pep8kcm/kcm_kdevpythonpep8.desktop index cd5b6ff1..4910577f 100644 --- a/pep8kcm/kcm_kdevpythonpep8.desktop +++ b/pep8kcm/kcm_kdevpythonpep8.desktop @@ -16,6 +16,7 @@ Name[ca@valencia]=Comprovació de l'estil de Python Name[da]=Python stiltjek Name[de]=Python-Stilüberprüfung Name[el]=Έλεγχος στιλ Python +Name[en_GB]=Python style checking Name[es]=Comprobación del estilo de Python Name[fi]=Pythonin tyylin tarkistus Name[fr]=Contrôle de styles de Python @@ -23,6 +24,7 @@ Name[gl]=Comprobación do estilo de Python Name[hu]=Python stílus ellenőrzés Name[it]=Controllo stile Python Name[kk]=Python стилін тексеру +Name[ko]=파이썬 문법 검사 Name[mr]=पायथोन शैली तपासणी Name[nb]=Sjekk Python-stil Name[nl]=Controleren in de stijl van Python diff --git a/pep8kcm/kcm_pep8.cpp b/pep8kcm/kcm_pep8.cpp index 71a23a3e..16ba0c2e 100644 --- a/pep8kcm/kcm_pep8.cpp +++ b/pep8kcm/kcm_pep8.cpp @@ -24,16 +24,14 @@ #include #include #include -#include -#include #include +#include -K_PLUGIN_FACTORY(PEP8KCModuleFactory, registerPlugin(); ) -K_EXPORT_PLUGIN(PEP8KCModuleFactory("kcm_pep8", "kdevpythonsupport")) +K_PLUGIN_FACTORY(PEP8KCModuleFactory, registerPlugin();) PEP8KCModule::PEP8KCModule(QWidget* parent, const QVariantList& args) - : KCModule(PEP8KCModuleFactory::componentData(), parent, args) + : KCModule(parent, args) { KConfig* config = new KConfig("kdevpythonsupportrc"); configGroup = config->group("pep8"); @@ -46,7 +44,7 @@ PEP8KCModule::PEP8KCModule(QWidget* parent, const QVariantList& args) QLabel* argumentlabel = new QLabel(i18n("PEP8 checker arguments:")); QLabel* enablelabel = new QLabel(i18n("Enable PEP8 checking:")); pep8url = new QLineEdit(configGroup.readEntry("pep8url", "/usr/bin/pep8-python2")); - pep8arguments = new QLineEdit(configGroup.readEntry("pap8arguments", "")); + pep8arguments = new QLineEdit(configGroup.readEntry("pep8arguments", "")); enableChecking = new QCheckBox; enableChecking->setChecked(configGroup.readEntry("pep8enabled", false)); formlayout->addRow(urllabel, pep8url); @@ -62,7 +60,7 @@ PEP8KCModule::PEP8KCModule(QWidget* parent, const QVariantList& args) void PEP8KCModule::save() { configGroup.writeEntry("pep8url", pep8url->text()); - configGroup.writeEntry("pap8arguments", pep8arguments->text()); + configGroup.writeEntry("pep8arguments", pep8arguments->text()); configGroup.writeEntry("pep8enabled", enableChecking->isChecked()); KCModule::save(); } @@ -72,3 +70,4 @@ PEP8KCModule::~PEP8KCModule() delete configGroup.config(); } +#include "kcm_pep8.moc" diff --git a/pep8kcm/kcm_pep8.h b/pep8kcm/kcm_pep8.h index e837d102..24d885ce 100644 --- a/pep8kcm/kcm_pep8.h +++ b/pep8kcm/kcm_pep8.h @@ -25,8 +25,11 @@ #include #include +#include + class PEP8KCModule : public KCModule { +Q_OBJECT public: PEP8KCModule( QWidget* parent, const QVariantList& args = QVariantList() ); virtual void save(); diff --git a/pythondebug.cpp b/pythondebug.cpp new file mode 100644 index 00000000..4c845f30 --- /dev/null +++ b/pythondebug.cpp @@ -0,0 +1,23 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "pythondebug.h" +Q_LOGGING_CATEGORY(KDEV_PYTHON, "kdev.python") + + diff --git a/pythondebug.h b/pythondebug.h new file mode 100644 index 00000000..5851dc46 --- /dev/null +++ b/pythondebug.h @@ -0,0 +1,27 @@ +/* This file is part of the KDE project + Copyright (C) 2014 Laurent Navet + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef PYTHONDEBUG_H +#define PYTHONDEBUG_H + +#include +Q_DECLARE_LOGGING_CATEGORY(KDEV_PYTHON) + +#endif + diff --git a/pythonlanguagesupport.cpp b/pythonlanguagesupport.cpp index d8a720f6..385b99a1 100644 --- a/pythonlanguagesupport.cpp +++ b/pythonlanguagesupport.cpp @@ -22,7 +22,6 @@ #include -#include #include #include #include @@ -55,6 +54,9 @@ #include "kdevpythonversion.h" #include "checks/basiccheck.h" +#include +#include "pythondebug.h" + using namespace KDevelop; K_PLUGIN_FACTORY( KDevPythonSupportFactory, registerPlugin(); ) @@ -83,7 +85,7 @@ KDevelop::ContextMenuExtension LanguageSupport::contextMenuExtension(KDevelop::C } LanguageSupport::LanguageSupport( QObject* parent, const QVariantList& /*args*/ ) - : KDevelop::IPlugin( KDevPythonSupportFactory::componentData(), parent ), + : KDevelop::IPlugin("pythonlanguagesupport", parent ), KDevelop::ILanguageSupport() { KDEV_USE_EXTENSION_INTERFACE( KDevelop::ILanguageSupport ) @@ -139,7 +141,7 @@ LanguageSupport* LanguageSupport::self() return m_self; } -bool LanguageSupport::enabledForFile(const KUrl& url) +bool LanguageSupport::enabledForFile(const QUrl& url) { // This is a bit more general than it would need to be, // but that way we can have the same code for both branches. @@ -191,7 +193,7 @@ SourceFormatterItemList LanguageSupport::sourceFormatterItems() const KDevelop::ILanguage *LanguageSupport::language() { - kDebug() << core()->languageController()->language( name() ); + qCDebug(KDEV_PYTHON) << core()->languageController()->language( name() ); return core()->languageController()->language( name() ); } diff --git a/pythonlanguagesupport.h b/pythonlanguagesupport.h index 0219612d..4d6f1eb1 100644 --- a/pythonlanguagesupport.h +++ b/pythonlanguagesupport.h @@ -73,7 +73,7 @@ class LanguageSupport virtual KDevelop::SourceFormatterItemList sourceFormatterItems() const; /// Tells whether this plugin is enabled for the given file. - static bool enabledForFile(const KUrl& url); + static bool enabledForFile(const QUrl& url); virtual QList providedChecks(); diff --git a/pythonparsejob.cpp b/pythonparsejob.cpp index dd449b9f..f09d381d 100644 --- a/pythonparsejob.cpp +++ b/pythonparsejob.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -55,7 +55,7 @@ #include #include #include -#include +#include #include #include @@ -81,7 +81,8 @@ CodeAst *ParseJob::ast() const return m_ast.data(); } -void ParseJob::run() + +void ParseJob::run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread) { if ( abortRequested() || ICore::self()->shuttingDown() ) { return abortJob(); @@ -157,7 +158,7 @@ void ParseJob::run() // check whether any unresolved imports were encountered bool needsReparse = ! builder.unresolvedImports().isEmpty(); - kDebug() << "Document needs update because of unresolved identifiers: " << needsReparse; + qDebug() << "Document needs update because of unresolved identifiers: " << needsReparse; if ( needsReparse ) { // check whether one of the imports is queued for parsing, this is to avoid deadlocks // it's also ok if the duchain is now available (and thus has been parsed before already) @@ -189,7 +190,7 @@ void ParseJob::run() DUChain::self()->updateContextEnvironment(m_duContext, parsingEnvironmentFile.data()); } - kDebug() << "---- Parsing Succeeded ----"; + qDebug() << "---- Parsing Succeeded ----"; if ( abortRequested() ) { return abortJob(); @@ -200,7 +201,7 @@ void ParseJob::run() } else { // No syntax tree was received from the parser, the expected reason for this is a syntax error in the document. - kWarning() << "---- Parsing FAILED ----"; + qWarning() << "---- Parsing FAILED ----"; DUChainWriteLocker lock; m_duContext = toUpdate.data(); // if there's already a chain for the document, do some cleanup. @@ -241,7 +242,7 @@ void ParseJob::run() if ( minimumFeatures() & TopDUContext::AST ) { DUChainWriteLocker lock; m_currentSession->ast = m_ast; - m_duContext->setAst(KSharedPtr::staticCast(m_currentSession)); + m_duContext->setAst(QExplicitlySharedDataPointer(m_currentSession.data())); } setDuChain(m_duContext); @@ -285,7 +286,7 @@ void ParseJob::eventuallyDoPEP8Checking(const IndexedString document, TopDUConte DUChainWriteLocker lock; topContext->setFeatures((TopDUContext::Features) ( topContext->features() | PEP8Checking )); } - kDebug() << "doing pep8 checking"; + qDebug() << "doing pep8 checking"; // TODO that's not very elegant, better would be making pep8 read from stdin -- but it doesn't support that atm QTemporaryFile tempfile; tempfile.open(); @@ -322,12 +323,12 @@ void ParseJob::eventuallyDoPEP8Checking(const IndexedString document, TopDUConte int lineno = texts.at(2).toInt(&lineno_ok); int colno = texts.at(3).toInt(&colno_ok); if ( ! lineno_ok || ! colno_ok ) { - kDebug() << "invalid line / col number:" << texts; + qDebug() << "invalid line / col number:" << texts; continue; } QString error = texts.at(4); KDevelop::Problem *p = new KDevelop::Problem(); - p->setFinalLocation(DocumentRange(document, SimpleRange(lineno - 1, qMax(colno - 4, 0), + p->setFinalLocation(DocumentRange(document, KTextEditor::Range(lineno - 1, qMax(colno - 4, 0), lineno - 1, colno + 4))); p->setSource(KDevelop::ProblemData::Preprocessor); p->setSeverity(KDevelop::ProblemData::Warning); @@ -336,14 +337,14 @@ void ParseJob::eventuallyDoPEP8Checking(const IndexedString document, TopDUConte topContext->addProblem(ptr); } else { - kDebug() << "invalid pep8 error line:" << error; + qDebug() << "invalid pep8 error line:" << error; } } } if ( error ) { DUChainWriteLocker lock; KDevelop::Problem *p = new KDevelop::Problem(); - p->setFinalLocation(DocumentRange(document, SimpleRange(0, 0, 0, 0))); + p->setFinalLocation(DocumentRange(document, KTextEditor::Range(0, 0, 0, 0))); p->setSource(KDevelop::ProblemData::Preprocessor); p->setSeverity(KDevelop::ProblemData::Warning); p->setDescription(i18n("The selected PEP8 syntax checker \"%1\" does not seem to work correctly.", url)); diff --git a/pythonparsejob.h b/pythonparsejob.h index 29ce2084..fa1b4a9a 100644 --- a/pythonparsejob.h +++ b/pythonparsejob.h @@ -60,7 +60,7 @@ class ParseJob : public KDevelop::ParseJob virtual DataAccessRepository* dataAccessInformation(); protected: - virtual void run(); + virtual void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread) override; private: CodeAst::Ptr m_ast; diff --git a/runtest.py b/runtest.py index 7498e92c..e9939919 100755 --- a/runtest.py +++ b/runtest.py @@ -1,6 +1,9 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +# Copyright 2014 by Sven Brauch +# License: GPL v2+ + import sys import subprocess