230 lines
6.8 KiB
Python
Executable File
230 lines
6.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
|
|
import argparse
|
|
|
|
class Generator(object):
|
|
|
|
implementationContent = ''
|
|
|
|
def GeneratePrologue(self):
|
|
|
|
self.implementationContent += \
|
|
"""
|
|
/*===- Generated file -------------------------------------------*- C++ -*-===*\
|
|
|* *|
|
|
|* Introspection of available AST node SourceLocations *|
|
|
|* *|
|
|
|* Automatically generated file, do not edit! *|
|
|
|* *|
|
|
\*===----------------------------------------------------------------------===*/
|
|
|
|
namespace clang {
|
|
namespace tooling {
|
|
|
|
using LocationAndString = SourceLocationMap::value_type;
|
|
using RangeAndString = SourceRangeMap::value_type;
|
|
"""
|
|
|
|
def GenerateBaseGetLocationsDeclaration(self, CladeName):
|
|
self.implementationContent += \
|
|
"""
|
|
void GetLocationsImpl(SharedLocationCall const& Prefix,
|
|
clang::{0} const *Object, SourceLocationMap &Locs,
|
|
SourceRangeMap &Rngs);
|
|
""".format(CladeName)
|
|
|
|
def GenerateSrcLocMethod(self, ClassName, ClassData):
|
|
|
|
self.implementationContent += \
|
|
"""
|
|
static void GetLocations{0}(SharedLocationCall const& Prefix,
|
|
clang::{0} const &Object,
|
|
SourceLocationMap &Locs, SourceRangeMap &Rngs)
|
|
{{
|
|
""".format(ClassName)
|
|
|
|
if 'sourceLocations' in ClassData:
|
|
for locName in ClassData['sourceLocations']:
|
|
self.implementationContent += \
|
|
"""
|
|
Locs.insert(LocationAndString(Object.{0}(),
|
|
llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}")));
|
|
""".format(locName)
|
|
|
|
self.implementationContent += '\n'
|
|
|
|
if 'sourceRanges' in ClassData:
|
|
for rngName in ClassData['sourceRanges']:
|
|
self.implementationContent += \
|
|
"""
|
|
Rngs.insert(RangeAndString(Object.{0}(),
|
|
llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}")));
|
|
""".format(rngName)
|
|
|
|
self.implementationContent += '\n'
|
|
|
|
self.implementationContent += '}\n'
|
|
|
|
def GenerateFiles(self, OutputFile):
|
|
with open(os.path.join(os.getcwd(),
|
|
OutputFile), 'w') as f:
|
|
f.write(self.implementationContent)
|
|
|
|
def GenerateBaseGetLocationsFunction(self, ASTClassNames, CladeName):
|
|
|
|
MethodReturnType = 'NodeLocationAccessors'
|
|
|
|
Signature = \
|
|
'GetLocations(clang::{0} const *Object)'.format(CladeName)
|
|
ImplSignature = \
|
|
"""
|
|
GetLocationsImpl(SharedLocationCall const& Prefix,
|
|
clang::{0} const *Object, SourceLocationMap &Locs,
|
|
SourceRangeMap &Rngs)
|
|
""".format(CladeName)
|
|
|
|
self.implementationContent += \
|
|
'void {0} {{ GetLocations{1}(Prefix, *Object, Locs, Rngs);'.format(
|
|
ImplSignature,
|
|
CladeName)
|
|
|
|
for ASTClassName in ASTClassNames:
|
|
if ASTClassName != CladeName:
|
|
self.implementationContent += \
|
|
"""
|
|
if (auto Derived = llvm::dyn_cast<clang::{0}>(Object)) {{
|
|
GetLocations{0}(Prefix, *Derived, Locs, Rngs);
|
|
}}
|
|
""".format(ASTClassName)
|
|
|
|
self.implementationContent += '}'
|
|
|
|
self.implementationContent += \
|
|
"""
|
|
{0} NodeIntrospection::{1} {{
|
|
NodeLocationAccessors Result;
|
|
SharedLocationCall Prefix;
|
|
|
|
GetLocationsImpl(Prefix, Object, Result.LocationAccessors,
|
|
Result.RangeAccessors);
|
|
""".format(MethodReturnType,
|
|
Signature)
|
|
|
|
self.implementationContent += 'return Result; }'
|
|
|
|
def GenerateDynNodeVisitor(self, CladeNames):
|
|
MethodReturnType = 'NodeLocationAccessors'
|
|
|
|
Signature = \
|
|
'GetLocations(clang::DynTypedNode const &Node)'
|
|
|
|
self.implementationContent += MethodReturnType \
|
|
+ ' NodeIntrospection::' + Signature + '{'
|
|
|
|
for CladeName in CladeNames:
|
|
self.implementationContent += \
|
|
"""
|
|
if (const auto *N = Node.get<{0}>())
|
|
return GetLocations(const_cast<{0} *>(N));""".format(CladeName)
|
|
|
|
self.implementationContent += '\nreturn {}; }'
|
|
|
|
def GenerateEpilogue(self):
|
|
|
|
self.implementationContent += '''
|
|
}
|
|
}
|
|
'''
|
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--json-input-path',
|
|
help='Read API description from FILE', metavar='FILE')
|
|
parser.add_argument('--output-file', help='Generate output in FILEPATH',
|
|
metavar='FILEPATH')
|
|
parser.add_argument('--empty-implementation',
|
|
help='Generate empty implementation',
|
|
action="store", type=int)
|
|
|
|
options = parser.parse_args()
|
|
|
|
use_empty_implementation = options.empty_implementation
|
|
|
|
if (not use_empty_implementation
|
|
and not os.path.exists(options.json_input_path)):
|
|
use_empty_implementation = True
|
|
|
|
if not use_empty_implementation:
|
|
with open(options.json_input_path) as f:
|
|
jsonData = json.load(f)
|
|
|
|
if not 'classesInClade' in jsonData or not jsonData["classesInClade"]:
|
|
use_empty_implementation = True
|
|
|
|
if use_empty_implementation:
|
|
with open(os.path.join(os.getcwd(),
|
|
options.output_file), 'w') as f:
|
|
f.write("""
|
|
namespace clang {
|
|
namespace tooling {
|
|
|
|
NodeLocationAccessors NodeIntrospection::GetLocations(clang::Stmt const *) {
|
|
return {};
|
|
}
|
|
NodeLocationAccessors NodeIntrospection::GetLocations(clang::Decl const *) {
|
|
return {};
|
|
}
|
|
NodeLocationAccessors NodeIntrospection::GetLocations(
|
|
clang::CXXCtorInitializer const *) {
|
|
return {};
|
|
}
|
|
NodeLocationAccessors NodeIntrospection::GetLocations(
|
|
clang::NestedNameSpecifierLoc const*) {
|
|
return {};
|
|
}
|
|
NodeLocationAccessors NodeIntrospection::GetLocations(
|
|
clang::TemplateArgumentLoc const*) {
|
|
return {};
|
|
}
|
|
NodeLocationAccessors NodeIntrospection::GetLocations(
|
|
clang::CXXBaseSpecifier const*) {
|
|
return {};
|
|
}
|
|
NodeLocationAccessors
|
|
NodeIntrospection::GetLocations(clang::DynTypedNode const &) {
|
|
return {};
|
|
}
|
|
} // namespace tooling
|
|
} // namespace clang
|
|
""")
|
|
sys.exit(0)
|
|
|
|
g = Generator()
|
|
|
|
g.GeneratePrologue()
|
|
|
|
for (CladeName, ClassNameData) in jsonData['classesInClade'].items():
|
|
g.GenerateBaseGetLocationsDeclaration(CladeName)
|
|
|
|
for (ClassName, ClassAccessors) in jsonData['classEntries'].items():
|
|
if ClassAccessors:
|
|
g.GenerateSrcLocMethod(ClassName, ClassAccessors)
|
|
|
|
for (CladeName, ClassNameData) in jsonData['classesInClade'].items():
|
|
g.GenerateBaseGetLocationsFunction(ClassNameData, CladeName)
|
|
|
|
g.GenerateDynNodeVisitor(jsonData['classesInClade'].keys())
|
|
|
|
g.GenerateEpilogue()
|
|
|
|
g.GenerateFiles(options.output_file)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|