📄 semantic.cpp
字号:
Member *member = candidates.at(0); Q_ASSERT(member); TypeMember *typeMember = member->toTypeMember(); if (typeMember) { Q_ASSERT(typeMember->type()); ClassType *classType = typeMember->type()->toClassType(); if (classType) { klass->addBaseClass(classType); } } } }}void Semantic::parseFunctionArguments(const DeclaratorAST *declarator, CodeModel::FunctionMember *method){ if(!declarator || !method) return; ParameterDeclarationClauseAST *clause = declarator->parameterDeclarationClause(); if (clause && clause->parameterDeclarationList()){ ParameterDeclarationListAST *params = clause->parameterDeclarationList(); List<ParameterDeclarationAST*> *l = params->parameterList(); if (!l) return; foreach (ParameterDeclarationAST *param, *l) { CodeModel::Argument *arg = CodeModel::Create<CodeModel::Argument>(m_storage); arg->setParent(method); if (param->declarator()){ QByteArray text = declaratorToString(param->declarator(), QByteArray(), true); if(param->declarator()->declaratorId()) arg->setNameToken(tokenRefFromAST(param->declarator()->declaratorId()->unqualifiedName())); if (!text.isEmpty()) arg->setName(text); } QByteArray tp = typeOfDeclaration(param->typeSpec(), param->declarator()); if (!tp.isEmpty()) { CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage); type->setName(tp); arg->setType(type); } method->addArgument(arg); } }}// using directive (using namespace A)void Semantic::parseUsingDirective(UsingDirectiveAST *ast){ QByteArray qualifiedname = textOf(ast->name()); QByteArray name = textOf(ast->name()->unqualifiedName()); //look up target namespace name QList<Member *> memberList = nameLookup(currentScope.top(), ast->name()); NamespaceScope *targetNamespace = 0; // search for namespace in member list. QList<Member *>::ConstIterator it = memberList.constBegin(); while(it != memberList.constEnd()) { if (NamespaceMember *namespaceMember = (*it)->toNamespaceMember()) { targetNamespace = namespaceMember->namespaceScope(); break; } ++it; } if (targetNamespace == 0) return; // Find the insertion namespace, which is the first common // ancesotor namespace for the current scope and the target namespace // currentScope might be a block scope, find its first namespace parent CodeModel::Scope *currentParent = currentScope.top(); while (currentParent->toNamespaceScope() == 0) { currentParent = currentParent->parent(); } CodeModel::Scope *namespaceA = currentParent; while (namespaceA != 0) { CodeModel::Scope *namespaceB = targetNamespace; while (namespaceB != 0) { if (namespaceB == namespaceA) break; namespaceB = namespaceB->parent(); } if (namespaceB == namespaceA) break; namespaceA = namespaceA->parent(); } if (namespaceA == 0 || namespaceA->toNamespaceScope() == 0) return; NamespaceScope *insertionNamespace = namespaceA->toNamespaceScope(); // Create using directive link UsingDirectiveLink *usingDirectiveLink = Create<UsingDirectiveLink>(m_storage); usingDirectiveLink->setParent(currentScope.top()); usingDirectiveLink->setTargetNamespace(targetNamespace); usingDirectiveLink->setInsertionNamespace(insertionNamespace); // add it to current namespace if (NamespaceScope *namespaceScope = currentScope.top()->toNamespaceScope()) namespaceScope->addUsingDirectiveLink(usingDirectiveLink); else if (BlockScope *blockScope = currentScope.top()->toBlockScope()) blockScope->addUsingDirectiveLink(usingDirectiveLink);}void Semantic::parseFunctionDefinition(FunctionDefinitionAST *ast){ AST *funSpec = ast->functionSpecifier(); AST *storageSpec = ast->storageSpecifier(); TypeSpecifierAST *typeSpec = ast->typeSpec(); InitDeclaratorAST *initDeclarator = ast->initDeclarator(); if (!ast->initDeclarator()) return; DeclaratorAST *d = initDeclarator->declarator(); if (!d->declaratorId()) return; parseFunctionDeclaration(funSpec, storageSpec, typeSpec, initDeclarator); CodeModel::FunctionMember *method = functionLookup(currentScope.top(), d); if(!method) { emit error("Error in Semantic::parseFunctionDefinition: Could not find declaration for function definition"); return; } CodeModel::Scope *parent = method->parent(); if(!ast->functionBody()) { emit error("Error in Semantic::parseFunctionDefinition: no function body in function definition"); return; } //create child function scope QByteArray id = textOf(d->declaratorId()->unqualifiedName()); CodeModel::BlockScope *functionScope = CodeModel::Create<CodeModel::BlockScope>(m_storage); functionScope->setName(QByteArray("__QT_ANON_BLOCK_SCOPE(Function: ") + id + QByteArray(")")); functionScope->setParent(parent); method->setFunctionBodyScope(functionScope); //add arguments to child scope ArgumentCollection arguments = method->arguments(); ArgumentCollection::ConstIterator it = arguments.constBegin(); while(it != arguments.constEnd()) { CodeModel::Argument *argument = *it; CodeModel::VariableMember *variableMember = CodeModel::Create<CodeModel::VariableMember>(m_storage); variableMember->setNameToken(argument->nameToken()); variableMember->setType(argument->type()); variableMember->setName(argument->name()); variableMember->setParent(functionScope); functionScope->addMember(variableMember); ++it; } //push function scope and parse function body currentScope.push(functionScope); parseStatementList(ast->functionBody()); currentScope.pop();}void Semantic::parseStatementList(StatementListAST *statemenList){ if(!statemenList) return; CodeModel::BlockScope *blockScope = CodeModel::Create<CodeModel::BlockScope>(m_storage); blockScope->setName("__QT_ANON_BLOCK_SCOPE"); blockScope->setParent(currentScope.top()); currentScope.top()->addScope(blockScope); currentScope.push(blockScope); TreeWalker::parseStatementList(statemenList); currentScope.pop();}void Semantic::parseExpression(AbstractExpressionAST* node){ if(!node) return; if(node->nodeType() == NodeType_ClassMemberAccess) parseClassMemberAccess(static_cast<ClassMemberAccessAST *>(node)); else TreeWalker::parseExpression(node);}/* Pretty hardwired code for handling class member access of the types: object.member and objectPtr->member. This function creates a name use for object to its declaration, and a name use from member to its declaration in the class.*/void Semantic::parseClassMemberAccess(ClassMemberAccessAST *node){ if(!node) return; parseExpression(node->expression()); // Get a name use for the 'object' name. NameUse *nameUse = findNameUse(node->expression()); // Since the NameUse refers to an object, its decalaration must be // a ClassType. Get the scope of this class type. if( nameUse && nameUse->declaration() && nameUse->declaration()->toVariableMember() && nameUse->declaration()->toVariableMember()->type() && nameUse->declaration()->toVariableMember()->type()->toClassType() && nameUse->declaration()->toVariableMember()->type()->toClassType()->scope()) { CodeModel::Scope *scope = nameUse->declaration()->toVariableMember()->type()->toClassType()->scope(); QList<CodeModel::Member *> members = lookupNameInScope(scope, node->name()); if(members.count() != 0) { createNameUse(members.at(0), node->name()); return; } } // Create a NameUse that refers to the global shared unknown type. createNameUse(m_sharedUnknownMember, node->name());}void Semantic::parseExpressionStatement(ExpressionStatementAST *node){ TreeWalker::parseExpressionStatement(node);}// using declaration (using A::b)void Semantic::parseUsing(UsingAST *ast){ //CodeModel::Scope *s = lookUpScope(currentScope.top(), ast->name()); QList<CodeModel::Member *> members = nameLookup(currentScope.top(), ast->name()); if(members.isEmpty()) { emit error("Error in Semantic::parseUsing: could not look up using target"); return; } //TODO: handle multiple members (when nameLookup returns a set of overloded functions) CodeModel::Member *member = members[0]; CodeModel::Scope *targetScope = member->parent(); if(!targetScope) { emit error("Error in Semantic::parseUsing: target has no parent scope"); return; } if(!ast->name()) return; AST *nameAST = ast->name()->unqualifiedName(); if(!nameAST) return; QByteArray name = textOf(nameAST);}void Semantic::parseEnumSpecifier(EnumSpecifierAST *ast){ if (!ast->name()) return; QByteArray name = textOf(ast->name()); //create a Type CodeModel::EnumType *enumType = CodeModel::Create<CodeModel::EnumType>(m_storage); enumType->setName(name); currentScope.top()->addType(enumType); enumType->setParent(currentScope.top()); //create a TypeMember CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage); if(ast->name()) typeMember->setNameToken(tokenRefFromAST(ast->name()->unqualifiedName())); typeMember->setName(name); typeMember->setType(enumType); currentScope.top()->addMember(typeMember); typeMember->setParent(currentScope.top()); //parse the eneumerators List<EnumeratorAST*> *list = ast->enumeratorList(); if (!list) return; foreach (EnumeratorAST *current, *list) { CodeModel::VariableMember *enumerator = CodeModel::Create<CodeModel::VariableMember>(m_storage); enumerator->setNameToken(tokenRefFromAST(current->id())); enumerator->setName(textOf(current->id())); enumerator->setAccess(m_currentAccess); enumerator->setStatic(true); enumerator->setType(enumType); currentScope.top()->addMember(enumerator); enumerator->setParent(currentScope.top()); }}void Semantic::parseTypedef(TypedefAST *ast){ TypeSpecifierAST *typeSpec = ast->typeSpec(); InitDeclaratorListAST *declarators = ast->initDeclaratorList(); if (typeSpec && declarators){ QByteArray typeId; if (typeSpec->name()) typeId = textOf(typeSpec->name()); List<InitDeclaratorAST*> *l = declarators->initDeclaratorList(); if (!l) return; foreach (InitDeclaratorAST *initDecl, *l) { QByteArray type, id; if (initDecl->declarator()){ type = typeOfDeclaration(typeSpec, initDecl->declarator()); DeclaratorAST *d = initDecl->declarator(); while (d->subDeclarator()){ d = d->subDeclarator(); } if (d->declaratorId()) id = textOf(d->declaratorId()); } //create a type CodeModel::Scope *scope = currentScope.top(); CodeModel::AliasType *typeAlias = CodeModel::Create<CodeModel::AliasType>(m_storage); //typeAlias->setName(id); //typeAlias->setParent(scope); scope->addType(typeAlias); //create a TypeMember CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage); if(typeSpec->name()) typeMember->setNameToken(tokenRefFromAST(typeSpec->name()->unqualifiedName())); typeMember->setName(id); typeMember->setType(typeAlias); currentScope.top()->addMember(typeMember); typeMember->setParent(currentScope.top()); } }}void Semantic::parseTypeSpecifier(TypeSpecifierAST *ast){ // If this is a classSpecifier or a EnumSpecifier we skip the name lookup, // becuase looking up the name "E" in a class definition like // "class E { ..." makes no sense. (There might be a variable named E // already declared, but that variable is now shadowed by the class type.) if( ast->nodeType() != NodeType_EnumSpecifier && ast->nodeType() != NodeType_ClassSpecifier && ast->nodeType() != NodeType_ElaboratedTypeSpecifier ) parseNameUse(ast->name()); TreeWalker::parseTypeSpecifier(ast);}/* Parses a name: looks up name, creates name use.*/void Semantic::parseNameUse(NameAST* name){ if(!name) return; // Look up name QList<CodeModel::Member *> members = nameLookup(currentScope.top(), name); if(members.isEmpty()) { //cout << "no declaration found for " << textOf(name).constData() << endl; // Create NameUse that refer to a shared UnknownMember createNameUse(m_sharedUnknownMember, name); return; } //TODO: handle multiple members (when nameLookup returns a set of overloaded functions) CodeModel::Member *member = members[0]; if(!member->parent()) { emit error("Error in Semantic::parseUsing: target has no parent scope"); return; } createNameUse(member, name);}/* looks up name used in basescope. If name->isGlobal() is true or if classOrNamespaceList() returns a non-emty list, the C++ qualified name lookup rules are used. Otherwise the unquialified name lookup rules are used. Returns the a list of members that was found, In most cases this list will contain zero or one element, exept in the case of overloaded functions. TODO: Argument-dependent name lookup*/QList<CodeModel::Member *> Semantic::nameLookup(CodeModel::Scope *baseScope, const NameAST* name){ if (name->isGlobal() || (name->classOrNamespaceNameList() && name->classOrNamespaceNameList()->size()>0 )) { return qualifiedNameLookup(baseScope, name); } else { return unqualifiedNameLookup(baseScope, name); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -