Changeset View
Changeset View
Standalone View
Standalone View
duchain/helpers.cpp
Context not available. | |||||
179 | Declaration* Helper::declarationForName(const QualifiedIdentifier& identifier, const RangeInRevision& nodeRange, | 179 | Declaration* Helper::declarationForName(const QualifiedIdentifier& identifier, const RangeInRevision& nodeRange, | ||
---|---|---|---|---|---|
180 | KDevelop::DUChainPointer<const DUContext> context) | 180 | KDevelop::DUChainPointer<const DUContext> context) | ||
181 | { | 181 | { | ||
182 | QList<Declaration*> declarations; | 182 | DUChainReadLocker lock(DUChain::lock()); | ||
183 | QList<Declaration*> localDeclarations; | 183 | auto localDeclarations = context->findLocalDeclarations(identifier.last(), nodeRange.end, 0, | ||
184 | QList<Declaration*> importedLocalDeclarations; | 184 | AbstractType::Ptr(0), DUContext::DontResolveAliases); | ||
185 | { | 185 | if ( !localDeclarations.isEmpty() ) { | ||
186 | DUChainReadLocker lock(DUChain::lock()); | 186 | return localDeclarations.last(); | ||
187 | if ( context.data() == context->topContext() && nodeRange.isValid() ) { | | |||
188 | declarations = context->topContext()->findDeclarations(identifier, nodeRange.end); | | |||
189 | } | | |||
190 | else { | | |||
191 | declarations = context->topContext()->findDeclarations(identifier, CursorInRevision::invalid()); | | |||
192 | } | | |||
193 | localDeclarations = context->findLocalDeclarations(identifier.last(), nodeRange.end, 0, | | |||
194 | AbstractType::Ptr(0), DUContext::DontResolveAliases); | | |||
195 | importedLocalDeclarations = context->findDeclarations(identifier.last(), nodeRange.end); | | |||
196 | } | | |||
197 | Declaration* declaration = 0; | | |||
198 | if ( localDeclarations.length() ) { | | |||
199 | declaration = localDeclarations.last(); | | |||
200 | } | 187 | } | ||
201 | else if ( importedLocalDeclarations.length() ) { | 188 | | ||
202 | // don't use declarations from class decls, they must be referenced through "self.<foo>" | 189 | QList<Declaration*> declarations; | ||
203 | do { | 190 | const DUContext* currentContext = context.data(); | ||
204 | declaration = importedLocalDeclarations.last(); | 191 | bool findInNext = true, findBeyondUse = false; | ||
205 | importedLocalDeclarations.pop_back(); | 192 | do { | ||
206 | if ( !declaration || (declaration->context()->type() == DUContext::Class && context->type() != DUContext::Function) ) { | 193 | if (findInNext) { | ||
207 | declaration = 0; | 194 | CursorInRevision findUntil = findBeyondUse ? currentContext->topContext()->range().end : nodeRange.end; | ||
195 | declarations = currentContext->findDeclarations(identifier.last(), findUntil); | ||||
196 | | ||||
197 | for (Declaration* declaration: declarations) { | ||||
198 | if (declaration->context()->type() != DUContext::Class || | ||||
199 | (currentContext->type() == DUContext::Function && declaration->context() == currentContext->parentContext())) { | ||||
200 | // Declarations from class decls must be referenced through `self.<foo>`, except | ||||
201 | // in their local scope (handled above) or when used as default arguments for methods of the same class. | ||||
202 | // Otherwise, we're done! | ||||
203 | return declaration; | ||||
204 | } | ||||
208 | } | 205 | } | ||
209 | if ( importedLocalDeclarations.isEmpty() ) { | 206 | if (!declarations.isEmpty()) { | ||
210 | break; | 207 | // If we found declarations but rejected all of them (i.e. didn't return), we need to keep searching. | ||
208 | findInNext = true; | ||||
209 | declarations.clear(); | ||||
211 | } | 210 | } | ||
212 | } while ( ! importedLocalDeclarations.isEmpty() ); | 211 | } | ||
213 | } | | |||
214 | 212 | | |||
215 | if ( !declaration && declarations.length() ) { | 213 | if (!findBeyondUse && currentContext->owner() && currentContext->owner()->isFunctionDeclaration()) { | ||
216 | declaration = declarations.last(); | 214 | // Names in the body may be defined after the function definition, before the function is called. | ||
217 | } | 215 | // Note: only the parameter list has type DUContext::Function, so we have to do this instead. | ||
218 | return declaration; | 216 | findBeyondUse = findInNext = true; | ||
217 | } | ||||
218 | } while ((currentContext = currentContext->parentContext())); | ||||
219 | | ||||
220 | return nullptr; | ||||
219 | } | 221 | } | ||
220 | 222 | | |||
221 | QVector<DUContext*> Helper::internalContextsForClass(const StructureType::Ptr classType, | 223 | QVector<DUContext*> Helper::internalContextsForClass(const StructureType::Ptr classType, | ||
Context not available. |