21#include <clang/Lex/Preprocessor.h>
26 clang::AccessSpecifier access_specifier)
29 switch (access_specifier) {
30 case clang::AccessSpecifier::AS_public:
33 case clang::AccessSpecifier::AS_private:
36 case clang::AccessSpecifier::AS_protected:
47 clang::ObjCIvarDecl::AccessControl access_specifier)
50 switch (access_specifier) {
51 case clang::ObjCIvarDecl::AccessControl::Public:
54 case clang::ObjCIvarDecl::AccessControl::Private:
57 case clang::ObjCIvarDecl::AccessControl::Protected:
71 const auto *parent{declaration.getParent()};
74 while ((parent !=
nullptr) && !parent->isNamespace()) {
75 parent = parent->getParent();
79 std::deque<std::string> namespace_tokens;
80 while ((parent !=
nullptr) && parent->isNamespace()) {
81 if (
const auto *ns_decl = clang::dyn_cast<clang::NamespaceDecl>(parent);
83 if (!ns_decl->isInline() && !ns_decl->isAnonymousNamespace())
84 namespace_tokens.push_front(ns_decl->getNameAsString());
87 parent = parent->getParent();
90 for (
const auto &ns_token : namespace_tokens) {
107 auto base_name = declaration.getNameAsString();
109 if (base_name.empty()) {
111 fmt::format(
"(anonymous_{})", std::to_string(declaration.getID()));
114 if ((declaration.getParent() !=
nullptr) &&
115 declaration.getParent()->isRecord()) {
119 std::deque<std::string> record_parent_names;
120 record_parent_names.push_front(base_name);
122 const auto *cls_parent{declaration.getParent()};
123 while (cls_parent->isRecord()) {
124 if (
const auto *record_decl =
125 clang::dyn_cast<clang::RecordDecl>(cls_parent);
126 record_decl !=
nullptr) {
127 record_parent_names.push_front(record_decl->getNameAsString());
129 cls_parent = cls_parent->getParent();
131 return fmt::format(
"{}", fmt::join(record_parent_names,
"##"));
137std::string
to_string(
const clang::ArrayType &array_type,
138 const clang::ASTContext &ctx,
bool try_canonical,
139 std::vector<std::string> &dimensions)
142 std::string array_size =
143 maybe_size.has_value() ? std::to_string(maybe_size.value()) :
"";
144 dimensions.emplace_back(std::move(array_size));
146 const auto underlying_type = array_type.getElementType();
148 if (underlying_type->isArrayType())
149 return to_string(*underlying_type->getAsArrayTypeUnsafe(), ctx,
150 try_canonical, dimensions);
152 std::string dimensions_str;
153 for (
const auto &d : dimensions) {
154 dimensions_str += fmt::format(
"[{}]", d);
157 "{}{}",
to_string(underlying_type, ctx, try_canonical), dimensions_str);
161 const clang::TemplateArgumentLoc &argLoc,
const clang::ASTContext &context)
164 llvm::raw_string_ostream stream(result);
166 clang::PrintingPolicy policy(context.getLangOpts());
168 const clang::TemplateArgument &arg = argLoc.getArgument();
170#if LLVM_VERSION_MAJOR > 18
171 arg.print(policy, stream,
false);
181std::string
to_string(
const clang::QualType &type,
const clang::ASTContext &ctx,
184 if (type->isArrayType()) {
185 std::vector<std::string> dimensions;
187 *type->getAsArrayTypeUnsafe(), ctx, try_canonical, dimensions);
190 clang::PrintingPolicy print_policy(ctx.getLangOpts());
191 print_policy.SuppressScope = 0;
192#if LLVM_VERSION_MAJOR < 21
193 print_policy.PrintCanonicalTypes = 0;
195 print_policy.PrintAsCanonical = 0;
200 result = type.getAsString(print_policy);
202 if (try_canonical && result.find(
'<') != std::string::npos) {
203 auto canonical_type_name =
204 type.getCanonicalType().getAsString(print_policy);
206 auto result_qualified_template_name =
207 result.substr(0, result.find(
'<'));
208 auto result_template_arguments = result.substr(result.find(
'<'));
210 auto canonical_qualified_template_name =
211 canonical_type_name.substr(0, canonical_type_name.find(
'<'));
214 if (result_qualified_template_name.size() <
215 canonical_qualified_template_name.size()) {
218 canonical_qualified_template_name + result_template_arguments;
225 result =
"(anonymous)";
230 const auto *declarationTag = type->getAsTagDecl();
231 if (declarationTag ==
nullptr) {
232 result =
"(unnamed undeclared)";
248 if (result.find(
"type-parameter-") != std::string::npos) {
251 [&result, &type](
auto *p) {
252 auto [unqualified_type, context] =
254 result = p->getDecl()->getNameAsString();
255 if (!context.empty()) {
256 std::vector<std::string> deduced_contexts;
258 for (
const auto &c : context) {
259 deduced_contexts.push_back(c.to_string());
262 result = fmt::format(
263 "{} {}", result, fmt::join(deduced_contexts,
" "));
272 const clang::ASTContext &ctx,
bool try_canonical)
274 return to_string(type.desugar(), ctx, try_canonical);
278 const clang::TemplateArgument &arg,
const clang::ASTContext *ctx)
280 switch (arg.getKind()) {
281 case clang::TemplateArgument::Expression:
283 case clang::TemplateArgument::Type:
284 return to_string(arg.getAsType(), *ctx,
false);
285 case clang::TemplateArgument::Null:
287 case clang::TemplateArgument::NullPtr:
289 case clang::TemplateArgument::Integral:
290 return std::to_string(arg.getAsIntegral().getExtValue());
291 case clang::TemplateArgument::Template:
293 case clang::TemplateArgument::TemplateExpansion:
294 return to_string(arg.getAsTemplateOrTemplatePattern());
302 if (templ.getAsTemplateDecl() !=
nullptr) {
303 return templ.getAsTemplateDecl()->getQualifiedNameAsString();
307 const clang::LangOptions lang_options;
308 llvm::raw_string_ostream ostream(result);
309 templ.print(ostream, clang::PrintingPolicy(lang_options));
316 const clang::LangOptions lang_options;
318 llvm::raw_string_ostream ostream(result);
319 expr->printPretty(ostream,
nullptr, clang::PrintingPolicy(lang_options));
326 return val->getQualifiedNameAsString();
331 const clang::LangOptions lang_options;
333 llvm::raw_string_ostream ostream(result);
334 stmt->printPretty(ostream,
nullptr, clang::PrintingPolicy(lang_options));
339std::string
to_string(
const clang::FunctionTemplateDecl *decl)
341 std::vector<std::string> template_parameters;
343 for (
const auto *parameter : *decl->getTemplateParameters()) {
344 if (clang::dyn_cast_or_null<clang::TemplateTypeParmDecl>(parameter) !=
346 const auto *template_type_parameter =
347 clang::dyn_cast_or_null<clang::TemplateTypeParmDecl>(parameter);
349 std::string template_parameter{
350 template_type_parameter->getNameAsString()};
352 if (template_type_parameter->isParameterPack())
353 template_parameter +=
"...";
355 template_parameters.emplace_back(std::move(template_parameter));
361 return fmt::format(
"{}<{}>({})", decl->getQualifiedNameAsString(),
362 fmt::join(template_parameters,
","),
"");
370 const clang::PrintingPolicy print_policy(
371 tc->getNamedConcept()->getASTContext().getLangOpts());
373 std::string ostream_buf;
374 llvm::raw_string_ostream ostream{ostream_buf};
375 tc->print(ostream, print_policy);
377 return ostream.str();
381 clang::SourceRange range,
const clang::SourceManager &sm)
383 return clang::Lexer::getSourceText(
384 clang::CharSourceRange::getCharRange(range), sm, clang::LangOptions())
389 clang::SourceRange range,
const clang::SourceManager &sm)
391 const clang::LangOptions lo;
393 auto start_loc = sm.getSpellingLoc(range.getBegin());
394 auto last_token_loc = sm.getSpellingLoc(range.getEnd());
395 auto end_loc = clang::Lexer::getLocForEndOfToken(last_token_loc, 0, sm, lo);
396 auto printable_range = clang::SourceRange{start_loc, end_loc};
400std::tuple<unsigned int, unsigned int, std::string>
403 assert(type_parameter.find(
"type-parameter-") == 0);
405 auto type_parameter_and_suffix =
util::split(type_parameter,
" ");
408 type_parameter_and_suffix.front().substr(strlen(
"type-parameter-")),
411 std::string qualifier;
413 if (type_parameter_and_suffix.size() > 1) {
414 qualifier = type_parameter_and_suffix.at(1);
417 return {std::stoi(toks.at(0)), std::stoi(toks.at(1)), std::move(qualifier)};
425 fmt::format(
"{}", std::filesystem::current_path().root_name().
string());
427 auto root_name = std::string{
"/"};
430 std::string lambda_prefix{fmt::format(
"(lambda at {}", root_name)};
432 while (parameter_type.find(lambda_prefix) != std::string::npos) {
433 auto lambda_begin = parameter_type.find(lambda_prefix);
434 auto lambda_prefix_size = lambda_prefix.size();
437 lambda_prefix_size++;
439 auto absolute_lambda_path_end =
440 parameter_type.find(
':', lambda_begin + lambda_prefix_size);
441 auto absolute_lambda_path = parameter_type.substr(
442 lambda_begin + lambda_prefix_size - 1,
443 absolute_lambda_path_end - (lambda_begin + lambda_prefix_size - 1));
448 parameter_type = fmt::format(
"{}(lambda at {}{}",
449 parameter_type.substr(0, lambda_begin), relative_lambda_path,
450 parameter_type.substr(absolute_lambda_path_end));
454bool is_subexpr_of(
const clang::Stmt *parent_stmt,
const clang::Stmt *sub_stmt)
456 if (parent_stmt ==
nullptr || sub_stmt ==
nullptr)
459 if (parent_stmt == sub_stmt)
462 return std::any_of(parent_stmt->child_begin(), parent_stmt->child_end(),
463 [sub_stmt](
const auto *e) { return is_subexpr_of(e, sub_stmt); });
468 return static_cast<eid_t>(
469 static_cast<uint64_t
>(std::hash<std::string>{}(full_name)));
472eid_t to_id(
const clang::QualType &type,
const clang::ASTContext &ctx)
477template <>
eid_t to_id(
const clang::NamespaceDecl &declaration)
489 return to_id(fmt::format(
"__objc__category__{}", type.getNameAsString()));
494 return to_id(fmt::format(
"__objc__interface__{}", type.getNameAsString()));
499 return to_id(fmt::format(
"__objc__protocol__{}", type.getNameAsString()));
512template <>
eid_t to_id(
const clang::CXXRecordDecl &declaration)
519 return to_id(*t.getDecl());
524 return to_id(file.lexically_normal().string());
527template <>
eid_t to_id(
const clang::TemplateArgument &template_argument)
529 if (template_argument.getKind() == clang::TemplateArgument::Type) {
530 if (
const auto *enum_type =
531 template_argument.getAsType()->getAs<clang::EnumType>();
532 enum_type !=
nullptr)
533 return to_id(*enum_type->getAsTagDecl());
535 if (
const auto *record_type =
536 template_argument.getAsType()->getAs<clang::RecordType>();
537 record_type !=
nullptr)
538 return to_id(*record_type->getAsRecordDecl());
541 throw std::runtime_error(
"Cannot generate id for template argument");
544std::pair<common::model::namespace_, std::string>
split_ns(
545 const std::string &full_name)
547 assert(!full_name.empty());
552 auto name = ns.name();
558 const std::string ¶ms,
559 const std::function<std::string(
const std::string &)> &ns_resolve,
564 std::vector<template_parameter> res;
566 auto it = params.begin();
567 while (std::isspace(*it) != 0)
571 std::vector<template_parameter> nested_params;
572 bool complete_class_template_argument{
false};
574 while (it != params.end()) {
577 auto bracket_match_begin = it + 1;
578 auto bracket_match_end = bracket_match_begin;
579 while (bracket_match_end != params.end()) {
580 if (*bracket_match_end ==
'<') {
583 else if (*bracket_match_end ==
'>') {
584 if (nested_level > 0)
594 std::string nested_params_str(
595 bracket_match_begin, bracket_match_end);
598 nested_params_str, ns_resolve, depth + 1);
600 if (nested_params.empty()) {
604 nested_params.emplace_back(
605 template_parameter::make_unexposed_argument(
609 it = bracket_match_end - 1;
611 else if (*it ==
'>') {
612 complete_class_template_argument =
true;
617 else if (*it ==
',') {
618 complete_class_template_argument =
true;
623 if (complete_class_template_argument) {
624 auto t = template_parameter::make_unexposed_argument(
627 for (
auto &¶m : nested_params)
628 t.add_template_param(std::move(param));
630 res.emplace_back(std::move(t));
631 complete_class_template_argument =
false;
637 auto t = template_parameter::make_unexposed_argument(
640 for (
auto &¶m : nested_params)
641 t.add_template_param(std::move(param));
643 res.emplace_back(std::move(t));
651 return t.find(
"type-parameter-") == 0;
656 return q ==
"&" || q ==
"&&" || q ==
"const&";
661 return b ==
"(" || b ==
")" || b ==
"[" || b ==
"]";
666 return std::isalnum(c) != 0 || c ==
'_';
671 return std::all_of(t.begin(), t.end(),
672 [](
const char c) { return is_identifier_character(c); });
677 static std::vector<std::string> keywords{
"alignas",
"alignof",
"asm",
678 "auto",
"bool",
"break",
"case",
"catch",
"char",
"char16_t",
679 "char32_t",
"class",
"concept",
"const",
"constexpr",
"const_cast",
680 "continue",
"decltype",
"default",
"delete",
"do",
"double",
681 "dynamic_cast",
"else",
"enum",
"explicit",
"export",
"extern",
"false",
682 "float",
"for",
"friend",
"goto",
"if",
"inline",
"int",
"long",
683 "mutable",
"namespace",
"new",
"noexcept",
"nullptr",
"operator",
684 "private",
"protected",
"public",
"register",
"reinterpret_cast",
685 "return",
"requires",
"short",
"signed",
"sizeof",
"static",
686 "static_assert",
"static_cast",
"struct",
"switch",
"template",
"this",
687 "thread_local",
"throw",
"true",
"try",
"typedef",
"typeid",
"typename",
688 "union",
"unsigned",
"using",
"virtual",
"void",
"volatile",
"wchar_t",
696 return std::isalpha(t.at(0)) != 0 &&
697 std::all_of(t.begin(), t.end(), [](
const char c) {
698 return is_identifier_character(c) || c ==
':';
710 std::string result{condition_text};
712 if (result.size() < 2)
715 std::vector<std::string> text_lines =
util::split(result,
"\n",
true);
718 for (
auto &line : text_lines) {
724 if (result.at(0) ==
'(' && result.back() ==
')')
725 return result.substr(1, result.size() - 2);
732 auto condition_range =
733 clang::SourceRange(stmt->getLParenLoc(), stmt->getRParenLoc());
740 auto condition_range =
741 clang::SourceRange(stmt->getLParenLoc(), stmt->getRParenLoc());
747 clang::SourceManager &sm, clang::CXXForRangeStmt *stmt)
749 auto condition_range = stmt->getRangeStmt()->getSourceRange();
756 auto condition_range =
757 clang::SourceRange(stmt->getLParenLoc(), stmt->getRParenLoc());
764 auto condition_range = stmt->getCond()->getSourceRange();
770 clang::SourceManager &sm, clang::ConditionalOperator *stmt)
772 auto condition_range = stmt->getCond()->getSourceRange();
782 if (res->isReferenceType())
783 res = res.getNonReferenceType();
784 else if (res->isPointerType())
785 res = res->getPointeeType();
793std::pair<clang::QualType, std::deque<common::model::context>>
796 std::deque<common::model::context> res;
799 bool try_again{
false};
802 if (type.isConstQualified()) {
807 if (type.isVolatileQualified()) {
812 if (type->isPointerType() || type->isReferenceType()) {
813 if (type.isConstQualified() || type.isVolatileQualified()) {
821 if (type->isLValueReferenceType()) {
825 else if (type->isRValueReferenceType()) {
829 else if (type->isMemberFunctionPointerType() &&
830 type->getPointeeType()->getAs<clang::FunctionProtoType>() !=
832 const auto ref_qualifier =
833 type->getPointeeType()
834 ->getAs<clang::FunctionProtoType>()
837 if (ref_qualifier == clang::RefQualifierKind::RQ_RValue) {
841 else if (ref_qualifier == clang::RefQualifierKind::RQ_LValue) {
846 else if (type->isPointerType()) {
852 if (type->isPointerType()) {
853 if (type->getPointeeType().isConstQualified())
855 if (type->getPointeeType().isVolatileQualified())
858 type = type->getPointeeType().getUnqualifiedType();
860 else if (type->isReferenceType()) {
861 if (type.getNonReferenceType().isConstQualified())
863 if (type.getNonReferenceType().isVolatileQualified())
866 type = type.getNonReferenceType().getUnqualifiedType();
868 else if (type.isConstQualified() || type.isVolatileQualified()) {
869 ctx.
is_const = type.isConstQualified();
871 type = type.getUnqualifiedType();
876 if (type->isMemberFunctionPointerType())
877 return std::make_pair(type, res);
880 return std::make_pair(type, res);
885 const std::string &t)
887 std::vector<std::string> result;
891 for (
const auto &word : spaced_out) {
893 if (word !=
"class" && word !=
"templated" && word !=
"struct")
894 result.emplace_back(word);
900 for (
const char c : word) {
901 if (c ==
'(' || c ==
')' || c ==
'[' || c ==
']' || c ==
'<' ||
904 result.emplace_back(tok);
905 result.emplace_back(std::string{c});
909 if (!tok.empty() && tok !=
":") {
910 result.emplace_back(tok);
913 else if (tok ==
":") {
914 result.emplace_back(
"::");
923 result.emplace_back(tok);
925 result.emplace_back(
",");
930 result.emplace_back(tok);
932 result.emplace_back(
"*");
939 result.emplace_back(
"...");
942 else if (tok ==
".") {
945 else if (!tok.empty()) {
946 result.emplace_back(tok);
958 if (tok !=
"class" && tok !=
"typename" && word !=
"struct")
959 result.emplace_back(tok);
968 unsigned &line,
unsigned &column)
972 if (tokens.size() < 3)
975 if (tokens.size() == 4) {
977 decltype(tokens) tmp_tokens{};
978 tmp_tokens.emplace_back(
979 fmt::format(
"{}:{}", tokens.at(0), tokens.at(1)));
980 tmp_tokens.emplace_back(tokens.at(2));
981 tmp_tokens.emplace_back(tokens.at(3));
983 tokens = std::move(tmp_tokens);
988 line = std::stoi(tokens.at(1));
990 catch (std::invalid_argument &e) {
995 column = std::stoi(tokens.at(2));
997 catch (std::invalid_argument &e) {
1005 const clang::ASTContext &context,
const clang::Stmt *stmt)
1011 const clang::ASTContext &context,
const clang::Decl *decl)
1017 const clang::ASTContext &context,
const clang::SourceRange &source_range)
1019 auto expr_begin = sm.getExpansionLoc(source_range.getBegin());
1020 const auto expr_begin_line = sm.getExpansionLineNumber(expr_begin);
1022 auto file_id = sm.getFileID(expr_begin);
1024 const auto has_comments = !context.Comments.empty();
1025 const auto *comments = context.Comments.getCommentsInFile(file_id);
1027 if (has_comments && comments !=
nullptr) {
1028 for (
const auto [offset, raw_comment] :
1029 *context.Comments.getCommentsInFile(sm.getFileID(expr_begin))) {
1030 const auto comment_end_line = sm.getExpansionLineNumber(
1031 raw_comment->getSourceRange().getEnd());
1033 if (expr_begin_line == comment_end_line ||
1034 expr_begin_line == comment_end_line + 1)
1044 const auto *body = decl.getBody();
1045 return clang::isa_and_nonnull<clang::CoroutineBodyStmt>(body);
1050 if (decl ==
nullptr)
1053 if (
const auto *record = clang::dyn_cast<clang::CXXRecordDecl>(decl);
1055 return record->isStruct();
1058 if (
const auto *tag = clang::dyn_cast<clang::TagDecl>(decl); tag) {
1059 return tag->isStruct();
1065bool has_attr(
const clang::FunctionDecl *decl, clang::attr::Kind function_attr)
1067 return std::any_of(decl->attrs().begin(), decl->attrs().end(),
1069 auto &&attr) { return attr->getKind() == function_attr; });
1074 if (
const auto *constant_array =
1075 clang::dyn_cast<clang::ConstantArrayType>(&type);
1076 constant_array !=
nullptr) {
1077 return {constant_array->getSize().getZExtValue()};
1084 const clang::SourceLocation &location,
1086 std::filesystem::path tu_path, std::filesystem::path relative_to_path_)
1088 namespace fs = std::filesystem;
1094 if (location.isValid()) {
1096 source_manager.getFilename(source_manager.getSpellingLoc(location))
1098 line = source_manager.getSpellingLineNumber(location);
1099 column = source_manager.getSpellingColumnNumber(location);
1104 location.printToString(source_manager), file, line, column);
1109 location.printToString(source_manager), file, line, column);
1111 LOG_DBG(
"Failed to extract source location for element from {}",
1112 location.printToString(source_manager));
1118 fs::path file_path{file};
1119 if (!file_path.is_absolute()) {
1120 file_path = fs::absolute(file_path);
1123 file_path = weakly_canonical(file_path);
1125 file = file_path.string();
1131 fs::path{element.
file()}.lexically_relative(relative_to_path_)));
1145 const auto *type_source_info = decl->getTypeSourceInfo();
1147 if (type_source_info ==
nullptr)
1150 return type_source_info->getType().split().Ty;
1155 if (decl ==
nullptr)
1160#if LLVM_VERSION_MAJOR < 22
1161 if (unqualified_type->getTypeClass() == clang::Type::Elaborated) {
1162 const auto *tag_decl =
1163 clang::cast<clang::ElaboratedType>(unqualified_type)
1167 if (tag_decl ==
nullptr)
1170 const auto *enum_decl = clang::dyn_cast<clang::EnumDecl>(tag_decl);
1171 if (enum_decl !=
nullptr && enum_decl->getIdentifier() ==
nullptr)
1176 const auto *tag_decl = unqualified_type->getAsTagDecl();
1178 if (tag_decl ==
nullptr)
1181 const auto *enum_decl = clang::dyn_cast<clang::EnumDecl>(tag_decl);
1182 if (enum_decl !=
nullptr && enum_decl->getIdentifier() ==
nullptr)
1191 const clang::TemplateTypeParmType *type_parameter,
1192 const clang::TemplateDecl *template_decl)
1194 clang::TemplateTypeParmDecl *template_type_parameter{
nullptr};
1196#if LLVM_VERSION_MAJOR >= 22
1203 if (template_decl->getTemplateParameters()->size() >
1204 type_parameter->getIndex()) {
1205 template_type_parameter = clang::dyn_cast<clang::TemplateTypeParmDecl>(
1206 template_decl->getTemplateParameters()->getParam(
1207 type_parameter->getIndex()));
1209 if (template_type_parameter ==
nullptr &&
1210 type_parameter->getDecl() !=
nullptr) {
1211 template_type_parameter = type_parameter->getDecl();
1214 if (type_parameter->getDecl() !=
nullptr) {
1215 template_type_parameter = type_parameter->getDecl();
1217 else if (template_decl->getTemplateParameters()->size() >
1218 type_parameter->getIndex()) {
1219 template_type_parameter = clang::dyn_cast<clang::TemplateTypeParmDecl>(
1220 template_decl->getTemplateParameters()->getParam(
1221 type_parameter->getIndex()));
1225 if (template_type_parameter ==
nullptr ||
1226 template_type_parameter->getTypeConstraint() ==
nullptr)
1229#if LLVM_VERSION_MAJOR < 22
1230 return template_type_parameter->getTypeConstraint()->getNamedConcept();
1232 return clang::cast<clang::ConceptDecl>(
1233 template_type_parameter->getTypeConstraint()->getNamedConcept());
1239 const auto *call_expr = clang::dyn_cast<clang::CallExpr>(expr);
1241 if (call_expr ==
nullptr)
1244 if (clang::dyn_cast_or_null<clang::LambdaExpr>(call_expr->getCallee()) !=
1249 const auto *function_callee = call_expr->getDirectCallee();
1250 if (function_callee !=
nullptr) {
1252 const auto *method_decl =
1253 clang::dyn_cast<clang::CXXMethodDecl>(function_callee);
1254 if (method_decl ==
nullptr)
1257 if (method_decl->getParent()->isLambda() &&
1258 method_decl->getOverloadedOperator() == clang::OO_Call) {
1268 if (decl ==
nullptr)
1271 if (
const auto *method = clang::dyn_cast<clang::CXXMethodDecl>(decl);
1272 method !=
nullptr) {
1273 if (method->getParent() !=
nullptr && method->getParent()->isLambda())