Add new wrapper target to invoke the newly added clang-query tool.
It seems there is a bug in the rewriter that prevents it to save the source files with replacements out to disk, so at the moment nothing get changed yet in the source tree. [ci only: Annotate]
This commit is contained in:
Родитель
4355e99c36
Коммит
dbd23c17a1
|
@ -260,6 +260,7 @@ if (URHO3D_CLANG_TOOLS)
|
||||||
# Require C++11 standard and no precompiled-header
|
# Require C++11 standard and no precompiled-header
|
||||||
set (URHO3D_C++11 1)
|
set (URHO3D_C++11 1)
|
||||||
set (URHO3D_PCH 0)
|
set (URHO3D_PCH 0)
|
||||||
|
set (URHO3D_LIB_TYPE SHARED)
|
||||||
# Set build options that would maximise the AST of Urho3D library
|
# Set build options that would maximise the AST of Urho3D library
|
||||||
foreach (OPT URHO3D_ANGELSCRIPT URHO3D_LUA URHO3D_FILEWATCHER URHO3D_PROFILING URHO3D_LOGGING URHO3D_NAVIGATION URHO3D_NETWORK URHO3D_PHYSICS URHO3D_URHO2D URHO3D_DATABASE_SQLITE)
|
foreach (OPT URHO3D_ANGELSCRIPT URHO3D_LUA URHO3D_FILEWATCHER URHO3D_PROFILING URHO3D_LOGGING URHO3D_NAVIGATION URHO3D_NETWORK URHO3D_PHYSICS URHO3D_URHO2D URHO3D_DATABASE_SQLITE)
|
||||||
set (${OPT} 1)
|
set (${OPT} 1)
|
||||||
|
|
|
@ -22,7 +22,9 @@
|
||||||
|
|
||||||
#include <clang/ASTMatchers/ASTMatchFinder.h>
|
#include <clang/ASTMatchers/ASTMatchFinder.h>
|
||||||
#include <clang/Tooling/CommonOptionsParser.h>
|
#include <clang/Tooling/CommonOptionsParser.h>
|
||||||
#include <clang/Tooling/Refactoring.h>
|
#include <clang/Tooling/RefactoringCallbacks.h>
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace clang::ast_matchers;
|
using namespace clang::ast_matchers;
|
||||||
|
@ -45,18 +47,59 @@ static cl::extrahelp MoreHelp(
|
||||||
"\n"
|
"\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
static cl::OptionCategory AnnotatorCategory("Annotator options");
|
static cl::OptionCategory annotatorCategory("Annotator options");
|
||||||
|
|
||||||
class BindingCallback : public MatchFinder::MatchCallback
|
// ClangTool only takes a reference to the array list without owning it, so we need to keep the filtered list ourselves
|
||||||
|
class PathFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <typename Fn>
|
||||||
|
PathFilter(const std::vector<std::string> sourcePaths, Fn fn)
|
||||||
|
{
|
||||||
|
std::copy_if(sourcePaths.begin(), sourcePaths.end(), std::back_inserter(pathList_), fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> GetPathList() {
|
||||||
|
return pathList_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::string> pathList_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::unordered_set<std::string> classNames_;
|
||||||
|
|
||||||
|
class ExtractCallback : public MatchFinder::MatchCallback
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
virtual void run(const MatchFinder::MatchResult& result)
|
virtual void run(const MatchFinder::MatchResult& result)
|
||||||
{
|
{
|
||||||
ASTContext* context = result.Context;
|
auto className = result.Nodes.getNodeAs<StringLiteral>("className");
|
||||||
const StringLiteral* stringLiteral = result.Nodes.getNodeAs<StringLiteral>("StringLiteral");
|
if (className)
|
||||||
if (stringLiteral)
|
classNames_.insert(className->getString());
|
||||||
// TODO: Store the exposed class name in a global hashset
|
}
|
||||||
outs() << stringLiteral->getString() << "\n";
|
|
||||||
|
virtual void onStartOfTranslationUnit()
|
||||||
|
{
|
||||||
|
outs() << '.'; // Sending a heart beat
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::unordered_set<std::string> annotatedClassNames_;
|
||||||
|
|
||||||
|
class AnnotateCallback : public RefactoringCallback
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
virtual void run(const MatchFinder::MatchResult& result)
|
||||||
|
{
|
||||||
|
auto className = result.Nodes.getNodeAs<RecordDecl>("className");
|
||||||
|
if (className && annotatedClassNames_.find(className->getName()) == annotatedClassNames_.end() &&
|
||||||
|
classNames_.find(className->getName()) == classNames_.end())
|
||||||
|
{
|
||||||
|
Replacement replacement(*result.SourceManager, className->getLocStart(), 0, "!!!TODO: WIP");
|
||||||
|
getReplacements().insert(replacement);
|
||||||
|
annotatedClassNames_.insert(className->getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onStartOfTranslationUnit()
|
virtual void onStartOfTranslationUnit()
|
||||||
|
@ -67,25 +110,52 @@ public :
|
||||||
|
|
||||||
int main(int argc, const char** argv)
|
int main(int argc, const char** argv)
|
||||||
{
|
{
|
||||||
CommonOptionsParser OptionsParser(argc, argv, AnnotatorCategory);
|
// Parse the arguments and pass them to the the internal sub-tools
|
||||||
ClangTool bindingExtractor(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());
|
CommonOptionsParser optionsParser(argc, argv, annotatorCategory);
|
||||||
RefactoringTool annotator(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());
|
PathFilter bindingPathFilter
|
||||||
BindingCallback bindingCallback;
|
(optionsParser.getSourcePathList(), [](const std::string& path) { return path.find("API.cpp") != std::string::npos; });
|
||||||
|
PathFilter nonBindingPathFilter
|
||||||
|
(optionsParser.getSourcePathList(), [](const std::string& path) { return path.find("API.cpp") == std::string::npos; });
|
||||||
|
ClangTool bindingExtractor(optionsParser.getCompilations(), bindingPathFilter.GetPathList());
|
||||||
|
RefactoringTool annotator(optionsParser.getCompilations(), nonBindingPathFilter.GetPathList());
|
||||||
|
|
||||||
|
// Setup finder to match against AST nodes from existing AngelScript binding source files
|
||||||
|
ExtractCallback extractCallback;
|
||||||
MatchFinder bindingFinder;
|
MatchFinder bindingFinder;
|
||||||
|
// Find exposed class names (they are registered through RegisterObjectType(), RegisterRefCounted(), RegisterObject(), etc)
|
||||||
bindingFinder.addMatcher(
|
bindingFinder.addMatcher(
|
||||||
memberCallExpr(
|
memberCallExpr(
|
||||||
callee(
|
callee(
|
||||||
methodDecl(hasName("RegisterObjectType"))),
|
methodDecl(hasName("RegisterObjectType"))),
|
||||||
hasArgument(0, stringLiteral().bind("StringLiteral"))), &bindingCallback);
|
hasArgument(0, stringLiteral().bind("className"))), &extractCallback);
|
||||||
bindingFinder.addMatcher(
|
bindingFinder.addMatcher(
|
||||||
callExpr(
|
callExpr(
|
||||||
hasDeclaration(
|
hasDeclaration(
|
||||||
functionDecl(hasParameter(1, hasName("className")))),
|
functionDecl(hasParameter(1, hasName("className")))),
|
||||||
hasArgument(1, stringLiteral().bind("StringLiteral"))), &bindingCallback);
|
hasArgument(1, stringLiteral().bind("className"))), &extractCallback);
|
||||||
|
|
||||||
|
// Setup finder to match against AST nodes for annotating Urho3D library source files
|
||||||
|
AnnotateCallback annotateCallback;
|
||||||
MatchFinder annotateFinder;
|
MatchFinder annotateFinder;
|
||||||
|
// Find exported class declaration with Urho3D namespace
|
||||||
|
annotateFinder.addMatcher(
|
||||||
|
recordDecl(
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
hasAttr(attr::Visibility),
|
||||||
|
#else
|
||||||
|
hasAttr(attr::DLLExport),
|
||||||
|
#endif
|
||||||
|
matchesName("Urho3D::")).bind("className"), &annotateCallback);
|
||||||
|
|
||||||
|
// Unbuffered stdout stream to keep the Travis-CI's log flowing and thus prevent it from killing a potentially long running job
|
||||||
|
outs().SetUnbuffered();
|
||||||
|
|
||||||
|
// Success when both sub-tools are run successfully
|
||||||
return (outs() << "Extracting", true) &&
|
return (outs() << "Extracting", true) &&
|
||||||
bindingExtractor.run(newFrontendActionFactory(&bindingFinder).get()) == EXIT_SUCCESS &&
|
bindingExtractor.run(newFrontendActionFactory(&bindingFinder).get()) == EXIT_SUCCESS &&
|
||||||
(outs() << "\nAnnotating", true) &&
|
(outs() << "\nExtracted " << classNames_.size() << " bound class names\n"
|
||||||
|
<< "Annotating", true) &&
|
||||||
annotator.runAndSave(newFrontendActionFactory(&annotateFinder).get()) == EXIT_SUCCESS &&
|
annotator.runAndSave(newFrontendActionFactory(&annotateFinder).get()) == EXIT_SUCCESS &&
|
||||||
(outs() << "\n", true) ? EXIT_SUCCESS : EXIT_FAILURE;
|
(outs() << "\nAnnotated " << annotatedClassNames_.size() << " exported class names as non-scriptable\n", true) ?
|
||||||
|
EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,11 @@ list (APPEND LIBS ${LLVM_SYSLIBS})
|
||||||
add_subdirectory (Annotator)
|
add_subdirectory (Annotator)
|
||||||
|
|
||||||
# List of targets
|
# List of targets
|
||||||
|
add_custom_target (ast-query
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "Building AST for query, please be patient..."
|
||||||
|
COMMAND ${BINDIR}clang-query -p ${CMAKE_BINARY_DIR} $$option ${SOURCES}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/Source/Urho3D
|
||||||
|
COMMENT "Executing clang-query on Urho3D library source files")
|
||||||
add_custom_target (ast
|
add_custom_target (ast
|
||||||
COMMAND ${CMAKE_COMMAND} -E echo "Usage: option=-help make ast"
|
COMMAND ${CMAKE_COMMAND} -E echo "Usage: option=-help make ast"
|
||||||
COMMAND ${BINDIR}clang-check -p ${CMAKE_BINARY_DIR} $$option ${SOURCES}
|
COMMAND ${BINDIR}clang-check -p ${CMAKE_BINARY_DIR} $$option ${SOURCES}
|
||||||
|
|
|
@ -115,6 +115,11 @@ endif ()
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
set (PRE_EXPORT_HEADER "\n#pragma warning(disable: 4251)\n#pragma warning(disable: 4275)\n")
|
set (PRE_EXPORT_HEADER "\n#pragma warning(disable: 4251)\n#pragma warning(disable: 4275)\n")
|
||||||
endif ()
|
endif ()
|
||||||
|
if (URHO3D_CLANG_TOOLS)
|
||||||
|
set (POST_EXPORT_HEADER "\n#define NONSCRIPTABLE __attribute__((annotate(\"nonscriptable\")))\n")
|
||||||
|
else ()
|
||||||
|
set (POST_EXPORT_HEADER "\n#define NONSCRIPTABLE\n")
|
||||||
|
endif ()
|
||||||
generate_export_header (${TARGET_NAME} ${URHO3D_LIB_TYPE} EXPORT_MACRO_NAME URHO3D_API EXPORT_FILE_NAME Urho3D.h.new)
|
generate_export_header (${TARGET_NAME} ${URHO3D_LIB_TYPE} EXPORT_MACRO_NAME URHO3D_API EXPORT_FILE_NAME Urho3D.h.new)
|
||||||
execute_process (COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/Urho3D.h.new ${CMAKE_CURRENT_BINARY_DIR}/Urho3D.h)
|
execute_process (COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/Urho3D.h.new ${CMAKE_CURRENT_BINARY_DIR}/Urho3D.h)
|
||||||
file (REMOVE ${CMAKE_CURRENT_BINARY_DIR}/Urho3D.h.new)
|
file (REMOVE ${CMAKE_CURRENT_BINARY_DIR}/Urho3D.h.new)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче