Urho3D/Source/Tools/BindingGenerator/XmlAnalyzer.h

499 lines
18 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Copyright (c) 2008-2021 the Urho3D project.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
#include <PugiXml/pugixml.hpp>
#include <string>
#include <memory>
#include <vector>
#include <map>
#include "XmlSourceData.h"
#include "Utils.h"
using namespace pugi;
using namespace std;
using TemplateSpecialization = map<string, string>;
// <type>...</type> | <defval>...</defval> | <para>...</para>
string RemoveRefs(xml_node node);
// <type>...</type>
class TypeAnalyzer
{
private:
string fullType_;
string name_;
bool isConst_;
bool isPointer_; // *
bool isReference_; // &
bool isRvalueReference_; // &&
bool isDoublePointer_; // **
bool isRefToPoiner_; // *&
string templateParams_;
public:
TypeAnalyzer(xml_node type, const TemplateSpecialization& specialization = {});
// Used for doxygen bug workaround https://github.com/doxygen/doxygen/issues/7732
TypeAnalyzer(const string& typeName);
string ToString() const { return fullType_; }
string GetName() const { return name_; }
bool IsConst() const { return isConst_; }
bool IsPointer() const { return isPointer_; }
bool IsReference() const { return isReference_; }
bool IsRvalueReference() const { return isRvalueReference_; }
bool IsDoublePointer() const { return isDoublePointer_; }
bool IsRefToPointer() const { return isRefToPoiner_; }
bool IsTemplate() const { return templateParams_.length() > 0; }
string GetTemplateParams() { return templateParams_; }
string GetNameWithTemplateParams() const { return IsTemplate() ? name_ + "<" + templateParams_ + ">" : name_; }
};
// <memberdef kind="function">
// <param>...</param>
class ParamAnalyzer
{
private:
xml_node node_;
TemplateSpecialization specialization_;
public:
ParamAnalyzer(xml_node param, const TemplateSpecialization& specialization = {});
xml_node GetNode() const { return node_; }
string ToString() const;
// <param>
// <type>....</type>
TypeAnalyzer GetType() const;
// <param>
// <declname>....</declname>
string GetDeclname() const;
// <param>
// <defval>....</defval>
string GetDefval() const; // Default value
};
// <memberdef>
inline bool IsMemberdef(xml_node node) { return node.name() == string("memberdef"); }
// <compounddef>
inline bool IsCompounddef(xml_node node) { return node.name() == string("compounddef"); }
// <member>
inline bool IsMember(xml_node node) { return node.name() == string("member"); }
// <sectiondef>
inline bool IsSectiondef(xml_node node) { return node.name() == string("sectiondef"); }
// <enumvalue>
inline bool IsEnumvalue(xml_node node) { return node.name() == string("enumvalue"); }
// <compounddef>
// <compoundname>...</compoundname>
string ExtractCompoundname(xml_node compounddef);
// <compounddef>
// <sectiondef kind="xxx">...</sectiondef>
xml_node FindSectiondef(xml_node compounddef, const string& kind);
// <memberdef static="yes">
bool IsStatic(xml_node memberdef);
// <memberdef kind="function" explicit="yes">
bool IsExplicit(xml_node memberdef);
// <memberdef>
// <definition>...</definition>
string ExtractDefinition(xml_node memberdef);
// <memberdef>
// <argsstring>...</argsstring>
string ExtractArgsstring(xml_node memberdef);
// <memberdef kind="function">
// <argsstring>(...)</argsstring>
// <argsstring>(...) xxx</argsstring>
// where xxx can be of const, override, =default, =delete, =0 or their combination
string ExtractCleanedFunctionArgsstring(xml_node memberdef);
// <memberdef prot="...">
string ExtractProt(xml_node memberdef);
// <memberdef>
// <type>...</type>
TypeAnalyzer ExtractType(xml_node memberdef, const TemplateSpecialization& specialization = {});
// <memberdef kind="function">
// <param>...</param>
// <param>...</param>
vector<ParamAnalyzer> ExtractParams(xml_node memberdef, const TemplateSpecialization& specialization = {});
// <memberdef kind="function">
// <param>...</param>
// <param>...</param>
string JoinParamsTypes(xml_node memberdef, const TemplateSpecialization& specialization = {});
string JoinParamsNames(xml_node memberdef, bool skipContext = false);
// <memberdef kind="function">
// ...
string GetFunctionDeclaration(xml_node memberdef);
// <memberdef kind="variable">
// ...
string GetVariableDeclaration(xml_node memberdef);
// <memberdef kind="function">
// ...
string GetFunctionLocation(xml_node memberdef);
// <compounddef|memberdef id="...">
string ExtractID(xml_node node);
// <compounddef|memberdef|member|sectiondef kind="...">
string ExtractKind(xml_node node);
// <memberdef|enumvalue>
// <name>...</name>
string ExtractName(xml_node node);
// <compounddef|memberdef>
// <location line="...">
string ExtractLine(xml_node node);
// <compounddef|memberdef>
// <location column="...">
string ExtractColumn(xml_node node);
// <compounddef|memberdef>
// <briefdescription>...</briefdescription>
// <detaileddescription>...</detaileddescription>
string ExtractComment(xml_node node);
// <compounddef|memberdef>
// <location ...>
// Extract header file path and convert to relative.
// Return empty string when declared in *.cpp
string ExtractHeaderFile(xml_node node);
// <compounddef|memberdef>
// <templateparamlist>
bool IsTemplate(xml_node node);
// <compounddef|memberdef>
// <templateparamlist>
// <param>...</param>
// <param>...</param>
vector<string> ExtractTemplateParams(xml_node node);
// <compounddef kind="namespace">
// <sectiondef kind="enum">
// <memberdef kind="enum">...</memberdef>
class EnumAnalyzer
{
xml_node memberdef_;
public:
EnumAnalyzer(xml_node memberdef);
string GetTypeName() const { return ExtractName(memberdef_); }
string GetHeaderFile() const { return ExtractHeaderFile(memberdef_); }
string GetComment() const { return ExtractComment(memberdef_); }
bool IsInternal() const { return GetHeaderFile().empty(); } // true if declared in .cpp file
string GetBaseType() const;
string GetLocation() const;
// <memberdef kind="enum">
// <enumvalue><name>...</name></enumvalue>
// <enumvalue><name>...</name></enumvalue>
vector<string> GetEnumerators() const;
};
// <compounddef kind="namespace">
// <sectiondef kind="var">
// <memberdef kind="variable">...</memberdef>
class GlobalVariableAnalyzer
{
xml_node memberdef_;
public:
GlobalVariableAnalyzer(xml_node memberdef);
string GetName() const { return ExtractName(memberdef_); }
string GetHeaderFile() const { return ExtractHeaderFile(memberdef_); }
bool IsStatic() const { return ::IsStatic(memberdef_); }
TypeAnalyzer GetType() const { return ExtractType(memberdef_); }
bool IsArray() const { return StartsWith(ExtractArgsstring(memberdef_), "["); }
string GetLocation() const { return GetVariableDeclaration(memberdef_) + " | File: " + GetHeaderFile(); }
};
class MethodAnalyzer;
class FieldAnalyzer;
// <compounddef kind="class|struct">...</compounddef>
class ClassAnalyzer
{
private:
xml_node compounddef_;
TemplateSpecialization specialization_;
vector<xml_node> GetMemberdefs() const;
public:
string usingLocation_;
xml_node GetCompounddef() const { return compounddef_; }
ClassAnalyzer(xml_node compounddef, const TemplateSpecialization& specialization = {});
const TemplateSpecialization& GetSpecialization() const { return specialization_; }
string GetClassName() const;
string GetComment() const { return ExtractComment(compounddef_); }
string GetHeaderFile() const { return ExtractHeaderFile(compounddef_); }
string GetDirName() const;
string GetKind() const { return ExtractKind(compounddef_); }
bool IsInternal() const;
bool IsTemplate() const { return ::IsTemplate(compounddef_); }
vector<MethodAnalyzer> GetAllMethods() const;
vector<MethodAnalyzer> GetAllPublicMethods() const;
vector<MethodAnalyzer> GetThisPublicMethods() const;
vector<MethodAnalyzer> GetThisPublicStaticMethods() const;
vector<FieldAnalyzer> GetAllFields() const;
vector<FieldAnalyzer> GetThisPublicFields() const;
vector<FieldAnalyzer> GetThisPublicStaticFields() const;
bool ContainsMethod(const string& name) const;
shared_ptr<MethodAnalyzer> GetMethod(const string& name) const;
int NumMethods(const string& name) const;
bool IsRefCounted() const;
bool HasThisDestructor() const { return ContainsMethod("~" + GetClassName()); }
bool HasThisConstructor() const;
bool IsAbstract() const;
string GetLocation() const { return GetKind() + " " + GetClassName() + " | File: " + GetHeaderFile(); }
bool AllFloats() const;
bool AllInts() const;
bool IsPod() const;
bool IsNoCount() const { return Contains(GetComment(), "NO_COUNT"); } // Have @nocount in comment -> asOBJ_NOCOUNT
shared_ptr<ClassAnalyzer> GetBaseClass() const;
vector<ClassAnalyzer> GetBaseClasses() const;
vector<ClassAnalyzer> GetAllBaseClasses() const;
vector<ClassAnalyzer> GetDerivedClasses() const;
vector<ClassAnalyzer> GetAllDerivedClasses() const;
// Return null if default constructor is implicitly-declared.
// Return pointer if default constructor is deleted
shared_ptr<MethodAnalyzer> GetDefinedThisDefaultConstructor() const;
vector<MethodAnalyzer> GetThisNonDefaultConstructors() const;
// Return null if destructor is implicitly-declared.
// Return pointer if destructor is deleted
shared_ptr<MethodAnalyzer> GetDefinedThisDestructor() const { return GetMethod("~" + GetClassName()); }
int GetInherianceDeep(int counter = 0) const;
vector<string> GetAllPublicMembersRefids() const;
// Base class members that were hidden in this class (c++ declarations)
vector<string> GetHiddenMethods() const;
vector<string> GetHiddenStaticMethods() const;
vector<string> GetHiddenFields() const;
vector<string> GetHiddenStaticFields() const;
};
// <memberdef kind="function">...</memberdef>
class FunctionAnalyzer
{
protected:
xml_node memberdef_;
TemplateSpecialization specialization_;
public:
FunctionAnalyzer(xml_node memberdef, const TemplateSpecialization& specialization = {});
xml_node GetMemberdef() const { return memberdef_; }
const TemplateSpecialization& GetSpecialization() const { return specialization_; }
string GetComment() const { return ExtractComment(memberdef_); }
string GetHeaderFile() const { return ExtractHeaderFile(memberdef_); }
string GetName() const { return ExtractName(memberdef_); }
vector<ParamAnalyzer> GetParams() const { return ExtractParams(memberdef_, specialization_); }
TypeAnalyzer GetReturnType() const { return ExtractType(memberdef_, specialization_); }
vector<string> GetTemplateParams() const { return ExtractTemplateParams(memberdef_); }
bool IsDefine() const { return CONTAINS(SourceData::defines_, GetName()); }
bool IsTemplate() const { return ::IsTemplate(memberdef_); }
string JoinParamsNames(bool skipContext = false) const { return ::JoinParamsNames(memberdef_, skipContext); } // TODO убрать skipContext, он больше не нужен
string JoinParamsTypes() const { return ::JoinParamsTypes(memberdef_, specialization_); }
virtual string GetLocation() const { return GetFunctionLocation(memberdef_); }
};
// <compounddef kind="class|struct">
// <sectiondef>
// <memberdef kind="function">...</memberdef>
class MethodAnalyzer : public FunctionAnalyzer
{
ClassAnalyzer classAnalyzer_;
public:
MethodAnalyzer(const ClassAnalyzer& classAnalyzer, xml_node memberdef, const TemplateSpecialization& specialization = {});
ClassAnalyzer GetClass() const { return classAnalyzer_; }
// <memberdef kind="function" virt="...">
string GetVirt() const;
bool IsPureVirtual() const { return GetVirt() == "pure-virtual"; }
// <memberdef kind="function" const="yes">
bool IsConst() const;
// <memberdef>
// <reimplements refid="..."></reimplements>
shared_ptr<MethodAnalyzer> Reimplements() const;
string GetClassName() const { return classAnalyzer_.GetClassName(); }
string GetContainsClassName() const; // May this function defined in parent class, so return name oа class, real define this function
bool IsStatic() const { return ::IsStatic(memberdef_); }
bool IsPublic() const { return ExtractProt(memberdef_) == "public"; }
// Constructor can have different name https://github.com/doxygen/doxygen/issues/8402
bool IsThisConstructor() const { return GetName() == GetClassName(); }
bool IsThisDefaultConstructor() const { return IsThisConstructor() && ExtractCleanedFunctionArgsstring(memberdef_).empty(); }
bool IsThisNonDefaultConstructor() const { return IsThisConstructor() && !ExtractCleanedFunctionArgsstring(memberdef_).empty(); }
bool IsConstructor() const;
bool IsDestructor() const;
bool IsParentConstructor() const;
bool IsThisDestructor() const { return GetName() == "~" + GetClassName(); }
bool IsParentDestructor() const;
bool CanBeGetProperty() const;
bool CanBeSetProperty() const;
bool IsExplicit() const { return ::IsExplicit(memberdef_); }
bool IsDeleted() const { return EndsWith(ExtractArgsstring(memberdef_), "=delete"); }
bool IsConsversionOperator() const { return StartsWith(GetName(), "operator "); }
bool IsThisMethod() const { return GetContainsClassName() == GetClassName(); } // Defined in this class
string GetDeclaration() const { return JoinNonEmpty({ classAnalyzer_.usingLocation_, GetFunctionDeclaration(memberdef_) }, " | "); }
string GetLocation() const override { return JoinNonEmpty({ classAnalyzer_.usingLocation_, GetFunctionLocation(memberdef_) }, " | "); }
};
// <compounddef kind="class|struct">
// <sectiondef>
// <memberdef kind="variable">...</memberdef>
class FieldAnalyzer
{
ClassAnalyzer classAnalyzer_;
xml_node memberdef_;
public:
FieldAnalyzer(ClassAnalyzer classAnalyzer, xml_node memberdef);
bool IsStatic() const { return ::IsStatic(memberdef_); }
TypeAnalyzer GetType() const { return ExtractType(memberdef_); }
string GetName() const { return ExtractName(memberdef_); }
string GetComment() const { return ExtractComment(memberdef_); }
bool IsPublic() const { return ExtractProt(memberdef_) == "public"; }
string GetHeaderFile() const { return ExtractHeaderFile(memberdef_); }
string GetDeclaration() const { return GetVariableDeclaration(memberdef_); }
string GetLocation() const;
string GetClassName() const { return classAnalyzer_.GetClassName(); }
bool IsArray() const { return StartsWith(ExtractArgsstring(memberdef_), "["); };
};
// <compounddef kind="namespace">
// <sectiondef kind="func">
// <memberdef kind="function">...</memberdef>
class GlobalFunctionAnalyzer : public FunctionAnalyzer
{
public:
GlobalFunctionAnalyzer(xml_node memberdef, const TemplateSpecialization& specialization = {});
};
// <compounddef kind="class|struct">
// <sectiondef kind="public-static-func">
// <memberdef kind="function" prot="public" static="yes">...</memberdef>
class ClassStaticFunctionAnalyzer : public FunctionAnalyzer
{
ClassAnalyzer classAnalyzer_;
public:
ClassStaticFunctionAnalyzer(const ClassAnalyzer& classAnalyzer, xml_node memberdef, const TemplateSpecialization& specialization = {});
string GetClassName() const { return classAnalyzer_.GetClassName(); }
};
// <memberdef kind="typedef">
// <definition>using ...</definition>
class UsingAnalyzer
{
private:
xml_node memberdef_;
public:
UsingAnalyzer(xml_node memberdef);
string GetComment() const { return ExtractComment(memberdef_); }
string GetHeaderFile() const { return ExtractHeaderFile(memberdef_); }
string GetLocation() const { return "using " + GetName() + " = " + GetType().ToString() + " | File: " + GetHeaderFile(); }
string GetName() const { return ExtractName(memberdef_); }
TypeAnalyzer GetType() const { return ExtractType(memberdef_); }
};
// <compounddef kind = "namespace">...</compounddef>
class NamespaceAnalyzer
{
private:
xml_node compounddef_;
public:
NamespaceAnalyzer(xml_node compounddef);
// <compounddef kind="namespace">
// <sectiondef kind="enum">
// <memberdef kind="enum">...</memberdef>
// <memberdef kind="enum">...</memberdef>
vector<EnumAnalyzer> GetEnums();
// <compounddef kind="namespace">
// <sectiondef kind="var">
// <memberdef kind="variable">...</memberdef>
// <memberdef kind="variable">...</memberdef>
vector<GlobalVariableAnalyzer> GetVariables();
// <compounddef kind="namespace">
// <sectiondef kind="func">
// <memberdef kind="function">...</memberdef>
// <memberdef kind="function">...</memberdef>
vector<GlobalFunctionAnalyzer> GetFunctions();
};