~ubuntu-branches/debian/sid/kdevelop/sid

« back to all changes in this revision

Viewing changes to languages/cpp/cppduchain/contextbuilder.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2010-05-05 07:21:55 UTC
  • mfrom: (1.2.3 upstream) (5.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100505072155-h78lx19pu04sbhtn
Tags: 4:4.0.0-2
* Upload to unstable (Closes: #579947, #481832).
* Acknowledge obsolete NMU fixes (Closes: #562410, #546961).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
  /* This file is part of KDevelop
 
2
    Copyright 2006 Roberto Raggi <roberto@kdevelop.org>
 
3
    Copyright 2006-2008 Hamish Rodda <rodda@kde.org>
 
4
    Copyright 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
 
5
 
 
6
   This library is free software; you can redistribute it and/or
 
7
   modify it under the terms of the GNU Library General Public
 
8
   License version 2 as published by the Free Software Foundation.
 
9
 
 
10
   This library is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
   Library General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU Library General Public License
 
16
   along with this library; see the file COPYING.LIB.  If not, write to
 
17
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
18
   Boston, MA 02110-1301, USA.
 
19
*/
 
20
 
 
21
#include "contextbuilder.h"
 
22
 
 
23
 
 
24
#include <ktexteditor/smartrange.h>
 
25
#include <ktexteditor/smartinterface.h>
 
26
#include <ktexteditor/document.h>
 
27
 
 
28
#include <language/duchain/duchain.h>
 
29
#include <language/duchain/topducontext.h>
 
30
#include <language/duchain/declaration.h>
 
31
#include <language/duchain/use.h>
 
32
#include <language/duchain/smartconverter.h>
 
33
#include <util/pushvalue.h>
 
34
 
 
35
#include "parsesession.h"
 
36
#include "name_compiler.h"
 
37
#include <language/duchain/dumpchain.h>
 
38
#include "environmentmanager.h"
 
39
 
 
40
#include <climits>
 
41
#include "cppdebughelper.h"
 
42
#include "debugbuilders.h"
 
43
#include "rpp/chartools.h"
 
44
#include "tokens.h"
 
45
#include <klocalizedstring.h>
 
46
 
 
47
using namespace KTextEditor;
 
48
using namespace KDevelop;
 
49
using namespace Cpp;
 
50
 
 
51
bool containsContext( const QList<LineContextPair>& lineContexts, TopDUContext* context ) {
 
52
  foreach( const LineContextPair& ctx, lineContexts )
 
53
    if( ctx.context.data() == context )
 
54
      return true;
 
55
  return false;
 
56
}
 
57
 
 
58
bool importsContext( const QList<LineContextPair>& lineContexts, TopDUContext* context ) {
 
59
  foreach( const LineContextPair& ctx, lineContexts )
 
60
    if( ctx.context && ctx.context->imports(context, KDevelop::SimpleCursor()) )
 
61
      return true;
 
62
  return false;
 
63
}
 
64
 
 
65
void removeContext( QList<LineContextPair>& lineContexts, TopDUContext* context ) {
 
66
  for( QList<LineContextPair>::iterator it = lineContexts.begin(); it != lineContexts.end(); ++it )
 
67
    if( (*it).context.data() == context ) {
 
68
    lineContexts.erase(it);
 
69
    return;
 
70
    }
 
71
}
 
72
 
 
73
///Retrieves the first and last item from a list
 
74
template <class _Tp>
 
75
void getFirstLast(AST** first, AST** last, const ListNode<_Tp> *nodes)
 
76
{
 
77
  *first = 0;
 
78
  *last = 0;
 
79
 
 
80
  if (!nodes)
 
81
    return;
 
82
 
 
83
  const ListNode<_Tp>
 
84
    *it = nodes->toFront(),
 
85
    *end = it;
 
86
 
 
87
  do
 
88
    {
 
89
      if( !*first )
 
90
        *first = it->element;
 
91
 
 
92
      *last = it->element;
 
93
 
 
94
      it = it->next;
 
95
    }
 
96
  while (it != end);
 
97
}
 
98
 
 
99
 
 
100
ContextBuilder::ContextBuilder ()
 
101
  : m_nameCompiler(0)
 
102
  , m_inFunctionDefinition(false)
 
103
  , m_templateDeclarationDepth(0)
 
104
  , m_typeSpecifierWithoutInitDeclarators((uint)-1)
 
105
  , m_onlyComputeVisible(false)
 
106
  , m_onlyComputeSimplified(false)
 
107
  , m_computeEmpty(false)
 
108
  , m_currentInitializer(0)
 
109
  , m_mapAst(false)
 
110
{
 
111
}
 
112
 
 
113
ContextBuilder::ContextBuilder (ParseSession* session)
 
114
  : m_nameCompiler(0)
 
115
  , m_inFunctionDefinition(false)
 
116
  , m_templateDeclarationDepth(0)
 
117
  , m_typeSpecifierWithoutInitDeclarators((uint)-1)
 
118
  , m_onlyComputeVisible(false)
 
119
  , m_onlyComputeSimplified(false)
 
120
  , m_computeEmpty(false)
 
121
  , m_currentInitializer(0)
 
122
  , m_mapAst(false)
 
123
{
 
124
  setEditor(new CppEditorIntegrator(session), true);
 
125
}
 
126
 
 
127
ContextBuilder::ContextBuilder (CppEditorIntegrator* editor)
 
128
  : m_nameCompiler(0)
 
129
  , m_inFunctionDefinition(false)
 
130
  , m_templateDeclarationDepth(0)
 
131
  , m_typeSpecifierWithoutInitDeclarators((uint)-1)
 
132
  , m_onlyComputeVisible(false)
 
133
  , m_onlyComputeSimplified(false)
 
134
  , m_computeEmpty(false)
 
135
  , m_currentInitializer(0)
 
136
  , m_mapAst(false)
 
137
{
 
138
  setEditor(editor, false);
 
139
}
 
140
 
 
141
void ContextBuilder::setOnlyComputeVisible(bool onlyVisible) {
 
142
  m_onlyComputeVisible = onlyVisible;
 
143
}
 
144
 
 
145
void ContextBuilder::setComputeSimplified(bool simplified)
 
146
{
 
147
  m_onlyComputeSimplified = simplified;
 
148
}
 
149
 
 
150
void ContextBuilder::setComputeEmpty(bool empty)
 
151
{
 
152
  m_computeEmpty = empty;
 
153
}
 
154
 
 
155
 
 
156
void ContextBuilder::createUserProblem(AST* node, QString text) {
 
157
    DUChainWriteLocker lock(DUChain::lock());
 
158
    KDevelop::ProblemPointer problem(new KDevelop::Problem);
 
159
    problem->setDescription(text);
 
160
    problem->setSource(KDevelop::ProblemData::DUChainBuilder);
 
161
    problem->setFinalLocation(DocumentRange(HashedString(currentContext()->url().str()), editor()->findRange(node).textRange()));
 
162
    currentContext()->topContext()->addProblem(problem);
 
163
}
 
164
 
 
165
void ContextBuilder::addBaseType( KDevelop::BaseClassInstance base, BaseSpecifierAST *node ) {
 
166
  DUChainWriteLocker lock(DUChain::lock());
 
167
 
 
168
  addImportedContexts(); //Make sure the template-contexts are imported first, before any parent-class contexts.
 
169
 
 
170
  Q_ASSERT(currentContext()->type() == DUContext::Class);
 
171
  AbstractType::Ptr baseClass = base.baseClass.abstractType();
 
172
  IdentifiedType* idType = dynamic_cast<IdentifiedType*>(baseClass.unsafeData());
 
173
  Declaration* idDecl = 0;
 
174
  if( idType && (idDecl = idType->declaration(currentContext()->topContext())) ) {
 
175
    DUContext* ctx = idDecl->logicalInternalContext(currentContext()->topContext());
 
176
    if(ctx) {
 
177
      currentContext()->addImportedParentContext( ctx );
 
178
    }else{
 
179
      currentContext()->addIndirectImport( DUContext::Import(idType->declarationId()) );
 
180
      QString text = i18n("Could not resolve base class, adding it indirectly: %1", (base.baseClass ? base.baseClass.abstractType()->toString() : QString()));
 
181
      lock.unlock();
 
182
      createUserProblem(node, text);
 
183
    }
 
184
  } else if( !baseClass.cast<DelayedType>() ) {
 
185
    QString text = i18n("Invalid base class: %1", (base.baseClass ? base.baseClass.abstractType()->toString() : QString()));
 
186
    lock.unlock();
 
187
    createUserProblem(node, text);
 
188
  }
 
189
}
 
190
 
 
191
void ContextBuilder::setEditor(CppEditorIntegrator* editor, bool ownsEditorIntegrator)
 
192
{
 
193
  ContextBuilderBase::setEditor(editor, ownsEditorIntegrator);
 
194
  m_nameCompiler = new NameCompiler(editor->parseSession());
 
195
}
 
196
 
 
197
 
 
198
void addImportedParentContextSafely(DUContext* context, DUContext* import) {
 
199
  if(import->imports(context)) {
 
200
    kDebug() << "prevented endless recursive import";
 
201
  }else{
 
202
    context->addImportedParentContext(import);
 
203
  }
 
204
}
 
205
 
 
206
QualifiedIdentifier ContextBuilder::identifierForNode(NameAST* id) {
 
207
  QualifiedIdentifier ret;
 
208
  identifierForNode(id, ret);
 
209
  return ret;
 
210
}
 
211
 
 
212
void ContextBuilder::setMapAst(bool mapAst)
 
213
{
 
214
  m_mapAst = mapAst;
 
215
}
 
216
 
 
217
void ContextBuilder::identifierForNode(NameAST* id, QualifiedIdentifier& target)
 
218
{
 
219
  return identifierForNode(id, 0, target);
 
220
}
 
221
 
 
222
void ContextBuilder::startVisiting( AST* node )
 
223
{
 
224
  visit( node );
 
225
}
 
226
 
 
227
void ContextBuilder::setContextOnNode( AST* node, DUContext* ctx )
 
228
{
 
229
  node->ducontext = ctx;
 
230
}
 
231
 
 
232
DUContext* ContextBuilder::contextFromNode( AST* node )
 
233
{
 
234
  return node->ducontext;
 
235
}
 
236
 
 
237
KTextEditor::Range ContextBuilder::editorFindRange( AST* fromRange, AST* toRange )
 
238
{
 
239
  return editor()->findRange(fromRange, toRange).textRange();
 
240
}
 
241
 
 
242
KTextEditor::Range ContextBuilder::editorFindRangeForContext( AST* fromRange, AST* toRange )
 
243
{
 
244
  return editor()->findRangeForContext(fromRange->start_token, toRange->end_token).textRange();
 
245
}
 
246
 
 
247
ContextBuilder::~ContextBuilder ()
 
248
{
 
249
  delete m_nameCompiler;
 
250
}
 
251
 
 
252
QPair<DUContext*, QualifiedIdentifier> ContextBuilder::findPrefixContext(const QualifiedIdentifier& id, KDevelop::SimpleCursor pos) {
 
253
  if(id.count() < 2)
 
254
    return qMakePair((DUContext*)0, QualifiedIdentifier());
 
255
  
 
256
  QualifiedIdentifier prefixId(id);
 
257
  prefixId.pop();
 
258
 
 
259
  DUContext* import = 0;
 
260
 
 
261
  {
 
262
    DUChainReadLocker lock(DUChain::lock());
 
263
 
 
264
    QualifiedIdentifier currentScopeId = currentContext()->scopeIdentifier(true);
 
265
 
 
266
    QList<Declaration*> decls = currentContext()->findDeclarations(prefixId, pos);
 
267
 
 
268
    if(!decls.isEmpty()) {
 
269
      DUContext* classContext = decls.first()->logicalInternalContext(0);
 
270
      if(classContext && classContext->type() == DUContext::Class) {
 
271
        import = classContext;
 
272
        //Change the prefix-id so it respects namespace-imports
 
273
        
 
274
        prefixId = classContext->scopeIdentifier(true);
 
275
        if(prefixId.count() >= currentScopeId.count() && prefixId.left(currentScopeId.count()) == currentScopeId)
 
276
          prefixId = prefixId.mid(currentScopeId.count());
 
277
        else
 
278
          kDebug() << "resolved bad prefix context. Should start with" << currentScopeId.toString() << "but is" << prefixId.toString();
 
279
      }
 
280
    }
 
281
  }
 
282
  
 
283
  return qMakePair(import, prefixId);
 
284
}
 
285
 
 
286
void ContextBuilder::openPrefixContext(AST* ast, const QualifiedIdentifier& id, const SimpleCursor& pos) {
 
287
  if(id.count() < 2)
 
288
    return;
 
289
 
 
290
  //When creating a prefix-context that is there to embed a class within another class, import the enclosing class into that context.
 
291
  //That way items from the base class can be found.
 
292
 
 
293
  QPair<DUContext*, QualifiedIdentifier> prefix = findPrefixContext(id, pos);
 
294
 
 
295
  openContext(ast, DUContext::Helper, prefix.second);
 
296
 
 
297
  DUContext* import = prefix.first;
 
298
  
 
299
  if(import) {
 
300
    DUChainWriteLocker lock(DUChain::lock());
 
301
    addImportedParentContextSafely(currentContext(), import);
 
302
  }
 
303
}
 
304
 
 
305
void ContextBuilder::closePrefixContext(const QualifiedIdentifier& id) {
 
306
  if(id.count() < 2)
 
307
    return;
 
308
  closeContext();
 
309
}
 
310
 
 
311
void ContextBuilder::visitTemplateDeclaration(TemplateDeclarationAST * ast) {
 
312
 
 
313
  ++m_templateDeclarationDepth;
 
314
  
 
315
  if(!m_onlyComputeSimplified)
 
316
  {
 
317
    AST* first, *last;
 
318
    getFirstLast(&first, &last, ast->template_parameters);
 
319
    DUContext* ctx = 0;
 
320
 
 
321
    if( first && last )
 
322
      ctx = openContext(first, last, DUContext::Template); //Open anonymous context for the template-parameters
 
323
    else
 
324
      ctx = openContextEmpty(ast, DUContext::Template); //Open an empty context, because there are no template-parameters
 
325
 
 
326
    visitNodes(this,ast->template_parameters);
 
327
    closeContext();
 
328
    
 
329
    queueImportedContext(ctx); //Import the context into the following function-argument context(so the template-parameters can be found from there)
 
330
  }
 
331
 
 
332
  DefaultVisitor::visit(ast->declaration);
 
333
 
 
334
  --m_templateDeclarationDepth;
 
335
}
 
336
 
 
337
KDevelop::TopDUContext* ContextBuilder::buildProxyContextFromContent(Cpp::EnvironmentFilePointer file, const TopDUContextPointer& content, const TopDUContextPointer& updateContext)
 
338
{
 
339
  Cpp::EnvironmentFile* filePtr = const_cast<Cpp::EnvironmentFile*>(file.data() );
 
340
  
 
341
  filePtr->setIsProxyContext(true);
 
342
  
 
343
  //Never give smart-ranges to proxy-contexts
 
344
  editor()->setCurrentUrl(file->url(), false);
 
345
 
 
346
  TopDUContext* topLevelContext = 0;
 
347
  {
 
348
    DUChainWriteLocker lock(DUChain::lock());
 
349
    topLevelContext = updateContext.data();
 
350
 
 
351
    CppDUContext<TopDUContext>* cppContext = 0;
 
352
 
 
353
    if (topLevelContext) {
 
354
      kDebug(9007) << "ContextBuilder::buildProxyContextFromContent: recompiling";
 
355
 
 
356
      Q_ASSERT(dynamic_cast<CppDUContext<TopDUContext>* >(topLevelContext));
 
357
      cppContext = static_cast<CppDUContext<TopDUContext>* >(topLevelContext);
 
358
 
 
359
      DUChain::self()->updateContextEnvironment( topLevelContext, filePtr );
 
360
    } else {
 
361
      kDebug(9007) << "ContextBuilder::buildProxyContextFromContent: compiling";
 
362
 
 
363
      topLevelContext = new CppDUContext<TopDUContext>(editor()->currentUrl(), SimpleRange(), filePtr);
 
364
      topLevelContext->setType(DUContext::Global);
 
365
 
 
366
      Q_ASSERT(dynamic_cast<CppDUContext<TopDUContext>* >(topLevelContext));
 
367
      cppContext = static_cast<CppDUContext<TopDUContext>* >(topLevelContext);
 
368
 
 
369
      DUChain::self()->addDocumentChain(topLevelContext);
 
370
      
 
371
      topLevelContext->updateImportsCache(); //Mark that we will use a cached import-structure
 
372
    }
 
373
 
 
374
    if(content) {
 
375
      cppContext->clearImportedParentContexts();
 
376
      cppContext->addImportedParentContext(content.data());
 
377
      cppContext->updateImportsCache(); //Mark that we will use a cached import-structure
 
378
    } else {
 
379
      ///This happens if a content-context is deleted from the du-chain during the time that the du-chain is not locked by this thread
 
380
      kDebug(9007) << "ContextBuilder::buildProxyContextFromContent: Content-context lost for " << file->url().str();
 
381
      Q_ASSERT(0);
 
382
    }
 
383
    Q_ASSERT(topLevelContext->importedParentContexts().count());
 
384
  }
 
385
 
 
386
  return topLevelContext;
 
387
}
 
388
 
 
389
ReferencedTopDUContext ContextBuilder::buildContexts(Cpp::EnvironmentFilePointer file, AST *node, IncludeFileList* includes, const ReferencedTopDUContext& updateContext, bool removeOldImports)
 
390
{
 
391
  Q_ASSERT(file);
 
392
  setCompilingContexts(true);
 
393
 
 
394
  {
 
395
    DUChainWriteLocker lock(DUChain::lock());
 
396
    if(updateContext && (updateContext->parsingEnvironmentFile() && updateContext->parsingEnvironmentFile()->isProxyContext())) {
 
397
      kDebug(9007) << "updating a context " << file->url().str() << " from a proxy-context to a content-context";
 
398
      updateContext->parsingEnvironmentFile()->setIsProxyContext(false);
 
399
    }
 
400
  }
 
401
 
 
402
  if(editor()->currentUrl() != file->url())
 
403
    editor()->setCurrentUrl(file->url(), true);
 
404
 
 
405
  ReferencedTopDUContext topLevelContext;
 
406
  {
 
407
    DUChainWriteLocker lock(DUChain::lock());
 
408
    topLevelContext = updateContext;
 
409
 
 
410
    if( topLevelContext && topLevelContext->smartRange() && !(topLevelContext->parsingEnvironmentFile() && topLevelContext->parsingEnvironmentFile()->isProxyContext()))
 
411
      if (topLevelContext->smartRange()->parentRange()) { //Top-range must have no parent, else something is wrong with the structure
 
412
        kWarning() << *topLevelContext->smartRange() << "erroneously has a parent range" << *topLevelContext->smartRange()->parentRange();
 
413
        Q_ASSERT(false);
 
414
      }
 
415
 
 
416
    if (topLevelContext) {
 
417
      kDebug(9007) << "ContextBuilder::buildContexts: recompiling";
 
418
      setRecompiling(true);
 
419
 
 
420
      if (compilingContexts()) {
 
421
        // To here...
 
422
        LockedSmartInterface iface = editor()->smart();
 
423
        if (iface && topLevelContext->range().textRange() != iface.currentDocument()->documentRange()) {
 
424
          topLevelContext->setRange(SimpleRange(iface.currentDocument()->documentRange()));
 
425
          //This happens the whole file is deleted, and then a space inserted.
 
426
          kDebug(9007) << "WARNING: Top-level context has wrong size: " << topLevelContext->range().textRange() << " should be: " << iface.currentDocument()->documentRange();
 
427
        }
 
428
      }
 
429
 
 
430
      DUChain::self()->updateContextEnvironment( topLevelContext, const_cast<Cpp::EnvironmentFile*>(file.data() ) );
 
431
    } else {
 
432
      kDebug(9007) << "ContextBuilder::buildContexts: compiling";
 
433
      setRecompiling(false);
 
434
 
 
435
      Q_ASSERT(compilingContexts());
 
436
 
 
437
      LockedSmartInterface iface = editor()->smart();
 
438
      topLevelContext = new CppDUContext<TopDUContext>(editor()->currentUrl(), iface.currentDocument() ? SimpleRange(iface.currentDocument()->documentRange()) : SimpleRange(SimpleCursor(0,0), SimpleCursor(INT_MAX, INT_MAX)), const_cast<Cpp::EnvironmentFile*>(file.data()));
 
439
 
 
440
      topLevelContext->setSmartRange(editor()->topRange(iface, CppEditorIntegrator::DefinitionUseChain), DocumentRangeObject::Own);
 
441
      topLevelContext->setType(DUContext::Global);
 
442
      topLevelContext->setFlags((TopDUContext::Flags)(TopDUContext::UpdatingContext | topLevelContext->flags()));
 
443
      DUChain::self()->addDocumentChain(topLevelContext);
 
444
    
 
445
      topLevelContext->updateImportsCache(); //Mark that we will use a cached import-structure
 
446
    }
 
447
 
 
448
    setEncountered(topLevelContext);
 
449
 
 
450
    if (includes) {
 
451
      if(removeOldImports) {
 
452
        foreach (const DUContext::Import &parent, topLevelContext->importedParentContexts())
 
453
          if (!containsContext(*includes, dynamic_cast<TopDUContext*>(parent.context(0))))
 
454
            topLevelContext->removeImportedParentContext(parent.context(0));
 
455
      }
 
456
 
 
457
      QList< QPair<TopDUContext*, SimpleCursor> > realIncluded;
 
458
      QList< QPair<TopDUContext*, SimpleCursor> > realTemporaryIncluded;
 
459
      foreach (const LineContextPair &included, *includes)
 
460
        if(!included.temporary)
 
461
          realIncluded << qMakePair(included.context.data(), SimpleCursor(included.sourceLine, 0));
 
462
        else
 
463
          realTemporaryIncluded << qMakePair(included.context.data(), SimpleCursor(included.sourceLine, 0));
 
464
 
 
465
      topLevelContext->addImportedParentContexts(realIncluded);
 
466
      topLevelContext->addImportedParentContexts(realTemporaryIncluded, true);
 
467
      
 
468
      topLevelContext->updateImportsCache();
 
469
    }
 
470
  }
 
471
 
 
472
  {
 
473
    DUChainReadLocker lock(DUChain::lock());
 
474
    //If we're debugging the current file, dump its preprocessed contents and the AST
 
475
    ifDebugFile( HashedString(file->identity().url().str()), { kDebug() << stringFromContents(editor()->parseSession()->contentsVector()); Cpp::DumpChain dump; dump.dump(node, editor()->parseSession()); } );
 
476
  }
 
477
 
 
478
  if(m_computeEmpty)
 
479
  {
 
480
    //Empty the top-context, in case we're updating
 
481
    DUChainWriteLocker lock(DUChain::lock());
 
482
    topLevelContext->cleanIfNotEncountered(QSet<DUChainBase*>());
 
483
  }else{
 
484
    node->ducontext = topLevelContext;
 
485
    supportBuild(node);
 
486
  }
 
487
 
 
488
  {
 
489
    LockedSmartInterface iface = editor()->smart();
 
490
    if (iface && topLevelContext->range().textRange() != iface.currentDocument()->documentRange()) {
 
491
      kDebug(9007) << "WARNING: Top-level context has wrong size: " << topLevelContext->range().textRange() << " should be: " << iface.currentDocument()->documentRange();
 
492
      topLevelContext->setRange( SimpleRange(iface.currentDocument()->documentRange()) );
 
493
    }
 
494
  }
 
495
 
 
496
  {
 
497
    DUChainReadLocker lock(DUChain::lock());
 
498
 
 
499
    kDebug(9007) << "built top-level context with" << topLevelContext->localDeclarations().size() << "declarations and" << topLevelContext->importedParentContexts().size() << "included files";
 
500
    //If we're debugging the current file, dump the du-chain and the smart ranges
 
501
    ifDebugFile( HashedString(file->identity().url().str()), { KDevelop::DumpChain dump; dump.dump(topLevelContext); if(topLevelContext->smartRange()) dump.dumpRanges(topLevelContext->smartRange()); } );
 
502
 
 
503
/*     if( m_recompiling ) {
 
504
      DumpChain dump;
 
505
      dump.dump(topLevelContext);
 
506
      kDebug(9007) << dump.dotGraph(topLevelContext);
 
507
     }*/
 
508
  }
 
509
 
 
510
  setCompilingContexts(false);
 
511
 
 
512
  if (!m_importedParentContexts.isEmpty()) {
 
513
    DUChainReadLocker lock(DUChain::lock());
 
514
    kWarning() << file->url().str() << "Previous parameter declaration context didn't get used??" ;
 
515
//    KDevelop::DumpChain dump;
 
516
//    dump.dump(topLevelContext);
 
517
    m_importedParentContexts.clear();
 
518
  }
 
519
 
 
520
 
 
521
  DUChainWriteLocker lock(DUChain::lock());
 
522
  topLevelContext->squeeze();
 
523
  return topLevelContext;
 
524
}
 
525
 
 
526
// KDevelop::DUContext* ContextBuilder::buildSubContexts(const HashedString& url, AST *node, KDevelop::DUContext* parent) {
 
527
//   setCompilingContexts(true);
 
528
//   setRecompiling(false);
 
529
//
 
530
//   editor()->setCurrentUrl(url);
 
531
//
 
532
//   node->ducontext = parent;
 
533
//
 
534
//   {
 
535
//     //copied out of supportBuild
 
536
//
 
537
//     openContext(node->ducontext);
 
538
//
 
539
//     editor()->setCurrentRange(editor()->topRange(EditorIntegrator::DefinitionUseChain));
 
540
//
 
541
//     visit (node);
 
542
//
 
543
//     closeContext();
 
544
//   }
 
545
//
 
546
//   setCompilingContexts(false);
 
547
//
 
548
//   if( node->ducontext == parent ) {
 
549
//     //The node's du-context should have been replaced!
 
550
//     //Maybe dump the node
 
551
//     kDebug(9007) << "Error in ContextBuilder::buildSubContexts(...): du-context was not replaced with new one";
 
552
//     DUChainWriteLocker lock(DUChain::lock());
 
553
//     delete node->ducontext;
 
554
//
 
555
//     node->ducontext = 0;
 
556
//   }
 
557
//
 
558
//   return node->ducontext;
 
559
// }
 
560
 
 
561
void ContextBuilder::visitNamespace (NamespaceAST *node)
 
562
{
 
563
  QualifiedIdentifier identifier;
 
564
  if (compilingContexts()) {
 
565
    DUChainReadLocker lock(DUChain::lock());
 
566
 
 
567
    if (node->namespace_name)
 
568
      identifier.push(QualifiedIdentifier(editor()->tokenToString(node->namespace_name)));
 
569
  }
 
570
 
 
571
  size_t realStart = node->start_token;
 
572
  
 
573
  if(node->namespace_name) //Move the start behind the name, the simple + hacky way
 
574
    node->start_token = node->namespace_name+1;
 
575
  
 
576
  openContext(node, DUContext::Namespace, identifier);
 
577
  
 
578
  node->start_token = realStart;
 
579
 
 
580
  DefaultVisitor::visitNamespace (node);
 
581
 
 
582
  closeContext();
 
583
}
 
584
 
 
585
void ContextBuilder::visitEnumSpecifier(EnumSpecifierAST* node)
 
586
{
 
587
  if(m_onlyComputeSimplified)
 
588
    return;
 
589
  
 
590
  //The created context must be unnamed, so the enumerators can be found globally with the correct scope
 
591
  openContext(node, DUContext::Enum, 0 );
 
592
 
 
593
  {
 
594
    DUChainWriteLocker lock(DUChain::lock());
 
595
    currentContext()->setPropagateDeclarations(true);
 
596
  }
 
597
 
 
598
  DefaultVisitor::visitEnumSpecifier(node);
 
599
 
 
600
  closeContext();
 
601
}
 
602
 
 
603
void ContextBuilder::classContextOpened(ClassSpecifierAST *node, DUContext* context)
 
604
{
 
605
  Q_UNUSED(node);
 
606
  Q_UNUSED(context);
 
607
}
 
608
 
 
609
void ContextBuilder::visitClassSpecifier (ClassSpecifierAST *node)
 
610
{
 
611
  //We only use the local identifier here, because we build a prefix-context around
 
612
  ///@todo think about this.
 
613
  QualifiedIdentifier id;
 
614
  if(node->name) {
 
615
    NameCompiler nc(editor()->parseSession());
 
616
    nc.run(node->name);
 
617
    id = nc.identifier();
 
618
  }
 
619
 
 
620
  openContext(node, editor()->findRangeForContext(node->name ? node->name->end_token : node->start_token, node->end_token), DUContext::Class, id.isEmpty() ? QualifiedIdentifier() : QualifiedIdentifier(id.last()) );
 
621
  addImportedContexts(); //eventually add template-context
 
622
 
 
623
  if(!node->name) {
 
624
 
 
625
    int kind = editor()->parseSession()->token_stream->kind(node->class_key);
 
626
 
 
627
    if ((kind == Token_union || id.isEmpty())) {
 
628
      //It's an unnamed union context, or an unnamed struct, propagate the declarations to the parent
 
629
      DUChainWriteLocker lock(DUChain::lock());
 
630
        
 
631
      if(kind == Token_enum || kind == Token_union || m_typeSpecifierWithoutInitDeclarators == node->start_token) {
 
632
        ///@todo Mark unions in the duchain in some way, instead of just representing them as a class
 
633
        currentContext()->setInSymbolTable(currentContext()->parentContext()->inSymbolTable());
 
634
        currentContext()->setPropagateDeclarations(true);
 
635
      }
 
636
    }
 
637
  }
 
638
  
 
639
  classContextOpened(node, currentContext());
 
640
 
 
641
  DefaultVisitor::visitClassSpecifier (node);
 
642
 
 
643
  closeContext();
 
644
}
 
645
 
 
646
void ContextBuilder::visitTypedef (TypedefAST *node)
 
647
{
 
648
  DefaultVisitor::visitTypedef (node);
 
649
 
 
650
  // Didn't get claimed if it was still set
 
651
  m_importedParentContexts.clear();
 
652
}
 
653
 
 
654
void ContextBuilder::visitFunctionDefinition (FunctionDefinitionAST *node)
 
655
{
 
656
  PushValue<bool> push(m_inFunctionDefinition, (bool)node->function_body);
 
657
 
 
658
  QualifiedIdentifier functionName;
 
659
  if (compilingContexts() && node->init_declarator && node->init_declarator->declarator && node->init_declarator->declarator->id) {
 
660
    identifierForNode(node->init_declarator->declarator->id, functionName);
 
661
 
 
662
    if (functionName.count() >= 2) {
 
663
      
 
664
      // This is a class function definition
 
665
      DUChainReadLocker lock(DUChain::lock());
 
666
      QualifiedIdentifier currentScope = currentContext()->scopeIdentifier(true);
 
667
      QualifiedIdentifier className = currentScope + functionName;
 
668
      className.pop();
 
669
      className.setExplicitlyGlobal(true);
 
670
      
 
671
      QList<Declaration*> classDeclarations = currentContext()->findDeclarations(className);
 
672
 
 
673
      if (classDeclarations.count() != 0 && classDeclarations.first()->internalContext()) {
 
674
        queueImportedContext(classDeclarations.first()->internalContext());
 
675
        
 
676
        QualifiedIdentifier newFunctionName(className);
 
677
        newFunctionName.push(functionName.last());
 
678
        if(newFunctionName.count() > currentScope.count())
 
679
          functionName = newFunctionName.mid(currentScope.count());
 
680
      }
 
681
    }
 
682
  }
 
683
  visitFunctionDeclaration(node);
 
684
 
 
685
  if(!m_onlyComputeVisible) { //If we only compute the publically visible, we don't need to go into function bodies
 
686
    m_openingFunctionBody = functionName;
 
687
 
 
688
    
 
689
    if (node->constructor_initializers && node->function_body) {
 
690
      //Since we put the context around the context for the compound statement, it also gets the local scope identifier.
 
691
      openContext(node->constructor_initializers, node->function_body, DUContext::Other, m_openingFunctionBody); //The constructor initializer context
 
692
      addImportedContexts();
 
693
      m_openingFunctionBody = QualifiedIdentifier();
 
694
    }
 
695
    // Otherwise, the context is created in the function body visit
 
696
 
 
697
    visit(node->constructor_initializers);
 
698
    visit(node->function_body);
 
699
    m_openingFunctionBody = QualifiedIdentifier();
 
700
 
 
701
    if (node->constructor_initializers) {
 
702
      closeContext();
 
703
    }
 
704
  }
 
705
  
 
706
  visit(node->win_decl_specifiers);
 
707
  // If still defined, not needed
 
708
  m_importedParentContexts.clear();
 
709
}
 
710
 
 
711
void ContextBuilder::visitFunctionDeclaration (FunctionDefinitionAST* node)
 
712
{
 
713
  visit(node->type_specifier);
 
714
  visit(node->init_declarator);
 
715
}
 
716
 
 
717
DUContext* ContextBuilder::openContextEmpty(AST* rangeNode, DUContext::ContextType type)
 
718
{
 
719
  if (compilingContexts()) {
 
720
#ifdef DEBUG_UPDATE_MATCHING
 
721
    kDebug() << "opening context with text" << editor()->tokensToStrings( rangeNode->start_token, rangeNode->end_token );
 
722
#endif
 
723
    KDevelop::SimpleRange range = editor()->findRangeForContext(rangeNode->start_token, rangeNode->end_token);
 
724
    range.end = range.start;
 
725
    DUContext* ret = openContextInternal(range, type, QualifiedIdentifier());
 
726
    rangeNode->ducontext = ret;
 
727
    return ret;
 
728
 
 
729
  } else {
 
730
    openContext(rangeNode->ducontext);
 
731
    {
 
732
      LockedSmartInterface iface = editor()->smart();
 
733
      editor()->setCurrentRange(iface, currentContext()->smartRange());
 
734
    }
 
735
    return currentContext();
 
736
  }
 
737
}
 
738
 
 
739
DUContext* ContextBuilder::openContextInternal(const KDevelop::SimpleRange& range, DUContext::ContextType type, const QualifiedIdentifier& identifier)
 
740
{
 
741
  DUContext* ret = ContextBuilderBase::openContextInternal(range, type, identifier);
 
742
 
 
743
  {
 
744
    DUChainWriteLocker lock(DUChain::lock());
 
745
    static_cast<CppDUContext<DUContext>*>(ret)->deleteAllInstantiations();
 
746
  }
 
747
  
 
748
  /**
 
749
   * @todo either remove this here and add it to the correct other places, or remove it in the over places.
 
750
   * The problem: For template-parameter contexts this needs to be imported into function-parameter contexts
 
751
   * and into class-contexts, directly when they are opened. Maybe it is easier leaving it here.
 
752
   * */
 
753
  addImportedContexts();
 
754
 
 
755
  return ret;
 
756
}
 
757
 
 
758
DUContext* ContextBuilder::newContext(const SimpleRange& range)
 
759
{
 
760
  return new CppDUContext<DUContext>(range, currentContext());
 
761
}
 
762
 
 
763
#ifdef DEBUG_CONTEXT_RANGES
 
764
void ContextBuilder::checkRanges()
 
765
{
 
766
  for(QHash<KDevelop::DUContext*, KDevelop::SimpleRange>::iterator it = m_contextRanges.begin(); it != m_contextRanges.end(); ) {
 
767
    if(it.key()->range() != *it) {
 
768
      kDebug(9007) << "Range of" << it.key()->scopeIdentifier(true).toString() << "changed from" << (*it).textRange() << "to" << it.key()->range().textRange() << "at\n" << kBacktrace();
 
769
      it = m_contextRanges.erase(it); //Remove it so we see each change only once
 
770
    }else{
 
771
      ++it;
 
772
    }
 
773
  }
 
774
}
 
775
#endif
 
776
 
 
777
void ContextBuilder::visitCompoundStatement(CompoundStatementAST * node)
 
778
{
 
779
  openContext(node, DUContext::Other, m_openingFunctionBody);
 
780
  m_openingFunctionBody.clear();
 
781
 
 
782
  addImportedContexts();
 
783
 
 
784
  DefaultVisitor::visitCompoundStatement(node);
 
785
 
 
786
  closeContext();
 
787
}
 
788
 
 
789
void ContextBuilder::preVisitSimpleDeclaration(SimpleDeclarationAST * node) {
 
790
  if(!node->init_declarators && node->type_specifier)
 
791
    m_typeSpecifierWithoutInitDeclarators = node->type_specifier->start_token;
 
792
}
 
793
 
 
794
void ContextBuilder::visitSimpleDeclaration(SimpleDeclarationAST *node)
 
795
{
 
796
  preVisitSimpleDeclaration(node);
 
797
  
 
798
  DefaultVisitor::visitSimpleDeclaration(node);
 
799
 
 
800
  // Didn't get claimed if it was still set
 
801
  m_importedParentContexts.clear();
 
802
}
 
803
 
 
804
void ContextBuilder::visitPostSimpleDeclaration(SimpleDeclarationAST*)
 
805
{
 
806
  // Didn't get claimed if it was still set
 
807
  m_importedParentContexts.clear();
 
808
}
 
809
 
 
810
void ContextBuilder::visitName (NameAST *)
 
811
{
 
812
  // Note: we don't want to visit the name node, the name compiler does that for us (only when we need it)
 
813
}
 
814
 
 
815
void ContextBuilder::visitUsing(UsingAST* node)
 
816
{
 
817
  // TODO store the using
 
818
  DefaultVisitor::visitUsing(node);
 
819
}
 
820
 
 
821
/**
 
822
 * This class is used to decide whether something is an expression or a declaration
 
823
 * Maybe using it is overkill
 
824
 * @todo Check how to do the test fast and correctly
 
825
 * */
 
826
class VerifyExpressionVisitor : public Cpp::ExpressionVisitor {
 
827
  public:
 
828
    VerifyExpressionVisitor(ParseSession* session) : Cpp::ExpressionVisitor(session), result(true) {
 
829
    }
 
830
    virtual void problem(AST* /*node*/, const QString& /*str*/) {
 
831
      result = false;
 
832
    }
 
833
 
 
834
    bool result;
 
835
};
 
836
 
 
837
class IdentifierVerifier : public DefaultVisitor
 
838
{
 
839
public:
 
840
  IdentifierVerifier(ContextBuilder* _builder, const SimpleCursor& _cursor)
 
841
    : builder(_builder)
 
842
    , result(true)
 
843
    , cursor(_cursor)
 
844
  {
 
845
  }
 
846
 
 
847
  ContextBuilder* builder;
 
848
  bool result; //Will be true when this should be an expression, else false.
 
849
  SimpleCursor cursor;
 
850
 
 
851
  void visitPostfixExpression(PostfixExpressionAST* node)
 
852
  {
 
853
    if( node->expression && node->expression->kind == AST::Kind_PrimaryExpression &&
 
854
        node->sub_expressions ) {
 
855
      const ListNode<ExpressionAST*> *it = node->sub_expressions->toFront(), *end = it;
 
856
      if( it->element && it->element->kind == AST::Kind_FunctionCall && it->next == end ) {
 
857
        ///Special-case: We have a primary expression with a function-call, always treat that as an expression.
 
858
        return;
 
859
      }
 
860
    }
 
861
    //First evaluate the primary expression, and then pass the result from sub-expression to sub-expression through m_lastType
 
862
 
 
863
    visit(node->expression);
 
864
 
 
865
    if( !node->sub_expressions )
 
866
      return;
 
867
    visitNodes( this, node->sub_expressions );
 
868
  }
 
869
 
 
870
  virtual void visitName (NameAST * node)
 
871
  {
 
872
    if (result) {
 
873
      QualifiedIdentifier id;
 
874
      builder->identifierForNode(node, id);
 
875
      if (!builder->currentContext()->findDeclarations(id, cursor).isEmpty()) {
 
876
        result = false;
 
877
      }else{
 
878
      }
 
879
    }
 
880
  }
 
881
};
 
882
 
 
883
void ContextBuilder::visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST* node)
 
884
{
 
885
  if(m_onlyComputeSimplified) {
 
886
    visit(node->declaration);
 
887
    return;
 
888
  }
 
889
  
 
890
  DUContext::ContextType type;
 
891
  {
 
892
    DUChainReadLocker lock(DUChain::lock());
 
893
    type = currentContext()->type();
 
894
  }
 
895
 
 
896
  switch (type) {
 
897
    case DUContext::Global:
 
898
    case DUContext::Namespace:
 
899
    case DUContext::Class:
 
900
    case DUContext::Helper:
 
901
    case DUContext::Enum:
 
902
      visit(node->declaration);
 
903
      break;
 
904
 
 
905
    case DUContext::Function:
 
906
    case DUContext::Other:
 
907
      if (compilingContexts()) {
 
908
        DUChainReadLocker lock(DUChain::lock());
 
909
/*        VerifyExpressionVisitor iv(editor()->parseSession());
 
910
 
 
911
        node->expression->ducontext = currentContext();
 
912
        iv.parse(node->expression);*/
 
913
        IdentifierVerifier iv(this, SimpleCursor(editor()->findPosition(node->start_token)));
 
914
        iv.visit(node->expression);
 
915
        //kDebug(9007) << editor()->findPosition(node->start_token) << "IdentifierVerifier returned" << iv.result;
 
916
        node->expressionChosen = iv.result;
 
917
      }
 
918
 
 
919
      if (node->expressionChosen)
 
920
        visit(node->expression);
 
921
      else
 
922
        visit(node->declaration);
 
923
      break;
 
924
    case DUContext::Template:
 
925
      break;
 
926
  }
 
927
}
 
928
 
 
929
void ContextBuilder::visitForStatement(ForStatementAST *node)
 
930
{
 
931
  // Not setting the member var because it gets nuked in visitSimpleDeclaration
 
932
  AST* first = node->init_statement;
 
933
  if (!first)
 
934
    first = node->condition;
 
935
  if (!first)
 
936
    first = node->expression;
 
937
  if (!first)
 
938
    return;
 
939
 
 
940
  AST* second = node->expression;
 
941
  if (!second)
 
942
    second = node->condition;
 
943
  if (!second)
 
944
    second = node->init_statement;
 
945
 
 
946
  DUContext* secondParentContext = openContext(first, second, DUContext::Other);
 
947
 
 
948
  visit(node->init_statement);
 
949
  visit(node->condition);
 
950
  visit(node->expression);
 
951
 
 
952
  closeContext();
 
953
 
 
954
  if (node->statement) {
 
955
    const bool contextNeeded = createContextIfNeeded(node->statement, secondParentContext);
 
956
 
 
957
    visit(node->statement);
 
958
 
 
959
    if (contextNeeded)
 
960
      closeContext();
 
961
  }
 
962
 
 
963
  // Didn't get claimed if it was still set
 
964
  m_importedParentContexts.clear();
 
965
}
 
966
 
 
967
void ContextBuilder::createTypeForInitializer(InitializerAST* /*node*/) {
 
968
}
 
969
 
 
970
void ContextBuilder::closeTypeForInitializer(InitializerAST* /*node*/) {
 
971
}
 
972
 
 
973
void ContextBuilder::createTypeForDeclarator(DeclaratorAST* /*node*/) {
 
974
}
 
975
 
 
976
void ContextBuilder::closeTypeForDeclarator(DeclaratorAST* /*node*/) {
 
977
}
 
978
 
 
979
void ContextBuilder::visitParameterDeclarationClause(ParameterDeclarationClauseAST* node)
 
980
{
 
981
  //Don't assign the initializer to parameter-declarations
 
982
  InitializerAST* oldCurrentInitializer = m_currentInitializer;
 
983
  m_currentInitializer = 0;
 
984
  
 
985
  DefaultVisitor::visitParameterDeclarationClause(node);
 
986
  
 
987
  m_currentInitializer = oldCurrentInitializer;
 
988
}
 
989
 
 
990
void ContextBuilder::visitInitDeclarator(InitDeclaratorAST *node)
 
991
{
 
992
  QualifiedIdentifier id;
 
993
  if(node->declarator && node->declarator->id && node->declarator->id->qualified_names && (!node->declarator->parameter_declaration_clause || node->declarator->parameter_is_initializer)) {
 
994
    //Build a prefix-context for external variable-definitions
 
995
    SimpleCursor pos = editor()->findPosition(node->start_token, KDevelop::EditorIntegrator::FrontEdge);
 
996
    identifierForNode(node->declarator->id, id);
 
997
    
 
998
    openPrefixContext(node, id, pos);
 
999
  }
 
1000
 
 
1001
  m_currentInitializer = node->initializer;
 
1002
  if(node->declarator)
 
1003
    visitDeclarator(node->declarator);
 
1004
  if(node->initializer)
 
1005
    visitInitializer(node->initializer);
 
1006
  m_currentInitializer = 0;
 
1007
  
 
1008
  closePrefixContext(id);
 
1009
}
 
1010
 
 
1011
void ContextBuilder::visitDeclarator(DeclaratorAST *node) {
 
1012
  
 
1013
  //BEGIN Copied from default visitor
 
1014
  visit(node->sub_declarator);
 
1015
  visitNodes(this, node->ptr_ops);
 
1016
  visit(node->id);
 
1017
  visit(node->bit_expression);
 
1018
  //END Finished with first part of default visitor
 
1019
 
 
1020
  if(m_onlyComputeSimplified)
 
1021
    return;
 
1022
 
 
1023
  createTypeForDeclarator(node);
 
1024
  
 
1025
  if(m_currentInitializer) //Needs to be visited now, so the type-builder can use the initializer to build a constant integral tyoe
 
1026
    createTypeForInitializer(m_currentInitializer); 
 
1027
 
 
1028
  if (node->parameter_declaration_clause && (compilingContexts() || node->parameter_declaration_clause->ducontext)) {
 
1029
    DUContext* ctx = openContext(node->parameter_declaration_clause, DUContext::Function, node->id);
 
1030
    addImportedContexts();
 
1031
    if(compilingContexts())
 
1032
      queueImportedContext(ctx);
 
1033
  }
 
1034
 
 
1035
  //BEGIN Copied from default visitor
 
1036
  visitNodes(this, node->array_dimensions);
 
1037
  visit(node->parameter_declaration_clause);
 
1038
  visit(node->exception_spec);
 
1039
  //END Finished with default visitor
 
1040
 
 
1041
  if(m_currentInitializer)
 
1042
    closeTypeForInitializer(m_currentInitializer);
 
1043
  
 
1044
  closeTypeForDeclarator(node);
 
1045
 
 
1046
  if (node->parameter_declaration_clause && (compilingContexts() || node->parameter_declaration_clause->ducontext))
 
1047
    closeContext();
 
1048
}
 
1049
 
 
1050
void ContextBuilder::addImportedContexts()
 
1051
{
 
1052
  if (compilingContexts() && !m_importedParentContexts.isEmpty()) {
 
1053
    DUChainWriteLocker lock(DUChain::lock());
 
1054
 
 
1055
    foreach (const DUContext::Import& imported, m_importedParentContexts)
 
1056
      if(DUContext* imp = imported.context(topContext()))
 
1057
        addImportedParentContextSafely(currentContext(), imp);
 
1058
 
 
1059
    //Move on the internal-context of Declarations/Definitions
 
1060
    foreach( const DUContext::Import& importedContext, m_importedParentContexts )  {
 
1061
      if( DUContext* imp = importedContext.context(topContext()) )
 
1062
        if( imp->type() == DUContext::Template || imp->type() == DUContext::Function )
 
1063
          if( imp->owner() && imp->owner()->internalContext() == imp )
 
1064
            imp->owner()->setInternalContext(currentContext());
 
1065
    }
 
1066
 
 
1067
    m_importedParentContexts.clear();
 
1068
  }
 
1069
  clearLastContext();
 
1070
}
 
1071
 
 
1072
void ContextBuilder::setInSymbolTable(KDevelop::DUContext* context) {
 
1073
  if(context->type() == DUContext::Class) {
 
1074
    //Do not put unnamed/unique structs and all their members into the symbol-table
 
1075
    QualifiedIdentifier scopeId = context->localScopeIdentifier();
 
1076
    if(scopeId.isEmpty() || (scopeId.count() == 1 && scopeId.first().isUnique())) {
 
1077
      context->setInSymbolTable(false);
 
1078
      return;
 
1079
    }
 
1080
  }
 
1081
  ContextBuilderBase::setInSymbolTable(context);
 
1082
}
 
1083
 
 
1084
void ContextBuilder::visitIfStatement(IfStatementAST* node)
 
1085
{
 
1086
  // Not setting the member var because it gets nuked in visitSimpleDeclaration
 
1087
  DUContext* secondParentContext = openContext(node->condition, DUContext::Other);
 
1088
 
 
1089
  visit(node->condition);
 
1090
 
 
1091
  closeContext();
 
1092
 
 
1093
  if (node->statement) {
 
1094
    const bool contextNeeded = createContextIfNeeded(node->statement, secondParentContext);
 
1095
 
 
1096
    visit(node->statement);
 
1097
 
 
1098
    if (contextNeeded)
 
1099
      closeContext();
 
1100
  }
 
1101
 
 
1102
  if (node->else_statement) {
 
1103
    const bool contextNeeded = createContextIfNeeded(node->else_statement, secondParentContext);
 
1104
 
 
1105
    visit(node->else_statement);
 
1106
 
 
1107
    if (contextNeeded)
 
1108
      closeContext();
 
1109
  }
 
1110
}
 
1111
 
 
1112
void ContextBuilder::visitDoStatement(DoStatementAST *node)
 
1113
{
 
1114
  if(!node->statement) {
 
1115
    kWarning() << "error, no statement"; //Warning instead of crashing here
 
1116
    return;
 
1117
  }
 
1118
  //We don't need to create a context for compound-statements, since those create a context by themselves
 
1119
  if(node->statement->kind != AST::Kind_CompoundStatement) {
 
1120
    openContext(node->statement, DUContext::Other);
 
1121
 
 
1122
    visit(node->statement);
 
1123
 
 
1124
    closeContext();
 
1125
  }else{
 
1126
    visit(node->statement);
 
1127
  }
 
1128
 
 
1129
  if (node->expression) {
 
1130
    const bool contextNeeded = createContextIfNeeded(node->expression, lastContext());
 
1131
 
 
1132
    visit(node->expression);
 
1133
 
 
1134
    if (contextNeeded)
 
1135
      closeContext();
 
1136
  }
 
1137
}
 
1138
 
 
1139
void ContextBuilder::visitTryBlockStatement(TryBlockStatementAST *node)
 
1140
{
 
1141
  QVector<DUContext::Import> parentContextsToImport = m_importedParentContexts;
 
1142
 
 
1143
  if(node->try_block->kind != AST::Kind_CompoundStatement) {
 
1144
    openContext(node->try_block, DUContext::Other, m_openingFunctionBody);
 
1145
    m_openingFunctionBody.clear();
 
1146
    addImportedContexts();
 
1147
 
 
1148
    visit(node->try_block);
 
1149
 
 
1150
    closeContext();
 
1151
  }else{
 
1152
    //Do not double-open a context on the same node, because that will lead to problems in the mapping
 
1153
    //and failures in use-building
 
1154
    visit(node->try_block);
 
1155
  }
 
1156
 
 
1157
  m_tryParentContexts.push(parentContextsToImport);
 
1158
 
 
1159
  visitNodes(this, node->catch_blocks);
 
1160
 
 
1161
  m_tryParentContexts.pop();
 
1162
}
 
1163
 
 
1164
void ContextBuilder::visitCatchStatement(CatchStatementAST *node)
 
1165
{
 
1166
  QVector<DUContext::Import> contextsToImport;
 
1167
 
 
1168
  if (node->condition) {
 
1169
    DUContext* secondParentContext = openContext(node->condition, DUContext::Other);
 
1170
    
 
1171
    {
 
1172
      DUChainReadLocker lock(DUChain::lock());
 
1173
      contextsToImport.append(DUContext::Import(secondParentContext, 0));
 
1174
    }
 
1175
 
 
1176
    visit(node->condition);
 
1177
 
 
1178
    closeContext();
 
1179
  }
 
1180
 
 
1181
  contextsToImport += m_tryParentContexts.top();
 
1182
 
 
1183
  if (node->statement) {
 
1184
    const bool contextNeeded = createContextIfNeeded(node->statement, contextsToImport);
 
1185
 
 
1186
    visit(node->statement);
 
1187
 
 
1188
    if (contextNeeded)
 
1189
      closeContext();
 
1190
  }
 
1191
}
 
1192
 
 
1193
bool ContextBuilder::createContextIfNeeded(AST* node, DUContext* importedParentContext)
 
1194
{
 
1195
  QVector<DUContext::Import> imports;
 
1196
  {
 
1197
    DUChainReadLocker lock(DUChain::lock());
 
1198
    imports << DUContext::Import(importedParentContext, 0);
 
1199
  }
 
1200
  
 
1201
  return createContextIfNeeded(node, imports);
 
1202
}
 
1203
 
 
1204
bool ContextBuilder::createContextIfNeeded(AST* node, const QVector<DUContext::Import>& importedParentContexts)
 
1205
{
 
1206
  m_importedParentContexts = importedParentContexts;
 
1207
 
 
1208
  const bool contextNeeded = !ast_cast<CompoundStatementAST*>(node);
 
1209
  if (contextNeeded) {
 
1210
    openContext(node, DUContext::Other);
 
1211
    addImportedContexts();
 
1212
  }
 
1213
  return contextNeeded;
 
1214
}
 
1215
 
 
1216
void ContextBuilder::identifierForNode(NameAST* id, TypeSpecifierAST** typeSpecifier, QualifiedIdentifier& target)
 
1217
{
 
1218
  if( !id ) {
 
1219
    target = QualifiedIdentifier();
 
1220
  }
 
1221
 
 
1222
  m_nameCompiler->run(id, &target);
 
1223
  if( typeSpecifier )
 
1224
    *typeSpecifier = m_nameCompiler->lastTypeSpecifier();
 
1225
}
 
1226
 
 
1227
bool ContextBuilder::smart() const {
 
1228
  return editor()->smart();
 
1229
}