void NameResolver::registerFunction(FunctionSymbol *sym) { Scope *scope = sym->scope(); assert(scope == globals_); Symbol *other = scope->localLookup(sym->name()); if (!other) { scope->addSymbol(sym); return; } // If |other| is not a function, it's an error. FunctionSymbol *orig = other->asFunction(); if (!orig) { reportRedeclaration(sym, other); return; } // If both have bodies, it's an error. FunctionStatement *sym_node = sym->node()->toFunctionStatement(); FunctionStatement *orig_node = orig->node()->toFunctionStatement(); if (sym_node->body() && orig_node->body()) { reportRedeclaration(sym, other); return; } // Build a shadow list, containing all symbols with this name. orig->addShadow(orig_node); orig->addShadow(sym_node); sym_node->setShadowed(orig); }
// TODO: remove me, this is taken from cppeditor.cpp. Find some common place for this method static Document::Ptr findDefinition(const Function *functionDeclaration, int *line) { CppTools::CppModelManagerInterface *cppModelManager = cppModelManagerInstance(); if (!cppModelManager) return Document::Ptr(); QVector<const Name *> qualifiedName; Scope *scope = functionDeclaration->scope(); for (; scope; scope = scope->enclosingScope()) { if (scope->isClassScope() || scope->isNamespaceScope()) { if (scope->owner() && scope->owner()->name()) { const Name *scopeOwnerName = scope->owner()->name(); if (const QualifiedNameId *q = scopeOwnerName->asQualifiedNameId()) { for (unsigned i = 0; i < q->nameCount(); ++i) { qualifiedName.prepend(q->nameAt(i)); } } else { qualifiedName.prepend(scopeOwnerName); } } } } qualifiedName.append(functionDeclaration->name()); Control control; const QualifiedNameId *q = control.qualifiedNameId(&qualifiedName[0], qualifiedName.size()); LookupContext context(&control); const Snapshot documents = cppModelManager->snapshot(); foreach (Document::Ptr doc, documents) { QList<Scope *> visibleScopes; visibleScopes.append(doc->globalSymbols()); visibleScopes = context.expand(visibleScopes); foreach (Scope *visibleScope, visibleScopes) { Symbol *symbol = 0; if (const NameId *nameId = q->unqualifiedNameId()->asNameId()) symbol = visibleScope->lookat(nameId->identifier()); else if (const DestructorNameId *dtorId = q->unqualifiedNameId()->asDestructorNameId()) symbol = visibleScope->lookat(dtorId->identifier()); else if (const TemplateNameId *templNameId = q->unqualifiedNameId()->asTemplateNameId()) symbol = visibleScope->lookat(templNameId->identifier()); else if (const OperatorNameId *opId = q->unqualifiedNameId()->asOperatorNameId()) symbol = visibleScope->lookat(opId->kind()); // ### cast operators for (; symbol; symbol = symbol->next()) { if (! symbol->isFunction()) continue; else if (! isCompatible(symbol->asFunction(), functionDeclaration, q)) continue; *line = symbol->line(); // TODO: shift the line so that we are inside a function. Maybe just find the nearest '{'? return doc; } }
void SemanticAnalysis::visitNameProxy(NameProxy *proxy) { Symbol *sym = proxy->sym(); VariableSymbol *var = sym->asVariable(); // If we see that a symbol is a function literal, then we bypass the scope // chain operations entirely and hardcode the function literal. if (sym->isFunction()) { assert(sym->scope()->kind() == Scope::Global); hir_ = new (pool_) HFunction(proxy, sym->asFunction()); return; } if (value_context_ == kLValue) { // Egads! We're being asked to construct an l-value instead of an r-value. *outp_ = LValue(var); return; } Scope *in = sym->scope(); switch (in->kind()) { case Scope::Global: hir_ = new (pool_) HGlobal(proxy, var); return; case Scope::Function: { assert(var->storage() == VariableSymbol::Arg); // Since we're in an r-value context, we need to strip the reference type. Type *type = var->type(); if (type->isReference()) type = type->toReference()->contained(); hir_ = new (pool_) HLocal(proxy, type, var); return; } default: assert(in->kind() == Scope::Block); assert(var->storage() == VariableSymbol::Local); hir_ = new (pool_) HLocal(proxy, var->type(), var); return; } }
QList<CppQuickFixOperation::Ptr> InsertQtPropertyMembers::match(const CppQuickFixState &state) { const QList<AST *> &path = state.path(); if (path.isEmpty()) return noResult(); AST * const ast = path.last(); QtPropertyDeclarationAST *qtPropertyDeclaration = ast->asQtPropertyDeclaration(); if (!qtPropertyDeclaration) return noResult(); ClassSpecifierAST *klass = 0; for (int i = path.size() - 2; i >= 0; --i) { klass = path.at(i)->asClassSpecifier(); if (klass) break; } if (!klass) return noResult(); CppRefactoringChanges refactoring(state.snapshot()); const CppRefactoringFile &file = refactoring.file(state.document()->fileName()); const QString propertyName = file.textOf(qtPropertyDeclaration->property_name); QString getterName; QString setterName; QString signalName; int generateFlags = 0; for (QtPropertyDeclarationItemListAST *it = qtPropertyDeclaration->property_declaration_item_list; it; it = it->next) { const QString tokenString = file.tokenAt(it->value->item_name_token).spell(); if (tokenString == QLatin1String("READ")) { getterName = file.textOf(it->value->expression); generateFlags |= GenerateGetter; } else if (tokenString == QLatin1String("WRITE")) { setterName = file.textOf(it->value->expression); generateFlags |= GenerateSetter; } else if (tokenString == QLatin1String("NOTIFY")) { signalName = file.textOf(it->value->expression); generateFlags |= GenerateSignal; } } QString storageName = QString("m_%1").arg(propertyName); generateFlags |= GenerateStorage; Class *c = klass->symbol; Overview overview; for (unsigned i = 0; i < c->memberCount(); ++i) { Symbol *member = c->memberAt(i); FullySpecifiedType type = member->type(); if (member->asFunction() || (type.isValid() && type->asFunctionType())) { const QString name = overview(member->name()); if (name == getterName) { generateFlags &= ~GenerateGetter; } else if (name == setterName) { generateFlags &= ~GenerateSetter; } else if (name == signalName) { generateFlags &= ~GenerateSignal; } } else if (member->asDeclaration()) { const QString name = overview(member->name()); if (name == storageName) generateFlags &= ~GenerateStorage; } } if (getterName.isEmpty() && setterName.isEmpty() && signalName.isEmpty()) return noResult(); return singleResult(new Operation(state, path.size() - 1, qtPropertyDeclaration, c, generateFlags, getterName, setterName, signalName, storageName)); }