| 1 | //===-- ObjCLanguage.h ------------------------------------------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H |
| 10 | #define LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H |
| 11 | |
| 12 | #include <cstring> |
| 13 | #include <vector> |
| 14 | |
| 15 | #include "Plugins/Language/ClangCommon/ClangHighlighter.h" |
| 16 | #include "lldb/Target/Language.h" |
| 17 | #include "lldb/Utility/ConstString.h" |
| 18 | #include "lldb/lldb-private.h" |
| 19 | |
| 20 | namespace lldb_private { |
| 21 | |
| 22 | class ObjCLanguage : public Language { |
| 23 | ClangHighlighter m_highlighter; |
| 24 | |
| 25 | public: |
| 26 | class ObjCMethodName { |
| 27 | public: |
| 28 | /// The static factory method for creating a ObjCMethodName. |
| 29 | /// |
| 30 | /// \param[in] name |
| 31 | /// The name of the method. |
| 32 | /// |
| 33 | /// \param[in] strict |
| 34 | /// Control whether or not the name parser is strict about +/- in the |
| 35 | /// front of the name. |
| 36 | /// |
| 37 | /// \return If the name failed to parse as a valid Objective-C method name, |
| 38 | /// returns std::nullopt. Otherwise returns a const ObjCMethodName. |
| 39 | static std::optional<const ObjCMethodName> Create(llvm::StringRef name, |
| 40 | bool strict); |
| 41 | |
| 42 | /// Determines if this method is a class method |
| 43 | /// |
| 44 | /// \return Returns true if the method is a class method. False otherwise. |
| 45 | bool IsClassMethod() const { return m_type == eTypeClassMethod; } |
| 46 | |
| 47 | /// Determines if this method is an instance method |
| 48 | /// |
| 49 | /// \return Returns true if the method is an instance method. False |
| 50 | /// otherwise. |
| 51 | bool IsInstanceMethod() const { return m_type == eTypeInstanceMethod; } |
| 52 | |
| 53 | /// Returns the full name of the method. |
| 54 | /// |
| 55 | /// This includes the class name, the category name (if applicable), and the |
| 56 | /// selector name. |
| 57 | /// |
| 58 | /// \return The name of the method in the form of a const std::string |
| 59 | /// reference. |
| 60 | const std::string &GetFullName() const { return m_full; } |
| 61 | |
| 62 | /// Creates a variation of this method without the category. |
| 63 | /// If this method has no category, it returns an empty string. |
| 64 | /// |
| 65 | /// Example: |
| 66 | /// Full name: "+[NSString(my_additions) myStringWithCString:]" |
| 67 | /// becomes "+[NSString myStringWithCString:]" |
| 68 | /// |
| 69 | /// \return The method name without the category or an empty string if there |
| 70 | /// was no category to begin with. |
| 71 | std::string GetFullNameWithoutCategory() const; |
| 72 | |
| 73 | /// Returns a reference to the class name. |
| 74 | /// |
| 75 | /// Example: |
| 76 | /// Full name: "+[NSString(my_additions) myStringWithCString:]" |
| 77 | /// will give you "NSString" |
| 78 | /// |
| 79 | /// \return A StringRef to the class name of this method. |
| 80 | llvm::StringRef GetClassName() const; |
| 81 | |
| 82 | /// Returns a reference to the class name with the category. |
| 83 | /// |
| 84 | /// Example: |
| 85 | /// Full name: "+[NSString(my_additions) myStringWithCString:]" |
| 86 | /// will give you "NSString(my_additions)" |
| 87 | /// |
| 88 | /// Note: If your method has no category, this will give the same output as |
| 89 | /// `GetClassName`. |
| 90 | /// |
| 91 | /// \return A StringRef to the class name (including the category) of this |
| 92 | /// method. If there was no category, returns the same as `GetClassName`. |
| 93 | llvm::StringRef GetClassNameWithCategory() const; |
| 94 | |
| 95 | /// Returns a reference to the category name. |
| 96 | /// |
| 97 | /// Example: |
| 98 | /// Full name: "+[NSString(my_additions) myStringWithCString:]" |
| 99 | /// will give you "my_additions" |
| 100 | /// \return A StringRef to the category name of this method. If no category |
| 101 | /// is present, the StringRef is empty. |
| 102 | llvm::StringRef GetCategory() const; |
| 103 | |
| 104 | /// Returns a reference to the selector name. |
| 105 | /// |
| 106 | /// Example: |
| 107 | /// Full name: "+[NSString(my_additions) myStringWithCString:]" |
| 108 | /// will give you "myStringWithCString:" |
| 109 | /// \return A StringRef to the selector of this method. |
| 110 | llvm::StringRef GetSelector() const; |
| 111 | |
| 112 | protected: |
| 113 | enum Type { eTypeUnspecified, eTypeClassMethod, eTypeInstanceMethod }; |
| 114 | |
| 115 | ObjCMethodName(llvm::StringRef name, Type type) |
| 116 | : m_full(name.str()), m_type(type) {} |
| 117 | |
| 118 | const std::string m_full; |
| 119 | Type m_type; |
| 120 | }; |
| 121 | |
| 122 | ObjCLanguage() = default; |
| 123 | |
| 124 | ~ObjCLanguage() override = default; |
| 125 | |
| 126 | lldb::LanguageType GetLanguageType() const override { |
| 127 | return lldb::eLanguageTypeObjC; |
| 128 | } |
| 129 | |
| 130 | llvm::StringRef GetUserEntryPointName() const override { return "main" ; } |
| 131 | |
| 132 | // Get all possible names for a method. Examples: |
| 133 | // If method_name is "+[NSString(my_additions) myStringWithCString:]" |
| 134 | // variant_names[0] => "+[NSString myStringWithCString:]" |
| 135 | // If name is specified without the leading '+' or '-' like |
| 136 | // "[NSString(my_additions) myStringWithCString:]" |
| 137 | // variant_names[0] => "+[NSString(my_additions) myStringWithCString:]" |
| 138 | // variant_names[1] => "-[NSString(my_additions) myStringWithCString:]" |
| 139 | // variant_names[2] => "+[NSString myStringWithCString:]" |
| 140 | // variant_names[3] => "-[NSString myStringWithCString:]" |
| 141 | // Also returns the FunctionNameType of each possible name. |
| 142 | std::vector<Language::MethodNameVariant> |
| 143 | GetMethodNameVariants(ConstString method_name) const override; |
| 144 | |
| 145 | std::pair<lldb::FunctionNameType, std::optional<ConstString>> |
| 146 | GetFunctionNameInfo(ConstString name) const override; |
| 147 | |
| 148 | bool SymbolNameFitsToLanguage(Mangled mangled) const override; |
| 149 | |
| 150 | lldb::TypeCategoryImplSP GetFormatters() override; |
| 151 | |
| 152 | std::vector<FormattersMatchCandidate> |
| 153 | GetPossibleFormattersMatches(ValueObject &valobj, |
| 154 | lldb::DynamicValueType use_dynamic) override; |
| 155 | |
| 156 | std::unique_ptr<TypeScavenger> GetTypeScavenger() override; |
| 157 | |
| 158 | std::pair<llvm::StringRef, llvm::StringRef> |
| 159 | GetFormatterPrefixSuffix(llvm::StringRef type_hint) override; |
| 160 | |
| 161 | bool IsNilReference(ValueObject &valobj) override; |
| 162 | |
| 163 | llvm::StringRef GetNilReferenceSummaryString() override { return "nil" ; } |
| 164 | |
| 165 | bool IsSourceFile(llvm::StringRef file_path) const override; |
| 166 | |
| 167 | const Highlighter *GetHighlighter() const override { return &m_highlighter; } |
| 168 | |
| 169 | // Static Functions |
| 170 | static void Initialize(); |
| 171 | |
| 172 | static void Terminate(); |
| 173 | |
| 174 | static lldb_private::Language *CreateInstance(lldb::LanguageType language); |
| 175 | |
| 176 | static llvm::StringRef GetPluginNameStatic() { return "objc" ; } |
| 177 | |
| 178 | static bool IsPossibleObjCMethodName(const char *name) { |
| 179 | if (!name) |
| 180 | return false; |
| 181 | bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '['; |
| 182 | bool ends_right = (name[strlen(s: name) - 1] == ']'); |
| 183 | return (starts_right && ends_right); |
| 184 | } |
| 185 | |
| 186 | static bool IsPossibleObjCSelector(const char *name) { |
| 187 | if (!name) |
| 188 | return false; |
| 189 | |
| 190 | if (strchr(s: name, c: ':') == nullptr) |
| 191 | return true; |
| 192 | else if (name[strlen(s: name) - 1] == ':') |
| 193 | return true; |
| 194 | else |
| 195 | return false; |
| 196 | } |
| 197 | |
| 198 | llvm::StringRef GetInstanceVariableName() override { return "self" ; } |
| 199 | |
| 200 | virtual std::optional<bool> |
| 201 | GetBooleanFromString(llvm::StringRef str) const override; |
| 202 | |
| 203 | bool SupportsExceptionBreakpointsOnThrow() const override { return true; } |
| 204 | |
| 205 | // PluginInterface protocol |
| 206 | llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } |
| 207 | }; |
| 208 | |
| 209 | } // namespace lldb_private |
| 210 | |
| 211 | #endif // LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H |
| 212 | |