1 //===-- Language.h ---------------------------------------------------*- C++ 2 //-*-===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef liblldb_Language_h_ 11 #define liblldb_Language_h_ 12 13 #include <functional> 14 #include <memory> 15 #include <set> 16 #include <vector> 17 18 #include "lldb/Core/Highlighter.h" 19 #include "lldb/Core/PluginInterface.h" 20 #include "lldb/DataFormatters/DumpValueObjectOptions.h" 21 #include "lldb/DataFormatters/FormatClasses.h" 22 #include "lldb/DataFormatters/StringPrinter.h" 23 #include "lldb/lldb-private.h" 24 #include "lldb/lldb-public.h" 25 26 namespace lldb_private { 27 28 class Language : public PluginInterface { 29 public: 30 class TypeScavenger { 31 public: 32 class Result { 33 public: 34 virtual bool IsValid() = 0; 35 36 virtual bool DumpToStream(Stream &stream, 37 bool print_help_if_available) = 0; 38 39 virtual ~Result() = default; 40 }; 41 42 typedef std::set<std::unique_ptr<Result>> ResultSet; 43 44 virtual ~TypeScavenger() = default; 45 46 size_t Find(ExecutionContextScope *exe_scope, const char *key, 47 ResultSet &results, bool append = true); 48 49 protected: 50 TypeScavenger() = default; 51 52 virtual bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 53 ResultSet &results) = 0; 54 }; 55 56 class ImageListTypeScavenger : public TypeScavenger { 57 class Result : public Language::TypeScavenger::Result { 58 public: 59 Result(CompilerType type) 60 : Language::TypeScavenger::Result(), m_compiler_type(type) {} 61 62 bool IsValid() override { return m_compiler_type.IsValid(); } 63 64 bool DumpToStream(Stream &stream, bool print_help_if_available) override { 65 if (IsValid()) { 66 m_compiler_type.DumpTypeDescription(&stream); 67 stream.EOL(); 68 return true; 69 } 70 return false; 71 } 72 73 ~Result() override = default; 74 75 private: 76 CompilerType m_compiler_type; 77 }; 78 79 protected: 80 ImageListTypeScavenger() = default; 81 82 ~ImageListTypeScavenger() override = default; 83 84 // is this type something we should accept? it's usually going to be a 85 // filter by language + maybe some sugar tweaking 86 // returning an empty type means rejecting this candidate entirely; 87 // any other result will be accepted as a valid match 88 virtual CompilerType AdjustForInclusion(CompilerType &candidate) = 0; 89 90 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 91 ResultSet &results) override; 92 }; 93 94 template <typename... ScavengerTypes> 95 class EitherTypeScavenger : public TypeScavenger { 96 public: 97 EitherTypeScavenger() : TypeScavenger(), m_scavengers() { 98 for (std::shared_ptr<TypeScavenger> scavenger : { std::shared_ptr<TypeScavenger>(new ScavengerTypes())... }) { 99 if (scavenger) 100 m_scavengers.push_back(scavenger); 101 } 102 } 103 protected: 104 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 105 ResultSet &results) override { 106 const bool append = false; 107 for (auto& scavenger : m_scavengers) { 108 if (scavenger && scavenger->Find(exe_scope, key, results, append)) 109 return true; 110 } 111 return false; 112 } 113 private: 114 std::vector<std::shared_ptr<TypeScavenger>> m_scavengers; 115 }; 116 117 template <typename... ScavengerTypes> 118 class UnionTypeScavenger : public TypeScavenger { 119 public: 120 UnionTypeScavenger() : TypeScavenger(), m_scavengers() { 121 for (std::shared_ptr<TypeScavenger> scavenger : { std::shared_ptr<TypeScavenger>(new ScavengerTypes())... }) { 122 if (scavenger) 123 m_scavengers.push_back(scavenger); 124 } 125 } 126 protected: 127 bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 128 ResultSet &results) override { 129 const bool append = true; 130 bool success = false; 131 for (auto& scavenger : m_scavengers) { 132 if (scavenger) 133 success = scavenger->Find(exe_scope, key, results, append) || success; 134 } 135 return success; 136 } 137 private: 138 std::vector<std::shared_ptr<TypeScavenger>> m_scavengers; 139 }; 140 141 enum class FunctionNameRepresentation { 142 eName, 143 eNameWithArgs, 144 eNameWithNoArgs 145 }; 146 147 ~Language() override; 148 149 static Language *FindPlugin(lldb::LanguageType language); 150 151 /// Returns the Language associated with the given file path or a nullptr 152 /// if there is no known language. 153 static Language *FindPlugin(llvm::StringRef file_path); 154 155 static Language *FindPlugin(lldb::LanguageType language, 156 llvm::StringRef file_path); 157 158 // return false from callback to stop iterating 159 static void ForEach(std::function<bool(Language *)> callback); 160 161 virtual lldb::LanguageType GetLanguageType() const = 0; 162 163 virtual bool IsTopLevelFunction(Function &function); 164 165 virtual bool IsSourceFile(llvm::StringRef file_path) const = 0; 166 167 virtual const Highlighter *GetHighlighter() const { return nullptr; } 168 169 virtual lldb::TypeCategoryImplSP GetFormatters(); 170 171 virtual HardcodedFormatters::HardcodedFormatFinder GetHardcodedFormats(); 172 173 virtual HardcodedFormatters::HardcodedSummaryFinder GetHardcodedSummaries(); 174 175 virtual HardcodedFormatters::HardcodedSyntheticFinder 176 GetHardcodedSynthetics(); 177 178 virtual HardcodedFormatters::HardcodedValidatorFinder 179 GetHardcodedValidators(); 180 181 virtual std::vector<ConstString> 182 GetPossibleFormattersMatches(ValueObject &valobj, 183 lldb::DynamicValueType use_dynamic); 184 185 virtual lldb_private::formatters::StringPrinter::EscapingHelper 186 GetStringPrinterEscapingHelper( 187 lldb_private::formatters::StringPrinter::GetPrintableElementType); 188 189 virtual std::unique_ptr<TypeScavenger> GetTypeScavenger(); 190 191 virtual const char *GetLanguageSpecificTypeLookupHelp(); 192 193 // If a language can have more than one possible name for a method, this 194 // function can be used to enumerate them. This is useful when doing name 195 // lookups. 196 virtual std::vector<ConstString> 197 GetMethodNameVariants(ConstString method_name) const { 198 return std::vector<ConstString>(); 199 }; 200 201 // if an individual data formatter can apply to several types and cross a 202 // language boundary it makes sense for individual languages to want to 203 // customize the printing of values of that type by appending proper 204 // prefix/suffix information in language-specific ways 205 virtual bool GetFormatterPrefixSuffix(ValueObject &valobj, 206 ConstString type_hint, 207 std::string &prefix, 208 std::string &suffix); 209 210 // if a language has a custom format for printing variable declarations that 211 // it wants LLDB to honor it should return an appropriate closure here 212 virtual DumpValueObjectOptions::DeclPrintingHelper GetDeclPrintingHelper(); 213 214 virtual LazyBool IsLogicalTrue(ValueObject &valobj, Status &error); 215 216 // for a ValueObject of some "reference type", if the value points to the 217 // nil/null object, this method returns true 218 virtual bool IsNilReference(ValueObject &valobj); 219 220 // for a ValueObject of some "reference type", if the language provides a 221 // technique to decide whether the reference has ever been assigned to some 222 // object, this method will return true if such detection is possible, and if 223 // the reference has never been assigned 224 virtual bool IsUninitializedReference(ValueObject &valobj); 225 226 virtual bool GetFunctionDisplayName(const SymbolContext *sc, 227 const ExecutionContext *exe_ctx, 228 FunctionNameRepresentation representation, 229 Stream &s); 230 231 virtual void GetExceptionResolverDescription(bool catch_on, bool throw_on, 232 Stream &s); 233 234 static void GetDefaultExceptionResolverDescription(bool catch_on, 235 bool throw_on, Stream &s); 236 237 // These are accessors for general information about the Languages lldb knows 238 // about: 239 240 static lldb::LanguageType 241 GetLanguageTypeFromString(const char *string) = delete; 242 static lldb::LanguageType GetLanguageTypeFromString(llvm::StringRef string); 243 244 static const char *GetNameForLanguageType(lldb::LanguageType language); 245 246 static void PrintAllLanguages(Stream &s, const char *prefix, 247 const char *suffix); 248 249 // return false from callback to stop iterating 250 static void ForAllLanguages(std::function<bool(lldb::LanguageType)> callback); 251 252 static bool LanguageIsCPlusPlus(lldb::LanguageType language); 253 254 static bool LanguageIsObjC(lldb::LanguageType language); 255 256 static bool LanguageIsC(lldb::LanguageType language); 257 258 /// Equivalent to \c LanguageIsC||LanguageIsObjC||LanguageIsCPlusPlus. 259 static bool LanguageIsCFamily(lldb::LanguageType language); 260 261 static bool LanguageIsPascal(lldb::LanguageType language); 262 263 // return the primary language, so if LanguageIsC(l), return eLanguageTypeC, 264 // etc. 265 static lldb::LanguageType GetPrimaryLanguage(lldb::LanguageType language); 266 267 static std::set<lldb::LanguageType> GetSupportedLanguages(); 268 269 static void GetLanguagesSupportingTypeSystems( 270 std::set<lldb::LanguageType> &languages, 271 std::set<lldb::LanguageType> &languages_for_expressions); 272 273 static void 274 GetLanguagesSupportingREPLs(std::set<lldb::LanguageType> &languages); 275 276 protected: 277 // Classes that inherit from Language can see and modify these 278 279 Language(); 280 281 private: 282 DISALLOW_COPY_AND_ASSIGN(Language); 283 }; 284 285 } // namespace lldb_private 286 287 #endif // liblldb_Language_h_ 288