📄 semantic.cpp
字号:
/******************************************************************************** Copyright (C) 2004-2006 Trolltech ASA. All rights reserved.** Copyright (C) 2001-2004 Roberto Raggi**** This file is part of the qt3to4 porting application of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "smallobject.h"#include "tokenengine.h"#include "semantic.h"#include <QtDebug>#include <QString>#include <QRegExp>using namespace TokenStreamAdapter;using namespace TokenEngine;using namespace CodeModel;Semantic::Semantic(CodeModel::NamespaceScope *globalScope, TokenStreamAdapter::TokenStream *tokenStream, TypedPool<CodeModel::Item> *storage){ m_storage = storage; m_tokenStream = tokenStream; m_currentAccess = CodeModel::Member::Public; m_inSlots = false; m_inSignals = false; m_inStorageSpec = false; m_inTypedef = false; globalScope->setName("::"); currentScope.push(globalScope); //create global UnknownType and UnknownTypeMember UnknownType *type = Create<UnknownType>(m_storage); type->setName("__UnknownType"); globalScope->addType(type); type->setParent(globalScope); m_sharedUnknownMember = Create<TypeMember>(m_storage); m_sharedUnknownMember->setNameToken(TokenRef()); m_sharedUnknownMember->setName("Unknown"); m_sharedUnknownMember->setType(type); globalScope->addMember(m_sharedUnknownMember); m_sharedUnknownMember->setParent(globalScope);}void Semantic::parseAST(TranslationUnitAST *node){ TreeWalker::parseTranslationUnit(node);}void Semantic::parseLinkageSpecification(LinkageSpecificationAST *ast){ if(!ast) return; int inStorageSpec = m_inStorageSpec; m_inStorageSpec = true; TreeWalker::parseLinkageSpecification(ast); m_inStorageSpec = inStorageSpec;}void Semantic::parseNamespace(NamespaceAST *ast){ CodeModel::NamespaceScope *parent = currentScope.top()->toNamespaceScope(); if(!parent->toNamespaceScope()) { emit error("Error in Semantic::parseNamespace: parent scope was not a namespace"); return; } QByteArray nsName; if (!ast->namespaceName() || textOf(ast->namespaceName()).isEmpty()){ nsName = "(__QT_ANON_NAMESPACE)"; } else { nsName = textOf(ast->namespaceName()); } CodeModel::NamespaceScope *namespaceScope = 0; // Look up namespace scope in case it is already defined. // (Unlike classes, C++ namespaces are "open" and can be added to.) CodeModel::Scope *scope = parent->scopes().value(nsName); if (scope) namespaceScope = scope->toNamespaceScope(); // Create new namespace if not found. if (!namespaceScope) { namespaceScope = CodeModel::Create<CodeModel::NamespaceScope>(m_storage); namespaceScope->setName(nsName); parent->addScope(namespaceScope); NamespaceMember *namespaceMember = Create<NamespaceMember>(m_storage); namespaceMember->setNameToken(tokenRefFromAST(ast->namespaceName())); namespaceMember->setName(nsName); namespaceMember->setNamespaceScope(namespaceScope); currentScope.top()->addMember(namespaceMember); namespaceMember->setParent(currentScope.top()); } currentScope.push(namespaceScope); TreeWalker::parseNamespace(ast); currentScope.pop();}void Semantic::parseClassSpecifier(ClassSpecifierAST *ast){ if (!ast->name()){ return; } QByteArray kind = textOf(ast->classKey()); if (kind == "class") m_currentAccess = CodeModel::Member::Private; else // kind =="struct" m_currentAccess = CodeModel::Member::Public; QByteArray className = textOf(ast->name()->unqualifiedName()); //create ClassScope CodeModel::ClassScope *klass = CodeModel::Create<CodeModel::ClassScope>(m_storage); klass->setName(className); currentScope.top()->addScope(klass); //create ClassType CodeModel::ClassType *type = CodeModel::Create<CodeModel::ClassType>(m_storage); type->setScope(klass); currentScope.top()->addType(type); type->setParent(currentScope.top()); //create TypeMember CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage); typeMember->setNameToken(tokenRefFromAST(ast->name()->unqualifiedName())); typeMember->setName(className); typeMember->setType(type); currentScope.top()->addMember(typeMember); typeMember->setParent(currentScope.top()); currentScope.push(klass); if (ast->baseClause()) parseBaseClause(ast->baseClause(), klass); //TreeWalker::parseClassSpecifier(ast); parseNode(ast->winDeclSpec()); parseNode(ast->classKey()); parseNode(ast->baseClause()); // Here's the trick for parsing c++ classes: // All inline function definitions must be interpreted as if they were // written after any other declarations in the class. QList<DeclarationAST *> functionDefinitions; if (ast->declarationList()) foreach(DeclarationAST *decl, *ast->declarationList()) { if(decl->nodeType() == NodeType_FunctionDefinition) functionDefinitions.append(decl); else parseNode(decl); } foreach(DeclarationAST *decl, functionDefinitions) parseNode(decl); currentScope.pop();}/* Parse a class, struct or enum forward decalration.*/void Semantic::parseElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node){ if (!node) return; AST *kind = node->kind(); if (!kind) return; const QByteArray kindText = textOf(kind); const QByteArray nameText = textOf(node->name()); // Don't do anything if the class, struct or enum has already been declared or defined. if (lookupNameInScope(currentScope.top(), node->name()).count() > 0) return; if (kindText == "class" || kindText == "struct") { // Create ClassType. CodeModel::ClassType *type = CodeModel::Create<CodeModel::ClassType>(m_storage); type->setScope(0); currentScope.top()->addType(type); type->setParent(currentScope.top()); // Create TypeMember. CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage); typeMember->setNameToken(tokenRefFromAST(node->name()->unqualifiedName())); typeMember->setName(nameText); typeMember->setType(type); currentScope.top()->addMember(typeMember); typeMember->setParent(currentScope.top()); } else if (kindText == "enum") { //create a Type CodeModel::EnumType *enumType = CodeModel::Create<CodeModel::EnumType>(m_storage); enumType->setName(nameText); currentScope.top()->addType(enumType); enumType->setParent(currentScope.top()); //create a TypeMember CodeModel::TypeMember *typeMember = CodeModel::Create<CodeModel::TypeMember>(m_storage); if(node->name()) typeMember->setNameToken(tokenRefFromAST(node->name()->unqualifiedName())); typeMember->setName(nameText); typeMember->setType(enumType); currentScope.top()->addMember(typeMember); typeMember->setParent(currentScope.top()); }}void Semantic::parseSimpleDeclaration(SimpleDeclarationAST *ast){ TypeSpecifierAST *typeSpec = ast->typeSpec(); InitDeclaratorListAST *declarators = ast->initDeclaratorList(); if (typeSpec) parseTypeSpecifier(typeSpec); if (declarators){ List<InitDeclaratorAST*> l = *declarators->initDeclaratorList(); foreach (InitDeclaratorAST *current, l) { parseDeclaration(ast->functionSpecifier(), ast->storageSpecifier(), typeSpec, current); } }}void Semantic::parseDeclaration(AST *funSpec, AST *storageSpec, TypeSpecifierAST *typeSpec, InitDeclaratorAST *decl){ if (m_inStorageSpec) return; if(!decl) return; DeclaratorAST *d = decl->declarator(); if (!d) return; if (!d->subDeclarator() && d->parameterDeclarationClause()) { parseFunctionDeclaration(funSpec, storageSpec, typeSpec, decl); return; } if(!typeSpec || !typeSpec->name()) return; DeclaratorAST *t = d; while (t && t->subDeclarator()) t = t->subDeclarator(); QByteArray id; if (t && t->declaratorId() && t->declaratorId()->unqualifiedName()) id = textOf(t->declaratorId()->unqualifiedName()); if (!t || !t->declaratorId() || !t->declaratorId()->unqualifiedName()) return; AST *nameAST = t->declaratorId()->unqualifiedName(); QByteArray name = textOf(nameAST); if (!scopeOfDeclarator(d, QList<QByteArray>()).isEmpty()){ return; } //Check if this is possibly a function call by searching for '(' and ')' const QByteArray declText = textOf(decl); if (declText.contains("(") && declText.contains(")")) { if (decl->declarator() && decl->declarator()->subDeclarator()) { NameAST * name = decl->declarator()->subDeclarator()->declaratorId(); if (name) parseNameUse(name); return; } } //create VariableMember CodeModel::VariableMember *variableMember = CodeModel::Create<CodeModel::VariableMember>(m_storage); variableMember->setNameToken(tokenRefFromAST(nameAST)); variableMember->setName(name); variableMember->setAccess(m_currentAccess); variableMember->setParent(currentScope.top()); currentScope.top()->addMember(variableMember); //look up type of variableMember, TypeMember *typeMember = typeLookup(currentScope.top(), typeSpec->name()); if(typeMember) { variableMember->setType(typeMember->type()); } else { QByteArray text = typeOfDeclaration(typeSpec, d); CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage); type->setName(text); variableMember->setType(type); } if (decl) parseNode(decl->initializer());}void Semantic::parseFunctionDeclaration(AST *funSpec, AST *storageSpec, TypeSpecifierAST * typeSpec, InitDeclaratorAST * initDeclarator){ bool isFriend = false; bool isVirtual = false; bool isStatic = false; bool isInline = false; bool isPure = initDeclarator->initializer() != 0; if (funSpec){ List<AST*> l = *funSpec->children(); foreach (AST *current, l) { QByteArray text = textOf(current); if (text == "virtual") isVirtual = true; else if (text == "inline") isInline = true; } } if (storageSpec){ List<AST*> l = *storageSpec->children(); foreach (AST *current, l) { QByteArray text = textOf(current); if (text == "friend") isFriend = true; else if (text == "static") isStatic = true; } } DeclaratorAST *declarator = initDeclarator->declarator(); if(!declarator || !declarator->declaratorId()) return; AST *nameAST = declarator->declaratorId()->unqualifiedName(); QByteArray name = textOf(nameAST); CodeModel::FunctionMember *method = CodeModel::Create<CodeModel::FunctionMember>(m_storage); method->setNameToken(tokenRefFromAST(nameAST)); method->setName(name); method->setAccess(m_currentAccess); method->setStatic(isStatic); method->setVirtual(isVirtual); method->setAbstract(isPure); parseFunctionArguments(declarator, method); if (m_inSignals) method->setSignal(true); if (m_inSlots) method->setSlot(true); method->setConstant(declarator->constant() != 0); QByteArray text = typeOfDeclaration(typeSpec, declarator); if (!text.isEmpty()) { CodeModel::UnknownType *type = CodeModel::Create<CodeModel::UnknownType>(m_storage); type->setName(text); method->setReturnType(type); } method->setParent(currentScope.top()); currentScope.top()->addMember(method);}void Semantic::parseBaseClause(BaseClauseAST * baseClause, CodeModel::ClassScope *klass){ if(!baseClause) return; if(!klass) return; List<BaseSpecifierAST*> *l = baseClause->baseSpecifierList(); if (!l) return; foreach (BaseSpecifierAST *baseSpecifier, *l) { QByteArray baseName; if (!baseSpecifier->name()) continue; // Look up a class with the correct name. QList<Member *> candidates = nameLookup(klass, baseSpecifier->name()); if (candidates.count() == 1 ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -