Code cleanups and improvements (#1713)

* Code cleanups.

* Run GetterSetterToPropertyPass for more generators.

* Fixed compile warning when compiling parser bindings.

* Cleanup driver code.

* Remove dead 32-bit code.

* Reduce verbosity when Options.Quiet is set.

* Remove test compile-time warnings.

* Move .NET tests to tests/dotnet.

* Remove unused AST viewer code and premake-qt submodule.

* Move tests2/ contents to tests/.
This commit is contained in:
João Matos 2023-02-04 15:37:19 +00:00 коммит произвёл GitHub
Родитель 117567d61f
Коммит 4417dd987a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
160 изменённых файлов: 234 добавлений и 2618 удалений

3
.gitmodules поставляемый
Просмотреть файл

@ -1,3 +0,0 @@
[submodule "build/modules/premake-qt"]
path = build/modules/premake-qt
url = https://github.com/dcourtois/premake-qt.git

Просмотреть файл

@ -47,7 +47,7 @@ rootdir = path.getabsolute("../")
srcdir = path.join(rootdir, "src");
incdir = path.join(rootdir, "include");
examplesdir = path.join(rootdir, "examples");
testsdir = path.join(rootdir, "tests");
testsdir = path.join(rootdir, "tests/dotnet");
builddir = path.join(rootdir, "build")
bindir = path.join(rootdir, "bin")
objsdir = path.join(builddir, "obj");

@ -1 +0,0 @@
Subproject commit 0ddc49715c7892211774d4b5e705a7c5559aeed4

Просмотреть файл

@ -44,7 +44,7 @@ workspace "CppSharp"
workspacefiles(path.join(builddir, "premake5.lua"))
workspacefiles(path.join(builddir, "*.sh"))
workspacefiles(path.join(rootdir, ".github/workflows/*.yml"))
workspacefiles(path.join(rootdir, "tests/Test*.props"))
workspacefiles(path.join(testsdir, "Test*.props"))
group "Libraries"
if EnableNativeProjects() then

Просмотреть файл

@ -22,109 +22,62 @@ namespace CppSharp.AST
parameters.AddRange(property.Parameters);
}
public Type Type
{
get { return QualifiedType.Type; }
}
public Type Type => QualifiedType.Type;
public QualifiedType QualifiedType { get; set; }
public bool IsStatic
{
get
{
return (GetMethod != null && GetMethod.IsStatic) ||
(SetMethod != null && SetMethod.IsStatic);
}
}
public bool IsStatic =>
GetMethod is {IsStatic: true} ||
SetMethod is {IsStatic: true};
public bool IsPure
{
get
{
return (GetMethod != null && GetMethod.IsPure) ||
(SetMethod != null && SetMethod.IsPure);
}
}
public bool IsPure =>
GetMethod is {IsPure: true} ||
SetMethod is {IsPure: true};
public bool IsVirtual
{
get
{
return (GetMethod != null && GetMethod.IsVirtual) ||
(SetMethod != null && SetMethod.IsVirtual);
}
}
public bool IsVirtual =>
GetMethod is {IsVirtual: true} ||
SetMethod is {IsVirtual: true};
public bool IsOverride
{
get
{
return (GetMethod != null && GetMethod.IsOverride) ||
(SetMethod != null && SetMethod.IsOverride);
}
}
public bool IsOverride =>
GetMethod is {IsOverride: true} ||
SetMethod is {IsOverride: true};
public Method GetMethod { get; set; }
public Method SetMethod { get; set; }
public bool HasGetter
{
get
{
return (GetMethod != null &&
public bool HasGetter =>
(GetMethod != null &&
GetMethod.GenerationKind != GenerationKind.None) ||
(Field != null &&
Field.GenerationKind != GenerationKind.None);
}
}
public bool HasSetter
{
get
{
return (SetMethod != null &&
public bool HasSetter =>
(SetMethod != null &&
SetMethod.GenerationKind != GenerationKind.None) ||
(Field != null &&
(!Field.QualifiedType.IsConst() ||
Field.Type.IsConstCharString()) &&
Field.GenerationKind != GenerationKind.None);
}
}
// The field that should be get and set by this property
public Field Field { get; set; }
public Class ExplicitInterfaceImpl { get; set; }
private readonly List<Parameter> parameters = new List<Parameter>();
private readonly List<Parameter> parameters = new();
/// <summary>
/// Only applicable to index ([]) properties.
/// </summary>
public List<Parameter> Parameters
{
get { return parameters; }
}
public List<Parameter> Parameters => parameters;
public bool IsIndexer
{
get
{
return GetMethod != null &&
GetMethod.OperatorKind == CXXOperatorKind.Subscript;
}
}
public bool IsIndexer =>
GetMethod is {OperatorKind: CXXOperatorKind.Subscript};
public bool IsSynthetized
{
get
{
return (GetMethod != null && GetMethod.IsSynthetized) ||
public bool IsSynthetized =>
(GetMethod != null && GetMethod.IsSynthetized) ||
(SetMethod != null && SetMethod.IsSynthetized);
}
}
public override T Visit<T>(IDeclVisitor<T> visitor)
{

Просмотреть файл

@ -1,141 +0,0 @@
#include "AstModel.h"
#include <qbrush.h>
AstModel::AstModel(GenericAstNode *data, QObject *parent):
QAbstractItemModel(parent),
rootItem(data)
{
}
AstModel::~AstModel()
{
}
int AstModel::columnCount(const QModelIndex &parent) const
{
return 1;
}
QVariant AstModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole && role != Qt::ForegroundRole && role != Qt::NodeRole)
return QVariant();
auto item = static_cast<GenericAstNode*>(index.internalPointer());
switch (role)
{
case Qt::DisplayRole:
return QVariant(QString::fromStdString(item->name));
case Qt::ForegroundRole:
switch (item->getColor())
{
case 0:
return QVariant(QBrush(Qt::GlobalColor::darkBlue));
case 1:
return QVariant(QBrush(Qt::GlobalColor::darkGreen));
default:
return QVariant(QBrush(Qt::GlobalColor::black));
}
case Qt::NodeRole:
return QVariant::fromValue(item);
}
return QVariant(QString::fromStdString(item->name));
}
Qt::ItemFlags AstModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
return QAbstractItemModel::flags(index);
}
QVariant AstModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
return QVariant("Test");
return QVariant();
}
QModelIndex AstModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
if (!parent.isValid())
{
return rootIndex();
}
auto parentItem = static_cast<GenericAstNode*>(parent.internalPointer());
auto &childItem = parentItem->myChidren[row];
if (childItem)
return createIndex(row, column, childItem.get());
else
return QModelIndex();
}
QModelIndex AstModel::rootIndex() const
{
return createIndex(0, 0, rootItem);
}
QModelIndex AstModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
GenericAstNode *childItem = static_cast<GenericAstNode*>(index.internalPointer());
if (childItem == rootItem || childItem->myParent == nullptr)
return QModelIndex();
GenericAstNode *parentItem = childItem->myParent;
if (parentItem == rootItem)
return rootIndex();
auto grandFather = parentItem->myParent;
auto parentRow = grandFather == nullptr ?
0 :
grandFather->findChildIndex(parentItem);
return createIndex(parentRow, 0, parentItem);
}
int AstModel::rowCount(const QModelIndex &parent) const
{
GenericAstNode *parentItem;
if (parent.column() > 0)
return 0;
if (parent.isValid())
{
parentItem = static_cast<GenericAstNode*>(parent.internalPointer());
return parentItem->myChidren.size();
}
else
{
return 1;
}
}
bool AstModel::hasChildren(const QModelIndex &parent) const
{
GenericAstNode *parentItem;
if (parent.column() > 0)
return false;
if (parent.isValid())
parentItem = static_cast<GenericAstNode*>(parent.internalPointer());
else
parentItem = rootItem;
return !parentItem->myChidren.empty();
}

Просмотреть файл

@ -1,35 +0,0 @@
#pragma once
#include <qabstractitemmodel.h>
#include "AstReader.h"
namespace Qt
{
int const NodeRole = UserRole + 1;
}
Q_DECLARE_METATYPE(GenericAstNode*)
class AstModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit AstModel(GenericAstNode *data, QObject *parent = 0);
~AstModel();
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QModelIndex rootIndex() const;
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
private:
void setupModelData(const QStringList &lines, GenericAstNode *parent);
GenericAstNode *rootItem;
};

Просмотреть файл

@ -1,543 +0,0 @@
#include "AstReader.h"
#include <sstream>
#include "CommandLineSplitter.h"
#include <iostream>
#include "ClangUtilities/StringLiteralExtractor.h"
#include "ClangUtilities/TemplateUtilities.h"
#pragma warning (push)
#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996)
#include <llvm/Support/Path.h>
#include <clang/Tooling/Tooling.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/AST/Decl.h>
#include <clang/Lex/Lexer.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/AST/Mangle.h>
#include <clang/Analysis/CFG.h>
#pragma warning (pop)
using namespace clang;
namespace props
{
std::string const Name = "Name";
std::string const Mangling = "Mangling";
std::string const Referenced = "Referenced name";
std::string const Resolved = "Resolved name";
std::string const Value = "Value";
std::string const InterpretedValue = "Interpreted value";
std::string const IsTemplateDecl = "Is template declaration";
std::string const IsGenerated = "Generated";
std::string const Type = "Type";
}
CFG::BuildOptions getCFGBuildOptions()
{
CFG::BuildOptions cfgBuildOptions; // TODO: Initialize it correctly
cfgBuildOptions.AddImplicitDtors = true;
cfgBuildOptions.AddTemporaryDtors = true;
cfgBuildOptions.AddCXXDefaultInitExprInCtors = true;
cfgBuildOptions.AddInitializers = true;
return cfgBuildOptions;
}
std::string getCFG(clang::FunctionDecl const *FD)
{
try
{
auto& astContext = FD->getASTContext();
auto cfgBuildOptions = getCFGBuildOptions();
auto cfg = CFG::buildCFG(FD, FD->getBody(), &astContext, cfgBuildOptions);
if (!cfg)
return "";
std::string dumpBuf;
llvm::raw_string_ostream dumpBufOS(dumpBuf);
cfg->print(dumpBufOS, astContext.getLangOpts(), false);
auto dumped = dumpBufOS.str();
return dumped;
}
catch (std::exception &e)
{
return std::string("<Error: ") + e.what() + ">";
}
}
GenericAstNode::GenericAstNode() :
myParent(nullptr), hasDetails(false)
{
}
int GenericAstNode::findChildIndex(GenericAstNode *node)
{
auto it = std::find_if(myChidren.begin(), myChidren.end(), [node](std::unique_ptr<GenericAstNode> const & n){return n.get() == node; });
return it == myChidren.end() ?
-1 :
it - myChidren.begin();
}
void GenericAstNode::attach(std::unique_ptr<GenericAstNode> child)
{
child->myParent = this;
myChidren.push_back(std::move(child));
}
//struct SourceRangeVisitor : boost::static_visitor<SourceRange>
//{
// template<class T>
// SourceRange operator()(T const *t) const
// {
// if (t == nullptr)
// return SourceRange();
// return t->getSourceRange();
// }
//};
SourceRange GenericAstNode::getRange()
{
//return boost::apply_visitor(SourceRangeVisitor(), myAstNode);
return SourceRange();
}
bool GenericAstNode::getRangeInMainFile(std::pair<int, int> &result, clang::SourceManager const &manager, clang::ASTContext &context)
{
auto range = getRange();
if (range.isInvalid())
{
return false;
}
auto start = manager.getDecomposedSpellingLoc(range.getBegin());
auto end = manager.getDecomposedSpellingLoc(clang::Lexer::getLocForEndOfToken(range.getEnd(), 0, manager, context.getLangOpts()));
if (start.first != end.first || start.first != manager.getMainFileID())
{
//Not in the same file, or not in the main file (probably #included)
return false;
}
result = std::make_pair(start.second, end.second);
return true;
}
//struct NodeColorVisitor : boost::static_visitor<int>
//{
// int operator()(Decl const *) const
// {
// return 0;
// }
// int operator()(Stmt const *) const
// {
// return 1;
// }
//};
int GenericAstNode::getColor()
{
//return boost::apply_visitor(NodeColorVisitor(), myAstNode);
return 0;
}
void GenericAstNode::setProperty(std::string const &propertyName, std::string const &value)
{
myProperties[propertyName] = value;
}
GenericAstNode::Properties const &GenericAstNode::getProperties() const
{
return myProperties;
}
class AstDumpVisitor : public RecursiveASTVisitor<AstDumpVisitor>
{
public:
using PARENT = clang::RecursiveASTVisitor<AstDumpVisitor>;
AstDumpVisitor(clang::ASTContext &context, GenericAstNode *rootNode) :
myRootNode(rootNode),
myAstContext(context)
{
myStack.push_back(myRootNode);
}
bool shouldVisitTemplateInstantiations() const
{
return true;
}
bool shouldVisitImplicitCode() const
{
return true;
}
std::string getMangling(clang::NamedDecl const *ND)
{
if (auto funcContext = dyn_cast<FunctionDecl>(ND->getDeclContext()))
{
if (funcContext->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
{
return "<Cannot mangle template name>";
}
}
std::vector<TagDecl const *> containers;
auto currentElement = dyn_cast<TagDecl>(ND->getDeclContext());
while (currentElement)
{
containers.push_back(currentElement);
currentElement = dyn_cast<TagDecl>(currentElement->getDeclContext());
}
for (auto tag : containers)
{
if (auto partialSpe = dyn_cast<ClassTemplatePartialSpecializationDecl>(tag))
{
return "<Inside partial specialization " + tag->getNameAsString() + ": " + ND->getNameAsString() + ">";
}
else if (auto recContext = dyn_cast<CXXRecordDecl>(tag))
{
if (recContext->getDescribedClassTemplate() != nullptr)
{
return "<Inside a template" + tag->getNameAsString() + ": " + ND->getNameAsString() + ">";
}
}
}
auto mangleContext = std::unique_ptr<clang::MangleContext>{ND->getASTContext().createMangleContext()};
std::string FrontendBuf;
llvm::raw_string_ostream FrontendBufOS(FrontendBuf);
if (auto ctor = dyn_cast<CXXConstructorDecl>(ND))
{
mangleContext->mangleCXXCtor(ctor, CXXCtorType::Ctor_Complete, FrontendBufOS);
}
else if (auto dtor = dyn_cast<CXXDestructorDecl>(ND))
{
mangleContext->mangleCXXDtor(dtor, CXXDtorType::Dtor_Complete, FrontendBufOS);
}
else if (mangleContext->shouldMangleDeclName(ND) && !isa<ParmVarDecl>(ND))
{
mangleContext->mangleName(ND, FrontendBufOS);
}
else
{
return ND->getNameAsString();
}
return FrontendBufOS.str();
}
bool TraverseDecl(clang::Decl *decl)
{
if (decl == nullptr)
{
return PARENT::TraverseDecl(decl);
}
auto node = std::make_unique<GenericAstNode>();
node->myAstNode = decl;
node->name = decl->getDeclKindName() + std::string("Decl"); // Try to mimick clang default dump
if (auto *FD = dyn_cast<FunctionDecl>(decl))
{
#ifndef NDEBUG
auto &mngr = FD->getASTContext().getSourceManager();
auto fileName = mngr.getFilename(FD->getLocation()).str();
bool invalid;
auto startingLine = mngr.getExpansionLineNumber(FD->getLocation(), &invalid);
std::string FrontendBuf;
llvm::raw_string_ostream FrontendBufOS(FrontendBuf);
clang::PrintingPolicy policyForDebug(FD->getASTContext().getLangOpts());
FD->getNameForDiagnostic(FrontendBufOS, policyForDebug, true);
auto debugName = FrontendBufOS.str();
RecordDecl const*containingClass = nullptr;
if (FD->isCXXClassMember())
{
auto methodDecl = cast<CXXMethodDecl>(FD);
containingClass = cast<RecordDecl>(methodDecl->getDeclContext());
}
#endif
node->name += " " + clang_utilities::getFunctionPrototype(FD, false);
if (FD->getTemplatedKind() != FunctionDecl::TK_FunctionTemplate)
{
node->setProperty(props::Mangling, getMangling(FD));
}
node->setProperty(props::Name, clang_utilities::getFunctionPrototype(FD, true));
if (auto *MD = dyn_cast<CXXMethodDecl>(FD))
{
node->setProperty(props::IsGenerated, MD->isUserProvided() ? "False" : "True");
}
node->hasDetails = true;
node->detailsTitle = "Control flow graph";
node->detailsComputer = [FD]() {return getCFG(FD); };
}
else if (auto *PVD = dyn_cast<ParmVarDecl>(decl))
{
if (auto *PFD = dyn_cast_or_null<FunctionDecl>(decl->getParentFunctionOrMethod()))
{
if (PFD->getTemplatedKind() != FunctionDecl::TK_FunctionTemplate)
{
node->setProperty(props::Mangling, getMangling(PFD));
}
}
else
{
node->setProperty(props::Mangling, getMangling(PVD));
}
node->setProperty(props::Name, PVD->getNameAsString());
}
else if (auto *VD = dyn_cast<VarDecl>(decl))
{
//node->setProperty(props::Mangling, getMangling(VD));
node->setProperty(props::Name, VD->getNameAsString());
node->setProperty(props::Type, clang_utilities::getTypeName(VD->getType(), true));
}
else if (auto *ECD = dyn_cast<EnumConstantDecl>(decl))
{
node->setProperty(props::Name, ECD->getNameAsString());
node->setProperty(props::Value, ECD->getInitVal().toString(10));
}
else if (auto *tag = dyn_cast<TagDecl>(decl))
{
std::string nameBuf;
llvm::raw_string_ostream os(nameBuf);
if (TypedefNameDecl *Typedef = tag->getTypedefNameForAnonDecl())
os << Typedef->getIdentifier()->getName();
else if (tag->getIdentifier())
os << tag->getIdentifier()->getName();
else
os << "No name";
if (auto templateInstance = dyn_cast<ClassTemplateSpecializationDecl>(tag))
{
clang::PrintingPolicy policy(templateInstance->getASTContext().getLangOpts());
clang_utilities::printTemplateArguments(os, policy, &templateInstance->getTemplateArgs(), false);
}
node->name += " " + tag->getNameAsString();
node->setProperty(props::Name, os.str());
}
else if (auto *ND = dyn_cast<NamedDecl>(decl))
{
node->name += " " + ND->getNameAsString();
node->setProperty(props::Name, ND->getNameAsString());
}
auto nodePtr = node.get();
myStack.back()->attach(std::move(node));
myStack.push_back(nodePtr);
auto res = PARENT::TraverseDecl(decl);
myStack.pop_back();
return res;
}
bool TraverseStmt(clang::Stmt *stmt)
{
if (stmt == nullptr)
{
return PARENT::TraverseStmt(stmt);
}
auto node = std::make_unique<GenericAstNode>();
node->myAstNode = stmt;
node->name = stmt->getStmtClassName();
auto nodePtr = node.get();
myStack.back()->attach(std::move(node));
myStack.push_back(nodePtr);
auto res = PARENT::TraverseStmt(stmt);
myStack.pop_back();
return res;
}
bool VisitStringLiteral(clang::StringLiteral *s)
{
myStack.back()->name += (" " + s->getBytes()).str();
myStack.back()->setProperty(props::InterpretedValue, s->getBytes());
auto parts = clang_utilities::splitStringLiteral(s, myAstContext.getSourceManager(), myAstContext.getLangOpts(), myAstContext.getTargetInfo());
if (parts.size() == 1)
{
myStack.back()->setProperty(props::Value, parts[0]);
}
else
{
int i = 0;
for (auto &part : parts)
{
++i;
myStack.back()->setProperty(props::Value + " " + std::to_string(i), part);
}
}
return true;
}
bool VisitIntegerLiteral(clang::IntegerLiteral *i)
{
bool isSigned = i->getType()->isSignedIntegerType();
myStack.back()->setProperty(props::Value, i->getValue().toString(10, isSigned));
return true;
}
bool VisitCharacterLiteral(clang::CharacterLiteral *c)
{
myStack.back()->setProperty(props::Value, std::string(1, c->getValue()));
return true;
}
bool VisitFloatingLiteral(clang::FloatingLiteral *f)
{
myStack.back()->setProperty(props::Value, std::to_string(f->getValueAsApproximateDouble()));
return true;
}
bool VisitCXXRecordDecl(clang::CXXRecordDecl *r)
{
myStack.back()->setProperty(props::IsTemplateDecl, std::to_string(r->getDescribedClassTemplate() != nullptr));
return true;
}
void addReference(GenericAstNode *node, clang::NamedDecl *referenced, std::string const &label)
{
auto funcDecl = dyn_cast<FunctionDecl>(referenced);
myStack.back()->setProperty(label, funcDecl == nullptr ?
referenced->getNameAsString() :
clang_utilities::getFunctionPrototype(funcDecl, false));
}
bool VisitDeclRefExpr(clang::DeclRefExpr *ref)
{
addReference(myStack.back(), ref->getDecl(), props::Referenced);
addReference(myStack.back(), ref->getFoundDecl(), props::Resolved);
return true;
}
bool TraverseType(clang::QualType type)
{
if (type.isNull())
{
return PARENT::TraverseType(type);
}
auto node = std::make_unique<GenericAstNode>();
//node->myType = d;
node->name = type->getTypeClassName();
auto nodePtr = node.get();
myStack.back()->attach(std::move(node));
myStack.push_back(nodePtr);
auto res = PARENT::TraverseType(type);
myStack.pop_back();
return res;
}
private:
std::vector<GenericAstNode*> myStack;
GenericAstNode *myRootNode;
ASTContext &myAstContext;
};
AstReader::AstReader() : isReady(false)
{
}
clang::SourceManager &AstReader::getManager()
{
return myAst->getSourceManager();
}
clang::ASTContext &AstReader::getContext()
{
return myAst->getASTContext();
}
GenericAstNode *AstReader::getRealRoot()
{
return myArtificialRoot->myChidren.front().get();
}
GenericAstNode *AstReader::findPosInChildren(std::vector<std::unique_ptr<GenericAstNode>> const &candidates, int position)
{
for (auto &candidate : candidates)
{
std::pair<int, int> location;
if (!candidate->getRangeInMainFile(location, getManager(), getContext()))
{
continue;
}
if (location.first <= position && position <= location.second)
{
return candidate.get();
}
}
return nullptr;
}
std::vector<GenericAstNode *> AstReader::getBestNodeMatchingPosition(int position)
{
std::vector<GenericAstNode *> result;
auto currentNode = getRealRoot();
result.push_back(currentNode);
currentNode = currentNode->myChidren[0].get();
result.push_back(currentNode); // Translation unit does not have position
while (true)
{
auto bestChild = findPosInChildren(currentNode->myChidren, position);
if (bestChild == nullptr)
{
return result;
}
result.push_back(bestChild);
currentNode = bestChild;
}
}
GenericAstNode *AstReader::readAst(std::string const &sourceCode, std::string const &options)
{
mySourceCode = sourceCode;
myArtificialRoot = std::make_unique<GenericAstNode>();
auto root = std::make_unique<GenericAstNode>();
root->name = "AST";
myArtificialRoot->attach(std::move(root));
auto args = splitCommandLine(options);
std::cout << "Launching Clang to create AST" << std::endl;
//myAst = clang::tooling::buildASTFromCodeWithArgs(mySourceCode, args);
myAst = nullptr;
if (myAst != nullptr)
{
for (auto it = myAst->top_level_begin(); it != myAst->top_level_end(); ++it)
{
//(*it)->dumpColor();
}
std::cout << "Visiting AST and creating Qt Tree" << std::endl;
auto visitor = AstDumpVisitor{ myAst->getASTContext(), getRealRoot() };
visitor.TraverseDecl(myAst->getASTContext().getTranslationUnitDecl());
}
isReady = true;
return myArtificialRoot.get();
}
bool AstReader::ready()
{
return isReady;
}
void AstReader::dirty()
{
isReady = false;
}

Просмотреть файл

@ -1,60 +0,0 @@
#pragma once
#pragma warning (push)
#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996)
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "clang/Basic/SourceLocation.h"
#pragma warning(pop)
#include <string>
#include <variant>
class GenericAstNode
{
public:
GenericAstNode();
int findChildIndex(GenericAstNode *node); // Return -1 if not found
void attach(std::unique_ptr<GenericAstNode> child);
std::string name;
std::vector<std::unique_ptr<GenericAstNode>> myChidren;
bool getRangeInMainFile(std::pair<int, int> &result, clang::SourceManager const &manager, clang::ASTContext &context); // Return false if the range is not fully in the main file
clang::SourceRange getRange();
int getColor(); // Will return a color identifier How this is linked to the real color is up to the user
using Properties = std::map<std::string, std::string>;
void setProperty(std::string const &propertyName, std::string const &value);
Properties const &getProperties() const;
std::variant<clang::Decl *, clang::Stmt *> myAstNode;
GenericAstNode *myParent;
bool hasDetails;
std::string detailsTitle;
std::string details;
std::function<std::string()> detailsComputer;
private:
Properties myProperties;
};
class AstReader
{
public:
AstReader();
GenericAstNode *readAst(std::string const &sourceCode, std::string const &options);
clang::SourceManager &getManager();
clang::ASTContext &getContext();
GenericAstNode *getRealRoot();
std::vector<GenericAstNode *> getBestNodeMatchingPosition(int position); // Return the path from root to the node
bool ready();
void dirty(); // Ready will be false until the reader is run again
private:
GenericAstNode *findPosInChildren(std::vector<std::unique_ptr<GenericAstNode>> const &candidates, int position);
std::string args;
std::string mySourceCode; // Needs to stay alive while we navigate the tree
std::unique_ptr<clang::ASTUnit> myAst;
std::unique_ptr<GenericAstNode> myArtificialRoot; // We need an artificial root on top of the real root, because the root is not displayed by Qt
bool isReady;
};

Просмотреть файл

@ -1,304 +0,0 @@
#include "StringLiteralExtractor.h"
#pragma warning (push)
#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996 4146)
#include <clang/AST/Expr.h>
#include <clang/Lex/Lexer.h>
#include <clang/Lex/LiteralSupport.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Basic/SourceLocation.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/CharInfo.h>
#include <llvm/ADT/StringExtras.h>
#include <llvm/Support/ConvertUTF.h>
#pragma warning (pop)
using namespace llvm;
using namespace clang;
namespace clang_utilities {
// This function is an direct adaptation from ProcessCharEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part)
unsigned ProcessCharEscape(const char *ThisTokBegin,
const char *&ThisTokBuf,
const char *ThisTokEnd, bool &HadError,
FullSourceLoc Loc, unsigned CharWidth,
const LangOptions &Features)
{
// Skip the '\' char.
++ThisTokBuf;
// We know that this character can't be off the end of the buffer, because
// that would have been \", which would not have been the end of string.
unsigned ResultChar = *ThisTokBuf++;
switch (ResultChar) {
// These map to themselves.
case '\\': case '\'': case '"': case '?': break;
// These have fixed mappings.
case 'a':
// TODO: K&R: the meaning of '\\a' is different in traditional C
ResultChar = 7;
break;
case 'b':
ResultChar = 8;
break;
case 'e':
ResultChar = 27;
break;
case 'E':
ResultChar = 27;
break;
case 'f':
ResultChar = 12;
break;
case 'n':
ResultChar = 10;
break;
case 'r':
ResultChar = 13;
break;
case 't':
ResultChar = 9;
break;
case 'v':
ResultChar = 11;
break;
case 'x': { // Hex escape.
ResultChar = 0;
if (ThisTokBuf == ThisTokEnd || !isHexDigit(*ThisTokBuf)) {
HadError = 1;
break;
}
// Hex escapes are a maximal series of hex digits.
bool Overflow = false;
for (; ThisTokBuf != ThisTokEnd; ++ThisTokBuf) {
int CharVal = llvm::hexDigitValue(ThisTokBuf[0]);
if (CharVal == -1) break;
// About to shift out a digit?
if (ResultChar & 0xF0000000)
Overflow = true;
ResultChar <<= 4;
ResultChar |= CharVal;
}
// See if any bits will be truncated when evaluated as a character.
if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) {
Overflow = true;
ResultChar &= ~0U >> (32 - CharWidth);
}
// Check for overflow.
break;
}
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7': {
// Octal escapes.
--ThisTokBuf;
ResultChar = 0;
// Octal escapes are a series of octal digits with maximum length 3.
// "\0123" is a two digit sequence equal to "\012" "3".
unsigned NumDigits = 0;
do {
ResultChar <<= 3;
ResultChar |= *ThisTokBuf++ - '0';
++NumDigits;
} while (ThisTokBuf != ThisTokEnd && NumDigits < 3 &&
ThisTokBuf[0] >= '0' && ThisTokBuf[0] <= '7');
// Check for overflow. Reject '\777', but not L'\777'.
if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) {
ResultChar &= ~0U >> (32 - CharWidth);
}
break;
}
// Otherwise, these are not valid escapes.
case '(': case '{': case '[': case '%':
// GCC accepts these as extensions. We warn about them as such though.
break;
default:
break;
}
return ResultChar;
}
// This function is an direct adaptation from ProcessUCNEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part)
bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
const char *ThisTokEnd,
uint32_t &UcnVal, unsigned short &UcnLen,
FullSourceLoc Loc,
const LangOptions &Features,
bool in_char_string_literal) {
const char *UcnBegin = ThisTokBuf;
// Skip the '\u' char's.
ThisTokBuf += 2;
if (ThisTokBuf == ThisTokEnd || !isHexDigit(*ThisTokBuf)) {
return false;
}
UcnLen = (ThisTokBuf[-1] == 'u' ? 4 : 8);
unsigned short UcnLenSave = UcnLen;
for (; ThisTokBuf != ThisTokEnd && UcnLenSave; ++ThisTokBuf, UcnLenSave--) {
int CharVal = llvm::hexDigitValue(ThisTokBuf[0]);
if (CharVal == -1) break;
UcnVal <<= 4;
UcnVal |= CharVal;
}
// If we didn't consume the proper number of digits, there is a problem.
if (UcnLenSave) {
return false;
}
// Check UCN constraints (C99 6.4.3p2) [C++11 lex.charset p2]
if ((0xD800 <= UcnVal && UcnVal <= 0xDFFF) || // surrogate codepoints
UcnVal > 0x10FFFF) { // maximum legal UTF32 value
return false;
}
// C++11 allows UCNs that refer to control characters and basic source
// characters inside character and string literals
if (UcnVal < 0xa0 &&
(UcnVal != 0x24 && UcnVal != 0x40 && UcnVal != 0x60)) { // $, @, `
bool IsError = (!Features.CPlusPlus11 || !in_char_string_literal);
if (IsError)
return false;
}
return true;
}
// This function is an direct adaptation from ProcessUCNEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part)
int MeasureUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
const char *ThisTokEnd, unsigned CharByteWidth,
const LangOptions &Features, bool &HadError) {
// UTF-32: 4 bytes per escape.
if (CharByteWidth == 4)
return 4;
uint32_t UcnVal = 0;
unsigned short UcnLen = 0;
FullSourceLoc Loc;
if (!ProcessUCNEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, UcnVal,
UcnLen, Loc, Features, true)) {
HadError = true;
return 0;
}
// UTF-16: 2 bytes for BMP, 4 bytes otherwise.
if (CharByteWidth == 2)
return UcnVal <= 0xFFFF ? 2 : 4;
// UTF-8.
if (UcnVal < 0x80)
return 1;
if (UcnVal < 0x800)
return 2;
if (UcnVal < 0x10000)
return 3;
return 4;
}
// This function is just the same as convertUTF16ToUTF8String, but adapted to UTF32, since it did not exist in clang
bool convertUTF32ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) {
assert(Out.empty());
// Error out on an uneven byte count.
if (SrcBytes.size() % 4)
return false;
// Avoid OOB by returning early on empty input.
if (SrcBytes.empty())
return true;
const UTF32 *Src = reinterpret_cast<const UTF32 *>(SrcBytes.begin());
const UTF32 *SrcEnd = reinterpret_cast<const UTF32 *>(SrcBytes.end());
// Byteswap if necessary.
// Ignore any potential BOM: We won't have the here...
// Just allocate enough space up front. We'll shrink it later. Allocate
// enough that we can fit a null terminator without reallocating.
Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1);
UTF8 *Dst = reinterpret_cast<UTF8 *>(&Out[0]);
UTF8 *DstEnd = Dst + Out.size();
ConversionResult CR =
ConvertUTF32toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
assert(CR != targetExhausted);
if (CR != conversionOK) {
Out.clear();
return false;
}
Out.resize(reinterpret_cast<char *>(Dst)-&Out[0]);
Out.push_back(0);
Out.pop_back();
return true;
}
// This function is an adaptation from StringLiteral::getLocationOfByte in llvm-3.7.1\src\tools\clang\lib\AST\Expr.cpp
std::vector<std::string>
splitStringLiteral(clang::StringLiteral *S, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target)
{
// Loop over all of the tokens in this string until we find the one that
// contains the byte we're looking for.
unsigned TokNo = 0;
std::vector<std::string> result;
for (TokNo = 0; TokNo < S->getNumConcatenated(); ++TokNo)
{
SourceLocation StrTokLoc = S->getStrTokenLoc(TokNo);
// Get the spelling of the string so that we can get the data that makes up
// the string literal, not the identifier for the macro it is potentially
// expanded through.
SourceLocation StrTokSpellingLoc = SM.getSpellingLoc(StrTokLoc);
// Re-lex the token to get its length and original spelling.
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(StrTokSpellingLoc);
bool Invalid = false;
StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid);
if (Invalid)
continue; // We ignore this part
const char *StrData = Buffer.data() + LocInfo.second;
// Create a lexer starting at the beginning of this token.
Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), Features,
Buffer.begin(), StrData, Buffer.end());
Token TheTok;
TheLexer.LexFromRawLexer(TheTok);
if (TheTok.isAnyIdentifier())
{
// It should not be, since we are parsing inside a string literal, but it can happen with special macros such as __func__
// of __PRETTY_FUNCTION__ that are not resolved at this time. In that case, we just ignore them...
continue;
}
// Get the spelling of the token.
SmallString<32> SpellingBuffer;
SpellingBuffer.resize(TheTok.getLength());
bool StringInvalid = false;
const char *SpellingPtr = &SpellingBuffer[0];
unsigned TokLen = Lexer::getSpelling(TheTok, SpellingPtr, SM, Features, &StringInvalid);
if (StringInvalid)
continue;
const char *SpellingStart = SpellingPtr;
const char *SpellingEnd = SpellingPtr + TokLen;
result.push_back(std::string(SpellingStart, SpellingEnd));
}
return result;
}
} // namespace clang_utilities

Просмотреть файл

@ -1,46 +0,0 @@
#pragma once
#include <vector>
#include <string>
#pragma warning (push)
#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996 4146)
#include <clang/AST/Decl.h>
#include <clang/Lex/Lexer.h>
#include <clang/Frontend/FrontendActions.h>
#include <llvm/ADT/ArrayRef.h>
#include <clang/Basic/LangOptions.h>
#pragma warning (pop)
namespace clang_utilities {
// This function is an direct adaptation from ProcessCharEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part)
unsigned ProcessCharEscape(const char *ThisTokBegin,
const char *&ThisTokBuf,
const char *ThisTokEnd, bool &HadError,
clang::FullSourceLoc Loc, unsigned CharWidth,
const clang::LangOptions &Features);
// This function is an direct adaptation from ProcessUCNEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part)
bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
const char *ThisTokEnd,
uint32_t &UcnVal, unsigned short &UcnLen,
clang::FullSourceLoc Loc,
const clang::LangOptions &Features,
bool in_char_string_literal = false);
// This function is an direct adaptation from ProcessUCNEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part)
int MeasureUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf,
const char *ThisTokEnd, unsigned CharByteWidth,
const clang::LangOptions &Features, bool &HadError);
bool convertUTF32ToUTF8String(llvm::ArrayRef<char> SrcBytes, std::string &Out);
std::vector<std::string>
splitStringLiteral(clang::StringLiteral *S, const clang::SourceManager &SM, const clang::LangOptions &Features, const clang::TargetInfo &Target);
} // namespace clang_utilities

Просмотреть файл

@ -1,287 +0,0 @@
#include "TemplateUtilities.h"
#pragma warning (push)
#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996)
#include <clang/Tooling/Tooling.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/AST/Decl.h>
#include <clang/Lex/Lexer.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/AST/Mangle.h>
#pragma warning (pop)
using namespace clang;
namespace clang_utilities {
void printDeclType(raw_ostream &out, PrintingPolicy const &policy, QualType T, StringRef DeclName, bool Pack) {
// Normally, a PackExpansionType is written as T[3]... (for instance, as a
// template argument), but if it is the type of a declaration, the ellipsis
// is placed before the name being declared.
if (auto *PET = T->getAs<PackExpansionType>()) {
Pack = true;
T = PET->getPattern();
}
T.print(out, policy, (Pack ? "..." : "") + DeclName);
}
void printTemplateParameters(raw_ostream &out, PrintingPolicy const &policy, TemplateParameterList const *params)
{
if (params == nullptr)
{
return;
}
out << "<";
for (unsigned i = 0, e = params->size(); i != e; ++i) {
if (i != 0)
out << ", ";
auto param = params->getParam(i);
printTemplateParameter(out, policy, param);
}
out << ">";
}
// Adapted from tools\clang\lib\AST\DeclPrinter.cpp DeclPrinter::PrintTemplateParameters
void printTemplateParameter(raw_ostream &out, PrintingPolicy const &policy, NamedDecl const *param)
{
if (const TemplateTypeParmDecl *TTP =
dyn_cast<TemplateTypeParmDecl>(param)) {
if (TTP->wasDeclaredWithTypename())
out << "typename ";
else
out << "class ";
if (TTP->isParameterPack())
out << "...";
out << *TTP;
if (TTP->hasDefaultArgument()) {
out << " = ";
out << TTP->getDefaultArgument().getAsString(policy);
};
}
else if (const NonTypeTemplateParmDecl *NTTP =
dyn_cast<NonTypeTemplateParmDecl>(param)) {
StringRef Name;
if (IdentifierInfo *II = NTTP->getIdentifier())
Name = II->getName();
printDeclType(out, policy, NTTP->getType(), Name, NTTP->isParameterPack());
if (NTTP->hasDefaultArgument()) {
out << " = ";
NTTP->getDefaultArgument()->printPretty(out, nullptr, policy, 0);
}
}
else if (const TemplateTemplateParmDecl *TTPD =
dyn_cast<TemplateTemplateParmDecl>(param)) {
out << "template";
printTemplateParameters(out, policy, TTPD->getTemplateParameters());
out << " class " << TTPD->getNameAsString();
//VisitTemplateDecl(TTPD);
// FIXME: print the default argument, if present.
}
}
static void printIntegral(const TemplateArgument &TemplArg,
raw_ostream &out, const PrintingPolicy& policy) {
const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
const llvm::APSInt &Val = TemplArg.getAsIntegral();
if (const EnumType *ET = T->getAs<EnumType>()) {
for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) {
// In Sema::CheckTemplateArugment, enum template arguments value are
// extended to the size of the integer underlying the enum type. This
// may create a size difference between the enum value and template
// argument value, requiring isSameValue here instead of operator==.
if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) {
ECD->printQualifiedName(out, policy);
return;
}
}
}
if (T->isBooleanType()) {
out << (Val.getBoolValue() ? "true" : "false");
}
else if (T->isCharType()) {
const char Ch = Val.getZExtValue();
out << ((Ch == '\'') ? "'\\" : "'");
out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
out << "'";
}
else {
out << Val;
}
}
void printTemplateName(raw_ostream &OS, const PrintingPolicy &policy, TemplateName const &name, bool qualifyNames = false)
{
if (auto Template = name.getAsTemplateDecl())
OS << (qualifyNames ? Template->getQualifiedNameAsString() : Template->getNameAsString());
else if (auto QTN = name.getAsQualifiedTemplateName()) {
OS << (qualifyNames ? QTN->getDecl()->getQualifiedNameAsString() : QTN->getDecl()->getNameAsString());
}
else if (auto DTN = name.getAsDependentTemplateName()) {
if (qualifyNames && DTN->getQualifier())
DTN->getQualifier()->print(OS, policy);
OS << "template ";
if (DTN->isIdentifier())
OS << DTN->getIdentifier()->getName();
else
OS << "operator " << getOperatorSpelling(DTN->getOperator());
}
else if (auto subst = name.getAsSubstTemplateTemplateParm()) {
subst->getReplacement().print(OS, policy, !qualifyNames);
}
else if (auto SubstPack = name.getAsSubstTemplateTemplateParmPack())
OS << *SubstPack->getParameterPack();
else {
auto OTS = name.getAsOverloadedTemplate();
(*OTS->begin())->printName(OS);
}
}
// Adapted from tools\clang\lib\AST\TemplateBase.cpp TemplateArgument::print
void printTemplateArgument(raw_ostream &out, const PrintingPolicy &policy, TemplateArgument const &arg, bool qualifyNames)
{
switch (arg.getKind()) {
case TemplateArgument::Null:
out << "(no value)";
break;
case TemplateArgument::Type: {
PrintingPolicy SubPolicy(policy);
SubPolicy.SuppressStrongLifetime = true;
arg.getAsType().print(out, SubPolicy);
break;
}
case TemplateArgument::Declaration: {
NamedDecl *ND = cast<NamedDecl>(arg.getAsDecl());
out << '&';
if (ND->getDeclName()) {
// FIXME: distinguish between pointer and reference args?
ND->printQualifiedName(out);
}
else {
out << "(anonymous)";
}
break;
}
case TemplateArgument::NullPtr:
out << "nullptr";
break;
case TemplateArgument::Template:
// Orig: arg.getAsTemplate().print(out, policy);
{
auto templateName = arg.getAsTemplate();
printTemplateName(out, policy, templateName, qualifyNames);
break;
}
case TemplateArgument::TemplateExpansion:
arg.getAsTemplateOrTemplatePattern().print(out, policy);
out << "...";
break;
case TemplateArgument::Integral: {
printIntegral(arg, out, policy);
break;
}
case TemplateArgument::Expression:
arg.getAsExpr()->printPretty(out, nullptr, policy);
break;
case TemplateArgument::Pack:
out << "<";
bool First = true;
for (const auto &P : arg.pack_elements()) {
if (First)
First = false;
else
out << ", ";
P.print(policy, out);
}
out << ">";
break;
}
}
void printTemplateArguments(raw_ostream &out, const PrintingPolicy &policy, TemplateArgumentList const *args, bool qualifyNames)
{
if (args == nullptr)
{
return;
}
out << "<";
for (unsigned i = 0, e = args->size(); i != e; ++i) {
if (i != 0)
out << ", ";
auto arg = args->get(i);
printTemplateArgument(out, policy, arg, qualifyNames);
}
out << ">";
}
std::string getTypeName(QualType qualType, bool qualifyNames)
{
auto langOptions = clang::LangOptions{};
auto printPolicy = PrintingPolicy{ langOptions };
printPolicy.SuppressSpecifiers = false;
printPolicy.ConstantArraySizeAsWritten = false;
return qualType.getAsString(printPolicy);
}
std::string getFunctionPrototype(FunctionDecl *f, bool qualifyNames)
{
std::string prototypeBuf;
llvm::raw_string_ostream os(prototypeBuf);
PrintingPolicy policy(f->getASTContext().getLangOpts());
policy.TerseOutput = false;
os << getTypeName(f->getReturnType(), qualifyNames) << ' ' << f->getNameAsString();
if (f->getTemplatedKind() == FunctionDecl::TK_FunctionTemplateSpecialization ||
// f->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
f->getTemplatedKind() == FunctionDecl::TK_DependentFunctionTemplateSpecialization)
{
printTemplateArguments(os, policy, f->getTemplateSpecializationArgs(), qualifyNames);
}
if (f->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate)
{
printTemplateParameters(os, policy, f->getDescribedFunctionTemplate()->getTemplateParameters());
}
os << '(';
bool first = true;
for (auto param : f->parameters())
{
if (!first)
{
os << ", ";
}
first = false;
os << getTypeName(param->getType(), qualifyNames) << ' ' << param->getNameAsString();
}
os << ')';
return os.str();
}
} // namespace clang_utilities

Просмотреть файл

@ -1,27 +0,0 @@
#pragma once
#pragma warning (push)
#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996)
#include <llvm/Support/raw_ostream.h>
#include <clang/AST/PrettyPrinter.h>
#include <clang/AST/Decl.h>
#include <clang/AST/DeclTemplate.h>
#pragma warning (pop)
namespace clang_utilities {
// Adapted from tools\clang\lib\AST\DeclPrinter.cpp DeclPrinter::PrintTemplateParameters
void printTemplateParameters(llvm::raw_ostream &out, clang::PrintingPolicy const &policy, const clang::TemplateParameterList *params);
void printTemplateParameter(llvm::raw_ostream &out, clang::PrintingPolicy const &policy, clang::NamedDecl const *param);
void printTemplateArguments(llvm::raw_ostream &out, const clang::PrintingPolicy &policy, clang::TemplateArgumentList const *args, bool qualifyNames);
// Adapted from tools\clang\lib\AST\TemplateBase.cpp TemplateArgument::print
void printTemplateArgument(llvm::raw_ostream &out, const clang::PrintingPolicy &policy, clang::TemplateArgument const &arg, bool qualifyNames);
std::string getFunctionPrototype(clang::FunctionDecl *f, bool qualifyNames);
std::string getTypeName(clang::QualType qualType, bool qualifyNames);
} // namespace clang_utilities

Просмотреть файл

@ -1,90 +0,0 @@
#ifdef _WIN32
#include <windows.h>
#else
#include <wordexp.h>
#endif
#include <vector>
#include <string>
#include <cassert>
std::vector<std::string> splitCommandLine(std::string const &cmdline)
{
int i;
char **argv = NULL;
int argc;
std::vector<std::string> result;
// Posix.
#ifndef _WIN32
{
wordexp_t p;
// Note! This expands shell variables.
if (wordexp(cmdline.c_str(), &p, 0))
{
return result;
}
argc = p.we_wordc;
if (!(argv = (char**) calloc(argc, sizeof(char *))))
{
goto fail;
}
for (i = 0; i < p.we_wordc; i++)
{
result.push_back(p.we_wordv[i]);
}
wordfree(&p);
return result;
fail:
wordfree(&p);
return result;
}
#else // WIN32
{
wchar_t **wargs = NULL;
size_t needed = 0;
wchar_t *cmdlinew = NULL;
size_t len = cmdline.size() + 1;
if (!(cmdlinew = static_cast<wchar_t*>(calloc(len, sizeof(wchar_t)))))
goto fail;
if (!MultiByteToWideChar(CP_ACP, 0, cmdline.c_str(), -1, cmdlinew, len))
goto fail;
if (!(wargs = CommandLineToArgvW(cmdlinew, &argc)))
goto fail;
// Convert from wchar_t * to ANSI char *
for (i = 0; i < argc; i++)
{
// Get the size needed for the target buffer.
// CP_ACP = Ansi Codepage.
needed = WideCharToMultiByte(CP_ACP, 0, wargs[i], -1,
NULL, 0, NULL, NULL);
char *argv;
if (!(argv = static_cast<char*>(malloc(needed))))
goto fail;
// Do the conversion.
needed = WideCharToMultiByte(CP_ACP, 0, wargs[i], -1,
argv, needed, NULL, NULL);
result.push_back(argv);
free(argv);
}
if (wargs) LocalFree(wargs);
if (cmdlinew) free(cmdlinew);
return result;
fail:
if (wargs) LocalFree(wargs);
if (cmdlinew) free(cmdlinew);
}
#endif // WIN32
}

Просмотреть файл

@ -1,6 +0,0 @@
#pragma once
#include <vector>
#include <string>
std::vector<std::string> splitCommandLine(std::string const &cmdline);

Просмотреть файл

@ -1,143 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "Highlighter.h"
//! [0]
Highlighter::Highlighter(QTextDocument *parent)
: QSyntaxHighlighter(parent)
{
HighlightingRule rule;
keywordFormat.setForeground(Qt::darkBlue);
QStringList keywordPatterns;
keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b"
<< "\\bdouble\\b" << "\\benum\\b" << "\\bexplicit\\b"
<< "\\bfriend\\b" << "\\binline\\b" << "\\bint\\b"
<< "\\blong\\b" << "\\bnamespace\\b" << "\\boperator\\b"
<< "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b"
<< "\\bshort\\b" << "\\bsignals\\b" << "\\bsigned\\b"
<< "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b"
<< "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b"
<< "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b"
<< "\\bvoid\\b" << "\\bvolatile\\b";
foreach (const QString &pattern, keywordPatterns) {
rule.pattern = QRegExp(pattern);
rule.format = keywordFormat;
highlightingRules.append(rule);
//! [0] //! [1]
}
//! [1]
//! [2]
classFormat.setFontWeight(QFont::Bold);
classFormat.setForeground(Qt::darkMagenta);
rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b");
rule.format = classFormat;
highlightingRules.append(rule);
//! [2]
//! [3]
singleLineCommentFormat.setForeground(Qt::darkGreen);
rule.pattern = QRegExp("//[^\n]*");
rule.format = singleLineCommentFormat;
highlightingRules.append(rule);
multiLineCommentFormat.setForeground(Qt::darkGreen);
//! [3]
//! [4]
quotationFormat.setForeground(Qt::darkMagenta);
rule.pattern = QRegExp("\".*\"");
rule.format = quotationFormat;
highlightingRules.append(rule);
//! [4]
//! [5]
functionFormat.setForeground(Qt::blue);
rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()");
rule.format = functionFormat;
highlightingRules.append(rule);
//! [5]
//! [6]
commentStartExpression = QRegExp("/\\*");
commentEndExpression = QRegExp("\\*/");
}
//! [6]
//! [7]
void Highlighter::highlightBlock(const QString &text)
{
foreach (const HighlightingRule &rule, highlightingRules) {
QRegExp expression(rule.pattern);
int index = expression.indexIn(text);
while (index >= 0) {
int length = expression.matchedLength();
setFormat(index, length, rule.format);
index = expression.indexIn(text, index + length);
}
}
//! [7] //! [8]
setCurrentBlockState(0);
//! [8]
//! [9]
int startIndex = 0;
if (previousBlockState() != 1)
startIndex = commentStartExpression.indexIn(text);
//! [9] //! [10]
while (startIndex >= 0) {
//! [10] //! [11]
int endIndex = commentEndExpression.indexIn(text, startIndex);
int commentLength;
if (endIndex == -1) {
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
} else {
commentLength = endIndex - startIndex
+ commentEndExpression.matchedLength();
}
setFormat(startIndex, commentLength, multiLineCommentFormat);
startIndex = commentStartExpression.indexIn(text, startIndex + commentLength);
}
}
//! [11]

Просмотреть файл

@ -1,84 +0,0 @@
#pragma once
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef HIGHLIGHTER_H
#define HIGHLIGHTER_H
#include <QSyntaxHighlighter>
#include <QTextCharFormat>
QT_BEGIN_NAMESPACE
class QTextDocument;
QT_END_NAMESPACE
//! [0]
class Highlighter : public QSyntaxHighlighter
{
Q_OBJECT
public:
Highlighter(QTextDocument *parent = 0);
protected:
void highlightBlock(const QString &text) Q_DECL_OVERRIDE;
private:
struct HighlightingRule
{
QRegExp pattern;
QTextCharFormat format;
};
QVector<HighlightingRule> highlightingRules;
QRegExp commentStartExpression;
QRegExp commentEndExpression;
QTextCharFormat keywordFormat;
QTextCharFormat classFormat;
QTextCharFormat singleLineCommentFormat;
QTextCharFormat multiLineCommentFormat;
QTextCharFormat quotationFormat;
QTextCharFormat functionFormat;
};
//! [0]
#endif // HIGHLIGHTER_H

Просмотреть файл

@ -1,165 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

Просмотреть файл

@ -1,169 +0,0 @@
#include "MainWindow.h"
#include <qmessagebox.h>
#include <qwindow.h>
#include <qfilesystemmodel.h>
#include <qstringlist.h>
#include "AstModel.h"
class UpdateLock
{
public:
UpdateLock(bool &lock) : myLock(lock)
{
myLock = true;
}
~UpdateLock()
{
myLock = false;
}
bool & myLock;
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
isUpdateInProgress(false)
{
myUi.setupUi(this);
connect(myUi.actionRefresh, &QAction::triggered, this, &MainWindow::RefreshAst);
myHighlighter = new Highlighter(myUi.codeViewer->document());
myUi.nodeProperties->setHeaderLabels({ "Property", "Value" });
connect(myUi.codeViewer, &QTextEdit::cursorPositionChanged, this, &MainWindow::HighlightNodeMatchingCode);
connect(myUi.codeViewer, &QTextEdit::textChanged, this, &MainWindow::OnCodeChange);
connect(myUi.showDetails, &QPushButton::clicked, this, &MainWindow::ShowNodeDetails);
}
void MainWindow::RefreshAst()
{
auto ast = myReader.readAst(myUi.codeViewer->document()->toPlainText().toStdString(),
myUi.commandLineArgs->document()->toPlainText().toStdString());
auto model = new AstModel(std::move(ast));
myUi.astTreeView->setModel(model);
myUi.astTreeView->setRootIndex(model->rootIndex());
connect(myUi.astTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &MainWindow::HighlightCodeMatchingNode);
connect(myUi.astTreeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &MainWindow::DisplayNodeProperties);
myUi.astTreeView->setEnabled(myReader.ready());
}
void MainWindow::HighlightCodeMatchingNode(const QModelIndex &newNode, const QModelIndex &previousNode)
{
if (isUpdateInProgress)
{
return;
}
auto lock = UpdateLock{ isUpdateInProgress };
auto node = myUi.astTreeView->model()->data(newNode, Qt::NodeRole).value<GenericAstNode*>();
auto &manager = myReader.getManager();
std::pair<int, int> location;
if (!node->getRangeInMainFile(location, manager, myReader.getContext()))
{
return;
}
auto cursor = myUi.codeViewer->textCursor();
cursor.setPosition(location.first);
cursor.setPosition(location.second, QTextCursor::KeepAnchor);
myUi.codeViewer->setTextCursor(cursor);
}
void MainWindow::DisplayNodeProperties(const QModelIndex &newNode, const QModelIndex &previousNode)
{
myUi.nodeProperties->clear();
auto node = myUi.astTreeView->model()->data(newNode, Qt::NodeRole).value<GenericAstNode*>();
for (auto &prop : node->getProperties())
{
new QTreeWidgetItem(myUi.nodeProperties, QStringList{ QString::fromStdString(prop.first), QString::fromStdString(prop.second) });
}
myUi.showDetails->setVisible(node->hasDetails);
}
void MainWindow::HighlightNodeMatchingCode()
{
if (isUpdateInProgress || !myReader.ready())
{
return;
}
auto lock = UpdateLock{ isUpdateInProgress };
auto cursorPosition = myUi.codeViewer->textCursor().position();
auto nodePath = myReader.getBestNodeMatchingPosition(cursorPosition);
auto model = myUi.astTreeView->model();
if (!nodePath.empty())
{
auto currentIndex = model->index(0, 0); // Returns the root
currentIndex = model->index(0, 0, currentIndex); // Returns the AST node
auto currentNode = nodePath.front();
bool first = true;
for (auto node : nodePath)
{
if (first)
{
first = false;
}
else
{
auto index = currentNode->findChildIndex(node);
if (index == -1)
{
// Something wrong, just silently return
return;
}
currentIndex = model->index(index, 0, currentIndex);
currentNode = node;
}
}
myUi.astTreeView->scrollTo(currentIndex, QAbstractItemView::EnsureVisible);
auto selectionModel = myUi.astTreeView->selectionModel();
// selectionModel->select(currentIndex, QItemSelectionModel::ClearAndSelect);
selectionModel->setCurrentIndex(currentIndex, QItemSelectionModel::ClearAndSelect);
DisplayNodeProperties(currentIndex, currentIndex); // Since we won't use the previous node, it's not an issue if it is wrong...
}
}
void MainWindow::ShowNodeDetails()
{
auto selectionModel = myUi.astTreeView->selectionModel();
auto model = myUi.astTreeView->model();
auto node = myUi.astTreeView->model()->data(selectionModel->currentIndex(), Qt::NodeRole).value<GenericAstNode*>();
if (! node || !node->hasDetails)
{
QMessageBox::warning(this, windowTitle() + " - Error in details",
"The currently selected node does not have details", QMessageBox::Ok);
return;
}
if (node->details.empty())
{
node->details = node->detailsComputer();
}
auto win = new QDialog(this);
win->setLayout(new QGridLayout());
win->resize(size());
win->move(pos());
win->setWindowTitle(windowTitle() + " - " + QString::fromStdString(node->name) + " - " + QString::fromStdString(node->detailsTitle));
auto edit = new QTextEdit(win);
win->layout()->addWidget(edit);
edit->setText(QString::fromStdString(node->details));
edit->setReadOnly(true);
myDetailWindows.push_back(win);
win->show();
}
void MainWindow::closeEvent(QCloseEvent *event)
{
for (auto win : myDetailWindows)
{
win->close();
}
event->accept();
}
void MainWindow::OnCodeChange()
{
myUi.astTreeView->setEnabled(false);
myReader.dirty();
}

Просмотреть файл

@ -1,27 +0,0 @@
#pragma once
#include "ui_MainWindow.h"
#include "Highlighter.h"
#include "AstReader.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
public slots:
void RefreshAst();
void HighlightCodeMatchingNode(const QModelIndex &newNode, const QModelIndex &previousNode);
void DisplayNodeProperties(const QModelIndex &newNode, const QModelIndex &previousNode);
void HighlightNodeMatchingCode();
void ShowNodeDetails();
void OnCodeChange();
void closeEvent(QCloseEvent *event) override;
private:
Ui::MainWindow myUi;
Highlighter *myHighlighter; // No need to delete, since is will have a parent that will take care of that
AstReader myReader;
std::vector<QDialog *> myDetailWindows;
bool isUpdateInProgress;
};

Просмотреть файл

@ -1,151 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Clang AST viewer</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTextEdit" name="codeViewer">
<property name="font">
<font>
<family>Consolas</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">selection-background-color: rgb(170, 85, 255);
selection-color: white</string>
</property>
<property name="tabStopWidth">
<number>25</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QDockWidget" name="astDock">
<property name="windowTitle">
<string>Clang AST</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTreeView" name="astTreeView">
<property name="enabled">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true">QTreeView::item:selected { color:white; background:rgb(170, 85, 255); }</string>
</property>
<property name="indentation">
<number>10</number>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionRefresh"/>
</widget>
<widget class="QDockWidget" name="dockWidget">
<property name="windowTitle">
<string>Command line arguments</string>
</property>
<attribute name="dockWidgetArea">
<number>8</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QPlainTextEdit" name="commandLineArgs">
<property name="plainText">
<string>-std=c++14 &quot;-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include&quot; -I&quot;C:\Program Files (x86)\Windows Kits\10\Include\10.0.10150.0\ucrt&quot; -fcxx-exceptions -fms-compatibility -fdelayed-template-parsing</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="dockWidget_2">
<property name="windowTitle">
<string>Properties</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_3">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QTreeWidget" name="nodeProperties">
<property name="columnCount">
<number>2</number>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">2</string>
</property>
</column>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="showDetails">
<property name="text">
<string>Show details</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<action name="actionRefresh">
<property name="text">
<string>Refresh</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

Просмотреть файл

@ -1,7 +0,0 @@
# Clang-ast-viewer
## Introduction
Fork of [https://github.com/CAST-projects/Clang-ast-viewer](https://github.com/CAST-projects/Clang-ast-viewer).
## License
This product is provided under LGPL. See the `LICENCE` file for more information.

Просмотреть файл

@ -1,14 +0,0 @@
#include <QApplication>
#include <QPushButton>
#include "MainWindow.h"
int main(int argc, char **argv)
{
QApplication app (argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}

Просмотреть файл

@ -1,32 +0,0 @@
require("premake-qt/qt")
local qt = premake.extensions.qt
project "CppSharp.ASTViewer"
SetupNativeProject()
kind "ConsoleApp"
systemversion("latest")
cppdialect "C++17"
qt.enable()
filter { "system:linux" }
buildoptions { "-fPIC" }
links { "pthread" }
qtincludepath "/usr/include/x86_64-linux-gnu/qt5"
qtlibpath "/usr/lib/x86_64-linux-gnu"
qtbinpath "/usr/lib/qt5/bin"
filter { "system:windows" }
qtpath "C:\\Qt\\5.12.0\\msvc2017"
filter {}
qtmodules { "core", "gui", "widgets" }
qtprefix "Qt5"
files { "**.h", "**.cpp", "**.ui", "**.qrc" }
SetupLLVMIncludes()
SetupLLVMLibs()
filter { "toolset:msc*" }
buildoptions { "/wd4141", "/wd4146", "/wd4996" }

Просмотреть файл

@ -138,7 +138,7 @@ namespace CppSharp
parserOptions.UnityBuild = options.UnityBuild;
parserOptions.EnableRTTI = options.EnableRTTI;
parserOptions.Setup();
parserOptions.Setup(options.Platform ?? Platform.Host);
if (triple.Contains("linux"))
SetupLinuxOptions(parserOptions);

Просмотреть файл

@ -5,6 +5,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
<IsPackable>true</IsPackable>
<NoWarn>0109</NoWarn>
<PlatformParserFolder Condition="$(IsWindows) AND $(PlatformTarget) == x64">x86_64-pc-win32-msvc</PlatformParserFolder>
<PlatformParserFolder Condition="$(IsLinux) AND $(PlatformTarget) == x64 AND $(UseCXX11ABI)">x86_64-linux-gnu-cxx11abi</PlatformParserFolder>
<PlatformParserFolder Condition="$(IsLinux) AND $(PlatformTarget) == x64 AND !$(UseCXX11ABI)">x86_64-linux-gnu</PlatformParserFolder>

Просмотреть файл

@ -35,23 +35,21 @@ namespace CppSharp.Utils
testModule.LibraryName, options.GeneratorKind.ToString());
if (Platform.IsMacOS)
driver.ParserOptions.TargetTriple = Environment.Is64BitProcess ?
"x86_64-apple-darwin" : "i686-apple-darwin";
driver.ParserOptions.TargetTriple = "x86_64-apple-darwin";
var path = Path.GetFullPath(GetTestsDirectory(name));
testModule.IncludeDirs.Add(path);
testModule.LibraryDirs.Add(options.OutputDir);
testModule.Libraries.Add($"{name}.Native");
Diagnostics.Message("Looking for tests in: {0}", path);
var files = Directory.EnumerateFiles(path, "*.h", SearchOption.AllDirectories);
foreach (var file in files)
{
string includeDir = Path.GetDirectoryName(file);
var includeDir = Path.GetDirectoryName(file);
if (!testModule.IncludeDirs.Contains(includeDir))
{
testModule.IncludeDirs.Add(includeDir);
}
testModule.Headers.Add(Path.GetFileName(file));
}
}
@ -76,12 +74,12 @@ namespace CppSharp.Utils
while (directory != null)
{
var path = Path.Combine(directory.FullName, "tests", name);
var path = Path.Combine(directory.FullName, "tests", "dotnet", name);
if (Directory.Exists(path))
return path;
path = Path.Combine(directory.FullName, "external", "CppSharp", "tests", name);
path = Path.Combine(directory.FullName, "external", "CppSharp", "tests", "dotnet", name);
if (Directory.Exists(path))
return path;

Просмотреть файл

@ -85,7 +85,7 @@ namespace CppSharp
public void Setup()
{
ValidateOptions();
ParserOptions.Setup();
ParserOptions.Setup(Platform.Host);
Context = new BindingContext(Options, ParserOptions);
Context.LinkerOptions.Setup(ParserOptions.TargetTriple, ParserOptions.LanguageVersion);
Generator = CreateGeneratorFromKind(Options.GeneratorKind);
@ -112,6 +112,7 @@ namespace CppSharp
switch (result.Kind)
{
case ParserResultKind.Success:
if (!Options.Quiet)
Diagnostics.Message("Parsed '{0}'", string.Join(", ", files));
break;
case ParserResultKind.Error:
@ -183,28 +184,23 @@ namespace CppSharp
ClangParser.LibraryParsed += OnFileParsed;
foreach (var module in Options.Modules)
{
using (var linkerOptions = new LinkerOptions(Context.LinkerOptions))
{
using var linkerOptions = new LinkerOptions(Context.LinkerOptions);
foreach (var libraryDir in module.LibraryDirs)
linkerOptions.AddLibraryDirs(libraryDir);
foreach (string library in module.Libraries)
foreach (var library in module.Libraries.Where(library =>
Context.Symbols.Libraries.All(l => l.FileName != library)))
{
if (Context.Symbols.Libraries.Any(l => l.FileName == library))
continue;
linkerOptions.AddLibraries(library);
}
using (var res = ClangParser.ParseLibrary(linkerOptions))
{
using var res = ClangParser.ParseLibrary(linkerOptions);
if (res.Kind != ParserResultKind.Success)
continue;
for (uint i = 0; i < res.LibrariesCount; i++)
Context.Symbols.Libraries.Add(ClangParser.ConvertLibrary(res.GetLibraries(i)));
}
}
}
ClangParser.LibraryParsed -= OnFileParsed;
Context.Symbols.IndexSymbols();
@ -215,95 +211,99 @@ namespace CppSharp
public void SetupPasses(ILibrary library)
{
var TranslationUnitPasses = Context.TranslationUnitPasses;
var passes = Context.TranslationUnitPasses;
TranslationUnitPasses.AddPass(new ResolveIncompleteDeclsPass());
TranslationUnitPasses.AddPass(new IgnoreSystemDeclarationsPass());
TranslationUnitPasses.AddPass(new MatchParamNamesWithInstantiatedFromPass());
passes.AddPass(new ResolveIncompleteDeclsPass());
passes.AddPass(new IgnoreSystemDeclarationsPass());
passes.AddPass(new MatchParamNamesWithInstantiatedFromPass());
if (Options.IsCSharpGenerator)
TranslationUnitPasses.AddPass(new EqualiseAccessOfOverrideAndBasePass());
passes.AddPass(new EqualiseAccessOfOverrideAndBasePass());
TranslationUnitPasses.AddPass(new FlattenAnonymousTypesToFields());
TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass());
TranslationUnitPasses.AddPass(new MarkUsedClassInternalsPass());
passes.AddPass(new FlattenAnonymousTypesToFields());
passes.AddPass(new CheckIgnoredDeclsPass());
passes.AddPass(new MarkUsedClassInternalsPass());
if (Options.IsCSharpGenerator)
{
TranslationUnitPasses.AddPass(new TrimSpecializationsPass());
TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions());
TranslationUnitPasses.AddPass(new GenerateSymbolsPass());
TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass());
passes.AddPass(new TrimSpecializationsPass());
passes.AddPass(new CheckAmbiguousFunctions());
passes.AddPass(new GenerateSymbolsPass());
passes.AddPass(new CheckIgnoredDeclsPass());
}
if (Options.IsCLIGenerator || Options.IsCSharpGenerator)
{
TranslationUnitPasses.AddPass(new MoveFunctionToClassPass());
TranslationUnitPasses.AddPass(new ValidateOperatorsPass());
passes.AddPass(new MoveFunctionToClassPass());
passes.AddPass(new ValidateOperatorsPass());
}
library.SetupPasses(this);
TranslationUnitPasses.AddPass(new FindSymbolsPass());
TranslationUnitPasses.AddPass(new CheckMacroPass());
TranslationUnitPasses.AddPass(new CheckStaticClass());
passes.AddPass(new FindSymbolsPass());
passes.AddPass(new CheckMacroPass());
passes.AddPass(new CheckStaticClass());
if (Options.IsCLIGenerator || Options.IsCSharpGenerator || Options.IsCppGenerator)
{
TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions());
passes.AddPass(new CheckAmbiguousFunctions());
}
TranslationUnitPasses.AddPass(new ConstructorToConversionOperatorPass());
TranslationUnitPasses.AddPass(new MarshalPrimitivePointersAsRefTypePass());
passes.AddPass(new ConstructorToConversionOperatorPass());
passes.AddPass(new MarshalPrimitivePointersAsRefTypePass());
if (Options.IsCLIGenerator || Options.IsCSharpGenerator)
{
TranslationUnitPasses.AddPass(new CheckOperatorsOverloadsPass());
passes.AddPass(new CheckOperatorsOverloadsPass());
}
TranslationUnitPasses.AddPass(new CheckVirtualOverrideReturnCovariance());
TranslationUnitPasses.AddPass(new CleanCommentsPass());
passes.AddPass(new CheckVirtualOverrideReturnCovariance());
passes.AddPass(new CleanCommentsPass());
Generator.SetupPasses();
TranslationUnitPasses.AddPass(new CleanInvalidDeclNamesPass());
TranslationUnitPasses.AddPass(new FastDelegateToDelegatesPass());
TranslationUnitPasses.AddPass(new FieldToPropertyPass());
TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass());
TranslationUnitPasses.AddPass(new CheckFlagEnumsPass());
TranslationUnitPasses.AddPass(new MakeProtectedNestedTypesPublicPass());
passes.AddPass(new CleanInvalidDeclNamesPass());
passes.AddPass(new FastDelegateToDelegatesPass());
passes.AddPass(new FieldToPropertyPass());
passes.AddPass(new CheckIgnoredDeclsPass());
passes.AddPass(new CheckFlagEnumsPass());
passes.AddPass(new MakeProtectedNestedTypesPublicPass());
if (Options.IsCSharpGenerator)
{
TranslationUnitPasses.AddPass(new GenerateAbstractImplementationsPass());
TranslationUnitPasses.AddPass(new MultipleInheritancePass());
passes.AddPass(new GenerateAbstractImplementationsPass());
passes.AddPass(new MultipleInheritancePass());
}
if (Options.IsCLIGenerator || Options.IsCSharpGenerator)
{
TranslationUnitPasses.AddPass(new DelegatesPass());
TranslationUnitPasses.AddPass(new GetterSetterToPropertyPass());
passes.AddPass(new DelegatesPass());
}
TranslationUnitPasses.AddPass(new StripUnusedSystemTypesPass());
if (Options.GeneratorKind != GeneratorKind.C)
{
passes.AddPass(new GetterSetterToPropertyPass());
}
passes.AddPass(new StripUnusedSystemTypesPass());
if (Options.IsCSharpGenerator)
{
TranslationUnitPasses.AddPass(new SpecializationMethodsWithDependentPointersPass());
TranslationUnitPasses.AddPass(new ParamTypeToInterfacePass());
passes.AddPass(new SpecializationMethodsWithDependentPointersPass());
passes.AddPass(new ParamTypeToInterfacePass());
}
TranslationUnitPasses.AddPass(new CheckDuplicatedNamesPass());
passes.AddPass(new CheckDuplicatedNamesPass());
if (Options.IsCLIGenerator || Options.IsCSharpGenerator)
{
TranslationUnitPasses.RenameDeclsUpperCase(RenameTargets.Any & ~RenameTargets.Parameter);
TranslationUnitPasses.AddPass(new CheckKeywordNamesPass());
passes.RenameDeclsUpperCase(RenameTargets.Any & ~RenameTargets.Parameter);
passes.AddPass(new CheckKeywordNamesPass());
}
Context.TranslationUnitPasses.AddPass(new HandleVariableInitializerPass());
passes.AddPass(new HandleVariableInitializerPass());
TranslationUnitPasses.AddPass(new MarkEventsWithUniqueIdPass());
passes.AddPass(new MarkEventsWithUniqueIdPass());
}
public void ProcessCode()
@ -345,9 +345,9 @@ namespace CppSharp
var file = Path.Combine(outputPath, fileRelativePath);
WriteGeneratedCodeToFile(file, template.Generate());
if (output.TranslationUnit.Module != null)
output.TranslationUnit.Module.CodeFiles.Add(file);
output.TranslationUnit.Module?.CodeFiles.Add(file);
if (!Options.Quiet)
Diagnostics.Message("Generated '{0}'", fileRelativePath);
}
}
@ -367,7 +367,7 @@ namespace CppSharp
public bool CompileCode(Module module)
{
var msBuildGenerator = new MSBuildGenerator(Context, module, libraryMappings);
var msBuildGenerator = new MSBuildGenerator(Context, module, LibraryMappings);
msBuildGenerator.Process();
string csproj = Path.Combine(Options.OutputDir,
$"{module.LibraryName}.{msBuildGenerator.FileExtension}");
@ -378,7 +378,7 @@ namespace CppSharp
if (error == 0)
{
Diagnostics.Message($@"Compilation succeeded: {
libraryMappings[module] = Path.Combine(
LibraryMappings[module] = Path.Combine(
Options.OutputDir, $"{module.LibraryName}.dll")}.");
return true;
}
@ -407,7 +407,7 @@ namespace CppSharp
}
private bool hasParsingErrors;
private static readonly Dictionary<Module, string> libraryMappings = new Dictionary<Module, string>();
private static readonly Dictionary<Module, string> LibraryMappings = new();
}
public static class ConsoleDriver
@ -415,8 +415,7 @@ namespace CppSharp
public static void Run(ILibrary library)
{
var options = new DriverOptions();
using (var driver = new Driver(options))
{
using var driver = new Driver(options);
library.Setup(driver);
driver.Setup();
@ -457,8 +456,9 @@ namespace CppSharp
if (!options.Quiet)
Diagnostics.Message("Generating code...");
if (!options.DryRun)
{
if (options.DryRun)
return;
var outputs = driver.GenerateCode();
library.GenerateCode(driver, outputs);
@ -466,16 +466,12 @@ namespace CppSharp
foreach (var output in outputs)
{
foreach (var pass in driver.Context.GeneratorOutputPasses.Passes)
{
pass.VisitGeneratorOutput(output);
}
}
driver.SaveCode(outputs);
if (driver.Options.IsCSharpGenerator && driver.Options.CompileCode)
driver.Options.Modules.Any(m => !driver.CompileCode(m));
}
}
}
}
}

