[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdev-python] /: Refactor import declaration creation code for dotted names
From: Sven Brauch <svenbrauch () googlemail ! com>
Date: 2012-02-29 21:30:11
Message-ID: 20120229213011.ED230A60A9 () git ! kde ! org
[Download RAW message or body]
Git commit e6af0a0e39480eb4697edfeae0b6f65f7f5e02ff by Sven Brauch.
Committed on 29/02/2012 at 22:29.
Pushed by brauch into branch 'master'.
Refactor import declaration creation code for dotted names
please test! should fix various issues
M +3 -0 codecompletion/pythoncodecompletioncontext.cpp
M +131 -93 duchain/declarationbuilder.cpp
M +31 -2 duchain/declarationbuilder.h
M +6 -2 duchain/helpers.cpp
http://commits.kde.org/kdev-python/e6af0a0e39480eb4697edfeae0b6f65f7f5e02ff
diff --git a/codecompletion/pythoncodecompletioncontext.cpp \
b/codecompletion/pythoncodecompletioncontext.cpp index 965c090..746a044 100644
--- a/codecompletion/pythoncodecompletioncontext.cpp
+++ b/codecompletion/pythoncodecompletioncontext.cpp
@@ -435,7 +435,10 @@ QList<CompletionTreeItemPointer> \
PythonCodeCompletionContext::getCompletionItems
QList<DUContext*> searchContexts = Helper::internalContextsForClass(cls, \
m_context->topContext()); QList<DeclarationDepthPair> keepDeclarations;
foreach ( const DUContext* currentlySearchedContext, searchContexts ) {
+ kDebug() << "searching context " << \
currentlySearchedContext->scopeIdentifier() << "for autocompletion \
items";
QList<DeclarationDepthPair> declarations = \
currentlySearchedContext->allDeclarations(CursorInRevision::invalid(), \
m_context->topContext(), false); + kDebug() << "found" << \
declarations.length() << "declarations"; +
// filter out those which are builtin functions, and those which were \
imported; we don't want those here
// TODO rework this, it's maybe not the most elegant solution possible
KUrl url = KUrl(KStandardDirs::locate("data", \
"kdevpythonsupport/documentation_files/builtindocumentation.py"));
diff --git a/duchain/declarationbuilder.cpp b/duchain/declarationbuilder.cpp
index 40594a8..30ced5d 100644
--- a/duchain/declarationbuilder.cpp
+++ b/duchain/declarationbuilder.cpp
@@ -399,6 +399,7 @@ void DeclarationBuilder::visitImportFrom(ImportFromAst* node)
{
Python::AstDefaultVisitor::visitImportFrom(node);
QString moduleName;
+ QString declarationName;
foreach ( AliasAst* name, node->names ) {
if ( node->module ) {
moduleName = node->module->value + "." + name->name->value;
@@ -407,16 +408,19 @@ void DeclarationBuilder::visitImportFrom(ImportFromAst* node)
moduleName = "." + name->name->value;
}
Identifier* declarationIdentifier = 0;
+ declarationName = "";
if ( name->asName ) {
declarationIdentifier = name->asName;
+ declarationName = name->asName->value;
}
else {
declarationIdentifier = name->name;
+ declarationName = name->name->value;
}
- Declaration* success = createModuleImportDeclaration(moduleName, \
declarationIdentifier, 0, DontCreateProblems); + Declaration* success = \
createModuleImportDeclaration(moduleName, declarationName, declarationIdentifier, 0, \
DontCreateProblems); if ( not success and node->module ) {
- moduleName = node->module->value + ".__init__." + name->name->value;
- createModuleImportDeclaration(moduleName, declarationIdentifier);
+ QString modifiedModuleName = node->module->value + ".__init__." + \
name->name->value; + createModuleImportDeclaration(modifiedModuleName, \
declarationName, declarationIdentifier); }
}
}
@@ -477,14 +481,129 @@ void DeclarationBuilder::visitImport(ImportAst* node)
QString moduleName = name->name->value;
// use alias if available, name otherwise
Identifier* declarationIdentifier = name->asName ? name->asName : \
name->name;
- createModuleImportDeclaration(moduleName, declarationIdentifier);
+ createModuleImportDeclaration(moduleName, declarationIdentifier->value, \
declarationIdentifier); }
}
-Declaration* DeclarationBuilder::createModuleImportDeclaration(QString dottedName, \
Identifier* declarationIdentifier, Ast* rangeNode, ProblemPolicy createProblem) \
+Declaration* DeclarationBuilder::createDeclarationTree(const QStringList& \
nameComponents, Identifier* declarationIdentifier, + \
const ReferencedTopDUContext& innerCtx, Declaration* aliasDeclaration, + \
const RangeInRevision& range) {
- QPair<KUrl, QStringList> moduleInfo = findModulePath(dottedName);
- kDebug() << dottedName;
+ Q_ASSERT( ( innerCtx.data() or aliasDeclaration ) && "exactly one of innerCtx or \
aliasDeclaration must be provided"); + Q_ASSERT( ( not innerCtx.data() or not \
aliasDeclaration ) && "exactly one of innerCtx or aliasDeclaration must be \
provided"); +
+ kDebug() << "creating declaration tree for" << nameComponents;
+
+ Declaration* lastDeclaration = 0;
+ int depth = 0;
+
+ // check for already existing trees to update
+ for ( int i = nameComponents.length() - 1; i >= 0; i-- ) {
+ QStringList currentName;
+ for ( int j = 0; j < i; j++ ) {
+ currentName.append(nameComponents.at(j));
+ }
+ lastDeclaration = findDeclarationInContext(currentName, topContext());
+ if ( lastDeclaration and lastDeclaration->range() < range ) {
+ depth = i;
+ break;
+ }
+ }
+
+ DUContext* extendingPreviousImportCtx = 0;
+ QStringList remainingNameComponents;
+ bool injectingContext = false;
+ if ( lastDeclaration and lastDeclaration->internalContext() ) {
+ kDebug() << "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;
+ }
+ else {
+ remainingNameComponents = nameComponents;
+ extendingPreviousImportCtx = topContext();
+ }
+
+ // now, proceed normally
+ QList<Declaration*> openedDeclarations;
+ QList<StructureType::Ptr> openedTypes;
+ QList<DUContext*> openedContexts;
+
+ DUChainWriteLocker lock(DUChain::lock());
+ for ( int i = 0; i < remainingNameComponents.length(); i++ ) {
+ const QString& component = remainingNameComponents.at(i);
+ kDebug() << "creating context for " << component;
+ Identifier* temporaryIdentifier = new Identifier(component);
+ Declaration* d = 0;
+ StructureType::Ptr moduleType = StructureType::Ptr(new StructureType());
+ temporaryIdentifier->copyRange(declarationIdentifier);
+ temporaryIdentifier->endCol = temporaryIdentifier->startCol - 1;
+ openType(moduleType);
+ if ( i != remainingNameComponents.length() - 1 or not aliasDeclaration ) {
+ d = visitVariableDeclaration<Declaration>(temporaryIdentifier);
+ if ( d ) {
+ if ( topContext() != extendingPreviousImportCtx ) {
+ \
d->setRange(RangeInRevision(extendingPreviousImportCtx->range().start, \
extendingPreviousImportCtx->range().start)); + }
+ d->setAutoDeclaration(true);
+ currentContext()->createUse(d->ownIndex(), \
editorFindRange(declarationIdentifier, declarationIdentifier)); + }
+ }
+ else {
+ AliasDeclaration* adecl = \
visitVariableDeclaration<AliasDeclaration>(temporaryIdentifier, range); + \
if ( adecl ) { + adecl->setAliasedDeclaration(aliasDeclaration);
+ }
+ d = adecl;
+ }
+
+ openedContexts.append(openContext(declarationIdentifier, \
KDevelop::DUContext::Other)); + openedDeclarations.append(d);
+ openedTypes.append(moduleType);
+ if ( i == remainingNameComponents.length() - 1 ) {
+ if ( innerCtx ) {
+ kDebug() << "adding imported context to inner declaration";
+ currentContext()->addImportedParentContext(innerCtx);
+ }
+ else if ( aliasDeclaration ) {
+ kDebug() << "setting alias declaration on inner declaration";
+ }
+ }
+ // TODO this sucks
+ currentContext()->setLocalScopeIdentifier(QualifiedIdentifier("__kdevpythonlanguagesupport_import_helper"));
+ delete temporaryIdentifier;
+ }
+ for ( int i = remainingNameComponents.length() - 1; i >= 0; i-- ) {
+ kDebug() << "closing context";
+ closeType();
+ closeContext();
+ Declaration* d = openedDeclarations.at(i);
+ if ( d and ( i != 0 or not aliasDeclaration ) ) {
+ openedTypes[i]->setDeclaration(d);
+ d->setType(openedTypes.at(i));
+ d->setInternalContext(openedContexts.at(i));
+ }
+ }
+
+ if ( injectingContext ) {
+ closeInjectedContext();
+ }
+
+ if ( ! openedDeclarations.isEmpty() ) {
+ return openedDeclarations.last();
+ }
+ else return 0;
+}
+
+Declaration* DeclarationBuilder::createModuleImportDeclaration(QString moduleName, \
QString declarationName, + \
Identifier* declarationIdentifier, + \
Ast* rangeNode, ProblemPolicy createProblem) +{
+ QPair<KUrl, QStringList> moduleInfo = findModulePath(moduleName);
+ kDebug() << moduleName;
RangeInRevision range(RangeInRevision::invalid());
if ( rangeNode ) {
range = rangeForNode(rangeNode, false);
@@ -507,7 +626,7 @@ Declaration* \
DeclarationBuilder::createModuleImportDeclaration(QString dottedNam
p->setFinalLocation(DocumentRange(currentlyParsedDocument(), \
range.castToSimpleRange())); // TODO ok? \
p->setSource(KDevelop::ProblemData::SemanticAnalysis); \
p->setSeverity(KDevelop::ProblemData::Warning);
- p->setDescription(i18n("Module \"%1\" not found", dottedName));
+ p->setDescription(i18n("Module \"%1\" not found", moduleName));
{
DUChainWriteLocker wlock(DUChain::lock());
ProblemPointer ptr(p);
@@ -533,89 +652,7 @@ Declaration* \
DeclarationBuilder::createModuleImportDeclaration(QString dottedNam if ( \
moduleInfo.second.isEmpty() ) { // import the whole module
kDebug() << "Got module, importing it" << declarationIdentifier->value;
- Declaration* lastDeclaration = 0;
- QStringList nameComponents = declarationIdentifier->value.split('.');
- int depth = 0;
-
- for ( int i = nameComponents.length() - 1; i >= 0; i-- ) {
- QStringList currentName;
- for ( int j = 0; j < i; j++ ) {
- currentName.append(nameComponents.at(j));
- }
- lastDeclaration = findDeclarationInContext(currentName, topContext());
- if ( lastDeclaration and lastDeclaration->range() < range ) {
- depth = i;
- break;
- }
- }
-
- DUContext* extendingPreviousImportCtx = 0;
- QStringList remainingNameComponents;
- bool injectingContext = false;
- if ( lastDeclaration and lastDeclaration->internalContext() ) {
- kDebug() << "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;
- }
- else {
- remainingNameComponents = nameComponents;
- extendingPreviousImportCtx = topContext();
- }
-
- // now, proceed normally
- QList<Declaration*> openedDeclarations;
- QList<StructureType::Ptr> openedTypes;
- QList<DUContext*> openedContexts;
-// bool extendingPreviousImports = true;
-
- DUChainWriteLocker lock(DUChain::lock());
- for ( int i = 0; i < remainingNameComponents.length(); i++ ) {
- const QString& component = remainingNameComponents.at(i);
- kDebug() << "creating context for " << component;
- Identifier* temporaryIdentifier = new Identifier(component);
- Declaration* d = 0;
- StructureType::Ptr moduleType;
- moduleType = StructureType::Ptr(new StructureType());
- temporaryIdentifier->copyRange(declarationIdentifier);
- temporaryIdentifier->endCol = temporaryIdentifier->startCol - 1;
- openType(moduleType);
- d = visitVariableDeclaration<Declaration>(temporaryIdentifier);
- delete temporaryIdentifier;
- if ( d ) {
- if ( topContext() != extendingPreviousImportCtx ) {
- \
d->setRange(RangeInRevision(extendingPreviousImportCtx->range().start, \
extendingPreviousImportCtx->range().start));
- }
- d->setAutoDeclaration(true);
- currentContext()->createUse(d->ownIndex(), \
editorFindRange(declarationIdentifier, declarationIdentifier));
- }
- openedContexts.append(openContext(declarationIdentifier, \
KDevelop::DUContext::Other));
- if ( i == remainingNameComponents.length() - 1 ) {
- currentContext()->addImportedParentContext(moduleContext);
- }
- // TODO this sucks
- currentContext()->setLocalScopeIdentifier(QualifiedIdentifier("__kdevpythonlanguagesupport_import_helper"));
- openedDeclarations.append(d);
- openedTypes.append(moduleType);
- }
- for ( int i = remainingNameComponents.length() - 1; i >= 0; i-- ) {
- kDebug() << "closing context";
- closeType();
- closeContext();
- Declaration* d = openedDeclarations.at(i);
- if ( d ) {
- openedTypes[i]->setDeclaration(d);
- d->setType(openedTypes.at(i));
- d->setInternalContext(openedContexts.at(i));
- }
- }
-
- if ( injectingContext ) {
- closeInjectedContext();
- }
+ resultingDeclaration = createDeclarationTree(declarationName.split("."), \
declarationIdentifier, moduleContext, 0, range); }
else {
// import a specific declaration from the given file
@@ -630,13 +667,14 @@ Declaration* \
DeclarationBuilder::createModuleImportDeclaration(QString dottedNam kDebug() << \
"Result: " << originalDeclaration; if ( originalDeclaration ) {
DUChainWriteLocker lock(DUChain::lock());
- resultingDeclaration = \
visitVariableDeclaration<AliasDeclaration>(declarationIdentifier, range); + \
resultingDeclaration = createDeclarationTree(declarationName.split("."), \
declarationIdentifier, ReferencedTopDUContext(0), originalDeclaration); + \
/** DEBUG **/
if ( dynamic_cast<AliasDeclaration*>(resultingDeclaration) ) {
- \
static_cast<AliasDeclaration*>(resultingDeclaration)->setAliasedDeclaration(originalDeclaration);
kDebug() << "Resulting alias: " << \
resultingDeclaration->toString(); }
else
kWarning() << "import declaration is being overwritten!";
+ /** END DEBUG **/
}
else if ( createProblem != DontCreateProblems ) {
KDevelop::Problem *p = new KDevelop::Problem();
diff --git a/duchain/declarationbuilder.h b/duchain/declarationbuilder.h
index fee837c..39aba2d 100644
--- a/duchain/declarationbuilder.h
+++ b/duchain/declarationbuilder.h
@@ -96,15 +96,44 @@ protected:
DontCreateProblems
};
- Declaration* createModuleImportDeclaration(QString dottedName, \
Python::Identifier* declarationIdentifier, + /**
+ * @brief Create a declaration for an import statement.
+ *
+ * @param dottedName The dotted name of the module, like "random.randint".
+ * @param declarationIdentifier provides the name and range
+ * @param rangeNode can be used to override the declarationIdentifier's range, \
if required. Defaults to 0. + * @param createProblem whether or not to create \
DUChain problems Defaults to CreateProblems. + * @return :Declaration* the \
declaration created, or 0 if none was found. + **/
+ Declaration* createModuleImportDeclaration(QString dottedName, QString \
declarationName, Python::Identifier* declarationIdentifier,
Python::Ast* rangeNode = 0, \
ProblemPolicy createProblem = CreateProblems); + /**
+ * @brief Create a tree of declarations for the specified list.
+ * Give the list ["foo","bar","baz"], and you'll get a declaration "foo" \
containing "bar" in its internal context, + * "bar" containing "baz" etc.
+ * This is used in import handling.
+ * This function automatically updates existing declaration trees to the maximum \
level possible! Thus, + * if you call this with ["foo", "bar"], then ["foo", \
"baz"], "baz" will be added to "foo". + *
+ * @warning The DUChain must not be locked when this is called.
+ *
+ * @param nameComponents the list of names to create declarations for
+ * @param declarationIdentifier provides the name and range
+ * @param innerCtx the internalContext() to set on the last created declaration. \
Either this or aliasDeclaration must be provided! + * @param aliasDeclaration the \
declaration to alias with the last created declaration + * @param rangeNode can \
be used to override the declarationIdentifier's range, if required. Defaults to 0. + \
* @return :Declaration* the top level declaration created + **/
+ Declaration* createDeclarationTree(const QStringList& nameComponents, \
Identifier* declarationIdentifier, + const \
ReferencedTopDUContext& innerCtx, Declaration* aliasDeclaration = 0, + \
const RangeInRevision& range = RangeInRevision::invalid());
/**
* @brief Find a declaration specified by "foo.bar.baz" in the given top \
context.
*
* @param dottedNameIdentifier string list of module names, starting with the \
most general one.
* @param ctx top context to search
- * @return :Declaration* declaration if found, 0x0 otherwise.
+ * @return :Declaration* declaration if found, 0 otherwise.
*
* @note The DUChain must not be locked.
**/
diff --git a/duchain/helpers.cpp b/duchain/helpers.cpp
index ed3b20f..88d5885 100644
--- a/duchain/helpers.cpp
+++ b/duchain/helpers.cpp
@@ -181,9 +181,13 @@ QList< DUContext* > \
Helper::internalContextsForClass(StructureType::Ptr klassTyp return searchContexts;
}
searchContexts << klassType->internalContext(context);
- Declaration* decl = klassType->declaration(context);
+ Declaration* decl = \
Helper::resolveAliasDeclaration(klassType->declaration(context)); ClassDeclaration* \
klass = dynamic_cast<ClassDeclaration*>(decl);
- kDebug() << "Got class Declaration:" << klass;
+ kDebug() << "Got class Declaration:" << klass << decl;
+ if ( decl ) {
+ kDebug() << decl->toString();
+ }
+ kDebug() << klassType->internalContext(context)->allDeclarations(CursorInRevision::invalid(), \
context).length(); if ( klass ) {
kDebug() << "Base classes: " << klass->baseClassesSize();
FOREACH_FUNCTION ( const BaseClassInstance& base, klass->baseClasses ) {
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic