Commit 7ce49ae8 authored by Sven Brauch's avatar Sven Brauch

Determining ranges of attributes works for first-level ones now

It's still buggy for stuff like foo.bar.baz, but foo.bar works pretty
well already. Yay!
Also, things like bar("Hello.World").foo (sh|c)ould work, but are not tested
yet.
parent 0c18c228
......@@ -20,7 +20,10 @@ void FunctionDeclarationCompletionItem::executed(KTextEditor::Document* document
{
kDebug() << "FunctionDeclarationCompletionItem executed";
DUChainPointer<FunctionDeclaration> decl = declaration().dynamicCast<FunctionDeclaration>();
Q_ASSERT(decl.data());
if ( ! decl.data() ) {
kError() << "ERROR: could not get declaration data, not executing completion item!";
return;
}
kDebug() << "declaration data: " << decl.data();
const QString suffix = "()";
int skip = 2; // place cursor behind bracktes
......
......@@ -85,6 +85,8 @@ QList<CompletionTreeItemPointer> PythonCodeCompletionContext::completionItems(bo
return items;
}
currentDeclaration = DeclarationPointer(declarations.at(i).first);
// if ( currentDeclaration.data()->rangeInCurrentRevision().start > m_position.castToSimpleCursor() ) continue;
kDebug() << "Adding item: " << currentDeclaration.data()->identifier().identifier().str();
NormalDeclarationCompletionItem* item;
if ( currentDeclaration.data()->abstractType() && currentDeclaration.data()->abstractType().constData()->whichType() == AbstractType::TypeFunction ) {
......
......@@ -183,6 +183,11 @@ template<typename T> T* DeclarationBuilder::visitVariableDeclaration(Identifier*
return result;
}
void DeclarationBuilder::visitAttribute(AttributeAst* node)
{
DeclarationBuilderBase::visitAttribute(node);
}
void DeclarationBuilder::visitExceptionHandler(ExceptionHandlerAst* node)
{
if ( node->name ) visitVariableDeclaration<Declaration>(node->name); // except Error as <vardecl>
......
......@@ -57,6 +57,7 @@ protected:
virtual void visitArguments(ArgumentsAst* node);
virtual void visitExceptionHandler(ExceptionHandlerAst* node);
virtual void visitCall(CallAst* node);
virtual void visitAttribute(AttributeAst* node);
template<typename T> T* visitVariableDeclaration(Python::Ast* node);
template<typename T> T* visitVariableDeclaration(Identifier* node, Ast* originalAst = 0);
......
......@@ -34,6 +34,7 @@
#include <parsesession.h>
#include <usebuilder.h>
#include "ast.h"
#include <language/duchain/types/structuretype.h>
using namespace KTextEditor;
using namespace KDevelop;
......@@ -54,10 +55,16 @@ void UseBuilder::visitName(NameAst* node)
{
DUChainWriteLocker lock(DUChain::lock());
QList<Declaration*> declarations = currentContext()->findDeclarations(identifierForNode(node->identifier), editorFindRange(node, node).start);
QList<Declaration*> localDeclarations = currentContext()->findLocalDeclarations(identifierForNode(node->identifier).last(), editorFindRange(node, node).end, currentContext()->topContext());
QList<Declaration*> localDeclarations = currentContext()->findLocalDeclarations(identifierForNode(node->identifier).last(), editorFindRange(node, node).end);
Declaration* declaration;
if ( localDeclarations.length() ) declaration = localDeclarations.last();
else if ( declarations.length() ) declaration = declarations.last();
if ( localDeclarations.length() ) {
declaration = localDeclarations.last();
kDebug() << "Using local declaration";
}
else if ( declarations.length() ) {
declaration = declarations.last();
kDebug() << "Using global declaration";
}
else declaration = 0;
kDebug() << currentContext()->type() << currentContext()->scopeIdentifier() << currentContext()->range().castToSimpleRange();
......@@ -71,6 +78,41 @@ void UseBuilder::visitName(NameAst* node)
UseBuilderBase::newUse(node, useRange, DeclarationPointer(declaration));
}
void UseBuilder::visitAttribute(AttributeAst* node)
{
kDebug() << "VisitAttribute start";
UseBuilderBase::visitAttribute(node);
kDebug() << "Visit Attribute base end";
NameAst* accessingAttributeOf = dynamic_cast<NameAst*>(node->value);
if ( ! accessingAttributeOf ) {
kWarning() << "Accessing attributes of non-names not implemented, aborting";
return;
}
QList<Declaration*> availableDeclarations = currentContext()->findDeclarations(identifierForNode(accessingAttributeOf->identifier), editorFindRange(node, node).start);
Declaration* accessingAttributeOfDeclaration;
if ( availableDeclarations.length() > 0 ) accessingAttributeOfDeclaration = availableDeclarations.last();
else {
kWarning() << "No declaration found to look up type of attribute in! This is probably something wrong in YOUR code. :)";
return; // TODO report error
}
TypePtr<StructureType> accessingAttributeOfType = accessingAttributeOfDeclaration->type<StructureType>();
DUContext* searchAttrInContext = accessingAttributeOfType.unsafeData()->declaration(currentContext()->topContext())->internalContext();
QList<Declaration*> foundDecls = searchAttrInContext->findDeclarations(identifierForNode(node->attribute), CursorInRevision::invalid(),
KDevelop::AbstractType::Ptr(), searchAttrInContext->topContext());
RangeInRevision useRange(node->attribute->startLine, node->attribute->startCol, node->attribute->endLine, node->attribute->endCol);
if ( foundDecls.length() > 0 ) {
kDebug() << "Creating a new attribute declaration:" << useRange.castToSimpleRange() << ", Declaration:" << foundDecls.last()->range();
UseBuilderBase::newUse(node, useRange, DeclarationPointer(foundDecls.last()));
}
else {
kWarning() << "No declaration found for attribute";
UseBuilderBase::newUse(node, useRange, DeclarationPointer(0));
}
kDebug() << "VisitAttribute end";
}
// void UseBuilder::openContext(DUContext * newContext)
// {
......
......@@ -50,6 +50,7 @@ public:
protected:
// virtual void visitIdentifier(Identifier* node);
virtual void visitName(NameAst* node);
virtual void visitAttribute(AttributeAst* node);
private:
ParseSession* m_session;
PythonEditorIntegrator* m_editor;
......
......@@ -9,7 +9,12 @@ def some_class(foo, bar):
some_instance = some_class()
some_instance.attr1
some_instance.attr2
some_instance.some_method()
some_instance.some_method().foobar
some_instance.some_method(some_arg, some_arg2).second_attribute
some_instance \
. attribute \
.funcfunc(argarg, arg2arg) \
.foo
#comment
"""
......
This diff is collapsed.
......@@ -64,3 +64,4 @@ X-KDevelop-Interfaces=ILanguageSupport
X-KDevelop-SupportedMimeTypes=text/x-python
X-KDE-PluginInfo-Name=kdevpythonsupport
X-KDevelop-Mode=NoGUI
X-KDE-PluginInfo-Category=Language Support
......@@ -52,6 +52,7 @@ CodeAst* AstBuilder::parse(KUrl filename, const QString& contents)
QString AstBuilder::getXmlForFile(KUrl filename, const QString& contents)
{
m_contents = contents.split("\n");
QProcess* parser = new QProcess();
// we call a python script to parse the code for us. It returns an XML string with the AST
// kDebug() << QDir::current();
......@@ -718,6 +719,37 @@ AttributeAst* AstBuilder::populateAttributeAst(Ast* ast, const Python::stringDic
currentNode->value = resolveNode<ExpressionAst>(currentAttributes.value("NR_value"));
currentNode->attribute = createIdentifier(currentAttributes.value("attr"), currentNode);
currentNode->context = resolveContext(currentAttributes.value("NR_ctx"));
kDebug() << m_contents.at(currentNode->startLine);
QString workingOnCode = m_contents.at(currentNode->startLine);
QRegExp removeQuotedSymbols(".*(\"[^A]*[^\\\\]\").*");
int matches = 0;
QStringList matchedTexts;
QRegExp replaceByTrivial(".");
do {
removeQuotedSymbols.exactMatch(workingOnCode);
matches = removeQuotedSymbols.captureCount();
if ( matches < 2 ) break;
matchedTexts = removeQuotedSymbols.capturedTexts();
kDebug() << "Found: " << matchedTexts;
QString replace = matchedTexts.last();
replace = "\"" + replace.replace(replaceByTrivial, "A") + "\""; // replace everything inside quotes by an A
workingOnCode.replace(matchedTexts.last(), replace);
} while ( matches >= 2 );
kDebug() << workingOnCode;
QRegExp dot("\\."); // we're always only interested in the 2nd match
dot.setMinimal(true);
int skip_offset = dot.indexIn(workingOnCode);
int real_offset = dot.indexIn(workingOnCode, skip_offset);
currentNode->startCol = currentNode->attribute->startCol = real_offset + 1;
currentNode->endCol = currentNode->attribute->endCol = currentNode->startCol + currentNode->attribute->value.length();
kDebug() << "Set range on " << currentNode->attribute->value << " to " << currentNode->startCol << currentNode->endCol;
return currentNode;
}
......
......@@ -73,6 +73,8 @@ private:
QMap<int, stringDictionary> m_attributeStore;
Ast* m_currentNode;
QStringList m_contents;
Ast::BooleanOperationTypes resolveBooleanOperator(const QString& identifier);
Ast::ComparisonOperatorTypes resolveComparisonOperator(const QString& identifier);
Ast::OperatorTypes resolveOperator(const QString& identifier);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment