diff --git a/bin/test/data/log/test_log.txt b/bin/test/data/log/test_log.txt index 5e4e1ebd..05aca32c 100644 --- a/bin/test/data/log/test_log.txt +++ b/bin/test/data/log/test_log.txt @@ -1,6 +1,46 @@ Token.cpp ERROR: Location Id was not referenced by this Token. Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class Edge.cpp ERROR: Nodes are not plain copies. + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc + INFO: Indexer - indexing source file: input.cc INFO: send TestMessage INFO: handle TestMessage INFO: send TestMessage diff --git a/java_indexer/src/io/coati/JavaAstVisitor.java b/java_indexer/src/io/coati/JavaAstVisitor.java index b0886d0d..d4d218e0 100644 --- a/java_indexer/src/io/coati/JavaAstVisitor.java +++ b/java_indexer/src/io/coati/JavaAstVisitor.java @@ -46,21 +46,14 @@ import me.tomassetti.symbolsolver.model.typesystem.*; public class JavaAstVisitor extends JavaAstVisitorAdapter { - private int m_callbackId = -1; + protected int m_callbackId = -1; private String m_filePath; private FileContent m_fileContent; private TypeSolver m_typeSolver; private List m_context = new ArrayList(); - private boolean m_verbose = false; - static int errorCount = 0; public JavaAstVisitor(int callbackId, String filePath, FileContent fileContent, TypeSolver typeSolver) - { - if (m_verbose) - { - System.out.println("indexing file: " + filePath); - } - + { m_callbackId = callbackId; m_filePath = filePath; m_fileContent = fileContent; @@ -80,7 +73,7 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter String packageName = JavaparserDeclNameResolver.getQualifiedName(nameExpr).toSerializedNameHierarchy(); - JavaIndexer.recordSymbolWithScope( + JavaIndexer.recordSymbolWithLocationAndScope( m_callbackId, packageName, SymbolType.PACKAGE, nameExpr.getBegin().line, nameExpr.getBegin().column, nameExpr.getEnd().line, nameExpr.getEnd().column, n.getBegin().line, n.getBegin().column, n.getEnd().line, n.getEnd().column, @@ -96,7 +89,7 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy(); - JavaIndexer.recordSymbolWithScope( + JavaIndexer.recordSymbolWithLocationAndScope( m_callbackId, qualifiedName, (n.isInterface() ? SymbolType.INTERFACE : SymbolType.CLASS), nameExpr.getBegin().line, nameExpr.getBegin().column, nameExpr.getEnd().line, nameExpr.getEnd().column, n.getBegin().line, n.getBegin().column, n.getEnd().line, n.getEnd().column, @@ -128,7 +121,7 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter qualifiedName += "\tn"; qualifiedName += n.getName() + "\ts\tp"; - JavaIndexer.recordSymbol( + JavaIndexer.recordSymbolWithLocation( m_callbackId, qualifiedName, SymbolType.TYPE_PARAMETER, n.getBegin().line, n.getBegin().column, n.getBegin().line, n.getBegin().column + n.getName().length() - 1, AccessKind.TYPE_PARAMETER, false @@ -147,7 +140,7 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy(); - JavaIndexer.recordSymbolWithScope( + JavaIndexer.recordSymbolWithLocationAndScope( m_callbackId, qualifiedName, SymbolType.ENUM, nameExpr.getBegin().line, nameExpr.getBegin().column, nameExpr.getEnd().line, nameExpr.getEnd().column, n.getBegin().line, n.getBegin().column, n.getEnd().line, n.getEnd().column, @@ -168,7 +161,7 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter { String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy(); - JavaIndexer.recordSymbol( + JavaIndexer.recordSymbolWithLocation( m_callbackId, qualifiedName, SymbolType.ENUM_CONSTANT, n.getBegin().line, n.getBegin().column, n.getEnd().line, n.getEnd().column, AccessKind.NONE, false @@ -187,7 +180,7 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy(); - JavaIndexer.recordSymbolWithScope( + JavaIndexer.recordSymbolWithLocationAndScope( m_callbackId, qualifiedName, SymbolType.METHOD, nameExpr.getBegin().line, nameExpr.getBegin().column, nameExpr.getEnd().line, nameExpr.getEnd().column, n.getBegin().line, n.getBegin().column, n.getEnd().line, n.getEnd().column, @@ -207,7 +200,7 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy(); - JavaIndexer.recordSymbolWithScope( + JavaIndexer.recordSymbolWithLocationAndScope( m_callbackId, qualifiedName, SymbolType.METHOD, nameExpr.getBegin().line, nameExpr.getBegin().column, nameExpr.getEnd().line, nameExpr.getEnd().column, n.getBegin().line, n.getBegin().column, n.getEnd().line, n.getEnd().column, @@ -290,7 +283,7 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(varDecl, m_typeSolver).toSerializedNameHierarchy(); VariableDeclaratorId varDeclId = varDecl.getId(); - JavaIndexer.recordSymbol( + JavaIndexer.recordSymbolWithLocation( m_callbackId, qualifiedName, SymbolType.FIELD, varDeclId.getBegin().line, varDeclId.getBegin().column, varDeclId.getEnd().line, varDeclId.getEnd().column, AccessKind.fromAccessSpecifier(Modifier.getAccessSpecifier(n.getModifiers())), false @@ -470,7 +463,7 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter { String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toSerializedNameHierarchy(); - JavaIndexer.recordSymbolWithoutLocation( + JavaIndexer.recordSymbol( m_callbackId, referencedName, SymbolType.BUILTIN_TYPE, AccessKind.NONE, true ); @@ -497,7 +490,7 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter { String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toSerializedNameHierarchy(); - JavaIndexer.recordSymbolWithoutLocation( + JavaIndexer.recordSymbol( m_callbackId, referencedName, SymbolType.BUILTIN_TYPE, AccessKind.NONE, true ); @@ -615,7 +608,6 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter MethodUsage solvedMethod = JavaParserFacade.get(m_typeSolver).solveMethodAsUsage(n); qualifiedName = getQualifiedName(solvedMethod); } - catch (UnsupportedOperationException e) { recordException(e, n); @@ -632,7 +624,6 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter { recordException(e, n); } - } if (!qualifiedName.isEmpty()) @@ -653,31 +644,22 @@ public class JavaAstVisitor extends JavaAstVisitorAdapter private void recordException(Exception e, Node n) { - JavaIndexer.recordSymbol( + JavaIndexer.logError(m_callbackId, e.getClass() + " at " + m_filePath + "<"+ n.getBegin().line + ", " + n.getBegin().column + ">"); + JavaIndexer.recordSymbolWithLocation( m_callbackId, "unsolved-symbol\ts\tp", SymbolType.TYPE_MAX, n.getBegin().line, n.getBegin().column, n.getEnd().line, n.getEnd().column, AccessKind.DEFAULT, false ); - errorCount++; - if (m_verbose) - { - System.out.println(e + " at location " + n.getBegin().line + ", " + n.getBegin().column + " [errors: " + errorCount + "]"); - } - } private void recordError(Error e, Node n) { - JavaIndexer.recordSymbol( + JavaIndexer.logError(m_callbackId, e.getClass() + " at " + m_filePath + "<"+ n.getBegin().line + ", " + n.getBegin().column + ">"); + JavaIndexer.recordSymbolWithLocation( m_callbackId, "unsolved-symbol\ts\tp", SymbolType.TYPE_MAX, n.getBegin().line, n.getBegin().column, n.getEnd().line, n.getEnd().column, AccessKind.DEFAULT, false ); - errorCount++; - if (m_verbose) - { - System.out.println(e + " at location " + n.getBegin().line + ", " + n.getBegin().column + " [errors: " + errorCount + "]"); - } } diff --git a/java_indexer/src/io/coati/JavaIndexer.java b/java_indexer/src/io/coati/JavaIndexer.java index 83168302..ff1be7bc 100644 --- a/java_indexer/src/io/coati/JavaIndexer.java +++ b/java_indexer/src/io/coati/JavaIndexer.java @@ -20,9 +20,9 @@ import me.tomassetti.symbolsolver.resolution.typesolvers.JreTypeSolver; public class JavaIndexer { - public static void processFile(int address, String filePath, String fileContent, String classPath) + public static void processFile(int address, String filePath, String fileContent, String classPath, int verbose) { -// System.out.println("indexing file: " + filePath); + logInfo(address, "indexing source file: " + filePath); try { @@ -51,8 +51,12 @@ public class JavaIndexer } CompilationUnit cu = JavaParser.parse(new StringReader(fileContent), true); - JavaAstVisitor astVisitor = new JavaAstVisitor(address, filePath, new FileContent(fileContent), typeSolver); - // JavaAstVisitor astVisitor = new ASTDumper(address, filePath, new FileContent(fileContent), typeSolver); + JavaAstVisitor astVisitor = ( + verbose == 1 ? + new JavaVerboseAstVisitor(address, filePath, new FileContent(fileContent), typeSolver) : + new JavaAstVisitor(address, filePath, new FileContent(fileContent), typeSolver) + ); + cu.accept(astVisitor, null); } catch (ParseProblemException e) @@ -61,8 +65,6 @@ public class JavaIndexer { if (problem.message.startsWith("Encountered unexpected token")) { - - int startLine = Integer.parseInt(problem.message.substring( problem.message.indexOf("line ") + ("line ").length(), problem.message.indexOf(",") @@ -117,38 +119,40 @@ public class JavaIndexer return packageName; } + // helpers + static public void recordSymbol( + int address, String symbolName, SymbolType symbolType, + AccessKind access, boolean isImplicit + ) + { + recordSymbol( + address, symbolName, symbolType.getValue(), + access.getValue(), (isImplicit ? 1 : 0) + ); + } + + static public void recordSymbolWithLocation( int address, String symbolName, SymbolType symbolType, int beginLine, int beginColumn, int endLine, int endColumn, AccessKind access, boolean isImplicit ) { - recordSymbol( + recordSymbolWithLocation( address, symbolName, symbolType.getValue(), beginLine, beginColumn, endLine, endColumn, access.getValue(), (isImplicit ? 1 : 0) ); } - static public void recordSymbolWithoutLocation( - int address, String symbolName, SymbolType symbolType, - AccessKind access, boolean isImplicit - ) - { - recordSymbolWithoutLocation( - address, symbolName, symbolType.getValue(), - access.getValue(), (isImplicit ? 1 : 0) - ); - } - - static public void recordSymbolWithScope( + static public void recordSymbolWithLocationAndScope( int address, String symbolName, SymbolType symbolType, int beginLine, int beginColumn, int endLine, int endColumn, int scopeBeginLine, int scopeBeginColumn, int scopeEndLine, int scopeEndColumn, AccessKind access, boolean isImplicit ) { - recordSymbolWithScope( + recordSymbolWithLocationAndScope( address, symbolName, symbolType.getValue(), beginLine, beginColumn, endLine, endColumn, scopeBeginLine, scopeBeginColumn, scopeEndLine, scopeEndColumn, @@ -176,19 +180,27 @@ public class JavaIndexer beginLine, beginColumn, endLine, endColumn ); } + + // the following methods are defines in the native c++ code + static public native void logInfo(int address, String info); + + static public native void logWarning(int address, String warning); + + static public native void logError(int address, String error); + static private native void recordSymbol( + int address, String symbolName, int symbolType, + int access, int isImplicit + ); + + static private native void recordSymbolWithLocation( int address, String symbolName, int symbolType, int beginLine, int beginColumn, int endLine, int endColumn, int access, int isImplicit ); - static private native void recordSymbolWithoutLocation( - int address, String symbolName, int symbolType, - int access, int isImplicit - ); - - static private native void recordSymbolWithScope( + static private native void recordSymbolWithLocationAndScope( int address, String symbolName, int symbolType, int beginLine, int beginColumn, int endLine, int endColumn, int scopeBeginLine, int scopeBeginColumn, int scopeEndLine, int scopeEndColumn, @@ -199,11 +211,11 @@ public class JavaIndexer int address, int referenceKind, String referencedName, String contextName, int beginLine, int beginColumn, int endLine, int endColumn ); - static native void recordLocalSymbol( + static public native void recordLocalSymbol( int address, String symbolName, int beginLine, int beginColumn, int endLine, int endColumn ); - static native void recordComment( + static public native void recordComment( int address, int beginLine, int beginColumn, int endLine, int endColumn ); diff --git a/java_indexer/src/io/coati/ASTDumper.java b/java_indexer/src/io/coati/JavaVerboseAstVisitor.java similarity index 94% rename from java_indexer/src/io/coati/ASTDumper.java rename to java_indexer/src/io/coati/JavaVerboseAstVisitor.java index fdeb0252..6bec3c40 100644 --- a/java_indexer/src/io/coati/ASTDumper.java +++ b/java_indexer/src/io/coati/JavaVerboseAstVisitor.java @@ -4,20 +4,34 @@ import com.github.javaparser.ast.*; import com.github.javaparser.ast.body.*; import com.github.javaparser.ast.comments.*; import com.github.javaparser.ast.expr.*; +import com.github.javaparser.ast.nodeTypes.NodeWithName; import com.github.javaparser.ast.stmt.*; import com.github.javaparser.ast.type.*; import me.tomassetti.symbolsolver.model.resolution.TypeSolver; -public class ASTDumper extends JavaAstVisitor{ +public class JavaVerboseAstVisitor extends JavaAstVisitor{ - public ASTDumper(int callbackId, String filePath, FileContent fileContent, TypeSolver typeSolver) { + public JavaVerboseAstVisitor(int callbackId, String filePath, FileContent fileContent, TypeSolver typeSolver) { super(callbackId, filePath, fileContent, typeSolver); } int indent = 0; String indentSymbol = "| "; + private String obfuscate(final String s) + { + if (s.isEmpty()) + { + return ""; + } + else if (s.length() <= 2) + { + return s; + } + return s.substring(0, 1) + ".." + s.substring(s.length() - 1, s.length()); + } + private void dump(Node n) { String line = ""; @@ -28,21 +42,13 @@ public class ASTDumper extends JavaAstVisitor{ } line += n.getClass().getName(); - if (n instanceof NameExpr) + if (n instanceof NodeWithName) { - line += " [" + ((NameExpr)n).getName() + "]"; - } - else if (n instanceof ClassOrInterfaceType) - { - line += " [" + ((ClassOrInterfaceType)n).getName() + "]"; - } - else if (n instanceof MethodCallExpr) - { - line += " [" + ((MethodCallExpr)n).getName() + "]"; + line += " [" + obfuscate(((NodeWithName)n).getName()) + "]"; } line += " line: " + n.getBegin().line; - System.out.println(line); + JavaIndexer.logInfo(m_callbackId, line); } //- Compilation Unit ---------------------------------- diff --git a/src/lib/data/parser/ParserClient.cpp b/src/lib/data/parser/ParserClient.cpp index 8cc715f7..98678ae8 100644 --- a/src/lib/data/parser/ParserClient.cpp +++ b/src/lib/data/parser/ParserClient.cpp @@ -24,19 +24,6 @@ std::string ParserClient::addAccessPrefix(const std::string& str, AccessKind acc return str; } -std::string ParserClient::addAbstractionPrefix(const std::string& str, AbstractionType abstraction) -{ - switch (abstraction) - { - case ABSTRACTION_VIRTUAL: - return "virtual " + str; - case ABSTRACTION_PURE_VIRTUAL: - return "pure virtual " + str; - case ABSTRACTION_NONE: - return str; - } -} - std::string ParserClient::addStaticPrefix(const std::string& str, bool isStatic) { if (isStatic) diff --git a/src/lib/data/parser/ParserClient.h b/src/lib/data/parser/ParserClient.h index 8623d104..4c61c07c 100644 --- a/src/lib/data/parser/ParserClient.h +++ b/src/lib/data/parser/ParserClient.h @@ -17,14 +17,7 @@ class DataType; class ParserClient { public: - enum AbstractionType { - ABSTRACTION_VIRTUAL, - ABSTRACTION_PURE_VIRTUAL, - ABSTRACTION_NONE - }; - static std::string addAccessPrefix(const std::string& str, AccessKind access); - static std::string addAbstractionPrefix(const std::string& str, AbstractionType abstraction); static std::string addStaticPrefix(const std::string& str, bool isStatic); static std::string addConstPrefix(const std::string& str, bool isConst, bool atFront); static std::string addLocationSuffix(const std::string& str, const ParseLocation& location); @@ -56,65 +49,9 @@ public: const ParseLocation& location) = 0; virtual void onError(const ParseLocation& location, const std::string& message, bool fatal, bool indexed) = 0; - - virtual void onTypedefParsed( - const ParseLocation& location, const NameHierarchy& typedefName, AccessKind access, bool isImplicit) = 0; - virtual void onClassParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) = 0; - virtual void onStructParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) = 0; - virtual void onGlobalVariableParsed(const ParseLocation& location, const NameHierarchy& variable, bool isImplicit) = 0; - virtual void onFieldParsed(const ParseLocation& location, const NameHierarchy& field, AccessKind access, bool isImplicit) = 0; - virtual void onFunctionParsed( - const ParseLocation& location, const NameHierarchy& function, const ParseLocation& scopeLocation, bool isImplicit) = 0; - virtual void onMethodParsed( - const ParseLocation& location, const NameHierarchy& method, AccessKind access, AbstractionType abstraction, - const ParseLocation& scopeLocation, bool isImplicit) = 0; - virtual void onNamespaceParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, - const ParseLocation& scopeLocation, bool isImplicit) = 0; - virtual void onEnumParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) = 0; - virtual void onEnumConstantParsed(const ParseLocation& location, const NameHierarchy& nameHierarchy, bool isImplicit) = 0; - virtual void onTemplateParameterTypeParsed( - const ParseLocation& location, const NameHierarchy& templateParameterTypeNameHierarchy, bool isImplicit) = 0; virtual void onLocalSymbolParsed(const std::string& name, const ParseLocation& location) = 0; virtual void onFileParsed(const FileInfo& fileInfo) = 0; - virtual void onMacroDefineParsed( - const ParseLocation& location, const NameHierarchy& macroNameHierarchy, const ParseLocation& scopeLocation) = 0; virtual void onCommentParsed(const ParseLocation& location) = 0; - - virtual void onInheritanceParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, - const NameHierarchy& baseNameHierarchy) = 0; - virtual void onMethodOverrideParsed( - const ParseLocation& location, const NameHierarchy& overridden, const NameHierarchy& overrider) = 0; - virtual void onCallParsed( - const ParseLocation& location, const NameHierarchy& caller, const NameHierarchy& callee) = 0; - virtual void onUsageParsed( - const ParseLocation& location, const NameHierarchy& userName, SymbolKind usedType, const NameHierarchy& usedName) = 0; - virtual void onTypeUsageParsed(const ParseLocation& location, const NameHierarchy& user, const NameHierarchy& used) = 0; - - virtual void onTemplateArgumentTypeParsed( - const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy, - const NameHierarchy& templateNameHierarchy) = 0; - virtual void onTemplateDefaultArgumentTypeParsed( - const ParseLocation& location, const NameHierarchy& defaultArgumentTypeNameHierarchy, - const NameHierarchy& templateParameterNameHierarchy) = 0; - virtual void onTemplateSpecializationParsed( - const ParseLocation& location, const NameHierarchy& specializedNameHierarchy, - const NameHierarchy& specializedFromNameHierarchy) = 0; - virtual void onTemplateMemberFunctionSpecializationParsed( - const ParseLocation& location, const NameHierarchy& instantiatedFunction, const NameHierarchy& specializedFunction) = 0; - - virtual void onFileIncludeParsed( - const ParseLocation& location, const FileInfo& fileInfo, const FileInfo& includedFileInfo) = 0; - - virtual void onMacroExpandParsed( - const ParseLocation& location, const NameHierarchy& macroNameHierarchy) = 0; }; #endif // PARSER_CLIENT_H diff --git a/src/lib/data/parser/ParserClientImpl.cpp b/src/lib/data/parser/ParserClientImpl.cpp index c8a53f19..040be879 100644 --- a/src/lib/data/parser/ParserClientImpl.cpp +++ b/src/lib/data/parser/ParserClientImpl.cpp @@ -76,328 +76,31 @@ void ParserClientImpl::recordReference( addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); } - - void ParserClientImpl::onError(const ParseLocation& location, const std::string& message, bool fatal, bool indexed) { - log(std::string(fatal ? "FATAL: " : "ERROR: "), message, location); - - if (!location.isValid()) + if (location.isValid()) { - return; + addError(message, fatal, indexed, location); } - - addError(message, fatal, indexed, location); -} - -void ParserClientImpl::onTypedefParsed( - const ParseLocation& location, const NameHierarchy& typedefName, AccessKind access, bool isImplicit) -{ - log("typedef", typedefName.getQualifiedName(), location); - - Id nodeId = addNodeHierarchy(Node::NODE_TYPEDEF, typedefName, (isImplicit ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT)); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); - addAccess(nodeId, access); -} - -void ParserClientImpl::onClassParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) -{ - log("class", nameHierarchy.getQualifiedName(), location); - - Id nodeId = addNodeHierarchy( - Node::NODE_CLASS, - nameHierarchy, - (isImplicit ? DEFINITION_IMPLICIT : (scopeLocation.isValid() ? DEFINITION_EXPLICIT : DEFINITION_NONE)) - ); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); - addSourceLocation(nodeId, scopeLocation, locationTypeToInt(LOCATION_SCOPE)); - addAccess(nodeId, access); -} - -void ParserClientImpl::onStructParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) -{ - log("struct", nameHierarchy.getQualifiedName(), location); - - Id nodeId = addNodeHierarchy( - Node::NODE_STRUCT, - nameHierarchy, - (isImplicit ? DEFINITION_IMPLICIT : (scopeLocation.isValid() ? DEFINITION_EXPLICIT : DEFINITION_NONE)) - ); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); - addSourceLocation(nodeId, scopeLocation, locationTypeToInt(LOCATION_SCOPE)); - addAccess(nodeId, access); -} - -void ParserClientImpl::onGlobalVariableParsed(const ParseLocation& location, const NameHierarchy& variable, bool isImplicit) -{ - log("global", variable.getQualifiedName(), location); - - Id nodeId = addNodeHierarchy(Node::NODE_GLOBAL_VARIABLE, variable, (isImplicit ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT)); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onFieldParsed(const ParseLocation& location, const NameHierarchy& field, AccessKind access, bool isImplicit) -{ - log("field", field.getQualifiedName(), location); - - Id nodeId = addNodeHierarchy(Node::NODE_FIELD, field, (isImplicit ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT)); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); - addAccess(nodeId, access); -} - -void ParserClientImpl::onFunctionParsed( - const ParseLocation& location, const NameHierarchy& function, const ParseLocation& scopeLocation, bool isImplicit) -{ - log("function", function.getQualifiedNameWithSignature(), location); - - Id nodeId = addNodeHierarchy(Node::NODE_FUNCTION, function, (isImplicit ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT)); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); - addSourceLocation(nodeId, scopeLocation, locationTypeToInt(LOCATION_SCOPE)); -} - -void ParserClientImpl::onMethodParsed( - const ParseLocation& location, const NameHierarchy& method, AccessKind access, AbstractionType abstraction, // todo: remove abstractio... better: remove this method! - const ParseLocation& scopeLocation, bool isImplicit) -{ - log("method", method.getQualifiedNameWithSignature(), location); - - Id nodeId = addNodeHierarchy( - Node::NODE_METHOD, - method, - (isImplicit ? DEFINITION_IMPLICIT : ((location.isValid() && scopeLocation.isValid()) ? (DEFINITION_EXPLICIT) : DEFINITION_NONE)) - ); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); - addSourceLocation(nodeId, scopeLocation, locationTypeToInt(LOCATION_SCOPE)); - addAccess(nodeId, access); -} - -void ParserClientImpl::onNamespaceParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, const ParseLocation& scopeLocation, bool isImplicit) -{ - log("namespace", nameHierarchy.getQualifiedName(), location); - - Id nodeId = addNodeHierarchy(Node::NODE_NAMESPACE, nameHierarchy, (isImplicit ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT)); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); - addSourceLocation(nodeId, scopeLocation, locationTypeToInt(LOCATION_SCOPE)); -} - -void ParserClientImpl::onEnumParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) -{ - log("enum", nameHierarchy.getQualifiedName(), location); - - Id nodeId = addNodeHierarchy(Node::NODE_ENUM, nameHierarchy, (isImplicit ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT)); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); - addSourceLocation(nodeId, scopeLocation, locationTypeToInt(LOCATION_SCOPE)); - addAccess(nodeId, access); -} - -void ParserClientImpl::onEnumConstantParsed(const ParseLocation& location, const NameHierarchy& nameHierarchy, bool isImplicit) -{ - log("enum constant", nameHierarchy.getQualifiedName(), location); - - Id nodeId = addNodeHierarchy(Node::NODE_ENUM_CONSTANT, nameHierarchy, (isImplicit ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT)); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onTemplateParameterTypeParsed( - const ParseLocation& location, const NameHierarchy& templateParameterTypeNameHierarchy, bool isImplicit) -{ - log("template parameter type", templateParameterTypeNameHierarchy.getQualifiedName(), location); - - Id nodeId = addNodeHierarchy(Node::NODE_TEMPLATE_PARAMETER_TYPE, templateParameterTypeNameHierarchy, (isImplicit ? DEFINITION_IMPLICIT : DEFINITION_EXPLICIT)); - addSourceLocation(nodeId, location, locationTypeToInt(LOCATION_TOKEN)); - addAccess(nodeId, ACCESS_TEMPLATE_PARAMETER); } void ParserClientImpl::onLocalSymbolParsed(const std::string& name, const ParseLocation& location) { - log( - "local symbol", - name, - location - ); - Id localSymbolId = addLocalSymbol(name); addSourceLocation(localSymbolId, location, locationTypeToInt(LOCATION_LOCAL_SYMBOL)); } void ParserClientImpl::onFileParsed(const FileInfo& fileInfo) { - log("file", fileInfo.path.str(), ParseLocation()); - addFile(fileInfo.path.fileName(), fileInfo.path.str(), fileInfo.lastWriteTime.toString()); } -void ParserClientImpl::onMacroDefineParsed( - const ParseLocation& location, const NameHierarchy& macroNameHierarchy, const ParseLocation& scopeLocation) -{ - log("macro", macroNameHierarchy.getQualifiedName(), location); - - Id macroId = addNodeHierarchy(Node::NODE_MACRO, macroNameHierarchy, DEFINITION_EXPLICIT); - addSourceLocation(macroId, location, locationTypeToInt(LOCATION_TOKEN)); - addSourceLocation(macroId, scopeLocation, locationTypeToInt(LOCATION_SCOPE)); - - Id fileNodeId = addFile(location.filePath.str()); - Id edgeId = addEdge(Edge::EDGE_MACRO_USAGE, fileNodeId, macroId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - void ParserClientImpl::onCommentParsed(const ParseLocation& location) { - log("comment", "no name", location); - addFile(location.filePath.str()); addCommentLocation(location); } -void ParserClientImpl::onInheritanceParsed( - const ParseLocation& location, const NameHierarchy& childNameHierarchy, - const NameHierarchy& parentNameHierarchy) -{ - log("inheritance", childNameHierarchy.getQualifiedName() + " : " + parentNameHierarchy.getQualifiedName(), location); - - Id childNodeId = addNodeHierarchy(Node::NODE_TYPE, childNameHierarchy, DEFINITION_NONE); - Id parentNodeId = addNodeHierarchy(Node::NODE_TYPE, parentNameHierarchy, DEFINITION_NONE); - Id edgeId = addEdge(Edge::EDGE_INHERITANCE, childNodeId, parentNodeId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onMethodOverrideParsed( - const ParseLocation& location, const NameHierarchy& overridden, const NameHierarchy& overrider) -{ - log("override", overridden.getQualifiedNameWithSignature() + " -> " + overrider.getQualifiedNameWithSignature(), location); - - Id overriddenNodeId = addNodeHierarchy(Node::NODE_FUNCTION, overridden, DEFINITION_NONE); - Id overriderNodeId = addNodeHierarchy(Node::NODE_FUNCTION, overrider, DEFINITION_NONE); - Id edgeId = addEdge(Edge::EDGE_OVERRIDE, overriderNodeId, overriddenNodeId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onCallParsed(const ParseLocation& location, const NameHierarchy& caller, const NameHierarchy& callee) -{ - log("call", caller.getQualifiedNameWithSignature() + " -> " + callee.getQualifiedNameWithSignature(), location); - - Id callerNodeId = addNodeHierarchy(Node::NODE_FUNCTION, caller, DEFINITION_NONE); - Id calleeNodeId = addNodeHierarchy(Node::NODE_FUNCTION, callee, DEFINITION_NONE); - Id edgeId = addEdge(Edge::EDGE_CALL, callerNodeId, calleeNodeId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onUsageParsed( - const ParseLocation& location, const NameHierarchy& userName, SymbolKind usedType, const NameHierarchy& usedName) -{ - log("usage", userName.getQualifiedNameWithSignature() + " -> " + usedName.getQualifiedName(), location); - - Id userNodeId = addNodeHierarchy(Node::NODE_UNDEFINED, userName, DEFINITION_NONE); - Id usedNodeId = addNodeHierarchy(symbolKindToNodeType(usedType), usedName, DEFINITION_NONE); - Id edgeId = addEdge(Edge::EDGE_USAGE, userNodeId, usedNodeId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onTypeUsageParsed(const ParseLocation& location, const NameHierarchy& user, const NameHierarchy& used) -{ - log("type usage", user.getQualifiedNameWithSignature() + " -> " + used.getQualifiedName(), location); - - if (!location.isValid()) - { - return; - } - - Id functionNodeId = addNodeHierarchy(Node::NODE_UNDEFINED, user, DEFINITION_NONE); - Id typeNodeId = addNodeHierarchy(Node::NODE_TYPE, used, DEFINITION_NONE); - Id edgeId = addEdge(Edge::EDGE_TYPE_USAGE, functionNodeId, typeNodeId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onTemplateArgumentTypeParsed( - const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy, - const NameHierarchy& templateNameHierarchy) -{ - log( - "template argument type", - argumentTypeNameHierarchy.getQualifiedName() + " -> " + templateNameHierarchy.getQualifiedName(), - location - ); - - Id argumentNodeId = addNodeHierarchy(Node::NODE_TYPE, argumentTypeNameHierarchy, DEFINITION_NONE); - Id templateNodeId = addNodeHierarchy(Node::NODE_UNDEFINED, templateNameHierarchy, DEFINITION_NONE); - Id edgeId = addEdge(Edge::EDGE_TEMPLATE_ARGUMENT, templateNodeId, argumentNodeId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onTemplateDefaultArgumentTypeParsed( - const ParseLocation& location, const NameHierarchy& defaultArgumentTypeNameHierarchy, - const NameHierarchy& templateParameterNameHierarchy) -{ - log( - "template default argument", - defaultArgumentTypeNameHierarchy.getQualifiedNameWithSignature() + " -> " + templateParameterNameHierarchy.getQualifiedName(), - location - ); - - Id defaultArgumentNodeId = addNodeHierarchy(Node::NODE_TYPE, defaultArgumentTypeNameHierarchy, DEFINITION_NONE); - Id parameterNodeId = addNodeHierarchy(Node::NODE_TYPE, templateParameterNameHierarchy, DEFINITION_NONE); - Id edgeId = addEdge(Edge::EDGE_TEMPLATE_DEFAULT_ARGUMENT, parameterNodeId, defaultArgumentNodeId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onTemplateSpecializationParsed( - const ParseLocation& location, const NameHierarchy& specializedNameHierarchy, - const NameHierarchy& specializedFromNameHierarchy) -{ - log( - "template record specialization", - specializedNameHierarchy.getQualifiedName() + " -> " + specializedFromNameHierarchy.getQualifiedName(), - location - ); - - Id specializedId = addNodeHierarchy(Node::NODE_TYPE, specializedNameHierarchy, DEFINITION_NONE); - Id recordNodeId = addNodeHierarchy(Node::NODE_TYPE, specializedFromNameHierarchy, DEFINITION_NONE); - Id edgeId = addEdge(Edge::EDGE_TEMPLATE_SPECIALIZATION_OF, specializedId, recordNodeId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onTemplateMemberFunctionSpecializationParsed( - const ParseLocation& location, const NameHierarchy& instantiatedFunction, const NameHierarchy& specializedFunction) -{ - log( - "template member function specialization", - instantiatedFunction.getQualifiedNameWithSignature() + " -> " + specializedFunction.getQualifiedNameWithSignature(), - location - ); - - Id instantiatedFunctionNodeId = addNodeHierarchy(Node::NODE_FUNCTION, instantiatedFunction, DEFINITION_NONE); - Id specializedFunctionNodeId = addNodeHierarchy(Node::NODE_FUNCTION, specializedFunction, DEFINITION_NONE); - Id edgeId = addEdge(Edge::EDGE_TEMPLATE_MEMBER_SPECIALIZATION_OF, instantiatedFunctionNodeId, specializedFunctionNodeId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onFileIncludeParsed(const ParseLocation& location, const FileInfo& fileInfo, const FileInfo& includedFileInfo) -{ - log("include", includedFileInfo.path.str(), location); - - Id fileNodeId = addFile(fileInfo.path.fileName(), fileInfo.path.str(), fileInfo.lastWriteTime.toString()); - Id includedFileNodeId = addFile(includedFileInfo.path.fileName(), includedFileInfo.path.str(), includedFileInfo.lastWriteTime.toString()); - Id edgeId = addEdge(Edge::EDGE_INCLUDE, fileNodeId, includedFileNodeId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - -void ParserClientImpl::onMacroExpandParsed(const ParseLocation &location, const NameHierarchy& macroNameHierarchy) -{ - log("macro use", macroNameHierarchy.getQualifiedName(), location); - - Id macroExpandId = addNodeHierarchy(Node::NODE_MACRO, macroNameHierarchy, DEFINITION_NONE); - Id fileNodeId = addFile(location.filePath.str()); - Id edgeId = addEdge(Edge::EDGE_MACRO_USAGE, fileNodeId, macroExpandId); - addSourceLocation(edgeId, location, locationTypeToInt(LOCATION_TOKEN)); -} - Node::NodeType ParserClientImpl::symbolKindToNodeType(SymbolKind symbolType) const { switch (symbolType) @@ -636,12 +339,3 @@ void ParserClientImpl::addError(const std::string& message, bool fatal, bool ind m_storage->addError(message, location.filePath, location.startLineNumber, location.startColumnNumber, fatal, indexed); } - -void ParserClientImpl::log(std::string type, std::string str, const ParseLocation& location) const -{ - LOG_INFO_STREAM_BARE( - << type << ": " << str << " <" << location.filePath.str() << " " - << location.startLineNumber << ":" << location.startColumnNumber << " " - << location.endLineNumber << ":" << location.endColumnNumber << ">" - ); -} diff --git a/src/lib/data/parser/ParserClientImpl.h b/src/lib/data/parser/ParserClientImpl.h index 47dc745f..c004969e 100644 --- a/src/lib/data/parser/ParserClientImpl.h +++ b/src/lib/data/parser/ParserClientImpl.h @@ -22,7 +22,6 @@ public: virtual void startParsingFile(); virtual void finishParsingFile(); - virtual Id recordSymbol( const NameHierarchy& symbolName, SymbolKind symbolType, AccessKind access = ACCESS_NONE, bool isImplicit = false); @@ -42,66 +41,10 @@ public: const ParseLocation& location); virtual void onError(const ParseLocation& location, const std::string& message, bool fatal, bool indexed); - - virtual void onTypedefParsed( - const ParseLocation& location, const NameHierarchy& typedefName, AccessKind access, bool isImplicit); - virtual void onClassParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit); - virtual void onStructParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit); - virtual void onGlobalVariableParsed(const ParseLocation& location, const NameHierarchy& variable, bool isImplicit); - virtual void onFieldParsed(const ParseLocation& location, const NameHierarchy& field, AccessKind access, bool isImplicit); - virtual void onFunctionParsed( - const ParseLocation& location, const NameHierarchy& function, const ParseLocation& scopeLocation, bool isImplicit); - virtual void onMethodParsed( - const ParseLocation& location, const NameHierarchy& method, AccessKind access, AbstractionType abstraction, - const ParseLocation& scopeLocation, bool isImplicit); - virtual void onNamespaceParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, - const ParseLocation& scopeLocation, bool isImplicit); - virtual void onEnumParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit); - virtual void onEnumConstantParsed(const ParseLocation& location, const NameHierarchy& nameHierarchy, bool isImplicit); - virtual void onTemplateParameterTypeParsed( - const ParseLocation& location, const NameHierarchy& templateParameterTypeNameHierarchy, bool isImplicit); virtual void onLocalSymbolParsed(const std::string& name, const ParseLocation& location); virtual void onFileParsed(const FileInfo& fileInfo); - virtual void onMacroDefineParsed( - const ParseLocation& location, const NameHierarchy& macroNameHierarchy, const ParseLocation& scopeLocation); virtual void onCommentParsed(const ParseLocation& location); - virtual void onInheritanceParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, - const NameHierarchy& baseNameHierarchy); - virtual void onMethodOverrideParsed( - const ParseLocation& location, const NameHierarchy& overridden, const NameHierarchy& overrider); - virtual void onCallParsed( - const ParseLocation& location, const NameHierarchy& caller, const NameHierarchy& callee); - virtual void onUsageParsed( - const ParseLocation& location, const NameHierarchy& userName, SymbolKind usedType, const NameHierarchy& usedName); - virtual void onTypeUsageParsed(const ParseLocation& location, const NameHierarchy& user, const NameHierarchy& used); - - virtual void onTemplateArgumentTypeParsed( - const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy, - const NameHierarchy& templateNameHierarchy); - virtual void onTemplateDefaultArgumentTypeParsed( - const ParseLocation& location, const NameHierarchy& defaultArgumentTypeNameHierarchy, - const NameHierarchy& templateParameterNameHierarchy); - virtual void onTemplateSpecializationParsed( - const ParseLocation& location, const NameHierarchy& specializedNameHierarchy, - const NameHierarchy& specializedFromNameHierarchy); - virtual void onTemplateMemberFunctionSpecializationParsed( - const ParseLocation& location, const NameHierarchy& instantiatedFunction, const NameHierarchy& specializedFunction); - - virtual void onFileIncludeParsed( - const ParseLocation& location, const FileInfo& fileInfo, const FileInfo& includedFileInfo); - - virtual void onMacroExpandParsed( - const ParseLocation& location, const NameHierarchy& macroNameHierarchy); - private: Node::NodeType symbolKindToNodeType(SymbolKind symbolType) const; Edge::EdgeType referenceKindToEdgeType(ReferenceKind referenceKind) const; @@ -118,8 +61,6 @@ private: void addCommentLocation(const ParseLocation& location); void addError(const std::string& message, bool fatal, bool indexed, const ParseLocation& location); - void log(std::string type, std::string str, const ParseLocation& location) const; - std::shared_ptr m_storage; }; diff --git a/src/lib/settings/ApplicationSettings.cpp b/src/lib/settings/ApplicationSettings.cpp index a4d94add..f920e87d 100644 --- a/src/lib/settings/ApplicationSettings.cpp +++ b/src/lib/settings/ApplicationSettings.cpp @@ -160,9 +160,19 @@ bool ApplicationSettings::getLoggingEnabled() const return getValue("application/logging_enabled", false); } -void ApplicationSettings::setLoggingEnabled(bool loggingEnabled) +void ApplicationSettings::setLoggingEnabled(bool value) { - setValue("application/logging_enabled", loggingEnabled); + setValue("application/logging_enabled", value); +} + +bool ApplicationSettings::getVerboseInderxerLoggingEnabled() const +{ + return getValue("application/verbose_indexer_logging_enabled", false); +} + +void ApplicationSettings::setVerboseInderxerLoggingEnabled(bool value) +{ + setValue("application/verbose_indexer_logging_enabled", value); } int ApplicationSettings::getIndexerThreadCount() const diff --git a/src/lib/settings/ApplicationSettings.h b/src/lib/settings/ApplicationSettings.h index 3067b64c..975e7e72 100644 --- a/src/lib/settings/ApplicationSettings.h +++ b/src/lib/settings/ApplicationSettings.h @@ -50,6 +50,9 @@ public: bool getLoggingEnabled() const; void setLoggingEnabled(bool loggingEnabled); + bool getVerboseInderxerLoggingEnabled() const; + void setVerboseInderxerLoggingEnabled(bool loggingEnabled); + // indexing int getIndexerThreadCount() const; void setIndexerThreadCount(const int count); diff --git a/src/lib/utility/logging/FileLogger.cpp b/src/lib/utility/logging/FileLogger.cpp index f5e59ca5..e88cc352 100644 --- a/src/lib/utility/logging/FileLogger.cpp +++ b/src/lib/utility/logging/FileLogger.cpp @@ -106,6 +106,7 @@ void FileLogger::logMessage(const std::string& type, const LogMessage& message) std::ofstream fileStream; fileStream.open(m_logDirectory + m_currentLogFileName, std::ios::app); fileStream << message.getTimeString("%H:%M:%S") << " | "; + fileStream << message.threadId << " | "; if (message.filePath.size()) { diff --git a/src/lib/utility/logging/LogManagerImplementation.cpp b/src/lib/utility/logging/LogManagerImplementation.cpp index 1c11403a..dfa9477c 100644 --- a/src/lib/utility/logging/LogManagerImplementation.cpp +++ b/src/lib/utility/logging/LogManagerImplementation.cpp @@ -70,7 +70,7 @@ void LogManagerImplementation::logInfo( std::lock_guard lockGuardLogger(m_loggerMutex); for (unsigned int i = 0; i < m_loggers.size(); i++) { - m_loggers[i]->onInfo(LogMessage(message, file, function, line, getTime())); + m_loggers[i]->onInfo(LogMessage(message, file, function, line, getTime(), std::this_thread::get_id())); } } @@ -84,7 +84,7 @@ void LogManagerImplementation::logWarning( std::lock_guard lockGuardLogger(m_loggerMutex); for (unsigned int i = 0; i < m_loggers.size(); i++) { - m_loggers[i]->onWarning(LogMessage(message, file, function, line, getTime())); + m_loggers[i]->onWarning(LogMessage(message, file, function, line, getTime(), std::this_thread::get_id())); } } @@ -98,7 +98,7 @@ void LogManagerImplementation::logError( std::lock_guard lockGuardLogger(m_loggerMutex); for (unsigned int i = 0; i < m_loggers.size(); i++) { - m_loggers[i]->onError(LogMessage(message, file, function, line, getTime())); + m_loggers[i]->onError(LogMessage(message, file, function, line, getTime(), std::this_thread::get_id())); } } diff --git a/src/lib/utility/logging/LogMessage.h b/src/lib/utility/logging/LogMessage.h index b5ded3a2..05c0564d 100644 --- a/src/lib/utility/logging/LogMessage.h +++ b/src/lib/utility/logging/LogMessage.h @@ -3,6 +3,7 @@ #include #include +#include struct LogMessage { @@ -12,13 +13,15 @@ public: const std::string& filePath, const std::string& functionName, const unsigned int line, - const std::tm& time + const std::tm& time, + const std::thread::id& threadId ) : message(message) , filePath(filePath) , functionName(functionName) , line(line) , time(time) + , threadId(threadId) {} std::string getTimeString(const std::string& format) const @@ -38,6 +41,7 @@ public: const std::string functionName; const unsigned int line; const std::tm time; + const std::thread::id threadId; }; #endif // LOG_MESSAGE_H diff --git a/src/lib/utility/logging/logging.h b/src/lib/utility/logging/logging.h index ee4fa075..690ebb75 100644 --- a/src/lib/utility/logging/logging.h +++ b/src/lib/utility/logging/logging.h @@ -65,4 +65,22 @@ } \ while(0) +#define LOG_WARNING_STREAM_BARE(__s__) \ + do \ + { \ + std::stringstream __ss__; \ + __ss__ __s__; \ + LogManager::getInstance()->logWarning(__ss__.str(), "", "", 0); \ + } \ + while(0) + +#define LOG_ERROR_STREAM_BARE(__s__) \ + do \ + { \ + std::stringstream __ss__; \ + __ss__ __s__; \ + LogManager::getInstance()->logError(__ss__.str(), "", "", 0); \ + } \ + while(0) + #endif // LOGGING_H diff --git a/src/lib_cxx/CMakeLists.txt b/src/lib_cxx/CMakeLists.txt index ff510597..5faebeba 100644 --- a/src/lib_cxx/CMakeLists.txt +++ b/src/lib_cxx/CMakeLists.txt @@ -17,16 +17,20 @@ add_files( data/parser/cxx/ASTActionFactory.h data/parser/cxx/ASTConsumer.cpp data/parser/cxx/ASTConsumer.h - data/parser/cxx/ASTVisitor.cpp - data/parser/cxx/ASTVisitor.h data/parser/cxx/CommentHandler.cpp data/parser/cxx/CommentHandler.h + data/parser/cxx/CxxASTVisitor.cpp + data/parser/cxx/CxxASTVisitor.h data/parser/cxx/CxxCompilationDatabaseSingle.cpp data/parser/cxx/CxxCompilationDatabaseSingle.h + data/parser/cxx/CxxContext.cpp + data/parser/cxx/CxxContext.h data/parser/cxx/CxxDiagnosticConsumer.cpp data/parser/cxx/CxxDiagnosticConsumer.h data/parser/cxx/CxxParser.cpp data/parser/cxx/CxxParser.h + data/parser/cxx/CxxVerboseAstVisitor.cpp + data/parser/cxx/CxxVerboseAstVisitor.h data/parser/cxx/PreprocessorCallbacks.cpp data/parser/cxx/PreprocessorCallbacks.h data/parser/cxx/utilityCxx.cpp diff --git a/src/lib_cxx/data/parser/cxx/ASTConsumer.cpp b/src/lib_cxx/data/parser/cxx/ASTConsumer.cpp index 0c99ab53..e0a35383 100644 --- a/src/lib_cxx/data/parser/cxx/ASTConsumer.cpp +++ b/src/lib_cxx/data/parser/cxx/ASTConsumer.cpp @@ -1,10 +1,18 @@ #include "data/parser/cxx/ASTConsumer.h" - -#include "data/parser/ParserClient.h" +#include "data/parser/cxx/CxxAstVisitor.h" +#include "data/parser/cxx/CxxVerboseAstVisitor.h" +#include "settings/ApplicationSettings.h" ASTConsumer::ASTConsumer(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister) - : m_visitor(context, preprocessor, client, fileRegister) { + if (ApplicationSettings::getInstance()->getVerboseInderxerLoggingEnabled()) + { + m_visitor = std::make_shared(context, preprocessor, client, fileRegister); + } + else + { + m_visitor = std::make_shared(context, preprocessor, client, fileRegister); + } } ASTConsumer::~ASTConsumer() @@ -13,5 +21,5 @@ ASTConsumer::~ASTConsumer() void ASTConsumer::HandleTranslationUnit(clang::ASTContext& context) { - m_visitor.indexDecl(context.getTranslationUnitDecl()); + m_visitor->indexDecl(context.getTranslationUnitDecl()); } diff --git a/src/lib_cxx/data/parser/cxx/ASTConsumer.h b/src/lib_cxx/data/parser/cxx/ASTConsumer.h index ea9e05fc..54cfb6a4 100644 --- a/src/lib_cxx/data/parser/cxx/ASTConsumer.h +++ b/src/lib_cxx/data/parser/cxx/ASTConsumer.h @@ -4,9 +4,10 @@ #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "utility/file/FileRegister.h" -#include "data/parser/cxx/ASTVisitor.h" +class CxxAstVisitor; +class FileRegister; +class ParserClient; class ASTConsumer : public clang::ASTConsumer @@ -18,7 +19,7 @@ public: virtual void HandleTranslationUnit(clang::ASTContext& context); private: - ASTVisitor m_visitor; + std::shared_ptr m_visitor; }; #endif // AST_CONSUMER_H diff --git a/src/lib_cxx/data/parser/cxx/ASTVisitor.cpp b/src/lib_cxx/data/parser/cxx/ASTVisitor.cpp deleted file mode 100644 index a5429054..00000000 --- a/src/lib_cxx/data/parser/cxx/ASTVisitor.cpp +++ /dev/null @@ -1,1688 +0,0 @@ -#include "data/parser/cxx/ASTVisitor.h" - -#include -#include -#include -#include -#include - -#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h" -#include "data/parser/cxx/utilityCxx.h" -#include "data/parser/ParseLocation.h" - -#include "utility/ScopedSwitcher.h" - -// TODO: For an array access, X[I], skip over the array-to-pointer decay. We -// currently record that X's address is taken, which is technically true, but -// the address does not generally escape. - -// TODO: A struct assignment in C++ turns into an operator= call, even if the -// user did not define an operator= function. Consider handling operator= -// calls the same way that normal assignment operations are handled. Consider -// doing the same for the other overloadable operators. - -// TODO: Unary ++ and -- -// TODO: Fix local extern variables. e.g. void func() { extern int var; } -// Consider extern "C", functions nested within classes or namespaces. - -/////////////////////////////////////////////////////////////////////////////// -// Misc routines - -ASTVisitor::ASTVisitor(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister) - : m_context(context) - , m_preprocessor(preprocessor) - , m_client(client) - , m_fileRegister(fileRegister) - , m_thisContext(0) - , m_childContext(0) - , m_typeContext(RT_Reference) - , m_contextAccess(ACCESS_NONE) -{ - m_declNameCache = std::make_shared([](const clang::NamedDecl* decl) -> NameHierarchy - { - if (decl) - { - return utility::getDeclNameHierarchy(decl); - } - return NameHierarchy("global"); - }); - m_typeNameCache = std::make_shared([](const clang::Type* type) -> NameHierarchy - { - if (type) - { - CxxTypeNameResolver resolver; - return resolver.getTypeNameHierarchy(type); - } - return NameHierarchy("global"); - }); -} - -ASTVisitor::~ASTVisitor() -{ -} - -bool ASTVisitor::VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl) -{ - // decl->dump(); - return true; -} - - -/////////////////////////////////////////////////////////////////////////////// -// Dispatcher routines - -// Set the "this" context to the "child" context and reset the child context -// to default. - -bool ASTVisitor::TraverseStmt(clang::Stmt *stmt) -{ - if (stmt == NULL) - return true; - - ScopedSwitcher sw1(m_thisContext, m_childContext); - - if (clang::Expr *e = llvm::dyn_cast(stmt)) { - if (e->isRValue()) - m_thisContext &= ~(CF_AddressTaken | CF_Assigned | CF_Modified); - } else { - m_thisContext = 0; - } - - ScopedSwitcher sw2(m_childContext, m_thisContext); - - return base::TraverseStmt(stmt); -} - -bool ASTVisitor::TraverseType(clang::QualType t) -{ - ScopedSwitcher sw1(m_thisContext, 0); - ScopedSwitcher sw2(m_childContext, 0); - return base::TraverseType(t); -} - -bool ASTVisitor::TraverseTypeLoc(clang::TypeLoc tl) -{ - ScopedSwitcher sw1(m_thisContext, 0); - ScopedSwitcher sw2(m_childContext, 0); - return base::TraverseTypeLoc(tl); -} - -bool ASTVisitor::TraverseDecl(clang::Decl *d) -{ - ScopedSwitcher sw1(m_thisContext, 0); - ScopedSwitcher sw2(m_childContext, 0); - - std::shared_ptr>> sw3; - if (d && clang::isa(d) && clang::isa(d) && !clang::isa(d)) - { - clang::NamedDecl* nd = clang::dyn_cast(d); - sw3 = std::make_shared>>( - m_contextNameGenerator, std::make_shared(nd, m_declNameCache) - ); - } - - return base::TraverseDecl(d); -} - -bool ASTVisitor::TraverseLambdaExpr(clang::LambdaExpr* e) -{ - ScopedSwitcher> switcher( - m_contextNameGenerator, std::make_shared(e->getCallOperator(), m_declNameCache) - ); - return base::TraverseLambdaExpr(e); -} - -bool ASTVisitor::TraverseFunctionDecl(clang::FunctionDecl* d) -{ - ScopedSwitcher> switcher( - m_childContextNameGenerator, std::make_shared(d, m_declNameCache) - ); // store context for template arguments of function specialitzation - return base::TraverseFunctionDecl(d); -} - -bool ASTVisitor::TraverseTypedefDecl(clang::TypedefDecl *d) -{ - ScopedSwitcher> switcher( - m_contextNameGenerator, std::make_shared(d, m_declNameCache) - ); - return base::TraverseTypedefDecl(d); -} - -bool ASTVisitor::TraverseTypeAliasDecl(clang::TypeAliasDecl *d) -{ - ScopedSwitcher> switcher( - m_contextNameGenerator, std::make_shared(d, m_declNameCache) - ); - return base::TraverseTypeAliasDecl(d); -} - -bool ASTVisitor::TraverseFieldDecl(clang::FieldDecl *d) -{ - ScopedSwitcher> switcher( - m_contextNameGenerator, std::make_shared(d, m_declNameCache) - ); - return base::TraverseFieldDecl(d); -} - -bool ASTVisitor::TraverseVarDecl(clang::VarDecl *d) -{ - std::shared_ptr>> switcher; - - NameHierarchy contextNameHierarchy = getContextName(); - if (!(contextNameHierarchy.size() > 0 && contextNameHierarchy.back()->hasSignature())) // TODO: whle test if its a function. optimize this: remove requirement to get the name here! - { - switcher = std::make_shared>>( - m_contextNameGenerator, std::make_shared(d, m_declNameCache) - ); - } - return base::TraverseVarDecl(d); -} - -bool ASTVisitor::TraverseClassTemplateDecl(clang::ClassTemplateDecl* d) -{ - ScopedSwitcher> switcher( - m_contextNameGenerator, std::make_shared(d, m_declNameCache) - ); - return base::TraverseClassTemplateDecl(d); -} - -bool ASTVisitor::TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl* d) -{ - // we need to use the templated decl here because name resolving for FunctionTemplateDecl is not returning a correct signature yet. - ScopedSwitcher> switcher( - m_contextNameGenerator, std::make_shared(d->getTemplatedDecl(), m_declNameCache) - ); - return base::TraverseFunctionTemplateDecl(d); -} - -bool ASTVisitor::TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d) -{ - // same as base::TraverseTemplateTypeParmDecl(..) but we need to integrate the setter for the context info. - WalkUpFromTemplateTypeParmDecl(d); - - if (d->hasDefaultArgument() && !d->defaultArgumentWasInherited()) - { - ScopedSwitcher sw1(m_typeContext, RT_TemplateDefaultArgument); - ScopedSwitcher> sw2( - m_contextNameGenerator, std::make_shared(d, m_declNameCache) - ); - TraverseTypeLoc(d->getDefaultArgumentInfo()->getTypeLoc()); - } - - traverseDeclContextHelper(clang::dyn_cast(d)); - return true; -} - -bool ASTVisitor::TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d) -{ - // same as base::TraverseTemplateTemplateParmDecl(..) but we need to integrate the setter for the context info. - WalkUpFromTemplateTemplateParmDecl(d); - - TraverseDecl(d->getTemplatedDecl()); - - if (d->hasDefaultArgument() && !d->defaultArgumentWasInherited()) - { - ScopedSwitcher sw1(m_typeContext, RT_TemplateDefaultArgument); - ScopedSwitcher> sw2( - m_contextNameGenerator, std::make_shared(d, m_declNameCache) - ); - - TraverseTemplateArgumentLoc(d->getDefaultArgument()); - } - - clang::TemplateParameterList* TPL = d->getTemplateParameters(); - if (TPL) - { - for (clang::TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); I != E; ++I) - { - TraverseDecl(*I); - } - } - - traverseDeclContextHelper(clang::dyn_cast(d)); - return true; -} - -bool ASTVisitor::TraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d) -{ - ScopedSwitcher> switcher( - m_childContextNameGenerator, std::make_shared(d, m_declNameCache) - ); - return base::TraverseClassTemplatePartialSpecializationDecl(d); -} - -bool ASTVisitor::TraverseDeclRefExpr(clang::DeclRefExpr* e) -{ - ScopedSwitcher> switcher( - m_childContextNameGenerator, std::make_shared(e->getDecl(), m_declNameCache) - ); - return base::TraverseDeclRefExpr(e); -} - -bool ASTVisitor::TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc) -{ - const clang::Type* t = loc.getTypePtr(); - ScopedSwitcher> switcher( - m_childContextNameGenerator, std::make_shared(t, m_typeNameCache) - ); - return base::TraverseTemplateSpecializationTypeLoc(loc); -} - -bool ASTVisitor::TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e) // TODO: do this for unresolved and dependent stuff -{ - std::shared_ptr clear; - ScopedSwitcher> sw(m_childContextNameGenerator, clear); - return base::TraverseUnresolvedLookupExpr(e); -} - -bool ASTVisitor::TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc) -{ - std::shared_ptr> sw1; - std::shared_ptr>> sw2; - - if (m_typeContext != RT_TemplateDefaultArgument - && m_childContextNameGenerator) - { - sw1 = std::make_shared>(m_typeContext, RT_TemplateArgument); - sw2 = std::make_shared>>( - m_contextNameGenerator, m_childContextNameGenerator - ); - } - - clang::TemplateArgument::ArgKind kk = loc.getArgument().getKind(); - if (kk == clang::TemplateArgument::Template) - { - RecordDeclRef(loc.getArgument().getAsTemplate().getAsTemplateDecl(), loc.getLocation(), m_typeContext); - } - - return base::TraverseTemplateArgumentLoc(loc); -} - -/////////////////////////////////////////////////////////////////////////////// -// Expression context propagation - -bool ASTVisitor::TraverseCallCommon(clang::CallExpr *call) -{ - { - m_childContext = CF_Called; - TraverseStmt(call->getCallee()); - } - for (unsigned int i = 0; i < call->getNumArgs(); ++i) { - clang::Expr *arg = call->getArg(i); - // If the child is really an lvalue, then this call is passing a - // reference. If the child is not an lvalue, then this address-taken - // flag will be masked out, and the rvalue will be assumed to be read. - m_childContext = CF_AddressTaken; - TraverseStmt(arg); - } - return true; -} - -bool ASTVisitor::TraverseBinComma(clang::BinaryOperator *s) -{ - { - m_childContext = 0; - TraverseStmt(s->getLHS()); - } - { - m_childContext = m_thisContext; - TraverseStmt(s->getRHS()); - } - return true; -} - -bool ASTVisitor::TraverseAssignCommon( - clang::BinaryOperator *e, - ContextFlags lhsFlag) -{ - { - m_childContext = m_thisContext | lhsFlag; - if (m_childContext & CF_Called) { - m_childContext ^= CF_Called; - m_childContext |= CF_Read; - } - TraverseStmt(e->getLHS()); - } - { - m_childContext = 0; - TraverseStmt(e->getRHS()); - } - return true; -} - -bool ASTVisitor::VisitCastExpr(clang::CastExpr *e) -{ - if (e->getCastKind() == clang::CK_ArrayToPointerDecay) { - // Note that e->getSubExpr() can be an rvalue array, in which case the - // CF_AddressTaken context will be masked away to 0. - m_childContext = CF_AddressTaken; - } else if (e->getCastKind() == clang::CK_ToVoid) { - m_childContext = 0; - } else if (e->getCastKind() == clang::CK_LValueToRValue) { - m_childContext = CF_Read; - } - return true; -} - -bool ASTVisitor::VisitUnaryAddrOf(clang::UnaryOperator *e) -{ - m_childContext = CF_AddressTaken; - return true; -} - -bool ASTVisitor::VisitUnaryDeref(clang::UnaryOperator *e) -{ - m_childContext = 0; - return true; -} - -bool ASTVisitor::VisitDeclStmt(clang::DeclStmt *s) -{ - // If a declaration is a reference to an lvalue initializer, then we - // record that that the initializer's address was taken. If it is - // an rvalue instead, then we'll see something else in the tree indicating - // what kind of reference to record (e.g. lval-to-rval cast, assignment, - // call, & operator) or assume the rvalue is being read. - m_childContext = CF_AddressTaken; - return true; -} - -bool ASTVisitor::VisitReturnStmt(clang::ReturnStmt *s) -{ - // See comment for VisitDeclStmt. - m_childContext = CF_AddressTaken; - return true; -} - -bool ASTVisitor::VisitVarDecl(clang::VarDecl *d) -{ - // See comment for VisitDeclStmt. Set the context for the variable's - // initializer. Also handle default arguments on parameter declarations. - m_childContext = CF_AddressTaken; - return true; -} - -bool ASTVisitor::VisitInitListExpr(clang::InitListExpr *e) -{ - // See comment for VisitDeclStmt. An initializer list can also bind - // references. - m_childContext = CF_AddressTaken; - return true; -} - -bool ASTVisitor::TraverseConstructorInitializer(clang::CXXCtorInitializer *init) -{ - if (init->getMember() != NULL) - { - RecordDeclRef(init->getMember(), - init->getMemberLocation(), - RT_Initialized, - SYMBOL_FIELD); - } - - // See comment for VisitDeclStmt. - m_childContext = CF_AddressTaken; - return base::TraverseConstructorInitializer(init); -} - - -/////////////////////////////////////////////////////////////////////////////// -// Expression reference recording - -bool ASTVisitor::VisitLambdaExpr(clang::LambdaExpr* e) -{ - RecordDeclRef(e->getCallOperator(), e->getLocStart(), RT_Definition, SYMBOL_FUNCTION); - return true; -} - -bool ASTVisitor::VisitMemberExpr(clang::MemberExpr *e) -{ - RecordDeclRefExpr( - e->getMemberDecl(), - e->getMemberLoc(), - e, - m_thisContext); - - // Update the child context for the base sub-expression. - if (e->isArrow()) { - m_childContext = CF_Read; - } else { - m_childContext = 0; - if (m_thisContext & CF_AddressTaken) - m_childContext |= CF_AddressTaken; - if (m_thisContext & (CF_Assigned | CF_Modified)) - m_childContext |= CF_Modified; - if (m_thisContext & CF_Read) - m_childContext |= CF_Read; - if (m_thisContext & CF_Called) { - // I'm not sure what the best behavior here is. - m_childContext |= CF_Read; - } - } - - return true; -} - -bool ASTVisitor::VisitDeclRefExpr(clang::DeclRefExpr *e) -{ - RecordDeclRefExpr( - e->getDecl(), - e->getLocation(), - e, - m_thisContext); - return true; -} - -bool ASTVisitor::VisitCXXConstructExpr(clang::CXXConstructExpr *e) -{ - //if (e->getParenOrBraceRange().isValid()) { - // // XXX: This code is a kludge. Recording calls to constructors is - // // troublesome because there isn't an obvious location to associate the - // // call with. Consider: - // // A::A() : field(1, 2, 3) {} - // // new A(1, 2, 3) - // // struct A { A(B); }; A f() { B b; return b; } - // // Implicit calls to conversion operator methods pose a similar - // // problem. - // // - // // Recording constructor calls is very useful, though, so, as a - // // temporary measure, when there are constructor arguments surrounded - // // by parentheses, associate the call with the right parenthesis. - // // - // // Perhaps the right fix is to associate the call with the line itself - // // or with a larger span which may have other references nested within - // // it. The fix may have implications for the navigator GUI. - // RecordDeclRefExpr( - // e->getConstructor(), - // e->getParenOrBraceRange().getEnd(), - // e, - // CF_Called); - //} - clang::SourceLocation loc; - clang::SourceLocation braceBeginLoc = e->getParenOrBraceRange().getBegin(); - clang::SourceLocation nameBeginLoc = e->getSourceRange().getBegin(); - if (braceBeginLoc.isValid()) - { - if (braceBeginLoc == nameBeginLoc) - { - loc = nameBeginLoc; - } - else - { - loc = braceBeginLoc.getLocWithOffset(-1); - } - } - else - { - loc = e->getSourceRange().getEnd(); - } - loc = clang::Lexer::GetBeginningOfToken(loc, m_context->getSourceManager(), m_context->getLangOpts()); - RecordDeclRefExpr( - e->getConstructor(), - loc, - e, - CF_Called); - return true; -} - -void ASTVisitor::RecordDeclRefExpr(clang::NamedDecl *d, clang::SourceLocation loc, clang::Expr *e, Context context) -{ - SymbolKind symbolType = SYMBOL_KIND_MAX; - - if (clang::isa(d)) - { - if (llvm::isa(d)) - { - symbolType = SYMBOL_PARAMETER; - } - else if (d->getParentFunctionOrMethod() == NULL) - { - symbolType = SYMBOL_GLOBAL_VARIABLE; - } - else - { - symbolType = SYMBOL_LOCAL_VARIABLE; - } - } - if (clang::isa(d)) - { - symbolType = SYMBOL_ENUM_CONSTANT; - } - else if (clang::isa(d)) - { - symbolType = SYMBOL_FIELD; - } - - if (m_typeContext == RT_TemplateArgument) - { - RecordDeclRef(d, loc, m_typeContext, symbolType); - } - else - { - - if (llvm::isa(*d)) - { - // XXX: This code seems sloppy, but I suspect it will work well enough. - if (context & CF_Called) - RecordDeclRef(d, loc, RT_Called, symbolType); - if (!(context & CF_Called) || (context & (CF_Read | CF_AddressTaken))) - RecordDeclRef(d, loc, RT_AddressTaken, symbolType); - } - else - { - if (context & CF_Called) - RecordDeclRef(d, loc, RT_Called, symbolType); - if (context & CF_Read) - RecordDeclRef(d, loc, RT_Read, symbolType); - if (context & CF_AddressTaken) - RecordDeclRef(d, loc, RT_AddressTaken, symbolType); - if (context & CF_Assigned) - RecordDeclRef(d, loc, RT_Assigned, symbolType); - if (context & CF_Modified) - RecordDeclRef(d, loc, RT_Modified, symbolType); - if (context == 0) - RecordDeclRef(d, loc, e->isRValue() ? RT_Read : RT_Other, symbolType); - } - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// NestedNameSpecifier handling - -bool ASTVisitor::TraverseNestedNameSpecifierLoc( - clang::NestedNameSpecifierLoc qualifier) -{ - for (; qualifier; qualifier = qualifier.getPrefix()) { - clang::NestedNameSpecifier *nns = qualifier.getNestedNameSpecifier(); - switch (nns->getKind()) { - case clang::NestedNameSpecifier::Namespace: - RecordDeclRef(nns->getAsNamespace(), - qualifier.getLocalBeginLoc(), - RT_Qualifier); - break; - case clang::NestedNameSpecifier::NamespaceAlias: - RecordDeclRef(nns->getAsNamespaceAlias(), - qualifier.getLocalBeginLoc(), - RT_Qualifier); - break; - case clang::NestedNameSpecifier::TypeSpec: - case clang::NestedNameSpecifier::TypeSpecWithTemplate: - if (const clang::TypedefType *tt = nns->getAsType()->getAs()) { - RecordDeclRef(tt->getDecl(), - qualifier.getLocalBeginLoc(), - RT_Qualifier); - } else if (const clang::RecordType *rt = nns->getAsType()->getAs()) { - RecordDeclRef(rt->getDecl(), - qualifier.getLocalBeginLoc(), - RT_Qualifier); - } else if (const clang::TemplateSpecializationType *tst = - nns->getAsType()->getAs()) { - - if (clang::TemplateDecl *decl = tst->getTemplateName().getAsTemplateDecl()) { - if (clang::NamedDecl *templatedDecl = decl->getTemplatedDecl()) { - RecordDeclRef(templatedDecl, - qualifier.getLocalBeginLoc(), - RT_Qualifier); - - } - } - } - break; - default: // case Global: case Super: - // do nothing for the remaining cases - break; - } - } - return true; -} - - -/////////////////////////////////////////////////////////////////////////////// -// Declaration and TypeLoc handling - -void ASTVisitor::traverseDeclContextHelper(clang::DeclContext *d) -{ - if (!d) - return; - - // Traverse children. - for (clang::DeclContext::decl_iterator it = d->decls_begin(), - itEnd = d->decls_end(); it != itEnd; ++it) { - // BlockDecls are traversed through BlockExprs. - if (!llvm::isa(*it)) - TraverseDecl(*it); - } -} - -// Overriding TraverseCXXRecordDecl lets us mark the base-class references -// with the "Base-Class" kind. -bool ASTVisitor::TraverseCXXRecordDecl(clang::CXXRecordDecl *d) -{ - if (d->isImplicit()) - { - // do nothing - return true; - } - - // Traverse qualifiers on the record decl. - TraverseNestedNameSpecifierLoc(d->getQualifierLoc()); - - // Visit the TagDecl to record its ref. - WalkUpFromCXXRecordDecl(d); - - // Traverse base classes. - if (d->isThisDeclarationADefinition()) { - for (clang::CXXRecordDecl::base_class_iterator it = d->bases_begin(); - it != d->bases_end(); - ++it) { - clang::CXXBaseSpecifier *baseSpecifier = it; - ScopedSwitcher sw1(m_typeContext, RT_BaseClass); - ScopedSwitcher sw2( - m_contextAccess, convertAccessType(baseSpecifier->getAccessSpecifier()) - ); - ScopedSwitcher> sw3( - m_contextNameGenerator, std::make_shared(d, m_declNameCache) - ); - TraverseTypeLoc(baseSpecifier->getTypeSourceInfo()->getTypeLoc()); - } - } - - traverseDeclContextHelper(d); - return true; -} - -bool ASTVisitor::TraverseClassTemplateSpecializationDecl( - clang::ClassTemplateSpecializationDecl *d) -{ - // base::TraverseClassTemplateSpecializationDecl calls TraverseTypeLoc, - // which then visits a clang::TemplateSpecializationTypeLoc. We want - // to mark the template specialization as Declaration or Definition, - // not Reference, so skip the TraverseTypeLoc call. - // - // The problem happens with code like this: - // template <> - // struct Vector {}; - - WalkUpFromClassTemplateSpecializationDecl(d); - - if (clang::TypeSourceInfo* tsi = d->getTypeAsWritten()) - { - ScopedSwitcher> switcher( - m_childContextNameGenerator, std::make_shared(d, m_declNameCache) - ); - clang::TypeLoc tl = tsi->getTypeLoc(); - clang::TemplateSpecializationTypeLoc tstl = tl.castAs(); - for (unsigned I = 0, E = tstl.getNumArgs(); I != E; ++I) - { - TraverseTemplateArgumentLoc(tstl.getArgLoc(I)); - } - } - - traverseDeclContextHelper(d); - - - - return true; - //base::TraverseClassTemplateSpecializationDecl(d); -} - -bool ASTVisitor::TraverseNamespaceAliasDecl(clang::NamespaceAliasDecl *d) -{ - // The base::TraverseNamespaceAliasDecl function avoids traversing the - // namespace decl itself because (I think) that would traverse the - // complete contents of the namespace. However, it fails to traverse - // the qualifiers on the target namespace, so we do that here. - TraverseNestedNameSpecifierLoc(d->getQualifierLoc()); - - return base::TraverseNamespaceAliasDecl(d); -} - -void ASTVisitor::templateParameterListsHelper(clang::DeclaratorDecl *d) -{ - for (unsigned i = 0, iEnd = d->getNumTemplateParameterLists(); - i != iEnd; ++i) { - clang::TemplateParameterList *parmList = - d->getTemplateParameterList(i); - for (clang::NamedDecl *parm : *parmList) - TraverseDecl(parm); - } -} - -bool ASTVisitor::VisitDecl(clang::Decl *d) -{ - if (clang::NamedDecl *nd = llvm::dyn_cast(d)) { - clang::SourceLocation loc = nd->getLocation(); - if (clang::FunctionDecl *fd = llvm::dyn_cast(d)) { - //if (fd->getTemplateInstantiationPattern() != NULL) { - // // When Clang instantiates a function template, it seems to - // // create a FunctionDecl for the instantiation that returns - // // false for fd->isThisDeclarationADefinition(). The result - // // is that the template function definition's location is - // // marked as both a Declaration and a Definition. Fix this by - // // omitting the ref on the instantiation. - //} else { -#if 0 - // This code recorded refs without appropriate qualifiers. For - // example, with the code - // template void Vector::clear() {} - // it would record the first A as "A", but it needs to record - // Vector::A. - templateParameterListsHelper(fd); -#endif - RefType refType; - refType = fd->isThisDeclarationADefinition() ? - RT_Definition : RT_Declaration; - SymbolKind symbolType; - if (llvm::isa(fd)) - { - symbolType = SYMBOL_METHOD; - } - else - { - symbolType = SYMBOL_FUNCTION; - } - RecordDeclRef(nd, loc, refType, symbolType); - if (fd->isFunctionTemplateSpecialization()) - { - RecordDeclRef(nd, loc, RT_TemplateSpecialization, symbolType); - } - //} - } else if (clang::VarDecl *vd = llvm::dyn_cast(d)) { - // Don't record the parameter definitions in a function declaration - // (unless the function declaration is also a definition). A - // definition will be recorded at the function's definition, and - // recording two definitions is unhelpful. This code could record - // a different kind of reference, but recording the position of - // parameter names in declarations doesn't seem useful. - bool omitParamVar = false; - const bool isParam = llvm::isa(vd); - if (isParam) { - clang::FunctionDecl *fd = - llvm::dyn_cast_or_null( - vd->getDeclContext()); - if (fd && !fd->isThisDeclarationADefinition()) - omitParamVar = true; - } - if (!omitParamVar) { - RefType refType; - if (vd->isThisDeclarationADefinition() == clang::VarDecl::DeclarationOnly) - refType = RT_Declaration; - else - refType = RT_Definition; - // TODO: Review for correctness. What about local extern? - SymbolKind symbolType; - if (isParam) - { - symbolType = SYMBOL_PARAMETER; - } - else if (vd->getParentFunctionOrMethod() == NULL) - { - if (vd->getAccess() == clang::AS_none) - { - symbolType = SYMBOL_GLOBAL_VARIABLE; - } - else - { - symbolType = SYMBOL_FIELD; - } - } - else - { - symbolType = SYMBOL_LOCAL_VARIABLE; - } - RecordDeclRef(nd, loc, refType, symbolType); - } - } else if (clang::TagDecl *td = llvm::dyn_cast(d)) { - RefType refType; - refType = td->isThisDeclarationADefinition() ? RT_Definition : RT_Declaration; - // Mark an extern template declaration as a Declaration rather than - // a Definition. For example: - // template class Foo {}; // Definition of Foo - // extern template class Foo; // Declaration of Foo - if (clang::ClassTemplateSpecializationDecl *spec = - llvm::dyn_cast(td)) { - if (spec->getTemplateSpecializationKind() != - clang::TSK_ExplicitSpecialization) - refType = RT_Declaration; - } - - SymbolKind symbolType = SYMBOL_KIND_MAX; - // TODO: Handle the C++11 fixed underlying type of enumeration - // declarations. - switch (td->getTagKind()) - { - case clang::TTK_Struct: symbolType = SYMBOL_STRUCT; break; - case clang::TTK_Union: symbolType = SYMBOL_UNION; break; - case clang::TTK_Class: symbolType = SYMBOL_CLASS; break; - case clang::TTK_Enum: symbolType = SYMBOL_ENUM; break; - default: assert(false); - } - RecordDeclRef(nd, loc, refType, symbolType); - - if (clang::isa(td)) - { - RecordDeclRef(nd, loc, RT_TemplateSpecialization, symbolType); - } - } else if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast(d)) { - RecordDeclRef( - ud->getNominatedNamespaceAsWritten(), - loc, RT_UsingDirective); - } else if (clang::UsingDecl *usd = llvm::dyn_cast(d)) { - for (auto it = usd->shadow_begin(), itEnd = usd->shadow_end(); - it != itEnd; ++it) { - clang::UsingShadowDecl *shadow = *it; - RecordDeclRef(shadow->getTargetDecl(), loc, RT_Using); - } - } else if (clang::NamespaceAliasDecl *nad = llvm::dyn_cast(d)) { - RecordDeclRef(nad, loc, RT_Declaration, SYMBOL_NAMESPACE); -// not needed right now! -// RecordDeclRef(nad, loc, RT_Declaration, ST_Namespace); -// RecordDeclRef(nad->getAliasedNamespace(), -// nad->getTargetNameLoc(), -// RT_NamespaceAlias); - } else if (llvm::isa(d)) { - // TODO: use these cases for creating the connection between two undefined template things - // Do nothing. The function will be recorded when it appears as a - // FunctionDecl. - } else if (llvm::isa(d)) { - // Do nothing. The class will be recorded when it appears as a - // RecordDecl. - } else if (llvm::isa(d)) { - // Do nothing. The type alias will be recorded when it appears as a - // TypeAliasDecl. - } else if (llvm::isa(d)) { - RecordDeclRef(nd, loc, RT_Declaration, SYMBOL_FIELD); - } else if (llvm::isa(d)) { - RecordDeclRef(nd, loc, RT_Declaration, SYMBOL_TYPEDEF); - } else if (llvm::isa(d)) { - RecordDeclRef(nd, loc, RT_Declaration, SYMBOL_TYPEDEF); - } else if (llvm::isa(d)) { - RecordDeclRef(nd, loc, RT_Declaration, SYMBOL_NAMESPACE); - } else if (llvm::isa(d)) { - RecordDeclRef(nd, loc, RT_Declaration, SYMBOL_ENUM_CONSTANT); - } else if ( - llvm::isa(d) || - llvm::isa(d) || - llvm::isa(d)) { - RecordDeclRef(nd, loc, RT_Declaration, SYMBOL_TEMPLATE_PARAMETER); - } else { - RecordDeclRef(nd, loc, RT_Declaration); - } - } - - return (m_interruptCounter.getCount() == 0); -} - -//#include "data/parser/ParseFunction.h" -//#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h" -//#include "data/type/NamedDataType.h" - -bool ASTVisitor::VisitTypeLoc(clang::TypeLoc tl) -{ - if (!tl.getAs().isNull()) - { - const clang::TagTypeLoc &ttl = tl.castAs(); - RecordDeclRef(ttl.getDecl(), - tl.getBeginLoc(), - m_typeContext); - } - else if (!tl.getAs().isNull()) - { - const clang::TypedefTypeLoc &ttl = tl.castAs(); - RecordDeclRef(ttl.getTypedefNameDecl(), - tl.getBeginLoc(), - m_typeContext); - } - else if (!tl.getAs().isNull()) - { - const clang::TemplateTypeParmTypeLoc &ttptl = - tl.castAs(); - RecordDeclRef(ttptl.getDecl(), - tl.getBeginLoc(), - m_typeContext); - } - else if (!tl.getAs().isNull()) - { - const clang::TemplateSpecializationTypeLoc &tstl = - tl.castAs(); - const clang::TemplateSpecializationType &tst = - *tstl.getTypePtr()->getAs(); - if (tst.getAsCXXRecordDecl()) - { - RecordDeclRef(tst.getAsCXXRecordDecl(), - tl.getBeginLoc(), - m_typeContext); - } - else // if template specialization cannot be resolved to a concrete declaration. - { // this is the case when using a specialization of a template template parameter. - RecordTypeRef(tstl.getTypePtr(), - tl.getBeginLoc(), - m_typeContext); - } - } - else if (!tl.getAs().isNull()) - { - const clang::DependentNameTypeLoc& dntl = - tl.castAs(); - RecordTypeRef(dntl.getTypePtr(), - dntl.getNameLoc(), - m_typeContext); - } - else if (!tl.getAs().isNull()) - { - const clang::BuiltinTypeLoc &btl = - tl.castAs(); - RecordTypeRef(btl.getTypePtr(), - tl.getBeginLoc(), - m_typeContext); - } - - return true; -} - - -/////////////////////////////////////////////////////////////////////////////// -// Reference recording - -// static inline bool isNamedDeclUnnamed(clang::NamedDecl *d) -// { -// return d->getDeclName().isIdentifier() && d->getIdentifier() == NULL; -// } - -ParseLocation ASTVisitor::getDeclRefRange(clang::NamedDecl *decl, clang::SourceLocation loc) -{ - ParseLocation parseLocation; - clang::SourceManager& sourceManager = m_context->getSourceManager(); - clang::SourceLocation sloc = sourceManager.getSpellingLoc(loc); - { - clang::FileID fileId = sourceManager.getFileID(sloc); - - if (!fileId.isInvalid()) - { - const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); - if (fileEntry != NULL) - { - parseLocation.filePath = FilePath(fileEntry->getName()).canonical(); - } - } - - unsigned int offset = sourceManager.getFileOffset(sloc); - parseLocation.startLineNumber = sourceManager.getLineNumber(fileId, offset); - parseLocation.startColumnNumber = sourceManager.getColumnNumber(fileId, offset); - } - if (decl) - { - clang::DeclarationName name = decl->getDeclName(); - clang::DeclarationName::NameKind nameKind = name.getNameKind(); - - // A C++ destructor name consists of two tokens, '~' and an identifier. - // Try to include both of them in the ref. - if (nameKind == clang::DeclarationName::CXXDestructorName) { - // Start by getting the destructor name, sans template arguments. - const clang::Type *nameType = name.getCXXNameType().getTypePtr(); - assert(nameType != NULL); - llvm::StringRef className; - if (const clang::InjectedClassNameType *injectedNameType = - nameType->getAs()) { - className = injectedNameType->getDecl()->getName(); - } - else if (const clang::RecordType *recordType = - nameType->getAs()) { - className = recordType->getDecl()->getName(); - } - if (!className.empty()) { // TODO: maybe its better to use tokens here. - // Scan the characters. - const char *const buffer = sourceManager.getCharacterData(sloc); - const char *p = buffer; - if (p != NULL && *p == '~') { - p++; - // Permit whitespace between the ~ and the class name. - // Technically there could be preprocessor tokens, comments, - // etc.. - while (*p == ' ' || *p == '\t') - p++; - // Match the class name against the text in the source. - if (!strncmp(p, className.data(), className.size())) { - p += className.size(); - if (!isalnum(*p) && *p != '_') { - parseLocation.endLineNumber = parseLocation.startLineNumber; - parseLocation.endColumnNumber = parseLocation.startColumnNumber; - parseLocation.endColumnNumber += p - buffer - 1; - return parseLocation; - } - } - } - } - } - - // For references to C++ overloaded operators, try to include both the - // operator keyword and the operator name in the ref. - if (nameKind == clang::DeclarationName::CXXOperatorName) { - const char *spelling = clang::getOperatorSpelling( - name.getCXXOverloadedOperator()); - if (spelling != NULL) { - const char *const buffer = sourceManager.getCharacterData(sloc); - const char *p = buffer; - if (p != NULL && !strncmp(p, "operator", 8)) { - p += 8; - // Skip whitespace between "operator" and the operator itself. - while (*p == ' ' || *p == '\t') - p++; - // Look for the operator name. This may be too restrictive for - // recognizing multi-token operators like operator[], operator - // delete[], or operator ->*. - if (!strncmp(p, spelling, strlen(spelling))) { - p += strlen(spelling); - parseLocation.endLineNumber = parseLocation.startLineNumber; - parseLocation.endColumnNumber = parseLocation.startColumnNumber; - parseLocation.endColumnNumber += p - buffer - 1; - return parseLocation; - } - } - } - } - } - // General case -- find the end of the token starting at loc. - - { - clang::SourceLocation endSloc = - m_preprocessor->getLocForEndOfToken(sloc); - - unsigned int offset = sourceManager.getFileOffset(endSloc); - clang::FileID fileId = sourceManager.getFileID(endSloc); - parseLocation.endLineNumber = sourceManager.getLineNumber(fileId, offset); - parseLocation.endColumnNumber = sourceManager.getColumnNumber(fileId, offset) - 1; - } - return parseLocation; -} - -void ASTVisitor::RecordTypeRef( - const clang::Type* type, - clang::SourceLocation beginLoc, - RefType refType, - SymbolKind symbolType) -{ - if (isLocatedInUnparsedProjectFile(beginLoc)) - { - ParseLocation parseLocation = getDeclRefRange(0, beginLoc); - NameHierarchy typeNameHierarchy = m_typeNameCache->getValue(type); - NameHierarchy contextNameHierarchy = getContextName(); - - if (refType == RT_TemplateArgument) - { - m_client->onTemplateArgumentTypeParsed( - parseLocation, typeNameHierarchy, contextNameHierarchy); - } - else if (refType == RT_BaseClass) - { - m_client->onInheritanceParsed( - parseLocation, contextNameHierarchy, typeNameHierarchy); - } - else if (refType == RT_TemplateDefaultArgument) - { - m_client->onTemplateDefaultArgumentTypeParsed( - parseLocation, typeNameHierarchy, contextNameHierarchy); - } - else - { - m_client->onTypeUsageParsed( - parseLocation, contextNameHierarchy, typeNameHierarchy); - } - } -} - -void ASTVisitor::RecordDeclRef( - clang::NamedDecl* d, - clang::SourceLocation beginLoc, - RefType refType, - SymbolKind symbolType) -{ - bool declIsImplicit = isImplicit(d); - - if (!d || - (declIsImplicit && !isLocatedInProjectFile(beginLoc)) || - (!declIsImplicit && !isLocatedInUnparsedProjectFile(beginLoc))) - { - return; - } - - ParseLocation parseLocation = getDeclRefRange(d, beginLoc); - NameHierarchy declNameHierarchy = m_declNameCache->getValue(d); - - bool fallback = false; - - - if (symbolType == SYMBOL_LOCAL_VARIABLE || symbolType == SYMBOL_PARAMETER) - { - if (!declIsImplicit) - { - if (clang::VarDecl* varDecl = clang::dyn_cast(d)) - { - ParseLocation declLocation = getParseLocation(varDecl->getSourceRange()); - std::string name = - declLocation.filePath.fileName() + "<" + - std::to_string(declLocation.startLineNumber) + ":" + - std::to_string(declLocation.startColumnNumber) + ">"; - m_client->onLocalSymbolParsed( - name, - parseLocation - ); - } - } - return; - } - - switch (refType) - { - case RT_Declaration: - case RT_Definition: - { - switch (symbolType) - { - case SYMBOL_TYPEDEF: - { - clang::AccessSpecifier accessSpecifier = clang::AccessSpecifier::AS_none; - if (clang::TypeAliasDecl* typeAliasDecl = clang::dyn_cast(d)) - { - accessSpecifier = typeAliasDecl->getAccess(); - } - else if (clang::TypedefDecl* typedefDecl = clang::dyn_cast(d)) - { - accessSpecifier = typedefDecl->getAccess(); - } - - m_client->onTypedefParsed( - parseLocation, - declNameHierarchy, - convertAccessType(accessSpecifier), - declIsImplicit); - } - break; - case SYMBOL_CLASS: - if (clang::RecordDecl* recordDecl = clang::dyn_cast(d)) - { - AccessKind access = convertAccessType(recordDecl->getAccess()); - /* if (access == ACCESS_NONE) // todo: test what's the default access if none is provided - { - access = - }*/ - m_client->onClassParsed( - parseLocation, - declNameHierarchy, - access, - (refType == RT_Definition ? getParseLocationOfRecordBody(recordDecl) : ParseLocation()), - declIsImplicit); - } - break; - case SYMBOL_STRUCT: - if (clang::RecordDecl* recordDecl = clang::dyn_cast(d)) - { - m_client->onStructParsed( - parseLocation, - declNameHierarchy, - convertAccessType(recordDecl->getAccess()), - (refType == RT_Definition ? getParseLocationOfRecordBody(recordDecl) : ParseLocation()), - declIsImplicit); - } - break; - case SYMBOL_GLOBAL_VARIABLE: - m_client->onGlobalVariableParsed( - parseLocation, - declNameHierarchy, - declIsImplicit); - break; - case SYMBOL_FIELD: - //if (clang::VarDecl* varDecl = clang::dyn_cast(d)) - { - m_client->onFieldParsed( - parseLocation, - declNameHierarchy, - convertAccessType(d->getAccess()), - declIsImplicit); - } - break; - case SYMBOL_FUNCTION: - if (clang::FunctionDecl* functionDecl = clang::dyn_cast(d)) - { - m_client->onFunctionParsed( - parseLocation, - declNameHierarchy, - (refType == RT_Definition ? getParseLocationOfFunctionBody(functionDecl) : ParseLocation()), - declIsImplicit); - } - break; - case SYMBOL_METHOD: - if (clang::CXXMethodDecl* methodDecl = clang::dyn_cast(d)) - { - m_client->onMethodParsed( - parseLocation, - declNameHierarchy, - convertAccessType(methodDecl->getAccess()), - getAbstractionType(methodDecl), - (refType == RT_Definition ? getParseLocationOfFunctionBody(methodDecl) : ParseLocation()), - declIsImplicit); - - for (clang::CXXMethodDecl::method_iterator it = methodDecl->begin_overridden_methods(); // iterate in traversal and use RT_Overridden or so.. - it != methodDecl->end_overridden_methods(); it++) - { - m_client->onMethodOverrideParsed( - parseLocation, - m_declNameCache->getValue(*it), - declNameHierarchy); - } - - clang::MemberSpecializationInfo* memberSpecializationInfo = methodDecl->getMemberSpecializationInfo(); - if (memberSpecializationInfo) - { - clang::NamedDecl* specializedNamedDecl = memberSpecializationInfo->getInstantiatedFrom(); - if (clang::isa(specializedNamedDecl)) - { - m_client->onTemplateMemberFunctionSpecializationParsed( - parseLocation, - declNameHierarchy, - m_declNameCache->getValue(specializedNamedDecl)); - } - } - } - break; - case SYMBOL_NAMESPACE: - if (clang::NamespaceDecl* namespaceDecl = clang::dyn_cast(d)) - { - m_client->onNamespaceParsed( - namespaceDecl->isAnonymousNamespace() ? ParseLocation() : parseLocation, - declNameHierarchy, - getParseLocation(namespaceDecl->getSourceRange()), - declIsImplicit); - } - else if (clang::NamespaceAliasDecl* namespaceAliasDecl = clang::dyn_cast(d)) - { - m_client->onNamespaceParsed( - parseLocation, - declNameHierarchy, - getParseLocation(namespaceAliasDecl->getAliasedNamespace()->getSourceRange()), - declIsImplicit); - } - break; - case SYMBOL_ENUM: - if (clang::EnumDecl* enumDecl = clang::dyn_cast(d)) - { - m_client->onEnumParsed( - parseLocation, - declNameHierarchy, - convertAccessType(enumDecl->getAccess()), - getParseLocation(enumDecl->getSourceRange()), - declIsImplicit); - } - break; - case SYMBOL_ENUM_CONSTANT: - m_client->onEnumConstantParsed( - parseLocation, - declNameHierarchy, - declIsImplicit); - break; - case SYMBOL_TEMPLATE_PARAMETER: - if (!d->getName().empty()) // We don't create symbols for unnamed template parameters. - { - m_client->onTemplateParameterTypeParsed( - parseLocation, - declNameHierarchy, - declIsImplicit); - } - break; - default: - fallback = true; - break; - } - break; - } - case RT_TemplateSpecialization: - { - if (clang::ClassTemplateSpecializationDecl* classTemplateSpecializationDecl = clang::dyn_cast(d)) - { - clang::NamedDecl* specializedFromDecl; - llvm::PointerUnion pu = classTemplateSpecializationDecl->getSpecializedTemplateOrPartial(); - if (pu.is()) - { - specializedFromDecl = pu.get(); - } - else if (pu.is()) - { - specializedFromDecl = pu.get(); - } - - m_client->onTemplateSpecializationParsed( - parseLocation, - declNameHierarchy, - m_declNameCache->getValue(specializedFromDecl)); // todo: use context and childcontext!! - } - else if (clang::FunctionDecl* functionDecl = clang::dyn_cast(d)) - { - m_client->onTemplateSpecializationParsed( - parseLocation, - declNameHierarchy, - m_declNameCache->getValue(functionDecl->getPrimaryTemplate()->getTemplatedDecl())); // TODO: use context and childcontext!! - } - break; - } - case RT_TemplateArgument: - { - const NameHierarchy contextNameHierarchy = getContextName(); - m_client->onTemplateArgumentTypeParsed( - parseLocation, declNameHierarchy, contextNameHierarchy); - break; - } - - case RT_Called: - { - const NameHierarchy contextNameHierarchy = getContextName(); - m_client->onCallParsed( - parseLocation, contextNameHierarchy, declNameHierarchy); - break; - } - case RT_Reference: - { - const NameHierarchy contextNameHierarchy = getContextName(); - m_client->onTypeUsageParsed( - parseLocation, contextNameHierarchy, declNameHierarchy); - break; - } - case RT_TemplateDefaultArgument: - { - const NameHierarchy contextNameHierarchy = getContextName(); - m_client->onTemplateDefaultArgumentTypeParsed( - parseLocation, declNameHierarchy, contextNameHierarchy); - break; - } - case RT_BaseClass: - { - const NameHierarchy contextNameHierarchy = getContextName(); - m_client->onInheritanceParsed( - parseLocation, contextNameHierarchy, declNameHierarchy); - break; - } - case RT_Assigned: - case RT_Read: - case RT_Initialized: - case RT_Modified: - case RT_Other: - case RT_AddressTaken: - { - const NameHierarchy contextNameHierarchy = getContextName(); - m_client->onUsageParsed( - parseLocation, - contextNameHierarchy, - symbolType, - declNameHierarchy - ); - break; - } - case RT_Qualifier: - // Do nothing. - break; - default: - { - fallback = true; - break; - } - } - - if (fallback) - { - std::string name = declNameHierarchy.back()->getName(); - declNameHierarchy.pop(); - declNameHierarchy.push(std::make_shared(name, NameElement::Signature("", "[" + std::to_string(symbolType) + "|" + std::to_string(refType) + "]"))); - - m_client->onFunctionParsed( - parseLocation, - declNameHierarchy, - parseLocation, - declIsImplicit - ); - } - - - - - - //beginLoc = m_indexerContext.sourceManager().getSpellingLoc(beginLoc); - //clang::FileID fileID; - //if (beginLoc.isValid()) - // fileID = m_indexerContext.sourceManager().getFileID(beginLoc); - //IndexerFileContext &fileContext = m_indexerContext.fileContext(fileID); - //indexdb::ID symbolID = fileContext.getDeclSymbolID(d); - - //// Pass the prepared data to the IndexBuilder to record. - //fileContext.builder().recordRef( - // symbolID, - // range.first, - // range.second, - // fileContext.getRefTypeID(refType)); - //if (symbolType != ST_Max) { - // fileContext.builder().recordSymbol( - // symbolID, - // fileContext.getSymbolTypeID(symbolType)); - // if (symbolType != ST_LocalVariable && symbolType != ST_Parameter) { - // fileContext.builder().recordGlobalSymbol(symbolID); - // } - //} -} - -bool ASTVisitor::isImplicit(clang::Decl* d) const -{ - if (!d) - { - return false; - } - - if (d->isImplicit()) - { - if (clang::RecordDecl* rd = clang::dyn_cast_or_null(d)) - { - if (rd->isLambda()) - { - return isImplicit(clang::dyn_cast_or_null(d->getDeclContext())); - } - } - return true; - } - else if (clang::ClassTemplateSpecializationDecl* ctsd = clang::dyn_cast_or_null(d)) - { - if (!ctsd->isExplicitSpecialization()) - { - return true; - } - } - else if (clang::FunctionDecl* fd = clang::dyn_cast_or_null(d)) - { - if (fd->isTemplateInstantiation() && fd->getTemplateSpecializationKind() != clang::TSK_ExplicitSpecialization) // or undefined?? - { - return true; - } - } - - return isImplicit(clang::dyn_cast_or_null(d->getDeclContext())); -} - -bool ASTVisitor::isLocatedInUnparsedProjectFile(clang::SourceLocation loc) -{ - clang::SourceManager& sourceManager = m_context->getSourceManager(); - clang::SourceLocation spellingLoc = sourceManager.getSpellingLoc(loc); - - clang::FileID fileId; - - if (spellingLoc.isValid()) - { - fileId = sourceManager.getFileID(spellingLoc); - } - if (!fileId.isInvalid()) - { - auto it = m_inUnparsedProjectFileMap.find(fileId); - if (it != m_inUnparsedProjectFileMap.end()) - { - return it->second; - } - - bool ret = false; - if (m_context->getSourceManager().isWrittenInMainFile(spellingLoc)) - { - ret = true; - } - else - { - const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); - if (fileEntry != NULL) - { - std::string fileName = fileEntry->getName(); - FilePath filePath = FilePath(fileName).canonical(); - - if (m_fileRegister->hasIncludeFile(filePath)) - { - ret = !(m_fileRegister->includeFileIsParsed(filePath)); - } - } - } - m_inUnparsedProjectFileMap[fileId] = ret; - return ret; - } - return false; -} - -bool ASTVisitor::isLocatedInProjectFile(clang::SourceLocation loc) -{ - clang::SourceManager& sourceManager = m_context->getSourceManager(); - clang::SourceLocation spellingLoc = sourceManager.getSpellingLoc(loc); - - clang::FileID fileId; - - if (spellingLoc.isValid()) - { - fileId = sourceManager.getFileID(spellingLoc); - } - - if (!fileId.isInvalid()) - { - auto it = m_inProjectFileMap.find(fileId); - if (it != m_inProjectFileMap.end()) - { - return it->second; - } - - const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); - if (fileEntry != NULL) - { - std::string fileName = fileEntry->getName(); - FilePath filePath = FilePath(fileName).canonical(); - bool ret = m_fileRegister->hasFilePath(filePath.str()); - m_inProjectFileMap[fileId] = ret; - return ret; - } - } - - return false; -} - -AccessKind ASTVisitor::convertAccessType(clang::AccessSpecifier access) const -{ - switch (access) - { - case clang::AS_public: - return ACCESS_PUBLIC; - case clang::AS_protected: - return ACCESS_PROTECTED; - case clang::AS_private: - return ACCESS_PRIVATE; - case clang::AS_none: - return ACCESS_NONE; - } -} - -ParserClient::AbstractionType ASTVisitor::getAbstractionType(const clang::CXXMethodDecl* methodDecl) const -{ - ParserClient::AbstractionType abstraction = ParserClient::ABSTRACTION_NONE; - if (methodDecl->isPure()) - { - abstraction = ParserClient::ABSTRACTION_PURE_VIRTUAL; - } - else if (methodDecl->isVirtual()) - { - abstraction = ParserClient::ABSTRACTION_VIRTUAL; - } - return abstraction; -} - -ParseLocation ASTVisitor::getParseLocationOfRecordBody(clang::RecordDecl* decl) const -{ - - if (decl->isThisDeclarationADefinition()) - { - clang::SourceRange range; - if (clang::CXXRecordDecl* cxxDecl = clang::dyn_cast_or_null(decl)) - { - clang::ClassTemplateDecl* templateDecl = cxxDecl->getDescribedClassTemplate(); - if (templateDecl) - { - range = templateDecl->getSourceRange(); - } - } - if (range.isInvalid()) - { - range = decl->getDefinition()->getSourceRange(); - } - - return getParseLocation(range); - } - - return ParseLocation(); -} - -ParseLocation ASTVisitor::getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const -{ - if (decl->hasBody() && decl->isThisDeclarationADefinition()) - { - clang::SourceRange range; - clang::FunctionTemplateDecl* templateDecl = decl->getDescribedFunctionTemplate(); - if (templateDecl) - { - range = templateDecl->getSourceRange(); - } - else - { - range = decl->getSourceRange(); - } - - return getParseLocation(range); - } - - return ParseLocation(); -} - -ParseLocation ASTVisitor::getParseLocation(const clang::SourceRange& sourceRange) const -{ - if (sourceRange.isInvalid()) - { - return ParseLocation(); - } - - const clang::SourceManager& sourceManager = m_context->getSourceManager(); - - const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(sourceRange.getBegin(), false); - const clang::PresumedLoc& presumedEnd = sourceManager.getPresumedLoc(sourceRange.getEnd(), false); - - return ParseLocation( - presumedBegin.getFilename(), - presumedBegin.getLine(), - presumedBegin.getColumn(), - presumedEnd.getLine(), - presumedEnd.getColumn() - ); -} - -NameHierarchy ASTVisitor::getContextName() const -{ - if (m_contextNameGenerator) - { - return m_contextNameGenerator->getName(); - } - return NameHierarchy("global"); -} diff --git a/src/lib_cxx/data/parser/cxx/ASTVisitor.h b/src/lib_cxx/data/parser/cxx/ASTVisitor.h deleted file mode 100644 index 43714c17..00000000 --- a/src/lib_cxx/data/parser/cxx/ASTVisitor.h +++ /dev/null @@ -1,248 +0,0 @@ -#ifndef AST_VISITOR_H -#define AST_VISITOR_H - -#include - -#include "clang/AST/ASTContext.h" -#include -#include -#include - -#include "data/parser/ParserClient.h" -#include "data/parser/SymbolKind.h" -#include "utility/file/FileRegister.h" -#include "utility/messaging/MessageInterruptTasksCounter.h" -#include "utility/Cache.h" - -class ASTVisitor - : clang::RecursiveASTVisitor -{ -public: - typedef Cache DeclNameCache; - typedef Cache TypeNameCache; - - class ContextNameGenerator - { - public: - virtual ~ContextNameGenerator() {} - virtual NameHierarchy getName() const = 0; - }; - - class ContextDeclNameGenerator: public ContextNameGenerator - { - public: - ContextDeclNameGenerator(const clang::NamedDecl* decl, std::shared_ptr nameCache) - : m_decl(decl) - , m_nameCache(nameCache) - {} - - virtual ~ContextDeclNameGenerator() {} - - virtual NameHierarchy getName() const - { - return m_nameCache->getValue(m_decl); - } - - private: - const clang::NamedDecl* m_decl; - std::shared_ptr m_nameCache; - }; - - class ContextTypeNameGenerator: public ContextNameGenerator - { - public: - ContextTypeNameGenerator(const clang::Type* type, std::shared_ptr nameCache) - : m_type(type) - , m_nameCache(nameCache) - {} - - virtual ~ContextTypeNameGenerator() {} - - virtual NameHierarchy getName() const - { - return m_nameCache->getValue(m_type); - } - - private: - const clang::Type* m_type; - std::shared_ptr m_nameCache; - }; - - ASTVisitor(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister); - virtual ~ASTVisitor(); - - // Left for debugging purposes. Uncomment to see a colored ast-dump of the parsed file. - virtual bool VisitTranslationUnitDecl(clang::TranslationUnitDecl* decl); - - - void indexDecl(clang::Decl *d) { TraverseDecl(d); } - -private: - typedef clang::RecursiveASTVisitor base; - friend class clang::RecursiveASTVisitor; - - // XXX: The CF_Read flag is useful mostly for lvalues -- for rvalues, we - // don't set the CF_Read flag, but the rvalue is assumed to be read anyway. - - enum ContextFlags { - CF_Called = 0x1, // the value is read only to be called - CF_Read = 0x2, // the value is read for any other use - CF_AddressTaken = 0x4, // the gl-value's address escapes - CF_Assigned = 0x8, // the gl-value is assigned to - CF_Modified = 0x10 // the gl-value is updated (i.e. compound assignment) - }; - - enum RefType : int { - RT_AddressTaken, - RT_Assigned, - RT_BaseClass, - RT_Called, - RT_Declaration, - RT_DefinedTest, - RT_Definition, - RT_Expansion, - RT_Included, - RT_Initialized, - RT_Modified, - RT_NamespaceAlias, - RT_Other, - RT_Qualifier, - RT_Read, - RT_Reference, - RT_TemplateArgument, - RT_TemplateDefaultArgument, - RT_TemplateSpecialization, - RT_Undefinition, - RT_Using, - RT_UsingDirective, - RT_Max - }; - - typedef unsigned int Context; - - clang::ASTContext* m_context; - clang::Preprocessor* m_preprocessor; - ParserClient* m_client; - FileRegister* m_fileRegister; - - Context m_thisContext; - Context m_childContext; - RefType m_typeContext; - - // Misc routines - bool shouldVisitTemplateInstantiations() const { return true; } - bool shouldVisitImplicitCode() const { return true; } - - // Dispatcher routines - bool TraverseStmt(clang::Stmt *stmt); - bool TraverseType(clang::QualType t); - bool TraverseTypeLoc(clang::TypeLoc tl); - bool TraverseDecl(clang::Decl *d); - bool TraverseLambdaExpr(clang::LambdaExpr* e); - bool TraverseFunctionDecl(clang::FunctionDecl* d); - bool TraverseTypedefDecl(clang::TypedefDecl *d); - bool TraverseTypeAliasDecl(clang::TypeAliasDecl *d); - bool TraverseFieldDecl(clang::FieldDecl *d); - bool TraverseVarDecl(clang::VarDecl *d); - bool TraverseClassTemplateDecl(clang::ClassTemplateDecl* d); - bool TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl* d); - bool TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d); - bool TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d); - bool TraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d); - bool TraverseDeclRefExpr(clang::DeclRefExpr* e); - bool TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc); - bool TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e); - bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc); - - // Expression context propagation - bool TraverseCallExpr(clang::CallExpr *e) { return TraverseCallCommon(e); } - bool TraverseCXXMemberCallExpr(clang::CXXMemberCallExpr *e) { return TraverseCallCommon(e); } - bool TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr *e) { return TraverseCallCommon(e); } - bool TraverseBinComma(clang::BinaryOperator *s); - bool TraverseBinAssign(clang::BinaryOperator *e) { return TraverseAssignCommon(e, CF_Assigned); } -#define OPERATOR(NAME) bool TraverseBin##NAME##Assign(clang::CompoundAssignOperator *e) { return TraverseAssignCommon(e, CF_Modified); } - OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) - OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) -#undef OPERATOR - bool VisitParenExpr(clang::ParenExpr *e) { m_childContext = m_thisContext; return true; } - bool VisitCastExpr(clang::CastExpr *e); - bool VisitUnaryAddrOf(clang::UnaryOperator *e); - bool VisitUnaryDeref(clang::UnaryOperator *e); - bool VisitDeclStmt(clang::DeclStmt *s); - bool VisitReturnStmt(clang::ReturnStmt *s); - bool VisitVarDecl(clang::VarDecl *d); - bool VisitInitListExpr(clang::InitListExpr *e); - bool TraverseConstructorInitializer(clang::CXXCtorInitializer *init); - bool TraverseCallCommon(clang::CallExpr *call); - bool TraverseAssignCommon(clang::BinaryOperator *e, ContextFlags lhsFlag); - - // Expression reference recording - bool VisitLambdaExpr(clang::LambdaExpr* e); - bool VisitMemberExpr(clang::MemberExpr *e); - bool VisitDeclRefExpr(clang::DeclRefExpr *e); - bool VisitCXXConstructExpr(clang::CXXConstructExpr *e); - void RecordDeclRefExpr(clang::NamedDecl *d, clang::SourceLocation loc, clang::Expr *e, Context context); - - // NestedNameSpecifier handling - bool TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc qualifier); - - // Declaration and TypeLoc handling - void traverseDeclContextHelper(clang::DeclContext *d); - bool TraverseCXXRecordDecl(clang::CXXRecordDecl *d); - bool TraverseNamespaceAliasDecl(clang::NamespaceAliasDecl *d); - bool TraverseClassTemplateSpecializationDecl( - clang::ClassTemplateSpecializationDecl *d); - void templateParameterListsHelper(clang::DeclaratorDecl *d); - bool VisitDecl(clang::Decl *d); - bool VisitTypeLoc(clang::TypeLoc tl); - - // Reference recording - ParseLocation getDeclRefRange( - clang::NamedDecl *decl, - clang::SourceLocation loc); - - void RecordTypeRef( - const clang::Type* type, - clang::SourceLocation beginLoc, - RefType refType, - SymbolKind symbolType = SYMBOL_KIND_MAX); - - void RecordDeclRef( - clang::NamedDecl *d, - clang::SourceLocation beginLoc, - RefType refType, - SymbolKind symbolType = SYMBOL_KIND_MAX); - - bool isImplicit(clang::Decl* d) const; - - bool isLocatedInUnparsedProjectFile(clang::SourceLocation loc); - bool isLocatedInProjectFile(clang::SourceLocation loc); - - AccessKind convertAccessType(clang::AccessSpecifier access) const; - ParserClient::AbstractionType getAbstractionType(const clang::CXXMethodDecl* methodDecl) const; - ParseLocation getParseLocationOfRecordBody(clang::RecordDecl* decl) const; - ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const; - ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const; - - NameHierarchy getContextName() const; - - struct FileIdHash { - size_t operator()(clang::FileID fileID) const { - return fileID.getHashValue(); - } - }; - - std::unordered_map m_inUnparsedProjectFileMap; - std::unordered_map m_inProjectFileMap; - - std::shared_ptr m_contextNameGenerator; - std::shared_ptr m_childContextNameGenerator; // TODO: rename templateArgumentContextNameGenerator - - std::shared_ptr m_declNameCache; - std::shared_ptr m_typeNameCache; - - AccessKind m_contextAccess; - MessageInterruptTasksCounter m_interruptCounter; -}; - -#endif // AST_VISITOR_H diff --git a/src/lib_cxx/data/parser/cxx/CxxASTVisitor.cpp b/src/lib_cxx/data/parser/cxx/CxxASTVisitor.cpp new file mode 100644 index 00000000..38c502bf --- /dev/null +++ b/src/lib_cxx/data/parser/cxx/CxxASTVisitor.cpp @@ -0,0 +1,1148 @@ +#include "data/parser/cxx/CxxAstVisitor.h" + +#include +#include +#include + +#include "data/parser/ParseLocation.h" +#include "data/parser/ParserClient.h" +#include "utility/file/FileRegister.h" +#include "utility/ScopedFunctor.h" +#include "utility/ScopedSwitcher.h" + +#include "data/parser/cxx/name_resolver/CxxDeclNameResolver.h" +#include "data/parser/cxx/name_resolver/CxxTypeNameResolver.h" + +CxxAstVisitor::CxxAstVisitor(clang::ASTContext* astContext, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister) + : m_astContext(astContext) + , m_preprocessor(preprocessor) + , m_client(client) + , m_fileRegister(fileRegister) + , m_typeRefContext(REFERENCE_TYPE_USAGE) + , m_declRefContext(REFERENCE_USAGE) +{ + m_declNameCache = std::make_shared([](const clang::NamedDecl* decl) -> NameHierarchy + { + if (decl) + { + CxxDeclNameResolver resolver(decl); + return resolver.getDeclNameHierarchy(); + } + return NameHierarchy("global"); + }); + m_typeNameCache = std::make_shared([](const clang::Type* type) -> NameHierarchy + { + if (type) + { + CxxTypeNameResolver resolver; + return resolver.getTypeNameHierarchy(type); + } + return NameHierarchy("global"); + }); +} + +CxxAstVisitor::~CxxAstVisitor() +{ +} + +void CxxAstVisitor::indexDecl(clang::Decl* d) +{ + this->TraverseDecl(d); +} + +bool CxxAstVisitor::shouldVisitTemplateInstantiations() const +{ + return true; +} + +bool CxxAstVisitor::shouldVisitImplicitCode() const +{ + return true; +} + +bool CxxAstVisitor::TraverseDecl(clang::Decl* d) +{ + std::shared_ptr removeContextFunctor; + if (d && + clang::isa(d) && + !clang::isa(d) && // no parameter + !(clang::isa(d) && d->getParentFunctionOrMethod() != NULL) && // no local variable + !clang::isa(d) && // no using directive decl + //!clang::isa(d) && // no using decl + !clang::isa(d) // no namespace + ){ + clang::NamedDecl* nd = clang::dyn_cast(d); + m_contextStack.push_back(std::make_shared(nd, m_declNameCache)); + removeContextFunctor = std::make_shared([this](){ m_contextStack.pop_back(); }); + } + return base::TraverseDecl(d); +} + +bool CxxAstVisitor::TraverseStmt(clang::Stmt* stmt) +{ + return base::TraverseStmt(stmt); +} + +bool CxxAstVisitor::TraverseType(clang::QualType t) +{ + return base::TraverseType(t); +} + +bool CxxAstVisitor::TraverseTypeLoc(clang::TypeLoc tl) +{ + std::shared_ptr removeContextFunctor; + if (!checkIgnoresTypeLoc(tl)) + { + m_contextStack.push_back(std::make_shared(tl.getTypePtr(), m_typeNameCache)); + removeContextFunctor = std::make_shared([this](){ m_contextStack.pop_back(); }); + } + return base::TraverseTypeLoc(tl); +} + +// same as base::TraverseCXXRecordDecl(..) but we need to integrate the setter for the context info. +// additionally: skip implicit CXXRecordDecls (this does not skip template specializations). +bool CxxAstVisitor::TraverseCXXRecordDecl(clang::CXXRecordDecl *d) +{ + if (isImplicit(d)) + { + return true; + } + + WalkUpFromCXXRecordDecl(d); + + TraverseNestedNameSpecifierLoc(d->getQualifierLoc()); + + if (d->isCompleteDefinition()) + { + ScopedSwitcher switcher(m_typeRefContext, REFERENCE_INHERITANCE); + for (const auto& base : d->bases()) + { + if (!TraverseTypeLoc(base.getTypeSourceInfo()->getTypeLoc())) + { + return false; + } + } + } + + traverseDeclContextHelper(clang::dyn_cast(d)); + return true; +} + +// same as base::TraverseTemplateTypeParmDecl(..) but we need to integrate the setter for the context info. +bool CxxAstVisitor::TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d) +{ + WalkUpFromTemplateTypeParmDecl(d); + + if (d->hasDefaultArgument() && !d->defaultArgumentWasInherited()) + { + ScopedSwitcher switcher(m_typeRefContext, REFERENCE_TEMPLATE_DEFAULT_ARGUMENT); + TraverseTypeLoc(d->getDefaultArgumentInfo()->getTypeLoc()); + } + + traverseDeclContextHelper(clang::dyn_cast(d)); + return true; +} + +// same as base::TraverseTemplateTemplateParmDecl(..) but we need to integrate the setter for the context info. +bool CxxAstVisitor::TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d) +{ + WalkUpFromTemplateTemplateParmDecl(d); + + TraverseDecl(d->getTemplatedDecl()); + + if (d->hasDefaultArgument() && !d->defaultArgumentWasInherited()) + { + ScopedSwitcher switcher(m_typeRefContext, REFERENCE_TEMPLATE_DEFAULT_ARGUMENT); + TraverseTemplateArgumentLoc(d->getDefaultArgument()); + } + + clang::TemplateParameterList* TPL = d->getTemplateParameters(); + if (TPL) + { + for (clang::TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); I != E; ++I) + { + TraverseDecl(*I); + } + } + + traverseDeclContextHelper(clang::dyn_cast(d)); + return true; +} + +bool CxxAstVisitor::TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc loc) +{ + // just skip all qualifiers (for now) + return true; +} + +bool CxxAstVisitor::TraverseConstructorInitializer(clang::CXXCtorInitializer* init) +{ + if (!VisitConstructorInitializer(init)) + { + return false; + } + return base::TraverseConstructorInitializer(init); +} + +bool CxxAstVisitor::TraverseCallExpr(clang::CallExpr* s) +{ + return TraverseCallCommon(s); +} + +bool CxxAstVisitor::TraverseCXXMemberCallExpr(clang::CXXMemberCallExpr* s) +{ + return TraverseCallCommon(s); +} + +bool CxxAstVisitor::TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr* s) +{ + return TraverseCallCommon(s); +} + +bool CxxAstVisitor::TraverseCXXConstructExpr(clang::CXXConstructExpr* s) +{ + { + ScopedSwitcher switcher(m_declRefContext, REFERENCE_CALL); + WalkUpFromCXXConstructExpr(s); + } + for (unsigned int i = 0; i < s->getNumArgs(); ++i) { + clang::Expr *arg = s->getArg(i); + TraverseStmt(arg); + } + return true; +} + +bool CxxAstVisitor::TraverseCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* s) +{ + ScopedSwitcher switcher(m_declRefContext, REFERENCE_CALL); + return base::TraverseCXXTemporaryObjectExpr(s); +} + +bool CxxAstVisitor::TraverseLambdaExpr(clang::LambdaExpr* s) +{ + clang::CXXMethodDecl* methodDecl = s->getCallOperator(); + m_contextStack.push_back(std::make_shared(methodDecl, m_declNameCache)); + std::shared_ptr removeContextFunctor = std::make_shared([this](){ m_contextStack.pop_back(); }); + return base::TraverseLambdaExpr(s); +} + +bool CxxAstVisitor::TraverseFunctionDecl(clang::FunctionDecl* d) +{ + ScopedSwitcher> switcher( + m_templateArgumentContext, std::make_shared(d, m_declNameCache) + ); + return base::TraverseFunctionDecl(d); +} + +bool CxxAstVisitor::TraverseClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl *d) +{ + ScopedSwitcher> switcher( + m_templateArgumentContext, std::make_shared(d, m_declNameCache) + ); + return base::TraverseClassTemplateSpecializationDecl(d); +} + +bool CxxAstVisitor::TraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d) +{ + ScopedSwitcher> switcher( + m_templateArgumentContext, std::make_shared(d, m_declNameCache) + ); + return base::TraverseClassTemplatePartialSpecializationDecl(d); +} + +bool CxxAstVisitor::TraverseDeclRefExpr(clang::DeclRefExpr* s) +{ + ScopedSwitcher> switcher( + m_templateArgumentContext, std::make_shared(s->getDecl(), m_declNameCache) + ); + return base::TraverseDeclRefExpr(s); +} + +bool CxxAstVisitor::TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc) +{ + const clang::Type* t = loc.getTypePtr(); + ScopedSwitcher> switcher( + m_templateArgumentContext, std::make_shared(t, m_typeNameCache) + ); + return base::TraverseTemplateSpecializationTypeLoc(loc); +} + +bool CxxAstVisitor::TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* e) // TODO: do this for unresolved and dependent stuff +{ + std::shared_ptr clear; + ScopedSwitcher> sw(m_templateArgumentContext, clear); + return base::TraverseUnresolvedLookupExpr(e); +} + + +bool CxxAstVisitor::TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc) +{ + std::shared_ptr> switcher; + std::shared_ptr removeContextFunctor; + + if (m_typeRefContext != REFERENCE_TEMPLATE_DEFAULT_ARGUMENT && m_templateArgumentContext) + { + switcher = std::make_shared>(m_typeRefContext, REFERENCE_TEMPLATE_ARGUMENT); + + m_contextStack.push_back(m_templateArgumentContext); + removeContextFunctor = std::make_shared([this](){ m_contextStack.pop_back(); }); + } + + if (loc.getArgument().getKind() == clang::TemplateArgument::Template) + { + // TODO: maybe move this to VisitTemplateName + m_client->recordReference( + m_typeRefContext, + m_declNameCache->getValue(loc.getArgument().getAsTemplate().getAsTemplateDecl()), + getContextName(), + getParseLocation(loc.getLocation()) + ); + } + + return base::TraverseTemplateArgumentLoc(loc); +} + +void CxxAstVisitor::traverseDeclContextHelper(clang::DeclContext *d) +{ + if (!d) + return; + + // Traverse children. + for (clang::DeclContext::decl_iterator it = d->decls_begin(), + itEnd = d->decls_end(); it != itEnd; ++it) { + // BlockDecls are traversed through BlockExprs. + if (!llvm::isa(*it)) + TraverseDecl(*it); + } +} + +bool CxxAstVisitor::TraverseCallCommon(clang::CallExpr* s) +{ + { + ScopedSwitcher switcher(m_declRefContext, REFERENCE_CALL); + TraverseStmt(s->getCallee()); + } + for (unsigned int i = 0; i < s->getNumArgs(); ++i) { + clang::Expr *arg = s->getArg(i); + TraverseStmt(arg); + } + return true; +} + +bool CxxAstVisitor::VisitTagDecl(clang::TagDecl* d) +{ + if (shouldVisitDecl(d)) + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + convertTagKind(d->getTagKind()), + getParseLocation(d->getLocation()), + getParseLocationOfTagDeclBody(d), + convertAccessSpecifier(d->getAccess()), + isImplicit(d) + ); + } + return true; +} + +bool CxxAstVisitor::VisitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl* d) +{ + if (shouldVisitDecl(d)) + { + clang::NamedDecl* specializedFromDecl; + + // todo: use context and childcontext!! + llvm::PointerUnion pu = d->getSpecializedTemplateOrPartial(); + if (pu.is()) + { + specializedFromDecl = pu.get(); + } + else if (pu.is()) + { + specializedFromDecl = pu.get(); + } + + m_client->recordReference( + REFERENCE_TEMPLATE_SPECIALIZATION_OF, // TODO: call this REFERENCE_TEMPLATE_SPECIALIZATION and reverse the following arguments + m_declNameCache->getValue(specializedFromDecl), + m_declNameCache->getValue(d), + getParseLocation(d->getLocation()) + ); + } + return true; +} + +bool CxxAstVisitor::VisitFunctionDecl(clang::FunctionDecl* d) +{ + if (shouldVisitDecl(d)) + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + clang::isa(d) ? SYMBOL_METHOD : SYMBOL_FUNCTION, + getParseLocation(d->getLocation()), + getParseLocationOfFunctionBody(d), + convertAccessSpecifier(d->getAccess()), + isImplicit(d) + ); + + if (d->isFunctionTemplateSpecialization()) + { + m_client->recordReference( + REFERENCE_TEMPLATE_SPECIALIZATION_OF, // TODO: call this REFERENCE_TEMPLATE_SPECIALIZATION and reverse the following arguments + m_declNameCache->getValue(d->getPrimaryTemplate()->getTemplatedDecl()), // todo: use context and childcontext!! + m_declNameCache->getValue(d), + getParseLocation(d->getLocation()) + ); + } + } + return true; +} + +bool CxxAstVisitor::VisitCXXMethodDecl(clang::CXXMethodDecl* d) +{ + // Decl has been recorded in VisitFunctionDecl + if (shouldVisitDecl(d)) + { + for (clang::CXXMethodDecl::method_iterator it = d->begin_overridden_methods(); // iterate in traversal and use RT_Overridden or so.. + it != d->end_overridden_methods(); it++) + { + m_client->recordReference( + REFERENCE_OVERRIDE, + m_declNameCache->getValue(*it), + m_declNameCache->getValue(d), + getParseLocation(d->getLocation()) + ); + } + + clang::MemberSpecializationInfo* memberSpecializationInfo = d->getMemberSpecializationInfo(); + if (memberSpecializationInfo) + { + clang::NamedDecl* specializedNamedDecl = memberSpecializationInfo->getInstantiatedFrom(); + if (clang::isa(specializedNamedDecl)) + { + m_client->recordReference( + REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION_OF, + m_declNameCache->getValue(specializedNamedDecl), + m_declNameCache->getValue(d), + getParseLocation(d->getLocation()) + ); + } + } + } + return true; +} + +bool CxxAstVisitor::VisitVarDecl(clang::VarDecl* d) +{ + if (shouldVisitDecl(d)) + { + SymbolKind symbolKind = SYMBOL_KIND_MAX; + + if (llvm::isa(d)) + { + symbolKind = SYMBOL_PARAMETER; + } + else if (d->getParentFunctionOrMethod() == NULL) + { + if (d->getAccess() == clang::AS_none) + { + symbolKind = SYMBOL_GLOBAL_VARIABLE; + } + else + { + symbolKind = SYMBOL_FIELD; + } + } + else + { + symbolKind = SYMBOL_LOCAL_VARIABLE; + } + + if (symbolKind == SYMBOL_LOCAL_VARIABLE || symbolKind == SYMBOL_PARAMETER) + { + if (!d->getNameAsString().empty()) // don't record anonymous parameters + { + ParseLocation declLocation = getParseLocation(d->getLocation()); + std::string name = + declLocation.filePath.fileName() + "<" + + std::to_string(declLocation.startLineNumber) + ":" + + std::to_string(declLocation.startColumnNumber) + ">"; + m_client->onLocalSymbolParsed(name, getParseLocation(d->getLocation())); + } + } + else + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + symbolKind, + getParseLocation(d->getLocation()), + convertAccessSpecifier(d->getAccess()), + isImplicit(d) + ); + } + } + return true; +} + +bool CxxAstVisitor::VisitFieldDecl(clang::FieldDecl* d) +{ + if (shouldVisitDecl(d)) + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + SYMBOL_FIELD, + getParseLocation(d->getLocation()), + convertAccessSpecifier(d->getAccess()), + isImplicit(d) + ); + } + return true; +} + +bool CxxAstVisitor::VisitTypedefDecl(clang::TypedefDecl* d) +{ + if (shouldVisitDecl(d)) + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + SYMBOL_TYPEDEF, + getParseLocation(d->getLocation()), + convertAccessSpecifier(d->getAccess()), + isImplicit(d) + ); + } + return true; +} + +bool CxxAstVisitor::VisitTypeAliasDecl(clang::TypeAliasDecl* d) +{ + if (shouldVisitDecl(d)) + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + SYMBOL_TYPEDEF, + getParseLocation(d->getLocation()), + convertAccessSpecifier(d->getAccess()), + isImplicit(d) + ); + } + return true; +} + +bool CxxAstVisitor::VisitNamespaceDecl(clang::NamespaceDecl* d) +{ + if (shouldVisitDecl(d)) + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + SYMBOL_NAMESPACE, + d->isAnonymousNamespace() ? ParseLocation() : getParseLocation(d->getLocation()), + getParseLocation(d->getSourceRange()), + convertAccessSpecifier(d->getAccess()), + isImplicit(d) + ); + } + return true; +} + +bool CxxAstVisitor::VisitNamespaceAliasDecl(clang::NamespaceAliasDecl* d) +{ + if (shouldVisitDecl(d)) + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + SYMBOL_NAMESPACE, + getParseLocation(d->getLocation()), + convertAccessSpecifier(d->getAccess()), + isImplicit(d) + ); + + m_client->recordReference( + REFERENCE_USAGE, + m_declNameCache->getValue(d->getAliasedNamespace()), + m_declNameCache->getValue(d), + getParseLocation(d->getTargetNameLoc()) + ); + } + return true; +} + +bool CxxAstVisitor::VisitEnumConstantDecl(clang::EnumConstantDecl* d) +{ + if (shouldVisitDecl(d)) + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + SYMBOL_ENUM_CONSTANT, + getParseLocation(d->getLocation()), + ACCESS_NONE, + isImplicit(d) + ); + } + return true; +} + +bool CxxAstVisitor::VisitUsingDirectiveDecl(clang::UsingDirectiveDecl* d) +{ + if (shouldVisitDecl(d)) + { + m_client->recordReference( + REFERENCE_USAGE, + m_declNameCache->getValue(d->getNominatedNamespaceAsWritten()), + getContextName(), // TODO: use file here, if no context available + getParseLocation(d->getLocation()) + ); + } + return true; +} + +bool CxxAstVisitor::VisitUsingDecl(clang::UsingDecl* d) +{ + //if (shouldVisitDecl(d)) + //{ + //m_client->recordReference( + // REFERENCE_USAGE, + // m_declNameCache->getValue(d), + // getContextName(), // TODO: use file here, if no context available + // getParseLocation(d->getLocation()) + //); + //} + return true; +} + +bool CxxAstVisitor::VisitNonTypeTemplateParmDecl(clang::NonTypeTemplateParmDecl* d) +{ + if (shouldVisitDecl(d) && !d->getName().empty()) // We don't create symbols for unnamed template parameters. + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + SYMBOL_TEMPLATE_PARAMETER, + getParseLocation(d->getLocation()), + ACCESS_TEMPLATE_PARAMETER, + isImplicit(d) + ); + } + return true; +} + +bool CxxAstVisitor::VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d) +{ + if (shouldVisitDecl(d) && !d->getName().empty()) // We don't create symbols for unnamed template parameters. + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + SYMBOL_TEMPLATE_PARAMETER, + getParseLocation(d->getLocation()), + ACCESS_TEMPLATE_PARAMETER, + isImplicit(d) + ); + } + return true; +} + +bool CxxAstVisitor::VisitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d) +{ + if (shouldVisitDecl(d) && !d->getName().empty()) // We don't create symbols for unnamed template parameters. + { + m_client->recordSymbol( + m_declNameCache->getValue(d), + SYMBOL_TEMPLATE_PARAMETER, + getParseLocation(d->getLocation()), + ACCESS_TEMPLATE_PARAMETER, + isImplicit(d) + ); + } + return true; +} + + + +/* +bool CxxAstVisitor::VisitNamedDecl(clang::NamedDecl* d) +{ + if (!shouldVisitDecl(d)) + { + return true; + } + + + + + //if (clang::UsingDirectiveDecl *ud = llvm::dyn_cast(d)) + //{ + // m_client->recordReference( + // REFERENCE_USAGE, + // m_declNameCache->getValue(ud->getNominatedNamespaceAsWritten()), + // m_con + + // return true; + + + // RecordDeclRef( + // ud->getNominatedNamespaceAsWritten(), + // loc, RT_UsingDirective); + //} + //else if (clang::UsingDecl *usd = llvm::dyn_cast(d)) + //{ + // for (auto it = usd->shadow_begin(), itEnd = usd->shadow_end(); + // it != itEnd; ++it) { + // clang::UsingShadowDecl *shadow = *it; + // RecordDeclRef(shadow->getTargetDecl(), loc, RT_Using); + // } + //} else + + + if (llvm::isa(d)) { + // TODO: use these cases for creating the connection between two undefined template things + // Do nothing. The function will be recorded when it appears as a + // FunctionDecl. + } else if (llvm::isa(d)) { + // Do nothing. The class will be recorded when it appears as a + // RecordDecl. + } else if (llvm::isa(d)) { + // Do nothing. The type alias will be recorded when it appears as a + // TypeAliasDecl. + } + + return true; +} + +*/ + + + + + + + +bool CxxAstVisitor::VisitTypeLoc(clang::TypeLoc tl) +{ + if ((isLocatedInUnparsedProjectFile(tl.getBeginLoc())) && + (!checkIgnoresTypeLoc(tl))) + { + clang::SourceLocation loc; + if (!tl.getAs().isNull()) + { + const clang::DependentNameTypeLoc& dntl = tl.castAs(); + loc = dntl.getNameLoc(); + } + else + { + loc = tl.getBeginLoc(); + } + + m_client->recordReference( + m_typeRefContext, + m_typeNameCache->getValue(tl.getTypePtr()), + getContextName(1), // we skip the last element because it refers to this typeloc. + getParseLocation(loc) + ); + } + return true; +} + +bool CxxAstVisitor::VisitDeclRefExpr(clang::DeclRefExpr* s) +{ + clang::ValueDecl* decl = s->getDecl(); + + if ((clang::isa(decl)) || + (clang::isa(decl) && decl->getParentFunctionOrMethod() != NULL) + ) { + ParseLocation declLocation = getParseLocation(decl->getLocation()); + std::string name = declLocation.filePath.fileName() + "<" + + std::to_string(declLocation.startLineNumber) + ":" + + std::to_string(declLocation.startColumnNumber) + ">"; + + m_client->onLocalSymbolParsed(name, getParseLocation(s->getLocation())); + } + else + { + m_client->recordReference( + m_typeRefContext == REFERENCE_TYPE_USAGE ? m_declRefContext : m_typeRefContext, + m_declNameCache->getValue(s->getDecl()), + getContextName(), + getParseLocation(s->getLocation()) + ); + } + + return true; +} + +bool CxxAstVisitor::VisitMemberExpr(clang::MemberExpr* s) +{ + m_client->recordReference( + m_typeRefContext == REFERENCE_TYPE_USAGE ? m_declRefContext : m_typeRefContext, + m_declNameCache->getValue(s->getMemberDecl()), + getContextName(), + getParseLocation(s->getMemberLoc()) + ); + return true; +} + +bool CxxAstVisitor::VisitCXXConstructExpr(clang::CXXConstructExpr* s) +{ + //if (e->getParenOrBraceRange().isValid()) { + // // XXX: This code is a kludge. Recording calls to constructors is + // // troublesome because there isn't an obvious location to associate the + // // call with. Consider: + // // A::A() : field(1, 2, 3) {} + // // new A(1, 2, 3) + // // struct A { A(B); }; A f() { B b; return b; } + // // Implicit calls to conversion operator methods pose a similar + // // problem. + // // + // // Recording constructor calls is very useful, though, so, as a + // // temporary measure, when there are constructor arguments surrounded + // // by parentheses, associate the call with the right parenthesis. + // // + // // Perhaps the right fix is to associate the call with the line itself + // // or with a larger span which may have other references nested within + // // it. The fix may have implications for the navigator GUI. + // RecordDeclRefExpr( + // e->getConstructor(), + // e->getParenOrBraceRange().getEnd(), + // e, + // CF_Called); + //} + clang::SourceLocation loc; + clang::SourceLocation braceBeginLoc = s->getParenOrBraceRange().getBegin(); + clang::SourceLocation nameBeginLoc = s->getSourceRange().getBegin(); + if (braceBeginLoc.isValid()) + { + if (braceBeginLoc == nameBeginLoc) + { + loc = nameBeginLoc; + } + else + { + loc = braceBeginLoc.getLocWithOffset(-1); + } + } + else + { + loc = s->getSourceRange().getEnd(); + } + loc = clang::Lexer::GetBeginningOfToken(loc, m_astContext->getSourceManager(), m_astContext->getLangOpts()); + + m_client->recordReference( + m_typeRefContext == REFERENCE_TYPE_USAGE ? m_declRefContext : m_typeRefContext, + m_declNameCache->getValue(s->getConstructor()), + getContextName(), + getParseLocation(loc) + ); + return true; +} + +bool CxxAstVisitor::VisitLambdaExpr(clang::LambdaExpr* s) +{ + clang::CXXMethodDecl* methodDecl = s->getCallOperator(); + m_client->recordSymbol( + m_declNameCache->getValue(methodDecl), + SYMBOL_FUNCTION, + getParseLocation(s->getLocStart()), + getParseLocationOfFunctionBody(methodDecl), + ACCESS_NONE, // TODO: introduce AccessLambda + isImplicit(methodDecl) + ); + return true; +} + +bool CxxAstVisitor::VisitConstructorInitializer(clang::CXXCtorInitializer* init) +{ + // record the field usage here because it is not a DeclRefExpr + if (clang::FieldDecl* memberDecl = init->getMember()) + { + m_client->recordReference( + REFERENCE_USAGE, + m_declNameCache->getValue(memberDecl), + getContextName(), + getParseLocation(init->getMemberLocation()) + ); + } + return true; +} + +bool CxxAstVisitor::isImplicit(clang::Decl* d) const +{ + if (!d) + { + return false; + } + + if (d->isImplicit()) + { + if (clang::RecordDecl* rd = clang::dyn_cast_or_null(d)) + { + if (rd->isLambda()) + { + return isImplicit(clang::dyn_cast_or_null(d->getDeclContext())); + } + } + return true; + } + else if (clang::ClassTemplateSpecializationDecl* ctsd = clang::dyn_cast_or_null(d)) + { + if (!ctsd->isExplicitSpecialization()) + { + return true; + } + } + else if (clang::FunctionDecl* fd = clang::dyn_cast_or_null(d)) + { + if (fd->isTemplateInstantiation() && fd->getTemplateSpecializationKind() != clang::TSK_ExplicitSpecialization) // or undefined?? + { + return true; + } + } + + return isImplicit(clang::dyn_cast_or_null(d->getDeclContext())); +} + +bool CxxAstVisitor::shouldVisitDecl(clang::Decl* d) +{ + clang::SourceLocation loc = d->getLocation(); + + bool declIsImplicit = isImplicit(d); + + if (!d || + (declIsImplicit && !isLocatedInProjectFile(loc)) || + (!declIsImplicit && !isLocatedInUnparsedProjectFile(loc))) + { + return false; + } + + return true; +} + +bool CxxAstVisitor::isLocatedInUnparsedProjectFile(clang::SourceLocation loc) +{ + clang::SourceManager& sourceManager = m_astContext->getSourceManager(); + clang::SourceLocation spellingLoc = sourceManager.getSpellingLoc(loc); + + clang::FileID fileId; + + if (spellingLoc.isValid()) + { + fileId = sourceManager.getFileID(spellingLoc); + } + if (!fileId.isInvalid()) + { + auto it = m_inUnparsedProjectFileMap.find(fileId); + if (it != m_inUnparsedProjectFileMap.end()) + { + return it->second; + } + + bool ret = false; + if (sourceManager.isWrittenInMainFile(spellingLoc)) + { + ret = true; + } + else + { + const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); + if (fileEntry != NULL) + { + std::string fileName = fileEntry->getName(); + FilePath filePath = FilePath(fileName).canonical(); + + if (m_fileRegister->hasIncludeFile(filePath)) + { + ret = !(m_fileRegister->includeFileIsParsed(filePath)); + } + } + } + m_inUnparsedProjectFileMap[fileId] = ret; + return ret; + } + return false; +} + +bool CxxAstVisitor::isLocatedInProjectFile(clang::SourceLocation loc) +{ + clang::SourceManager& sourceManager = m_astContext->getSourceManager(); + clang::SourceLocation spellingLoc = sourceManager.getSpellingLoc(loc); + + clang::FileID fileId; + + if (spellingLoc.isValid()) + { + fileId = sourceManager.getFileID(spellingLoc); + } + + if (!fileId.isInvalid()) + { + auto it = m_inProjectFileMap.find(fileId); + if (it != m_inProjectFileMap.end()) + { + return it->second; + } + + const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); + if (fileEntry != NULL) + { + std::string fileName = fileEntry->getName(); + FilePath filePath = FilePath(fileName).canonical(); + bool ret = m_fileRegister->hasFilePath(filePath.str()); + m_inProjectFileMap[fileId] = ret; + return ret; + } + } + + return false; +} + +ParseLocation CxxAstVisitor::getParseLocationOfTagDeclBody(clang::TagDecl* decl) const +{ + if (decl->isThisDeclarationADefinition()) + { + clang::SourceRange range; + if (clang::CXXRecordDecl* cxxDecl = clang::dyn_cast_or_null(decl)) + { + clang::ClassTemplateDecl* templateDecl = cxxDecl->getDescribedClassTemplate(); + if (templateDecl) + { + range = templateDecl->getSourceRange(); + } + } + if (range.isInvalid()) + { + range = decl->getDefinition()->getSourceRange(); + } + return getParseLocation(range); + } + return ParseLocation(); +} + +ParseLocation CxxAstVisitor::getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const +{ + if (decl->hasBody() && decl->isThisDeclarationADefinition()) + { + clang::SourceRange range; + clang::FunctionTemplateDecl* templateDecl = decl->getDescribedFunctionTemplate(); + if (templateDecl) + { + range = templateDecl->getSourceRange(); + } + else + { + range = decl->getSourceRange(); + } + return getParseLocation(range); + } + return ParseLocation(); +} + +ParseLocation CxxAstVisitor::getParseLocation(const clang::SourceLocation& loc) const +{ + ParseLocation parseLocation; + if (loc.isValid()) + { + clang::SourceManager& sourceManager = m_astContext->getSourceManager(); + clang::SourceLocation startLoc = sourceManager.getSpellingLoc(loc); + clang::FileID fileId = sourceManager.getFileID(startLoc); + + // find the location file + if (!fileId.isInvalid()) + { + const clang::FileEntry* fileEntry = sourceManager.getFileEntryForID(fileId); + if (fileEntry != NULL) + { + parseLocation.filePath = FilePath(fileEntry->getName()).canonical(); + } + } + + // find the start location + { + unsigned int offset = sourceManager.getFileOffset(startLoc); + parseLocation.startLineNumber = sourceManager.getLineNumber(fileId, offset); + parseLocation.startColumnNumber = sourceManager.getColumnNumber(fileId, offset); + } + + // General case -- find the end of the token starting at loc. + { + clang::SourceLocation endSloc = m_preprocessor->getLocForEndOfToken(startLoc); + unsigned int offset = sourceManager.getFileOffset(endSloc); + parseLocation.endLineNumber = sourceManager.getLineNumber(fileId, offset); + parseLocation.endColumnNumber = sourceManager.getColumnNumber(fileId, offset) - 1; + } + } + + + return parseLocation; +} + +ParseLocation CxxAstVisitor::getParseLocation(const clang::SourceRange& sourceRange) const +{ + ParseLocation parseLocation; + if (sourceRange.isValid()) + { + const clang::SourceManager& sourceManager = m_astContext->getSourceManager(); + + const clang::PresumedLoc& presumedBegin = sourceManager.getPresumedLoc(sourceRange.getBegin(), false); + const clang::PresumedLoc& presumedEnd = sourceManager.getPresumedLoc(sourceRange.getEnd(), false); + + parseLocation = ParseLocation( + presumedBegin.getFilename(), + presumedBegin.getLine(), + presumedBegin.getColumn(), + presumedEnd.getLine(), + presumedEnd.getColumn() + ); + } + return parseLocation; +} + +AccessKind CxxAstVisitor::convertAccessSpecifier(clang::AccessSpecifier access) const +{ + switch (access) + { + case clang::AS_public: + return ACCESS_PUBLIC; + case clang::AS_protected: + return ACCESS_PROTECTED; + case clang::AS_private: + return ACCESS_PRIVATE; + } + return ACCESS_NONE; +} + +SymbolKind CxxAstVisitor::convertTagKind(clang::TagTypeKind tagKind) +{ + switch (tagKind) + { + case clang::TTK_Struct: + return SYMBOL_STRUCT; + case clang::TTK_Union: + return SYMBOL_UNION; + case clang::TTK_Class: + return SYMBOL_CLASS; + case clang::TTK_Enum: + return SYMBOL_ENUM; + } + return SYMBOL_KIND_MAX; +} + +NameHierarchy CxxAstVisitor::getContextName(const int skip) const +{ + if (m_contextStack.size() <= skip) + { + return m_declNameCache->getValue(nullptr); + } + return m_contextStack[m_contextStack.size() - 1 - skip]->getName(); // todo: performance optimize this +} + +bool CxxAstVisitor::checkIgnoresTypeLoc(const clang::TypeLoc& tl) +{ + + if ((!tl.getAs().isNull()) || + (!tl.getAs().isNull()) || + (!tl.getAs().isNull()) || + (!tl.getAs().isNull()) || + (!tl.getAs().isNull()) || + (!tl.getAs().isNull()) + ){ + return false; + } + return true; +} diff --git a/src/lib_cxx/data/parser/cxx/CxxASTVisitor.h b/src/lib_cxx/data/parser/cxx/CxxASTVisitor.h new file mode 100644 index 00000000..b7f2d352 --- /dev/null +++ b/src/lib_cxx/data/parser/cxx/CxxASTVisitor.h @@ -0,0 +1,161 @@ +#ifndef CXX_AST_VISITOR_H +#define CXX_AST_VISITOR_H + +#include +#include + +#include "clang/AST/ASTContext.h" +#include + +#include "data/parser/cxx/CxxContext.h" +#include "data/parser/AccessKind.h" +#include "data/parser/ReferenceKind.h" +#include "data/parser/SymbolKind.h" +#include "utility/messaging/MessageInterruptTasksCounter.h" +#include "utility/Cache.h" + +class ParserClient; +struct ParseLocation; +class FileRegister; + +// methods are called in this order: +// TraverseDecl() +// `- TraverseFunctionDecl() +// |- WalkUpFromFunctionDecl() +// | |- WalkUpFromNamedDecl() +// | | |- WalkUpFromDecl() +// | | | `- VisitDecl() +// | | `- VisitNamedDecl() +// | `- VisitFunctionDecl() +// `- TraverseChildNodes() + +class ScopedContextKindSetter +{ +public: + ScopedContextKindSetter(const ReferenceKind refKind, std::vector* stack) + : m_stack(stack) + { + m_stack->push_back(refKind); + } + + ~ScopedContextKindSetter() + { + m_stack->pop_back(); + } +private: + std::vector* m_stack; +}; + +class CxxAstVisitor: public clang::RecursiveASTVisitor +{ +public: + CxxAstVisitor(clang::ASTContext* astContext, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister); + virtual ~CxxAstVisitor(); + + // Indexing entry point + void indexDecl(clang::Decl *d); + + // Visitor options + virtual bool shouldVisitTemplateInstantiations() const; + virtual bool shouldVisitImplicitCode() const; + + // Traversal methods. These specify how to traverse the AST and record context info. + virtual bool TraverseDecl(clang::Decl *d); + virtual bool TraverseTypeLoc(clang::TypeLoc tl); + virtual bool TraverseType(clang::QualType t); + virtual bool TraverseStmt(clang::Stmt *stmt); + + virtual bool TraverseCXXRecordDecl(clang::CXXRecordDecl *d); + virtual bool TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d); + virtual bool TraverseTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d); + virtual bool TraverseNestedNameSpecifierLoc(clang::NestedNameSpecifierLoc loc); + virtual bool TraverseConstructorInitializer(clang::CXXCtorInitializer* init); + virtual bool TraverseCallExpr(clang::CallExpr* s); + virtual bool TraverseCXXMemberCallExpr(clang::CXXMemberCallExpr* s); + virtual bool TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr* s); + virtual bool TraverseCXXConstructExpr(clang::CXXConstructExpr* s); + virtual bool TraverseCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* s); + virtual bool TraverseLambdaExpr(clang::LambdaExpr* s); + virtual bool TraverseFunctionDecl(clang::FunctionDecl* d); + virtual bool TraverseClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl *d); + virtual bool TraverseClassTemplatePartialSpecializationDecl(clang::ClassTemplatePartialSpecializationDecl* d); + virtual bool TraverseDeclRefExpr(clang::DeclRefExpr* s); + virtual bool TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc); + virtual bool TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* s); + virtual bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);; + void traverseDeclContextHelper(clang::DeclContext *d); + bool TraverseCallCommon(clang::CallExpr* s); + + // Visitor methods. These actually record stuff and store it in the database. + virtual bool VisitTagDecl(clang::TagDecl* d); + virtual bool VisitClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl* d); + virtual bool VisitFunctionDecl(clang::FunctionDecl* d); + virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl* d); + virtual bool VisitVarDecl(clang::VarDecl* d); + virtual bool VisitFieldDecl(clang::FieldDecl* d); + virtual bool VisitTypedefDecl(clang::TypedefDecl* d); + virtual bool VisitTypeAliasDecl(clang::TypeAliasDecl* d); + virtual bool VisitNamespaceDecl(clang::NamespaceDecl* d); + virtual bool VisitNamespaceAliasDecl(clang::NamespaceAliasDecl* d); + virtual bool VisitEnumConstantDecl(clang::EnumConstantDecl* d); + virtual bool VisitUsingDirectiveDecl(clang::UsingDirectiveDecl* d); + virtual bool VisitUsingDecl(clang::UsingDecl* d); + virtual bool VisitNonTypeTemplateParmDecl(clang::NonTypeTemplateParmDecl* d); + virtual bool VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl* d); + virtual bool VisitTemplateTemplateParmDecl(clang::TemplateTemplateParmDecl* d); + + virtual bool VisitTypeLoc(clang::TypeLoc tl); + + virtual bool VisitDeclRefExpr(clang::DeclRefExpr* s); + virtual bool VisitMemberExpr(clang::MemberExpr* s); + virtual bool VisitCXXConstructExpr(clang::CXXConstructExpr* s); + virtual bool VisitLambdaExpr(clang::LambdaExpr* s); + virtual bool VisitConstructorInitializer(clang::CXXCtorInitializer* init); + +protected: + // General helpers + bool isImplicit(clang::Decl* d) const; + bool shouldVisitDecl(clang::Decl* d); + bool isLocatedInUnparsedProjectFile(clang::SourceLocation loc); + bool isLocatedInProjectFile(clang::SourceLocation loc); + + ParseLocation getParseLocationOfTagDeclBody(clang::TagDecl* decl) const; + ParseLocation getParseLocationOfFunctionBody(const clang::FunctionDecl* decl) const; + ParseLocation getParseLocation(const clang::SourceLocation& loc) const; + ParseLocation getParseLocation(const clang::SourceRange& sourceRange) const; + AccessKind convertAccessSpecifier(clang::AccessSpecifier access) const; + SymbolKind convertTagKind(clang::TagTypeKind tagKind); + +private: + typedef clang::RecursiveASTVisitor base; + + NameHierarchy getContextName(const int skip = 0) const; + bool checkIgnoresTypeLoc(const clang::TypeLoc& tl); + + struct FileIdHash + { + size_t operator()(clang::FileID fileID) const + { + return fileID.getHashValue(); + } + }; + + clang::ASTContext* m_astContext; + clang::Preprocessor* m_preprocessor; + ParserClient* m_client; + FileRegister* m_fileRegister; + + MessageInterruptTasksCounter m_interruptCounter; + + ReferenceKind m_typeRefContext; + ReferenceKind m_declRefContext; + std::vector> m_contextStack; + std::shared_ptr m_templateArgumentContext; + + std::shared_ptr m_declNameCache; + std::shared_ptr m_typeNameCache; + std::unordered_map m_inUnparsedProjectFileMap; + std::unordered_map m_inProjectFileMap; +}; + +#endif // CXX_AST_VISITOR_H diff --git a/src/lib_cxx/data/parser/cxx/CxxContext.cpp b/src/lib_cxx/data/parser/cxx/CxxContext.cpp new file mode 100644 index 00000000..147fc9d9 --- /dev/null +++ b/src/lib_cxx/data/parser/cxx/CxxContext.cpp @@ -0,0 +1,35 @@ +#include "data/parser/cxx/CxxContext.h" + +CxxContext::~CxxContext() +{ +} + +CxxContextDecl::CxxContextDecl(const clang::NamedDecl* decl, std::shared_ptr nameCache) + : m_decl(decl) + , m_nameCache(nameCache) +{ +} + +CxxContextDecl::~CxxContextDecl() +{ +} + +NameHierarchy CxxContextDecl::getName() +{ + return m_nameCache->getValue(m_decl); +} + +CxxContextType::CxxContextType(const clang::Type* type, std::shared_ptr nameCache) + : m_type(type) + , m_nameCache(nameCache) +{ +} + +CxxContextType::~CxxContextType() +{ +} + +NameHierarchy CxxContextType::getName() +{ + return m_nameCache->getValue(m_type); +} diff --git a/src/lib_cxx/data/parser/cxx/CxxContext.h b/src/lib_cxx/data/parser/cxx/CxxContext.h new file mode 100644 index 00000000..32c28a20 --- /dev/null +++ b/src/lib_cxx/data/parser/cxx/CxxContext.h @@ -0,0 +1,44 @@ +#ifndef CXX_CONTEXT_H +#define CXX_CONTEXT_H + +#include + +#include "data/name/NameHierarchy.h" +#include "utility/Cache.h" + +typedef Cache DeclNameCache; +typedef Cache TypeNameCache; + +class CxxContext +{ +public: + virtual ~CxxContext(); + virtual NameHierarchy getName() = 0; +}; + +class CxxContextDecl: public CxxContext +{ +public: + CxxContextDecl(const clang::NamedDecl* decl, std::shared_ptr nameCache); + virtual ~CxxContextDecl(); + virtual NameHierarchy getName(); + +private: + const clang::NamedDecl* m_decl; + std::shared_ptr m_nameCache; +}; + +class CxxContextType: public CxxContext +{ +public: + CxxContextType(const clang::Type* type, std::shared_ptr nameCache); + virtual ~CxxContextType(); + virtual NameHierarchy getName(); + +private: + const clang::Type* m_type; + std::shared_ptr m_nameCache; +}; + +#endif // CXX_CONTEXT_H + diff --git a/src/lib_cxx/data/parser/cxx/CxxVerboseAstVisitor.cpp b/src/lib_cxx/data/parser/cxx/CxxVerboseAstVisitor.cpp new file mode 100644 index 00000000..b2fa7890 --- /dev/null +++ b/src/lib_cxx/data/parser/cxx/CxxVerboseAstVisitor.cpp @@ -0,0 +1,110 @@ +#include "data/parser/cxx/CxxVerboseAstVisitor.h" + +#include + +#include +#include + +#include "data/parser/ParseLocation.h" +#include "data/parser/ParserClient.h" +#include "utility/file/FileRegister.h" + +#include "utility/logging/logging.h" +#include "utility/ScopedSwitcher.h" + +CxxVerboseAstVisitor::CxxVerboseAstVisitor(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister) + : base(context, preprocessor, client, fileRegister) + , m_indentation(0) +{ +} + +CxxVerboseAstVisitor::~CxxVerboseAstVisitor() +{ +} + +bool CxxVerboseAstVisitor::TraverseDecl(clang::Decl *d) +{ + if (d) + { + std::stringstream stream; + stream << getIndentString() << d->getDeclKindName() << "Decl"; + if (clang::NamedDecl *namedDecl = clang::dyn_cast_or_null(d)) + { + stream << " [" << obfuscateName(namedDecl->getNameAsString()) << "]"; + } + + ParseLocation loc = getParseLocation(d->getSourceRange()); + stream << " <" << loc.startLineNumber << ":" << loc.startColumnNumber << ", " << loc.endLineNumber << ":" << loc.endColumnNumber << ">"; + + LOG_INFO_STREAM_BARE(<< "Indexer - " << stream.str()); + + { + ScopedSwitcher switcher(m_indentation, m_indentation + 1); + return base::TraverseDecl(d); + } + } + return true; +} + +bool CxxVerboseAstVisitor::TraverseStmt(clang::Stmt *stmt) +{ + if (stmt) + { + ParseLocation loc = getParseLocation(stmt->getSourceRange()); + LOG_INFO_STREAM_BARE( + << "Indexer - " + << getIndentString() << stmt->getStmtClassName() + << " <" << loc.startLineNumber << ":" << loc.startColumnNumber + << ", " << loc.endLineNumber << ":" << loc.endColumnNumber << ">" + ); + + { + ScopedSwitcher switcher(m_indentation, m_indentation + 1); + return base::TraverseStmt(stmt); + } + } + return true; +} + +bool CxxVerboseAstVisitor::TraverseType(clang::QualType t) +{ + LOG_INFO_STREAM_BARE(<< "Indexer - " << getIndentString() << t->getTypeClassName() << "Type"); + { + ScopedSwitcher switcher(m_indentation, m_indentation + 1); + return base::TraverseType(t); + } +} + +bool CxxVerboseAstVisitor::TraverseTypeLoc(clang::TypeLoc tl) +{ + ParseLocation loc = getParseLocation(tl.getSourceRange()); + LOG_INFO_STREAM_BARE( + << "Indexer - " + << getIndentString() << typeLocClassToString(tl) + << "TypeLoc <" << loc.startLineNumber << ":" << loc.startColumnNumber + << ", " << loc.endLineNumber << ":" << loc.endColumnNumber << ">" + ); + { + ScopedSwitcher switcher(m_indentation, m_indentation + 1); + return base::TraverseTypeLoc(tl); + } +} + +std::string CxxVerboseAstVisitor::getIndentString() const +{ + std::string indentString = ""; + for (unsigned int i = 0; i < m_indentation; i++) + { + indentString += "| "; + } + return indentString; +} + +std::string CxxVerboseAstVisitor::obfuscateName(const std::string& name) const +{ + if (name.length() <= 2) + { + return name; + } + return name.substr(0, 1) + ".." + name.substr(name.length() - 1); +} diff --git a/src/lib_cxx/data/parser/cxx/CxxVerboseAstVisitor.h b/src/lib_cxx/data/parser/cxx/CxxVerboseAstVisitor.h new file mode 100644 index 00000000..ff417066 --- /dev/null +++ b/src/lib_cxx/data/parser/cxx/CxxVerboseAstVisitor.h @@ -0,0 +1,47 @@ +#ifndef CXX_VERBOSE_AST_VISITOR_H +#define CXX_VERBOSE_AST_VISITOR_H + +#include "clang/AST/TypeLoc.h" + +#include "data/parser/cxx/CxxAstVisitor.h" + +class ParserClient; +class FileRegister; + +class CxxVerboseAstVisitor: public CxxAstVisitor +{ +public: + CxxVerboseAstVisitor(clang::ASTContext* context, clang::Preprocessor* preprocessor, ParserClient* client, FileRegister* fileRegister); + virtual ~CxxVerboseAstVisitor(); + +private: + typedef CxxAstVisitor base; + + virtual bool TraverseDecl(clang::Decl *d); + virtual bool TraverseStmt(clang::Stmt *stmt); + virtual bool TraverseType(clang::QualType t); + virtual bool TraverseTypeLoc(clang::TypeLoc tl); + + std::string getIndentString() const; + std::string obfuscateName(const std::string& name) const; + + std::string typeLocClassToString(clang::TypeLoc tl) const + { + switch(tl.getTypeLocClass()) + { +#define STRINGIFY(X) #X +#define ABSTRACT_TYPE(Class, Base) +#define TYPE(Class, Base) \ + case clang::TypeLoc::Class: \ + return STRINGIFY(Class); +#include "clang/AST/TypeNodes.def" + case clang::TypeLoc::TypeLocClass::Qualified: + return "Qualified"; + } + return ""; + } + + unsigned int m_indentation; +}; + +#endif // CXX_VERBOSE_AST_VISITOR_H diff --git a/src/lib_cxx/data/parser/cxx/PreprocessorCallbacks.cpp b/src/lib_cxx/data/parser/cxx/PreprocessorCallbacks.cpp index 278512f4..9928c0e0 100644 --- a/src/lib_cxx/data/parser/cxx/PreprocessorCallbacks.cpp +++ b/src/lib_cxx/data/parser/cxx/PreprocessorCallbacks.cpp @@ -55,10 +55,18 @@ void PreprocessorCallbacks::InclusionDirective( FilePath includedFilePath = FilePath(fileEntry->getName()).canonical(); if (m_fileRegister->hasFilePath(includedFilePath)) { - m_client->onFileIncludeParsed( - getParseLocation(fileNameRange.getAsRange()), - m_fileRegister->getFileInfo(m_currentPath), - m_fileRegister->getFileInfo(includedFilePath) + + NameHierarchy referencedNameHierarchy; + referencedNameHierarchy.push(std::make_shared(includedFilePath.fileName())); + + NameHierarchy contextNameHierarchy; + contextNameHierarchy.push(std::make_shared(m_currentPath.fileName())); + + m_client->recordReference( + REFERENCE_INCLUDE, + referencedNameHierarchy, + contextNameHierarchy, + getParseLocation(fileNameRange.getAsRange()) ); } } @@ -77,8 +85,12 @@ void PreprocessorCallbacks::MacroDefined(const clang::Token& macroNameToken, con NameHierarchy nameHierarchy; nameHierarchy.push(std::make_shared(macroNameToken.getIdentifierInfo()->getName().str())); - m_client->onMacroDefineParsed( - getParseLocation(macroNameToken), nameHierarchy, getParseLocation(macroDirective->getMacroInfo())); + m_client->recordSymbol( + nameHierarchy, + SYMBOL_MACRO, + getParseLocation(macroNameToken), + getParseLocation(macroDirective->getMacroInfo()) + ); } } @@ -116,10 +128,20 @@ void PreprocessorCallbacks::onMacroUsage(const clang::Token& macroNameToken) { if (!m_currentPath.empty()) { - NameHierarchy nameHierarchy; - nameHierarchy.push(std::make_shared(macroNameToken.getIdentifierInfo()->getName().str())); + const ParseLocation loc = getParseLocation(macroNameToken); - m_client->onMacroExpandParsed(getParseLocation(macroNameToken), nameHierarchy); + NameHierarchy referencedNameHierarchy; + referencedNameHierarchy.push(std::make_shared(macroNameToken.getIdentifierInfo()->getName().str())); + + NameHierarchy contextNameHierarchy; + contextNameHierarchy.push(std::make_shared(loc.filePath.fileName())); + + m_client->recordReference( + REFERENCE_MACRO_USAGE, + referencedNameHierarchy, + contextNameHierarchy, + loc + ); } } diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp index 17f8438f..eacda84f 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.cpp @@ -60,10 +60,12 @@ void QtProjectWizzardContentPreferences::populate(QGridLayout* layout, int& row) // logging m_loggingEnabled = addCheckBox("Logging", "Enable console and file logging", "Save log files and show log information in the console.", layout, row); + connect(m_loggingEnabled, SIGNAL(clicked()), this, SLOT(loggingEnabledChanged())); + + m_verboseIndexerLoggingEnabled = addCheckBox("Indexer Logging", "Enable verbose indexer logging", "", layout, row); addGap(layout, row); - // Controls addTitle("CONTROLS", layout, row); @@ -170,6 +172,8 @@ void QtProjectWizzardContentPreferences::load() } m_loggingEnabled->setChecked(appSettings->getLoggingEnabled()); + m_verboseIndexerLoggingEnabled->setChecked(appSettings->getVerboseInderxerLoggingEnabled()); + m_verboseIndexerLoggingEnabled->setEnabled(m_loggingEnabled->isChecked()); m_scrollSpeed->setText(QString::number(appSettings->getScrollSpeed(), 'f', 1)); m_graphZooming->setChecked(appSettings->getControlsGraphZoomOnMouseWheel()); @@ -200,6 +204,7 @@ void QtProjectWizzardContentPreferences::save() m_oldColorSchemeIndex = -1; appSettings->setLoggingEnabled(m_loggingEnabled->isChecked()); + appSettings->setVerboseInderxerLoggingEnabled(m_verboseIndexerLoggingEnabled->isChecked()); float scrollSpeed = m_scrollSpeed->text().toFloat(); if (scrollSpeed) appSettings->setScrollSpeed(scrollSpeed); @@ -243,6 +248,11 @@ void QtProjectWizzardContentPreferences::javaPathDetectionClicked() } } +void QtProjectWizzardContentPreferences::loggingEnabledChanged() +{ + m_verboseIndexerLoggingEnabled->setEnabled(m_loggingEnabled->isChecked()); +} + void QtProjectWizzardContentPreferences::addJavaPathDetection(QGridLayout* layout, int& row) { std::vector detectorNames = m_javaPathDetector->getWorkingDetectorNames(); diff --git a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.h b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.h index c51d405d..9a6482d3 100644 --- a/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.h +++ b/src/lib_gui/qt/window/project_wizzard/QtProjectWizzardContentPreferences.h @@ -29,6 +29,7 @@ public: private slots: void colorSchemeChanged(int index); void javaPathDetectionClicked(); + void loggingEnabledChanged(); private: void addJavaPathDetection(QGridLayout* layout, int& row); @@ -50,6 +51,7 @@ private: std::vector m_colorSchemePaths; int m_oldColorSchemeIndex; QCheckBox* m_loggingEnabled; + QCheckBox* m_verboseIndexerLoggingEnabled; QLineEdit* m_scrollSpeed; QCheckBox* m_graphZooming; diff --git a/src/lib_java/data/parser/java/JavaEnvironment.cpp b/src/lib_java/data/parser/java/JavaEnvironment.cpp index b8ae68aa..752560b1 100644 --- a/src/lib_java/data/parser/java/JavaEnvironment.cpp +++ b/src/lib_java/data/parser/java/JavaEnvironment.cpp @@ -10,17 +10,18 @@ JavaEnvironment::~JavaEnvironment() JavaEnvironmentFactory::getInstance()->unregisterEnvironment(); } -bool JavaEnvironment::callStaticVoidMethod(std::string className, std::string methodName, int arg1, std::string arg2, std::string arg3, std::string arg4) +bool JavaEnvironment::callStaticVoidMethod(std::string className, std::string methodName, int arg1, std::string arg2, std::string arg3, std::string arg4, int arg5) { jclass javaClass = getJavaClass(className); - jmethodID javaMethodId = getJavaStaticMethod(javaClass, methodName, "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + jmethodID javaMethodId = getJavaStaticMethod(javaClass, methodName, "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V"); if(javaMethodId != nullptr) { jint jarg1 = arg1; jstring jarg2 = m_env->NewStringUTF(arg2.c_str()); jstring jarg3 = m_env->NewStringUTF(arg3.c_str()); jstring jarg4 = m_env->NewStringUTF(arg4.c_str()); - m_env->CallStaticVoidMethod(javaClass, javaMethodId, jarg1, jarg2, jarg3, jarg4); + jint jarg5 = arg5; + m_env->CallStaticVoidMethod(javaClass, javaMethodId, jarg1, jarg2, jarg3, jarg4, jarg5); return true; } return false; diff --git a/src/lib_java/data/parser/java/JavaEnvironment.h b/src/lib_java/data/parser/java/JavaEnvironment.h index 0e41c26c..b6911dfd 100644 --- a/src/lib_java/data/parser/java/JavaEnvironment.h +++ b/src/lib_java/data/parser/java/JavaEnvironment.h @@ -32,7 +32,7 @@ public: }; ~JavaEnvironment(); - bool callStaticVoidMethod(std::string className, std::string methodName, int arg1, std::string arg2, std::string arg3, std::string arg4); + bool callStaticVoidMethod(std::string className, std::string methodName, int arg1, std::string arg2, std::string arg3, std::string arg4, int arg5); bool callStaticMethod(std::string className, std::string methodName, std::string& ret, std::string arg1); std::string toStdString(jstring s); diff --git a/src/lib_java/data/parser/java/JavaParser.cpp b/src/lib_java/data/parser/java/JavaParser.cpp index 249b77f5..6b7e8c1a 100644 --- a/src/lib_java/data/parser/java/JavaParser.cpp +++ b/src/lib_java/data/parser/java/JavaParser.cpp @@ -6,6 +6,7 @@ #include "data/parser/ParseLocation.h" #include "data/parser/ReferenceKind.h" #include "data/parser/ParserClient.h" +#include "settings/ApplicationSettings.h" #include "utility/file/FileSystem.h" #include "utility/text/TextAccess.h" #include "utility/utilityString.h" @@ -22,9 +23,12 @@ JavaParser::JavaParser(ParserClient* client) std::vector methods; - methods.push_back({"recordSymbol", "(ILjava/lang/String;IIIIIII)V", (void*)&JavaParser::RecordSymbol}); - methods.push_back({"recordSymbolWithoutLocation", "(ILjava/lang/String;III)V", (void*)&JavaParser::RecordSymbolWithoutLocation}); - methods.push_back({"recordSymbolWithScope", "(ILjava/lang/String;IIIIIIIIIII)V", (void*)&JavaParser::RecordSymbolWithScope}); + methods.push_back({"logInfo", "(ILjava/lang/String;)V", (void*)&JavaParser::LogInfo}); + methods.push_back({"logWarning", "(ILjava/lang/String;)V", (void*)&JavaParser::LogWarning}); + methods.push_back({"logError", "(ILjava/lang/String;)V", (void*)&JavaParser::LogError}); + methods.push_back({"recordSymbol", "(ILjava/lang/String;III)V", (void*)&JavaParser::RecordSymbol}); + methods.push_back({"recordSymbolWithLocation", "(ILjava/lang/String;IIIIIII)V", (void*)&JavaParser::RecordSymbolWithLocation}); + methods.push_back({"recordSymbolWithLocationAndScope", "(ILjava/lang/String;IIIIIIIIIII)V", (void*)&JavaParser::RecordSymbolWithLocationAndScope}); methods.push_back({"recordReference", "(IILjava/lang/String;Ljava/lang/String;IIII)V", (void*)&JavaParser::RecordReference}); methods.push_back({"recordLocalSymbol", "(ILjava/lang/String;IIII)V", (void*)&JavaParser::RecordLocalSymbol}); methods.push_back({"recordComment", "(IIIII)V", (void*)&JavaParser::RecordComment}); @@ -73,7 +77,15 @@ void JavaParser::parseFile(const FilePath& filePath, std::shared_ptr // remove tabs because they screw with javaparser's location resolver std::string fileContent = utility::replace(textAccess->getText(), "\t", " "); - m_javaEnvironment->callStaticVoidMethod("io/coati/JavaIndexer", "processFile", m_id, filePath.str(), fileContent, classPath); + m_javaEnvironment->callStaticVoidMethod( + "io/coati/JavaIndexer", + "processFile", + m_id, + filePath.str(), + fileContent, + classPath, + ApplicationSettings::getInstance()->getVerboseInderxerLoggingEnabled() ? 1 : 0 + ); } } @@ -99,13 +111,40 @@ std::mutex JavaParser::s_parsersMutex; +// definition of native methods +void JavaParser::doLogInfo(jstring jInfo) +{ + LOG_INFO_STREAM_BARE(<< "Indexer - " << m_javaEnvironment->toStdString(jInfo)); +} +void JavaParser::doLogWarning(jstring jWarning) +{ + LOG_WARNING_STREAM_BARE(<< "Indexer - " << m_javaEnvironment->toStdString(jWarning)); +} - - +void JavaParser::doLogError(jstring jError) +{ + LOG_ERROR_STREAM_BARE(<< "Indexer - " << m_javaEnvironment->toStdString(jError)); +} void JavaParser::doRecordSymbol( + jstring jSymbolName, jint jSymbolType, + jint jAccess, jint jIsImplicit +) +{ + AccessKind access = intToAccessKind(jAccess); + bool isImplicit = jIsImplicit; + + m_client->recordSymbol( + NameHierarchy::deserialize(m_javaEnvironment->toStdString(jSymbolName)), + intToSymbolKind(jSymbolType), + access, + isImplicit + ); +} + +void JavaParser::doRecordSymbolWithLocation( jstring jSymbolName, jint jSymbolType, jint beginLine, jint beginColumn, jint endLine, jint endColumn, jint jAccess, jint jIsImplicit @@ -123,23 +162,7 @@ void JavaParser::doRecordSymbol( ); } -void JavaParser::doRecordSymbolWithoutLocation( - jstring jSymbolName, jint jSymbolType, - jint jAccess, jint jIsImplicit -) -{ - AccessKind access = intToAccessKind(jAccess); - bool isImplicit = jIsImplicit; - - m_client->recordSymbol( - NameHierarchy::deserialize(m_javaEnvironment->toStdString(jSymbolName)), - intToSymbolKind(jSymbolType), - access, - isImplicit - ); -} - -void JavaParser::doRecordSymbolWithScope( +void JavaParser::doRecordSymbolWithLocationAndScope( jstring jSymbolName, jint jSymbolType, jint beginLine, jint beginColumn, jint endLine, jint endColumn, jint scopeBeginLine, jint scopeBeginColumn, jint scopeEndLine, jint scopeEndColumn, diff --git a/src/lib_java/data/parser/java/JavaParser.h b/src/lib_java/data/parser/java/JavaParser.h index 41d52aeb..380b7d31 100644 --- a/src/lib_java/data/parser/java/JavaParser.h +++ b/src/lib_java/data/parser/java/JavaParser.h @@ -70,6 +70,14 @@ private: //.. add as many MAKE_ARGS_* as there are MAKE_PARAMS_* +#define DEF_RELAYING_METHOD_1(NAME, t1) \ + DEF_RELAYING_METHOD(NAME, MAKE_PARAMS_1(t1), MAKE_ARGS_1(t1)) + +#define DEF_RELAYING_METHOD_2(NAME, t1, t2) \ + DEF_RELAYING_METHOD(NAME, MAKE_PARAMS_2(t1, t2), MAKE_ARGS_2(t1, t2)) + +#define DEF_RELAYING_METHOD_3(NAME, t1, t2, t3) \ + DEF_RELAYING_METHOD(NAME, MAKE_PARAMS_3(t1, t2, t3), MAKE_ARGS_3(t1, t2, t3)) #define DEF_RELAYING_METHOD_4(NAME, t1, t2, t3, t4) \ DEF_RELAYING_METHOD(NAME, MAKE_PARAMS_4(t1, t2, t3, t4), MAKE_ARGS_4(t1, t2, t3, t4)) @@ -112,9 +120,12 @@ private: } \ } - DEF_RELAYING_METHOD_8(RecordSymbol, jstring, jint, jint, jint, jint, jint, jint, jint) - DEF_RELAYING_METHOD_4(RecordSymbolWithoutLocation, jstring, jint, jint, jint) - DEF_RELAYING_METHOD_12(RecordSymbolWithScope, jstring, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint) + DEF_RELAYING_METHOD_1(LogInfo, jstring) + DEF_RELAYING_METHOD_1(LogWarning, jstring) + DEF_RELAYING_METHOD_1(LogError, jstring) + DEF_RELAYING_METHOD_4(RecordSymbol, jstring, jint, jint, jint) + DEF_RELAYING_METHOD_8(RecordSymbolWithLocation, jstring, jint, jint, jint, jint, jint, jint, jint) + DEF_RELAYING_METHOD_12(RecordSymbolWithLocationAndScope, jstring, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint, jint) DEF_RELAYING_METHOD_7(RecordReference, jint, jstring, jstring, jint, jint, jint, jint) DEF_RELAYING_METHOD_5(RecordLocalSymbol, jstring, jint, jint, jint, jint) DEF_RELAYING_METHOD_4(RecordComment, jint, jint, jint, jint) @@ -128,19 +139,24 @@ private: + void doLogInfo(jstring jInfo); + + void doLogWarning(jstring jWarning); + + void doLogError(jstring jError); void doRecordSymbol( + jstring jSymbolName, jint jSymbolType, + jint jAccess, jint jIsImplicit + ); + + void doRecordSymbolWithLocation( jstring jSymbolName, jint jSymbolType, jint beginLine, jint beginColumn, jint endLine, jint endColumn, jint jAccess, jint jIsImplicit ); - void doRecordSymbolWithoutLocation( - jstring jSymbolName, jint jSymbolType, - jint jAccess, jint jIsImplicit - ); - - void doRecordSymbolWithScope( + void doRecordSymbolWithLocationAndScope( jstring jSymbolName, jint jSymbolType, jint beginLine, jint beginColumn, jint endLine, jint endColumn, jint scopeBeginLine, jint scopeBeginColumn, jint scopeEndLine, jint scopeEndColumn, diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 663a50bb..db61ed43 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -3,6 +3,7 @@ add_files( helper/TestFileManager.cpp helper/TestFileManager.h + helper/TestParserClient.h TestSuiteFixture.cpp TestSuiteFixture.h diff --git a/src/test/CxxParserTestSuite.h b/src/test/CxxParserTestSuite.h index 4b6a9488..ec8ea2e7 100644 --- a/src/test/CxxParserTestSuite.h +++ b/src/test/CxxParserTestSuite.h @@ -9,10 +9,29 @@ #include "data/parser/ParserClient.h" #include "helper/TestFileManager.h" +#include "helper/TestParserClient.h" class CxxParserTestSuite: public CxxTest::TestSuite { public: + void test_cxx_parser_usage_of_field_in_function_call_arguments() + { + std::shared_ptr client = parseCode( + "class A\n" + "{\n" + "public:\n" + " void foo(int i)\n" + " {\n" + " foo(bar);\n" + " }\n" + " int bar;\n" + "};\n" + ); + + TS_ASSERT_EQUALS(client->usages.size(), 1); + TS_ASSERT_EQUALS(client->usages[0], "void A::foo(int) -> A::bar <6:7 6:9>"); + } + /////////////////////////////////////////////////////////////////////////////// // test finding symbol definitions and declarations @@ -164,7 +183,7 @@ public: ); TS_ASSERT_EQUALS(client->methods.size(), 4); - TS_ASSERT_EQUALS(client->methods[0], "public virtual void B::process() <4:15 4:21>"); + TS_ASSERT_EQUALS(client->methods[0], "public void B::process() <4:15 4:21>"); } void test_cxx_parser_finds_pure_virtual_method_declaration() @@ -178,7 +197,7 @@ public: ); TS_ASSERT_EQUALS(client->methods.size(), 4); - TS_ASSERT_EQUALS(client->methods[0], "protected pure virtual void B::process() <4:15 4:21>"); + TS_ASSERT_EQUALS(client->methods[0], "protected void B::process() <4:15 4:21>"); } void test_cxx_parser_finds_named_namespace_declaration() @@ -302,7 +321,7 @@ public: ); TS_ASSERT_EQUALS(client->macroUses.size(), 1); - TS_ASSERT_EQUALS(client->macroUses[0], "PI <1:8 1:9>"); + TS_ASSERT_EQUALS(client->macroUses[0], "input.cc -> PI <1:8 1:9>"); } void test_cxx_parser_finds_macro_in_ifdef() @@ -317,7 +336,7 @@ public: ); TS_ASSERT_EQUALS(client->macroUses.size(), 1); - TS_ASSERT_EQUALS(client->macroUses[0], "PI <2:8 2:9>"); + TS_ASSERT_EQUALS(client->macroUses[0], "input.cc -> PI <2:8 2:9>"); } void test_cxx_parser_finds_macro_in_ifndef() @@ -332,7 +351,7 @@ public: ); TS_ASSERT_EQUALS(client->macroUses.size(), 1); - TS_ASSERT_EQUALS(client->macroUses[0], "PI <2:9 2:10>"); + TS_ASSERT_EQUALS(client->macroUses[0], "input.cc -> PI <2:9 2:10>"); } void test_cxx_parser_finds_macro_in_ifdefined() @@ -347,7 +366,7 @@ public: ); TS_ASSERT_EQUALS(client->macroUses.size(), 1); - TS_ASSERT_EQUALS(client->macroUses[0], "PI <2:13 2:14>"); + TS_ASSERT_EQUALS(client->macroUses[0], "input.cc -> PI <2:13 2:14>"); } void test_cxx_parser_finds_macro_expand() @@ -361,7 +380,7 @@ public: ); TS_ASSERT_EQUALS(client->macroUses.size(), 1); - TS_ASSERT_EQUALS(client->macroUses[0], "PI <4:12 4:13>"); + TS_ASSERT_EQUALS(client->macroUses[0], "input.cc -> PI <4:12 4:13>"); } void test_cxx_parser_finds_macro_expand_within_macro() @@ -376,8 +395,8 @@ public: ); TS_ASSERT_EQUALS(client->macroUses.size(), 2); - TS_ASSERT_EQUALS(client->macroUses[0], "TAU <5:12 5:14>"); - TS_ASSERT_EQUALS(client->macroUses[1], "PI <2:18 2:19>"); + TS_ASSERT_EQUALS(client->macroUses[0], "input.cc -> TAU <5:12 5:14>"); + TS_ASSERT_EQUALS(client->macroUses[1], "input.cc -> PI <2:18 2:19>"); } void test_cxx_parser_finds_macro_define_scope() @@ -860,7 +879,7 @@ public: ); TS_ASSERT_EQUALS(client->localSymbols.size(), 1); - TS_ASSERT_EQUALS(client->localSymbols[0], "input.cc<1:11>"); + TS_ASSERT_EQUALS(client->localSymbols[0], "input.cc<1:15> <1:15 1:15>"); } void test_cxx_parser_finds_definition_of_local_symbol_in_function_scope() @@ -873,7 +892,7 @@ public: ); TS_ASSERT_EQUALS(client->localSymbols.size(), 1); - TS_ASSERT_EQUALS(client->localSymbols[0], "input.cc<3:2>"); + TS_ASSERT_EQUALS(client->localSymbols[0], "input.cc<3:6> <3:6 3:6>"); } /////////////////////////////////////////////////////////////////////////////// @@ -1198,7 +1217,7 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 1); - TS_ASSERT_EQUALS(client->inheritances[0], "B : A <2:11 2:11>"); + TS_ASSERT_EQUALS(client->inheritances[0], "B -> A <2:11 2:11>"); } void test_cxx_parser_finds_class_public_inheritance() @@ -1209,7 +1228,7 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 1); - TS_ASSERT_EQUALS(client->inheritances[0], "B : A <2:18 2:18>"); + TS_ASSERT_EQUALS(client->inheritances[0], "B -> A <2:18 2:18>"); } void test_cxx_parser_finds_class_protected_inheritance() @@ -1220,7 +1239,7 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 1); - TS_ASSERT_EQUALS(client->inheritances[0], "B : A <2:21 2:21>"); + TS_ASSERT_EQUALS(client->inheritances[0], "B -> A <2:21 2:21>"); } void test_cxx_parser_finds_class_private_inheritance() @@ -1231,7 +1250,7 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 1); - TS_ASSERT_EQUALS(client->inheritances[0], "B : A <2:19 2:19>"); + TS_ASSERT_EQUALS(client->inheritances[0], "B -> A <2:19 2:19>"); } void test_cxx_parser_finds_class_multiple_inheritance() @@ -1246,8 +1265,8 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 2); - TS_ASSERT_EQUALS(client->inheritances[0], "C : A <4:11 4:11>"); - TS_ASSERT_EQUALS(client->inheritances[1], "C : B <5:12 5:12>"); + TS_ASSERT_EQUALS(client->inheritances[0], "C -> A <4:11 4:11>"); + TS_ASSERT_EQUALS(client->inheritances[1], "C -> B <5:12 5:12>"); } void test_cxx_parser_finds_struct_default_public_inheritance() @@ -1258,7 +1277,7 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 1); - TS_ASSERT_EQUALS(client->inheritances[0], "B : A <2:12 2:12>"); + TS_ASSERT_EQUALS(client->inheritances[0], "B -> A <2:12 2:12>"); } void test_cxx_parser_finds_struct_public_inheritance() @@ -1269,7 +1288,7 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 1); - TS_ASSERT_EQUALS(client->inheritances[0], "B : A <2:19 2:19>"); + TS_ASSERT_EQUALS(client->inheritances[0], "B -> A <2:19 2:19>"); } void test_cxx_parser_finds_struct_protected_inheritance() @@ -1280,7 +1299,7 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 1); - TS_ASSERT_EQUALS(client->inheritances[0], "B : A <2:22 2:22>"); + TS_ASSERT_EQUALS(client->inheritances[0], "B -> A <2:22 2:22>"); } void test_cxx_parser_finds_struct_private_inheritance() @@ -1291,7 +1310,7 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 1); - TS_ASSERT_EQUALS(client->inheritances[0], "B : A <2:20 2:20>"); + TS_ASSERT_EQUALS(client->inheritances[0], "B -> A <2:20 2:20>"); } void test_cxx_parser_finds_struct_multiple_inheritance() @@ -1306,8 +1325,8 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 2); - TS_ASSERT_EQUALS(client->inheritances[0], "C : A <4:11 4:11>"); - TS_ASSERT_EQUALS(client->inheritances[1], "C : B <5:12 5:12>"); + TS_ASSERT_EQUALS(client->inheritances[0], "C -> A <4:11 4:11>"); + TS_ASSERT_EQUALS(client->inheritances[1], "C -> B <5:12 5:12>"); } void test_cxx_parser_finds_method_override_when_virtual() @@ -1322,7 +1341,7 @@ public: ); TS_ASSERT_EQUALS(client->overrides.size(), 1); - TS_ASSERT_EQUALS(client->overrides[0], "void A::foo() -> void B::foo() <5:7 5:9>"); + TS_ASSERT_EQUALS(client->overrides[0], "void B::foo() -> void A::foo() <5:7 5:9>"); } void test_cxx_parser_finds_multi_layer_method_overrides() @@ -1340,8 +1359,8 @@ public: ); TS_ASSERT_EQUALS(client->overrides.size(), 2); - TS_ASSERT_EQUALS(client->overrides[0], "void A::foo() -> void B::foo() <5:7 5:9>"); - TS_ASSERT_EQUALS(client->overrides[1], "void B::foo() -> void C::foo() <8:7 8:9>"); + TS_ASSERT_EQUALS(client->overrides[0], "void B::foo() -> void A::foo() <5:7 5:9>"); + TS_ASSERT_EQUALS(client->overrides[1], "void C::foo() -> void B::foo() <8:7 8:9>"); } void test_cxx_parser_finds_method_overrides_on_different_return_types() @@ -1357,7 +1376,7 @@ public: ); TS_ASSERT_EQUALS(client->overrides.size(), 1); - TS_ASSERT_EQUALS(client->overrides[0], "void A::foo() -> int B::foo() <5:6 5:8>"); + TS_ASSERT_EQUALS(client->overrides[0], "int B::foo() -> void A::foo() <5:6 5:8>"); TS_ASSERT_EQUALS(client->errors.size(), 1); } @@ -1646,7 +1665,7 @@ public: ); TS_ASSERT_EQUALS(client->usages.size(), 1); - TS_ASSERT_EQUALS(client->usages[0], "void test() -> my_int_func <8:9 8:19>"); + TS_ASSERT_EQUALS(client->usages[0], "void test() -> void my_int_func(int) <8:9 8:19>"); } void test_cxx_parser_finds_usage_of_global_variable_in_function() @@ -1975,7 +1994,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->int <7:4 7:6>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A -> int <7:4 7:6>"); } void test_cxx_parser_finds_type_template_argument_for_parameter_pack_of_explicit_template_instantiation() { @@ -1991,8 +2010,8 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<>->int <7:6 7:8>"); - TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<>->float <7:11 7:15>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<> -> int <7:6 7:8>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<> -> float <7:11 7:15>"); } void test_cxx_parser_finds_type_template_argument_in_non_default_constructor_of_explicit_template_instaitiation() @@ -2011,7 +2030,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->int <9:4 9:6>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A -> int <9:4 9:6>"); } void test_cxx_parser_finds_type_template_argument_in_default_constructor_of_explicit_template_instaitiation() @@ -2030,7 +2049,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->int <9:4 9:6>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A -> int <9:4 9:6>"); } void test_cxx_parser_finds_type_template_argument_in_new_expression_of_explicit_template_instaitiation() @@ -2049,7 +2068,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->int <9:8 9:10>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A -> int <9:8 9:10>"); } void test_cxx_parser_finds_no_template_argument_for_builtin_non_type_int_template_parameter_of_explicit_template_instantiation() @@ -2102,7 +2121,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p>->g_p <9:5 9:7>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p> -> g_p <9:5 9:7>"); } void test_cxx_parser_finds_non_type_custom_reference_template_argument_of_implicit_template_instantiation() @@ -2121,7 +2140,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p>->g_p <9:4 9:6>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p> -> g_p <9:4 9:6>"); } void test_cxx_parser_finds_no_template_argument_for_builtin_non_type_int_template_parameter_pack_of_explicit_template_instantiation() @@ -2156,7 +2175,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B->A <9:4 9:4>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B -> A <9:4 9:4>"); } void test_cxx_parser_finds_template_template_argument_for_parameter_pack_of_explicit_template_instantiation() @@ -2177,8 +2196,8 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<>->A <11:4 11:4>"); - TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "B<>->A <11:7 11:7>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B<> -> A <11:4 11:4>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "B<> -> A <11:7 11:7>"); } void test_cxx_parser_finds_template_member_specialization_of_implicit_template_specialization() @@ -2214,7 +2233,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->int <6:9 6:11>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A -> int <6:9 6:11>"); } void test_cxx_parser_finds_no_template_argument_for_builtin_non_type_int_template_parameter_of_explicit_template_specialization() @@ -2265,7 +2284,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p>->g_p <8:10 8:12>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p> -> g_p <8:10 8:12>"); } void test_cxx_parser_finds_non_type_custom_reference_template_argument_of_explicit_template_specialization() @@ -2284,7 +2303,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p>->g_p <8:9 8:11>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p> -> g_p <8:9 8:11>"); } void test_cxx_parser_finds_template_template_argument_of_explicit_template_specialization() @@ -2303,7 +2322,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B->A <8:9 8:9>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B -> A <8:9 8:9>"); } void test_cxx_parser_finds_type_template_argument_of_explicit_partial_template_specialization() @@ -2320,8 +2339,8 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->A::T <6:9 6:9>"); - TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A->int <6:12 6:14>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A -> A::T <6:9 6:9>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A -> int <6:12 6:14>"); } void test_cxx_parser_finds_no_template_argument_for_builtin_non_type_int_template_parameter_of_explicit_partial_template_specialization() @@ -2338,7 +2357,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<3, int U>->A<3, int U>::U <6:12 6:12>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<3, int U> -> A<3, int U>::U <6:12 6:12>"); } void test_cxx_parser_finds_no_template_argument_for_builtin_non_type_bool_template_parameter_of_explicit_partial_template_specialization() @@ -2355,7 +2374,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A->A::U <6:15 6:15>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A -> A::U <6:15 6:15>"); } void test_cxx_parser_finds_template_argument_for_non_type_custom_pointer_template_parameter_of_explicit_partial_template_specialization() @@ -2374,8 +2393,8 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p, P * q>->g_p <8:10 8:12>"); - TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<&g_p, P * q>->A<&g_p, P * q>::q <8:15 8:15>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p, P * q> -> g_p <8:10 8:12>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<&g_p, P * q> -> A<&g_p, P * q>::q <8:15 8:15>"); } void test_cxx_parser_finds_template_argument_for_non_type_custom_reference_template_parameter_of_explicit_partial_template_specialization() @@ -2394,8 +2413,8 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p, P & q>->g_p <8:9 8:11>"); // why reference here? - TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<&g_p, P & q>->A<&g_p, P & q>::q <8:14 8:14>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<&g_p, P & q> -> g_p <8:9 8:11>"); // why reference here? + TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<&g_p, P & q> -> A<&g_p, P & q>::q <8:14 8:14>"); } void test_cxx_parser_finds_template_argument_for_template_template_parameter_of_explicit_partial_template_specialization() @@ -2414,8 +2433,8 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B typename U>->A <8:9 8:9>"); - TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "B typename U>->B typename U>::U <8:12 8:12>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "B typename U> -> A <8:9 8:9>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "B typename U> -> B typename U>::U <8:12 8:12>"); } void test_cxx_parser_finds_non_type_template_argument_that_depends_on_type_template_parameter_of_explicit_partial_template_specialization() @@ -2432,8 +2451,8 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<3, typename T2, T2 T3>->A<3, typename T2, T2 T3>::T2 <6:12 6:13>"); - TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<3, typename T2, T2 T3>->A<3, typename T2, T2 T3>::T3 <6:16 6:17>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<3, typename T2, T2 T3> -> A<3, typename T2, T2 T3>::T2 <6:12 6:13>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<3, typename T2, T2 T3> -> A<3, typename T2, T2 T3>::T3 <6:16 6:17>"); } //void _test_cxx_parser_finds_non_type_template_argument_that_depends_on_template_template_parameter_of_explicit_partial_template_specialization() @@ -2450,8 +2469,8 @@ public: // ); // TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 2); - // TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<3, template typename T2, T2 T3>->A<3, template typename T2, T2 T3>::T2 <6:12 6:13>"); - // TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<3, template typename T2, T2 T3>->A<3, template typename T2, T2 T3>::T3 <6:16 6:17>"); + // TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<3, template typename T2, T2 T3> -> A<3, template typename T2, T2 T3>::T2 <6:12 6:13>"); + // TS_ASSERT_EQUALS(client->templateArgumentTypes[1], "A<3, template typename T2, T2 T3> -> A<3, template typename T2, T2 T3>::T3 <6:16 6:17>"); //} void test_cxx_parser_finds_implicit_template_class_specialization() @@ -2485,7 +2504,7 @@ public: ); TS_ASSERT_EQUALS(client->inheritances.size(), 1); - TS_ASSERT_EQUALS(client->inheritances[0], "B : A <7:17 7:17>"); + TS_ASSERT_EQUALS(client->inheritances[0], "B -> A <7:17 7:17>"); } void test_cxx_parser_finds_template_class_specialization_with_template_argument() @@ -2504,7 +2523,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A::U>->B::U <8:19 8:19>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A::U> -> B::U <8:19 8:19>"); } void test_cxx_parser_finds_template_class_constructor_usage_of_field() @@ -2546,7 +2565,7 @@ public: ); TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> A::T <1:24 1:26>"); + TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "A::T -> int <1:24 1:26>"); } void test_cxx_parser_finds_no_default_argument_type_for_non_type_bool_template_parameter_of_template_class() @@ -2573,7 +2592,7 @@ public: ); TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "A -> B typename T>::T <4:40 4:40>"); + TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "B typename T>::T -> A <4:40 4:40>"); } void test_cxx_parser_finds_implicit_instantiation_of_template_function() @@ -2630,7 +2649,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "void test()->int <7:11 7:13>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "void test() -> int <7:11 7:13>"); } void test_cxx_parser_finds_explicit_type_template_argument_of_function_call_in_function() @@ -2647,7 +2666,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "void test()->int <6:7 6:9>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "void test() -> int <6:7 6:9>"); } void test_cxx_parser_finds_no_explicit_non_type_int_template_argument_of_function_call_in_function() @@ -2681,7 +2700,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "void test()->A <7:7 7:7>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "void test() -> A <7:7 7:7>"); } void test_cxx_parser_finds_no_implicit_type_template_argument_of_function_call_in_function() @@ -2713,7 +2732,7 @@ public: ); TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "int test()->int <6:17 6:19>"); + TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "int test() -> int <6:17 6:19>"); } void test_cxx_parser_finds_no_implicit_type_template_argument_of_function_call_in_var_decl() @@ -2747,7 +2766,7 @@ public: ); TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes.size(), 1); - TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "int -> test::T <1:24 1:26>"); + TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes[0], "test::T -> int <1:24 1:26>"); } void test_cxx_parser_does_not_find_default_argument_type_for_non_type_bool_template_parameter_of_template_function() @@ -2777,7 +2796,7 @@ public: TS_ASSERT_EQUALS(client->templateDefaultArgumentTypes.size(), 1); TS_ASSERT_EQUALS( client->templateDefaultArgumentTypes[0], - "A -> test typename T>::T <4:40 4:40>"); + "test typename T>::T -> A <4:40 4:40>"); } void test_cxx_parser_finds_lambda_calling_a_function() @@ -2853,7 +2872,7 @@ public: // ); // TS_ASSERT_EQUALS(client->templateArgumentTypes.size(), 1); - // TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<1>->int <0:0 0:0>"); + // TS_ASSERT_EQUALS(client->templateArgumentTypes[0], "A<1> -> int <0:0 0:0>"); //} //void _test_cxx_parser_finds_implicit_constructor_call_in_initialization() @@ -2960,262 +2979,6 @@ public: // } private: - class TestParserClient: public ParserClient - { - public: - virtual void startParsingFile() - { - } - - virtual void finishParsingFile() - { - } - - virtual Id recordSymbol( - const NameHierarchy& symbolName, SymbolKind symbolKind, - AccessKind access = ACCESS_NONE, bool isImplicit = false) - { - // todo: implement and replace all the on..DeclParsed - return 0; - } - - virtual Id recordSymbol( - const NameHierarchy& symbolName, SymbolKind symbolKind, - const ParseLocation& location, - AccessKind access = ACCESS_NONE, bool isImplicit = false) - { - // todo: implement and replace all the on..DeclParsed - return 0; - } - - virtual Id recordSymbol( - const NameHierarchy& symbolName, SymbolKind symbolKind, - const ParseLocation& location, const ParseLocation& scopeLocation, - AccessKind access = ACCESS_NONE, bool isImplicit = false) - { - // todo: implement and replace all the on..DeclParsed - return 0; - } - - virtual void recordReference( - ReferenceKind referenceKind, const NameHierarchy& referencedName, const NameHierarchy& contextName, - const ParseLocation& location) - { - } - - virtual void onError(const ParseLocation& location, const std::string& message, bool fatal, bool indexed) - { - errors.push_back(addLocationSuffix(message, location)); - } - - virtual void onTypedefParsed( - const ParseLocation& location, const NameHierarchy& typedefName, AccessKind access, bool isImplicit - ) - { - std::string str = addAccessPrefix(typedefName.getQualifiedName(), access); - typedefs.push_back(addLocationSuffix(str, location)); - } - - virtual void onClassParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) - { - classes.push_back(addLocationSuffix(addAccessPrefix(nameHierarchy.getQualifiedName(), access), location, scopeLocation)); - } - - virtual void onStructParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) - { - structs.push_back(addLocationSuffix(addAccessPrefix(nameHierarchy.getQualifiedName(), access), location, scopeLocation)); - } - - virtual void onGlobalVariableParsed(const ParseLocation& location, const NameHierarchy& variable, bool isImplicit) - { - globalVariables.push_back(addLocationSuffix(variable.getQualifiedName(), location)); - } - - virtual void onFieldParsed(const ParseLocation& location, const NameHierarchy& field, AccessKind access, bool isImplicit) - { - fields.push_back(addLocationSuffix(addAccessPrefix(field.getQualifiedName(), access), location)); - } - - virtual void onFunctionParsed( - const ParseLocation& location, const NameHierarchy& function, const ParseLocation& scopeLocation, bool isImplicit) - { - functions.push_back(addLocationSuffix(function.getQualifiedNameWithSignature(), location, scopeLocation)); - } - - virtual void onMethodParsed( - const ParseLocation& location, const NameHierarchy& method, AccessKind access, AbstractionType abstraction, - const ParseLocation& scopeLocation, bool isImplicit) - { - std::string str = method.getQualifiedNameWithSignature(); - str = addAbstractionPrefix(str, abstraction); - str = addAccessPrefix(str, access); - str = addLocationSuffix(str, location, scopeLocation); - methods.push_back(str); - } - - virtual void onNamespaceParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, const ParseLocation& scopeLocation, bool isImplicit) - { - namespaces.push_back(addLocationSuffix(nameHierarchy.getQualifiedName(), location, scopeLocation)); - } - - virtual void onEnumParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) - { - enums.push_back(addLocationSuffix(addAccessPrefix(nameHierarchy.getQualifiedName(), access), location, scopeLocation)); - } - - virtual void onEnumConstantParsed(const ParseLocation& location, const NameHierarchy& nameHierarchy, bool isImplicit) - { - enumConstants.push_back(addLocationSuffix(nameHierarchy.getQualifiedName(), location)); - } - - virtual void onTemplateParameterTypeParsed( - const ParseLocation& location, const NameHierarchy& templateParameterTypeNameHierarchy, bool isImplicit) - { - templateParameterTypes.push_back( - addLocationSuffix(templateParameterTypeNameHierarchy.getQualifiedName(), location) - ); - } - - virtual void onLocalSymbolParsed(const std::string& name, const ParseLocation& location) - { - localSymbols.push_back(name); - } - - virtual void onFileParsed(const FileInfo& fileInfo) - { - files.push_back(fileInfo.path.str()); - } - - virtual void onMacroExpandParsed(const ParseLocation& location, const NameHierarchy& macroNameHierarchy) - { - macroUses.push_back(addLocationSuffix(macroNameHierarchy.getQualifiedName() ,location)); - } - - virtual void onCommentParsed(const ParseLocation& location) - { - comments.push_back(addLocationSuffix("comment", location)); - - } - - virtual void onInheritanceParsed( - const ParseLocation& location, const NameHierarchy& childNameHierarchy, - const NameHierarchy& parentNameHierarchy) - { - std::string str = childNameHierarchy.getQualifiedName() + " : " + parentNameHierarchy.getQualifiedName(); - inheritances.push_back(addLocationSuffix(str, location)); - } - - virtual void onMethodOverrideParsed( - const ParseLocation& location, const NameHierarchy& overridden, const NameHierarchy& overrider) - { - overrides.push_back(addLocationSuffix(overridden.getQualifiedNameWithSignature() + " -> " + overrider.getQualifiedNameWithSignature(), location)); - } - - virtual void onCallParsed( - const ParseLocation& location, const NameHierarchy& caller, const NameHierarchy& callee) - { - std::string callerSignature = caller.getQualifiedNameWithSignature(); - calls.push_back(addLocationSuffix(caller.getQualifiedNameWithSignature() + " -> " + callee.getQualifiedNameWithSignature(), location)); - } - - virtual void onUsageParsed( - const ParseLocation& location, const NameHierarchy& userName, SymbolKind usedType, const NameHierarchy& usedName) - { - usages.push_back(addLocationSuffix(userName.getQualifiedNameWithSignature() + " -> " + usedName.getQualifiedName(), location)); - } - - virtual void onTypeUsageParsed(const ParseLocation& location, const NameHierarchy& user, const NameHierarchy& used) - { - typeUses.push_back(addLocationSuffix(user.getQualifiedNameWithSignature() + " -> " + used.getQualifiedNameWithSignature(), location)); - } - - virtual void onTemplateArgumentTypeParsed( - const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy, - const NameHierarchy& templateNameHierarchy) - { - templateArgumentTypes.push_back( - addLocationSuffix(templateNameHierarchy.getQualifiedNameWithSignature() + "->" + argumentTypeNameHierarchy.getQualifiedName(), location) - ); - } - - virtual void onTemplateDefaultArgumentTypeParsed( - const ParseLocation& location, const NameHierarchy& defaultArgumentTypeNameHierarchy, - const NameHierarchy& templateParameterNameHierarchy) - { - templateDefaultArgumentTypes.push_back( - addLocationSuffix(defaultArgumentTypeNameHierarchy.getQualifiedNameWithSignature() + " -> " + templateParameterNameHierarchy.getQualifiedName(), location) - ); - } - - virtual void onTemplateSpecializationParsed( - const ParseLocation& location, const NameHierarchy& specializedNameHierarchy, - const NameHierarchy& specializedFromNameHierarchy) - { - templateSpecializations.push_back(addLocationSuffix( - specializedNameHierarchy.getQualifiedNameWithSignature() + " -> " + specializedFromNameHierarchy.getQualifiedNameWithSignature(), location - )); - } - - virtual void onTemplateMemberFunctionSpecializationParsed( - const ParseLocation& location, const NameHierarchy& instantiatedFunction, const NameHierarchy& specializedFunction) - { - templateMemberSpecializations.push_back(addLocationSuffix( - instantiatedFunction.getQualifiedNameWithSignature() + " -> " + specializedFunction.getQualifiedNameWithSignature(), location - )); - } - - virtual void onFileIncludeParsed( - const ParseLocation& location, const FileInfo& fileInfo, const FileInfo& includedFileInfo) - { - includes.push_back(fileInfo.path.str() + " -> " + includedFileInfo.path.str()); - } - - virtual void onMacroDefineParsed( - const ParseLocation& location, const NameHierarchy& macroNameHierarchy, const ParseLocation& scopeLocation) - { - macros.push_back(addLocationSuffix(macroNameHierarchy.getQualifiedName(), location, scopeLocation)); - } - - std::vector errors; - - std::vector typedefs; - std::vector classes; - std::vector enums; - std::vector enumConstants; - std::vector functions; - std::vector fields; - std::vector globalVariables; - std::vector methods; - std::vector namespaces; - std::vector structs; - std::vector macros; - - std::vector inheritances; - std::vector overrides; - std::vector calls; - std::vector usages; // for variables - std::vector typeUses; // for types - std::vector macroUses; - std::vector templateParameterTypes; - std::vector templateArgumentTypes; - std::vector templateDefaultArgumentTypes; - std::vector templateSpecializations; - std::vector templateMemberSpecializations; - std::vector localSymbols; - - std::vector files; - std::vector includes; - - std::vector comments; - }; - std::shared_ptr parseCode(std::string code, bool logErrors = true) { NameHierarchy::setDelimiter("::"); diff --git a/src/test/JavaParserTestSuite.h b/src/test/JavaParserTestSuite.h index 8e4a1040..94fa6dd9 100644 --- a/src/test/JavaParserTestSuite.h +++ b/src/test/JavaParserTestSuite.h @@ -7,11 +7,9 @@ #include "data/parser/java/JavaEnvironmentFactory.h" #include "data/parser/java/JavaParser.h" -#include "data/parser/ParseLocation.h" -#include "data/parser/ParserClient.h" #include "helper/TestFileManager.h" - +#include "helper/TestParserClient.h" class JavaParserTestSuite: public CxxTest::TestSuite @@ -783,372 +781,6 @@ public: private: - class TestParserClient: public ParserClient - { - public: - virtual void startParsingFile() - { - } - - virtual void finishParsingFile() - { - } - - - std::vector* getBinForSymbolKind(SymbolKind symbolType) - { - switch (symbolType) - { - case SYMBOL_PACKAGE: - return &packages; - case SYMBOL_CLASS: - return &classes; - case SYMBOL_INTERFACE: - return &interfaces; - case SYMBOL_ENUM: - return &enums; - case SYMBOL_ENUM_CONSTANT: - return &enumConstants; - case SYMBOL_METHOD: - return &methods; - case SYMBOL_FIELD: - return &fields; - case SYMBOL_TYPE_PARAMETER: - return &typeParameters; - default: - break; - } - return nullptr; - } - - virtual Id recordSymbol( - const NameHierarchy& symbolName, SymbolKind symbolKind, - AccessKind access = ACCESS_NONE, bool isImplicit = false) - { - std::vector* bin = getBinForSymbolKind(symbolKind); - if (bin != nullptr) - { - bin->push_back(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access)); - } - return 0; - } - - virtual Id recordSymbol( - const NameHierarchy& symbolName, SymbolKind symbolKind, - const ParseLocation& location, - AccessKind access = ACCESS_NONE, bool isImplicit = false) - { - std::vector* bin = getBinForSymbolKind(symbolKind); - if (bin != nullptr) - { - bin->push_back(addLocationSuffix(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access), location)); - } - return 0; - } - - virtual Id recordSymbol( - const NameHierarchy& symbolName, SymbolKind symbolKind, - const ParseLocation& location, const ParseLocation& scopeLocation, - AccessKind access = ACCESS_NONE, bool isImplicit = false) - { - std::vector* bin = getBinForSymbolKind(symbolKind); - if (bin != nullptr) - { - bin->push_back(addLocationSuffix(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access), location, scopeLocation)); - } - return 0; - } - - void recordReference( - ReferenceKind referenceKind, const NameHierarchy& referencedName, const NameHierarchy& contextName, - const ParseLocation& location) - { - std::vector* referenceContainer = nullptr; - switch (referenceKind) - { - case REFERENCE_TYPE_USAGE: - referenceContainer = &typeUses; - break; - case REFERENCE_USAGE: - referenceContainer = &usages; - break; - case REFERENCE_CALL: - referenceContainer = &calls; - break; - case REFERENCE_INHERITANCE: - referenceContainer = &inheritances; - break; - case REFERENCE_OVERRIDE: - referenceContainer = &overrides; - break; - case REFERENCE_TEMPLATE_ARGUMENT: - referenceContainer = &templateArgumentTypes; - break; - case REFERENCE_TYPE_ARGUMENT: - referenceContainer = &typeArguments; - break; - case REFERENCE_TEMPLATE_DEFAULT_ARGUMENT: - referenceContainer = &templateDefaultArgumentTypes; - break; - case REFERENCE_TEMPLATE_SPECIALIZATION_OF: - referenceContainer = &templateSpecializations; - break; - case REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION_OF: - referenceContainer = &templateMemberSpecializations; - break; - case REFERENCE_INCLUDE: - referenceContainer = &includes; - break; - case REFERENCE_IMPORT: - referenceContainer = &imports; - break; - case REFERENCE_MACRO_USAGE: - referenceContainer = ¯oUses; - break; - default: - break; - } - if (referenceContainer != nullptr) - { - referenceContainer->push_back(addLocationSuffix( - contextName.getQualifiedNameWithSignature() + " -> " + referencedName.getQualifiedNameWithSignature(), location) - ); - } - } - - - - - - - - - - - - - - - - - - - virtual void onError(const ParseLocation& location, const std::string& message, bool fatal, bool indexed) - { - errors.push_back(addLocationSuffix(message, location)); - } - - virtual void onTypedefParsed( - const ParseLocation& location, const NameHierarchy& typedefName, AccessKind access, bool isImplicit - ) - { - std::string str = addAccessPrefix(typedefName.getQualifiedName(), access); - typedefs.push_back(addLocationSuffix(str, location)); - } - - virtual void onClassParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) - { - classes.push_back(addLocationSuffix(addAccessPrefix(nameHierarchy.getQualifiedName(), access), location, scopeLocation)); - } - - virtual void onStructParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) - { - structs.push_back(addLocationSuffix(addAccessPrefix(nameHierarchy.getQualifiedName(), access), location, scopeLocation)); - } - - virtual void onGlobalVariableParsed(const ParseLocation& location, const NameHierarchy& variable, bool isImplicit) - { - globalVariables.push_back(addLocationSuffix(variable.getQualifiedName(), location)); - } - - virtual void onFieldParsed(const ParseLocation& location, const NameHierarchy& field, AccessKind access, bool isImplicit) - { - fields.push_back(addLocationSuffix(addAccessPrefix(field.getQualifiedName(), access), location)); - } - - virtual void onFunctionParsed( - const ParseLocation& location, const NameHierarchy& function, const ParseLocation& scopeLocation, bool isImplicit) - { - functions.push_back(addLocationSuffix(function.getQualifiedNameWithSignature(), location, scopeLocation)); - } - - virtual void onMethodParsed( - const ParseLocation& location, const NameHierarchy& method, AccessKind access, AbstractionType abstraction, - const ParseLocation& scopeLocation, bool isImplicit) - { - std::string str = method.getQualifiedNameWithSignature(); - str = addAbstractionPrefix(str, abstraction); - str = addAccessPrefix(str, access); - str = addLocationSuffix(str, location, scopeLocation); - methods.push_back(str); - } - - virtual void onNamespaceParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, const ParseLocation& scopeLocation, bool isImplicit) - { - namespaces.push_back(addLocationSuffix(nameHierarchy.getQualifiedName(), location, scopeLocation)); - } - - virtual void onEnumParsed( - const ParseLocation& location, const NameHierarchy& nameHierarchy, AccessKind access, - const ParseLocation& scopeLocation, bool isImplicit) - { - enums.push_back(addLocationSuffix(addAccessPrefix(nameHierarchy.getQualifiedName(), access), location, scopeLocation)); - } - - virtual void onEnumConstantParsed(const ParseLocation& location, const NameHierarchy& nameHierarchy, bool isImplicit) - { - enumConstants.push_back(addLocationSuffix(nameHierarchy.getQualifiedName(), location)); - } - - virtual void onTemplateParameterTypeParsed( - const ParseLocation& location, const NameHierarchy& templateParameterTypeNameHierarchy, bool isImplicit) - { - templateParameterTypes.push_back( - addLocationSuffix(templateParameterTypeNameHierarchy.getQualifiedName(), location) - ); - } - - virtual void onLocalSymbolParsed(const std::string& name, const ParseLocation& location) - { - localSymbols.push_back(addLocationSuffix(name, location)); - } - - virtual void onFileParsed(const FileInfo& fileInfo) - { - files.push_back(fileInfo.path.str()); - } - - virtual void onMacroExpandParsed(const ParseLocation& location, const NameHierarchy& macroNameHierarchy) - { - macroUses.push_back(addLocationSuffix(macroNameHierarchy.getQualifiedName() ,location)); - } - - virtual void onCommentParsed(const ParseLocation& location) - { - comments.push_back(addLocationSuffix("comment", location)); - - } - - virtual void onInheritanceParsed( - const ParseLocation& location, const NameHierarchy& childNameHierarchy, - const NameHierarchy& parentNameHierarchy) - { - std::string str = childNameHierarchy.getQualifiedName() + " : " + parentNameHierarchy.getQualifiedName(); - inheritances.push_back(addLocationSuffix(str, location)); - } - - virtual void onMethodOverrideParsed( - const ParseLocation& location, const NameHierarchy& overridden, const NameHierarchy& overrider) - { - overrides.push_back(addLocationSuffix(overridden.getQualifiedNameWithSignature() + " -> " + overrider.getQualifiedNameWithSignature(), location)); - } - - virtual void onCallParsed( - const ParseLocation& location, const NameHierarchy& caller, const NameHierarchy& callee) - { - calls.push_back(addLocationSuffix(caller.getQualifiedNameWithSignature() + " -> " + callee.getQualifiedNameWithSignature(), location)); - } - - virtual void onUsageParsed( - const ParseLocation& location, const NameHierarchy& userName, SymbolKind usedType, const NameHierarchy& usedName) - { - usages.push_back(addLocationSuffix(userName.getQualifiedNameWithSignature() + " -> " + usedName.getQualifiedName(), location)); - } - - virtual void onTypeUsageParsed(const ParseLocation& location, const NameHierarchy& user, const NameHierarchy& used) - { - typeUses.push_back(addLocationSuffix(user.getQualifiedNameWithSignature() + " -> " + used.getQualifiedNameWithSignature(), location)); - } - - virtual void onTemplateArgumentTypeParsed( - const ParseLocation& location, const NameHierarchy& argumentTypeNameHierarchy, - const NameHierarchy& templateNameHierarchy) - { - templateArgumentTypes.push_back( - addLocationSuffix(templateNameHierarchy.getQualifiedNameWithSignature() + "->" + argumentTypeNameHierarchy.getQualifiedName(), location) - ); - } - - virtual void onTemplateDefaultArgumentTypeParsed( - const ParseLocation& location, const NameHierarchy& defaultArgumentTypeNameHierarchy, - const NameHierarchy& templateParameterNameHierarchy) - { - templateDefaultArgumentTypes.push_back( - addLocationSuffix(defaultArgumentTypeNameHierarchy.getQualifiedNameWithSignature() + " -> " + templateParameterNameHierarchy.getQualifiedName(), location) - ); - } - - virtual void onTemplateSpecializationParsed( - const ParseLocation& location, const NameHierarchy& specializedNameHierarchy, - const NameHierarchy& specializedFromNameHierarchy) - { - templateSpecializations.push_back(addLocationSuffix( - specializedNameHierarchy.getQualifiedNameWithSignature() + " -> " + specializedFromNameHierarchy.getQualifiedNameWithSignature(), location - )); - } - - virtual void onTemplateMemberFunctionSpecializationParsed( - const ParseLocation& location, const NameHierarchy& instantiatedFunction, const NameHierarchy& specializedFunction) - { - templateMemberSpecializations.push_back(addLocationSuffix( - instantiatedFunction.getQualifiedNameWithSignature() + " -> " + specializedFunction.getQualifiedNameWithSignature(), location - )); - } - - virtual void onFileIncludeParsed( - const ParseLocation& location, const FileInfo& fileInfo, const FileInfo& includedFileInfo) - { - includes.push_back(fileInfo.path.str() + " -> " + includedFileInfo.path.str()); - } - - virtual void onMacroDefineParsed( - const ParseLocation& location, const NameHierarchy& macroNameHierarchy, const ParseLocation& scopeLocation) - { - macros.push_back(addLocationSuffix(macroNameHierarchy.getQualifiedName(), location, scopeLocation)); - } - - std::vector errors; - - std::vector packages; - std::vector typedefs; - std::vector classes; - std::vector interfaces; - std::vector enums; - std::vector enumConstants; - std::vector functions; - std::vector fields; - std::vector globalVariables; - std::vector methods; - std::vector namespaces; - std::vector structs; - std::vector macros; - std::vector templateParameterTypes; - std::vector typeParameters; - std::vector localSymbols; - std::vector files; - std::vector comments; - - std::vector inheritances; - std::vector overrides; - std::vector calls; - std::vector usages; // for variables - std::vector typeUses; // for types - std::vector macroUses; - std::vector templateArgumentTypes; - std::vector typeArguments; - std::vector templateDefaultArgumentTypes; - std::vector templateSpecializations; - std::vector templateMemberSpecializations; - std::vector includes; - std::vector imports; - - }; - void setupJavaEnvironmentFactory() { if (!JavaEnvironmentFactory::getInstance()) diff --git a/src/test/helper/TestParserClient.h b/src/test/helper/TestParserClient.h new file mode 100644 index 00000000..35e9ecfa --- /dev/null +++ b/src/test/helper/TestParserClient.h @@ -0,0 +1,210 @@ +#ifndef TEST_PARSER_CLIENT_H +#define TEST_PARSER_CLIENT_H + +#include "data/parser/ParseLocation.h" +#include "data/parser/ParserClient.h" + +class TestParserClient: public ParserClient +{ +public: + virtual void startParsingFile() + { + } + + virtual void finishParsingFile() + { + } + + virtual Id recordSymbol( + const NameHierarchy& symbolName, SymbolKind symbolKind, + AccessKind access = ACCESS_NONE, bool isImplicit = false) + { + std::vector* bin = getBinForSymbolKind(symbolKind); + if (bin != nullptr) + { + bin->push_back(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access)); + } + return 0; + } + + virtual Id recordSymbol( + const NameHierarchy& symbolName, SymbolKind symbolKind, + const ParseLocation& location, + AccessKind access = ACCESS_NONE, bool isImplicit = false) + { + std::vector* bin = getBinForSymbolKind(symbolKind); + if (bin != nullptr) + { + bin->push_back(addLocationSuffix(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access), location)); + } + return 0; + } + + virtual Id recordSymbol( + const NameHierarchy& symbolName, SymbolKind symbolKind, + const ParseLocation& location, const ParseLocation& scopeLocation, + AccessKind access = ACCESS_NONE, bool isImplicit = false) + { + std::vector* bin = getBinForSymbolKind(symbolKind); + if (bin != nullptr) + { + bin->push_back(addLocationSuffix(addAccessPrefix(symbolName.getQualifiedNameWithSignature(), access), location, scopeLocation)); + } + return 0; + } + + void recordReference( + ReferenceKind referenceKind, const NameHierarchy& referencedName, const NameHierarchy& contextName, + const ParseLocation& location) + { + std::vector* referenceContainer = nullptr; + switch (referenceKind) + { + case REFERENCE_TYPE_USAGE: + referenceContainer = &typeUses; + break; + case REFERENCE_USAGE: + referenceContainer = &usages; + break; + case REFERENCE_CALL: + referenceContainer = &calls; + break; + case REFERENCE_INHERITANCE: + referenceContainer = &inheritances; + break; + case REFERENCE_OVERRIDE: + referenceContainer = &overrides; + break; + case REFERENCE_TEMPLATE_ARGUMENT: + referenceContainer = &templateArgumentTypes; + break; + case REFERENCE_TYPE_ARGUMENT: + referenceContainer = &typeArguments; + break; + case REFERENCE_TEMPLATE_DEFAULT_ARGUMENT: + referenceContainer = &templateDefaultArgumentTypes; + break; + case REFERENCE_TEMPLATE_SPECIALIZATION_OF: + referenceContainer = &templateSpecializations; + break; + case REFERENCE_TEMPLATE_MEMBER_SPECIALIZATION_OF: + referenceContainer = &templateMemberSpecializations; + break; + case REFERENCE_INCLUDE: + referenceContainer = &includes; + break; + case REFERENCE_IMPORT: + referenceContainer = &imports; + break; + case REFERENCE_MACRO_USAGE: + referenceContainer = ¯oUses; + break; + default: + break; + } + if (referenceContainer != nullptr) + { + referenceContainer->push_back(addLocationSuffix( + contextName.getQualifiedNameWithSignature() + " -> " + referencedName.getQualifiedNameWithSignature(), location) + ); + } + } + + virtual void onError(const ParseLocation& location, const std::string& message, bool fatal, bool indexed) + { + errors.push_back(addLocationSuffix(message, location)); + } + + virtual void onLocalSymbolParsed(const std::string& name, const ParseLocation& location) + { + localSymbols.push_back(addLocationSuffix(name, location)); + } + + virtual void onFileParsed(const FileInfo& fileInfo) + { + files.push_back(fileInfo.path.str()); + } + + virtual void onCommentParsed(const ParseLocation& location) + { + comments.push_back(addLocationSuffix("comment", location)); + } + + std::vector errors; + + std::vector packages; + std::vector typedefs; + std::vector classes; + std::vector interfaces; + std::vector enums; + std::vector enumConstants; + std::vector functions; + std::vector fields; + std::vector globalVariables; + std::vector methods; + std::vector namespaces; + std::vector structs; + std::vector macros; + std::vector templateParameterTypes; + std::vector typeParameters; + std::vector localSymbols; + std::vector files; + std::vector comments; + + std::vector inheritances; + std::vector overrides; + std::vector calls; + std::vector usages; // for variables + std::vector typeUses; // for types + std::vector macroUses; + std::vector templateArgumentTypes; + std::vector typeArguments; + std::vector templateDefaultArgumentTypes; + std::vector templateSpecializations; + std::vector templateMemberSpecializations; + std::vector includes; + std::vector imports; + +private: + std::vector* getBinForSymbolKind(SymbolKind symbolType) + { + switch (symbolType) + { + case SYMBOL_PACKAGE: + return &packages; + case SYMBOL_TYPEDEF: + return &typedefs; + case SYMBOL_CLASS: + return &classes; + case SYMBOL_INTERFACE: + return &interfaces; + case SYMBOL_ENUM: + return &enums; + case SYMBOL_ENUM_CONSTANT: + return &enumConstants; + case SYMBOL_FUNCTION: + return &functions; + case SYMBOL_FIELD: + return &fields; + case SYMBOL_GLOBAL_VARIABLE: + return &globalVariables; + case SYMBOL_METHOD: + return &methods; + case SYMBOL_NAMESPACE: + return &namespaces; + case SYMBOL_STRUCT: + return &structs; + case SYMBOL_MACRO: + return ¯os; + case SYMBOL_TEMPLATE_PARAMETER: + return &templateParameterTypes; + case SYMBOL_TYPE_PARAMETER: + return &typeParameters; + default: + break; + } + return nullptr; + } +}; + +#endif // TEST_PARSER_CLIENT_H