2 # -*- coding: utf-8 -*-
12 class Generator(object):
14 implementationContent
= ""
17 "DeclarationNameInfo",
18 "NestedNameSpecifierLoc",
19 "TemplateArgumentLoc",
23 def __init__(self
, templateClasses
):
24 self
.templateClasses
= templateClasses
26 def GeneratePrologue(self
):
28 self
.implementationContent
+= r
"""
29 /*===- Generated file -------------------------------------------*- C++ -*-===*\
31 |* Introspection of available AST node SourceLocations *|
33 |* Automatically generated file, do not edit! *|
35 \*===----------------------------------------------------------------------===*/
40 using LocationAndString = SourceLocationMap::value_type;
41 using RangeAndString = SourceRangeMap::value_type;
43 bool NodeIntrospection::hasIntrospectionSupport() { return true; }
45 struct RecursionPopper
47 RecursionPopper(std::vector<clang::TypeLoc> &TypeLocRecursionGuard)
48 : TLRG(TypeLocRecursionGuard)
59 std::vector<clang::TypeLoc> &TLRG;
63 def GenerateBaseGetLocationsDeclaration(self
, CladeName
):
64 InstanceDecoration
= "*"
65 if CladeName
in self
.RefClades
:
66 InstanceDecoration
= "&"
68 self
.implementationContent
+= """
69 void GetLocationsImpl(SharedLocationCall const& Prefix,
70 clang::{0} const {1}Object, SourceLocationMap &Locs,
72 std::vector<clang::TypeLoc> &TypeLocRecursionGuard);
74 CladeName
, InstanceDecoration
77 def GenerateSrcLocMethod(self
, ClassName
, ClassData
, CreateLocalRecursionGuard
):
79 NormalClassName
= ClassName
80 RecursionGuardParam
= (
82 if CreateLocalRecursionGuard
83 else ", std::vector<clang::TypeLoc>& TypeLocRecursionGuard"
86 if "templateParms" in ClassData
:
87 TemplatePreamble
= "template <typename "
90 for TA
in ClassData
["templateParms"]:
93 TemplatePreamble
+= ", typename "
97 TemplatePreamble
+= TA
100 TemplatePreamble
+= ">\n"
101 self
.implementationContent
+= TemplatePreamble
103 self
.implementationContent
+= """
104 static void GetLocations{0}(SharedLocationCall const& Prefix,
105 clang::{1} const &Object,
106 SourceLocationMap &Locs, SourceRangeMap &Rngs {2})
109 NormalClassName
, ClassName
, RecursionGuardParam
112 if "sourceLocations" in ClassData
:
113 for locName
in ClassData
["sourceLocations"]:
114 self
.implementationContent
+= """
115 Locs.insert(LocationAndString(Object.{0}(),
116 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}")));
121 self
.implementationContent
+= "\n"
123 if "sourceRanges" in ClassData
:
124 for rngName
in ClassData
["sourceRanges"]:
125 self
.implementationContent
+= """
126 Rngs.insert(RangeAndString(Object.{0}(),
127 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}")));
132 self
.implementationContent
+= "\n"
135 "typeLocs" in ClassData
136 or "typeSourceInfos" in ClassData
137 or "nestedNameLocs" in ClassData
138 or "declNameInfos" in ClassData
140 if CreateLocalRecursionGuard
:
141 self
.implementationContent
+= (
142 "std::vector<clang::TypeLoc> TypeLocRecursionGuard;\n"
145 self
.implementationContent
+= "\n"
147 if "typeLocs" in ClassData
:
148 for typeLoc
in ClassData
["typeLocs"]:
150 self
.implementationContent
+= """
153 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}"),
154 Object.{0}(), Locs, Rngs, TypeLocRecursionGuard);
160 self
.implementationContent
+= "\n"
161 if "typeSourceInfos" in ClassData
:
162 for tsi
in ClassData
["typeSourceInfos"]:
163 self
.implementationContent
+= """
165 GetLocationsImpl(llvm::makeIntrusiveRefCnt<LocationCall>(
166 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}",
167 LocationCall::ReturnsPointer), "getTypeLoc"),
168 Object.{0}()->getTypeLoc(), Locs, Rngs, TypeLocRecursionGuard);
174 self
.implementationContent
+= "\n"
176 if "nestedNameLocs" in ClassData
:
177 for NN
in ClassData
["nestedNameLocs"]:
178 self
.implementationContent
+= """
181 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}"),
182 Object.{0}(), Locs, Rngs, TypeLocRecursionGuard);
187 if "declNameInfos" in ClassData
:
188 for declName
in ClassData
["declNameInfos"]:
190 self
.implementationContent
+= """
192 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}"),
193 Object.{0}(), Locs, Rngs, TypeLocRecursionGuard);
198 self
.implementationContent
+= "}\n"
200 def GenerateFiles(self
, OutputFile
):
201 with
open(os
.path
.join(os
.getcwd(), OutputFile
), "w") as f
:
202 f
.write(self
.implementationContent
)
204 def GenerateBaseGetLocationsFunction(
210 CreateLocalRecursionGuard
,
213 MethodReturnType
= "NodeLocationAccessors"
214 InstanceDecoration
= "*"
215 if CladeName
in self
.RefClades
:
216 InstanceDecoration
= "&"
218 Signature
= "GetLocations(clang::{0} const {1}Object)".format(
219 CladeName
, InstanceDecoration
222 GetLocationsImpl(SharedLocationCall const& Prefix,
223 clang::{0} const {1}Object, SourceLocationMap &Locs,
224 SourceRangeMap &Rngs,
225 std::vector<clang::TypeLoc> &TypeLocRecursionGuard)
227 CladeName
, InstanceDecoration
230 self
.implementationContent
+= "void {0} {{ ".format(ImplSignature
)
232 if CladeName
== "TypeLoc":
233 self
.implementationContent
+= "if (Object.isNull()) return;"
235 self
.implementationContent
+= """
236 if (llvm::find(TypeLocRecursionGuard, Object) != TypeLocRecursionGuard.end())
238 TypeLocRecursionGuard.push_back(Object);
239 RecursionPopper RAII(TypeLocRecursionGuard);
242 RecursionGuardParam
= ""
243 if not CreateLocalRecursionGuard
:
244 RecursionGuardParam
= ", TypeLocRecursionGuard"
247 if CladeName
in self
.RefClades
:
249 self
.implementationContent
+= (
250 "GetLocations{0}(Prefix, {1}Object, Locs, Rngs {2});".format(
251 CladeName
, ArgPrefix
, RecursionGuardParam
255 if CladeName
== "TypeLoc":
256 self
.implementationContent
+= """
257 if (auto QTL = Object.getAs<clang::QualifiedTypeLoc>()) {
258 auto Dequalified = QTL.getNextTypeLoc();
259 return GetLocationsImpl(llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "getNextTypeLoc"),
263 TypeLocRecursionGuard);
266 for ASTClassName
in ASTClassNames
:
267 if ASTClassName
in self
.templateClasses
:
269 if ASTClassName
== CladeName
:
271 if CladeName
!= "TypeLoc":
272 self
.implementationContent
+= """
273 if (auto Derived = llvm::dyn_cast<clang::{0}>(Object)) {{
274 GetLocations{0}(Prefix, *Derived, Locs, Rngs {1});
277 ASTClassName
, RecursionGuardParam
281 self
.GenerateBaseTypeLocVisit(
282 ASTClassName
, ClassEntries
, RecursionGuardParam
, InheritanceMap
285 self
.implementationContent
+= "}"
287 self
.implementationContent
+= """
288 {0} NodeIntrospection::{1} {{
289 NodeLocationAccessors Result;
290 SharedLocationCall Prefix;
291 std::vector<clang::TypeLoc> TypeLocRecursionGuard;
293 GetLocationsImpl(Prefix, Object, Result.LocationAccessors,
294 Result.RangeAccessors, TypeLocRecursionGuard);
296 MethodReturnType
, Signature
299 self
.implementationContent
+= "return Result; }"
301 def GenerateBaseTypeLocVisit(
302 self
, ASTClassName
, ClassEntries
, RecursionGuardParam
, InheritanceMap
304 CallPrefix
= "Prefix"
305 if ASTClassName
!= "TypeLoc":
306 CallPrefix
= """llvm::makeIntrusiveRefCnt<LocationCall>(Prefix,
307 "getAs<clang::{0}>", LocationCall::IsCast)
312 if ASTClassName
in ClassEntries
:
314 self
.implementationContent
+= """
315 if (auto ConcreteTL = Object.getAs<clang::{0}>())
316 GetLocations{1}({2}, ConcreteTL, Locs, Rngs {3});
318 ASTClassName
, ASTClassName
, CallPrefix
, RecursionGuardParam
321 if ASTClassName
in InheritanceMap
:
322 for baseTemplate
in self
.templateClasses
:
323 if baseTemplate
in InheritanceMap
[ASTClassName
]:
324 self
.implementationContent
+= """
325 if (auto ConcreteTL = Object.getAs<clang::{0}>())
326 GetLocations{1}({2}, ConcreteTL, Locs, Rngs {3});
328 InheritanceMap
[ASTClassName
],
334 def GenerateDynNodeVisitor(self
, CladeNames
):
335 MethodReturnType
= "NodeLocationAccessors"
337 Signature
= "GetLocations(clang::DynTypedNode const &Node)"
339 self
.implementationContent
+= (
340 MethodReturnType
+ " NodeIntrospection::" + Signature
+ "{"
343 for CladeName
in CladeNames
:
344 if CladeName
== "DeclarationNameInfo":
346 self
.implementationContent
+= """
347 if (const auto *N = Node.get<{0}>())
352 if CladeName
in self
.RefClades
:
354 self
.implementationContent
+= """
355 return GetLocations({0}const_cast<{1} *>(N));""".format(
359 self
.implementationContent
+= "\nreturn {}; }"
361 def GenerateEpilogue(self
):
363 self
.implementationContent
+= """
371 parser
= argparse
.ArgumentParser()
373 "--json-input-path", help="Read API description from FILE", metavar
="FILE"
376 "--output-file", help="Generate output in FILEPATH", metavar
="FILEPATH"
379 "--use-empty-implementation",
380 help="Generate empty implementation",
385 "--empty-implementation",
386 help="Copy empty implementation from FILEPATH",
391 options
= parser
.parse_args()
393 use_empty_implementation
= options
.use_empty_implementation
395 if not use_empty_implementation
and not os
.path
.exists(options
.json_input_path
):
396 use_empty_implementation
= True
398 if not use_empty_implementation
:
399 with
open(options
.json_input_path
) as f
:
400 jsonData
= json
.load(f
)
402 if not "classesInClade" in jsonData
or not jsonData
["classesInClade"]:
403 use_empty_implementation
= True
405 if use_empty_implementation
:
406 if not os
.path
.exists(options
.output_file
) or not filecmp
.cmp(
407 options
.empty_implementation
, options
.output_file
409 shutil
.copyfile(options
.empty_implementation
, options
.output_file
)
413 for (ClassName
, ClassAccessors
) in jsonData
["classEntries"].items():
414 if "templateParms" in ClassAccessors
:
415 templateClasses
.append(ClassName
)
417 g
= Generator(templateClasses
)
421 for (CladeName
, ClassNameData
) in jsonData
["classesInClade"].items():
422 g
.GenerateBaseGetLocationsDeclaration(CladeName
)
424 def getCladeName(ClassName
):
425 for (CladeName
, ClassNameData
) in jsonData
["classesInClade"].items():
426 if ClassName
in ClassNameData
:
429 for (ClassName
, ClassAccessors
) in jsonData
["classEntries"].items():
430 cladeName
= getCladeName(ClassName
)
431 g
.GenerateSrcLocMethod(
432 ClassName
, ClassAccessors
, cladeName
not in Generator
.RefClades
435 for (CladeName
, ClassNameData
) in jsonData
["classesInClade"].items():
436 g
.GenerateBaseGetLocationsFunction(
438 jsonData
["classEntries"],
440 jsonData
["classInheritance"],
441 CladeName
not in Generator
.RefClades
,
444 g
.GenerateDynNodeVisitor(jsonData
["classesInClade"].keys())
448 g
.GenerateFiles(options
.output_file
)
451 if __name__
== "__main__":