Просмотреть файл

@ -7,7 +7,7 @@ namespace CppSharp.Generators.Emscripten
/// Generates Emscripten Embind C/C++ header files.
/// Embind documentation: https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html
/// </summary>
public class EmscriptenHeaders : EmscriptenCodeGenerator
public sealed class EmscriptenHeaders : EmscriptenCodeGenerator
{
public EmscriptenHeaders(BindingContext context, IEnumerable<TranslationUnit> units)
: base(context, units)

Просмотреть файл

@ -62,7 +62,7 @@ namespace CppSharp.Passes
}
if (function.IsAmbiguous)
Diagnostics.Message($"Found ambiguous overload: {function.QualifiedOriginalName}");
Diagnostics.Debug($"Found ambiguous overload: {function.QualifiedOriginalName}");
return true;
}

Просмотреть файл

@ -33,8 +33,7 @@ namespace CppSharp.Passes
return false;
}
var @class = field.Namespace as Class;
if (@class == null)
if (field.Namespace is not Class @class)
return false;
// Check if we already have a synthetized property.

Просмотреть файл

@ -21,19 +21,16 @@ namespace CppSharp.Passes
private static void LoadVerbs()
{
var assembly = Assembly.GetAssembly(typeof(GetterSetterToPropertyPass));
using (var resourceStream = GetResourceStream(assembly))
{
using (var streamReader = new StreamReader(resourceStream))
using var resourceStream = GetResourceStream(assembly);
using var streamReader = new StreamReader(resourceStream);
while (!streamReader.EndOfStream)
verbs.Add(streamReader.ReadLine());
}
Verbs.Add(streamReader.ReadLine());
}
private static Stream GetResourceStream(Assembly assembly)
{
var resources = assembly.GetManifestResourceNames();
if (resources.Count() == 0)
if (!resources.Any())
throw new Exception("Cannot find embedded verbs data resource.");
// We are relying on this fact that there is only one resource embedded.
@ -54,13 +51,12 @@ namespace CppSharp.Passes
return false;
}
protected virtual List<Property> GetProperties(Class @class) =>
new List<Property>();
protected virtual List<Property> GetProperties() => new();
protected IEnumerable<Property> GenerateProperties(Class @class)
{
List<Property> properties = GetProperties(@class);
foreach (Method method in @class.Methods.Where(
var properties = GetProperties();
foreach (var method in @class.Methods.Where(
m => !m.IsConstructor && !m.IsDestructor && !m.IsOperator && m.IsGenerated &&
(properties.All(p => p.GetMethod != m && p.SetMethod != m) ||
m.OriginalFunction != null) &&
@ -72,15 +68,16 @@ namespace CppSharp.Passes
if (IsGetter(method))
{
string name = GetPropertyName(method.Name);
GetProperty(properties, method, name, method.OriginalReturnType);
CreateOrUpdateProperty(properties, method, name, method.OriginalReturnType);
continue;
}
if (IsSetter(method))
{
string name = GetPropertyNameFromSetter(method.Name);
QualifiedType type = method.Parameters.First(
p => p.Kind == ParameterKind.Regular).QualifiedType;
GetProperty(properties, method, name, type, true);
CreateOrUpdateProperty(properties, method, name, type, true);
}
}
@ -104,7 +101,7 @@ namespace CppSharp.Passes
continue;
if (Match(firstWord, new[] { "to", "new", "on" }) ||
verbs.Contains(firstWord))
Verbs.Contains(firstWord))
{
property.GetMethod.GenerationKind = GenerationKind.Generate;
@class.Properties.Remove(property);
@ -115,12 +112,10 @@ namespace CppSharp.Passes
return properties;
}
private static void GetProperty(List<Property> properties, Method method,
private static void CreateOrUpdateProperty(List<Property> properties, Method method,
string name, QualifiedType type, bool isSetter = false)
{
Type underlyingType = GetUnderlyingType(type);
Class @class = (Class)method.Namespace;
Property property = properties.Find(
p => p.Field == null &&
((!isSetter && p.SetMethod?.IsStatic == method.IsStatic) ||
@ -255,14 +250,13 @@ namespace CppSharp.Passes
private static Type GetUnderlyingType(QualifiedType type)
{
TagType tagType = type.Type as TagType;
if (tagType != null)
if (type.Type is TagType)
return type.Type;
// TODO: we should normally check pointer types for const;
// however, there's some bug, probably in the parser, that returns IsConst = false for "const Type& arg"
// so skip the check for the time being
PointerType pointerType = type.Type as PointerType;
return pointerType != null ? pointerType.Pointee : type.Type;
return type.Type is PointerType pointerType ? pointerType.Pointee : type.Type;
}
private static void CombineComments(Property property)
@ -277,6 +271,7 @@ namespace CppSharp.Passes
BriefText = getter.Comment.BriefText,
Text = getter.Comment.Text
};
if (getter.Comment.FullComment != null)
{
comment.FullComment = new FullComment();
@ -295,20 +290,18 @@ namespace CppSharp.Passes
private static string GetPropertyName(string name)
{
var firstWord = GetFirstWord(name);
if (Match(firstWord, new[] { "get" }) &&
(string.Compare(name, firstWord, StringComparison.InvariantCultureIgnoreCase) != 0) &&
!char.IsNumber(name[3]))
{
if (!Match(firstWord, new[] {"get"}) ||
(string.Compare(name, firstWord, StringComparison.InvariantCultureIgnoreCase) == 0) ||
char.IsNumber(name[3])) return name;
if (name.Length == 4)
{
return char.ToLowerInvariant(
name[3]).ToString(CultureInfo.InvariantCulture);
}
return char.ToLowerInvariant(
name[3]).ToString(CultureInfo.InvariantCulture) +
name.Substring(4);
}
return name;
return string.Concat(char.ToLowerInvariant(
name[3]).ToString(CultureInfo.InvariantCulture), name.AsSpan(4));
}
private static string GetPropertyNameFromSetter(string name)
@ -328,7 +321,7 @@ namespace CppSharp.Passes
private bool IsGetter(Method method) =>
!method.IsDestructor &&
!method.OriginalReturnType.Type.IsPrimitiveType(PrimitiveType.Void) &&
!method.Parameters.Any(p => p.Kind != ParameterKind.IndirectReturnType);
method.Parameters.All(p => p.Kind == ParameterKind.IndirectReturnType);
private static bool IsSetter(Method method)
{
@ -365,6 +358,6 @@ namespace CppSharp.Passes
return new string(firstWord.ToArray());
}
private static readonly HashSet<string> verbs = new HashSet<string>();
private static readonly HashSet<string> Verbs = new();
}
}

Просмотреть файл

@ -227,8 +227,6 @@ namespace CppSharp.Types.Std
return (Context.Options.Encoding, nameof(Encoding.ASCII));
if (Context.Options.Encoding == Encoding.UTF8)
return (Context.Options.Encoding, nameof(Encoding.UTF8));
if (Context.Options.Encoding == Encoding.UTF7)
return (Context.Options.Encoding, nameof(Encoding.UTF7));
if (Context.Options.Encoding == Encoding.BigEndianUnicode)
return (Context.Options.Encoding, nameof(Encoding.BigEndianUnicode));
if (Context.Options.Encoding == Encoding.Unicode)

Просмотреть файл

@ -710,7 +710,6 @@ namespace Mono.Options
get { return this.option; }
}
[SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);

Просмотреть файл

@ -276,15 +276,21 @@ namespace CppSharp.Parser
AddSystemIncludeDirs($"{headersPath}/usr/include/linux");
}
public void Setup()
private bool setupDone;
public void Setup(TargetPlatform targetPlatform)
{
SetupArguments();
if (setupDone) return;
SetupArguments(targetPlatform);
if (!NoBuiltinIncludes)
SetupIncludes();
SetupIncludes(targetPlatform);
setupDone = true;
}
private void SetupArguments()
private void SetupArguments(TargetPlatform targetPlatform)
{
LanguageVersion ??= CppSharp.Parser.LanguageVersion.CPP14_GNU;
@ -296,7 +302,7 @@ namespace CppSharp.Parser
// setup methods, below is generic fallback in case that logic was disabled.
if (NoBuiltinIncludes)
{
switch (Platform.Host)
switch (targetPlatform)
{
case TargetPlatform.MacOS:
case TargetPlatform.Linux:
@ -370,18 +376,21 @@ namespace CppSharp.Parser
{
get
{
var assemblyDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var assemblyDir = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
if (assemblyDir == null)
throw new InvalidOperationException();
return Path.Combine(assemblyDir, "lib", "clang", ClangVersion, "include");
}
}
private void SetupIncludes()
private void SetupIncludes(TargetPlatform targetPlatform)
{
// Check that the builtin includes folder exists.
if (!Directory.Exists(BuiltinsDir))
throw new Exception($"Clang resource folder 'lib/clang/{ClangVersion}/include' was not found.");
switch (Platform.Host)
switch (targetPlatform)
{
case TargetPlatform.Windows:
SetupMSVC();
@ -392,6 +401,16 @@ namespace CppSharp.Parser
case TargetPlatform.Linux:
SetupLinux();
break;
case TargetPlatform.Android:
throw new NotImplementedException();
case TargetPlatform.iOS:
case TargetPlatform.WatchOS:
case TargetPlatform.TVOS:
throw new NotImplementedException();
case TargetPlatform.Emscripten:
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -1,11 +0,0 @@
function SetupWrapper(name)
if not EnabledManagedProjects() then
return
end
SetupExternalManagedTestProject(name .. ".CSharp")
end
group "Tests/Namespaces"
SetupTestNativeProject("NamespacesBase")
targetdir (path.join(gendir, "NamespacesDerived"))

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -1,4 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<NoWarn>0108</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Include="CSharpPartialMethods.cs" />
</ItemGroup>

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -1,5 +1,5 @@
<Project>
<Import Project="../Directory.Build.props" />
<Import Project="../../Directory.Build.props" />
<Import Project="Test.Common.props" />
<Import Project="Test.Generator.props" Condition="$(IsTestGenerator)" />
<Import Project="Test.Bindings.props" Condition="$(IsTestBindings)" />

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше