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 MethodName { |
27 | public: |
28 | /// The static factory method for creating a MethodName. |
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 MethodName. |
39 | static std::optional<const MethodName> 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 | MethodName(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 | bool SymbolNameFitsToLanguage(Mangled mangled) const override; |
146 | |
147 | lldb::TypeCategoryImplSP GetFormatters() override; |
148 | |
149 | std::vector<FormattersMatchCandidate> |
150 | GetPossibleFormattersMatches(ValueObject &valobj, |
151 | lldb::DynamicValueType use_dynamic) override; |
152 | |
153 | std::unique_ptr<TypeScavenger> GetTypeScavenger() override; |
154 | |
155 | std::pair<llvm::StringRef, llvm::StringRef> |
156 | GetFormatterPrefixSuffix(llvm::StringRef type_hint) override; |
157 | |
158 | bool IsNilReference(ValueObject &valobj) override; |
159 | |
160 | llvm::StringRef GetNilReferenceSummaryString() override { return "nil" ; } |
161 | |
162 | bool IsSourceFile(llvm::StringRef file_path) const override; |
163 | |
164 | const Highlighter *GetHighlighter() const override { return &m_highlighter; } |
165 | |
166 | // Static Functions |
167 | static void Initialize(); |
168 | |
169 | static void Terminate(); |
170 | |
171 | static lldb_private::Language *CreateInstance(lldb::LanguageType language); |
172 | |
173 | static llvm::StringRef GetPluginNameStatic() { return "objc" ; } |
174 | |
175 | static bool IsPossibleObjCMethodName(const char *name) { |
176 | if (!name) |
177 | return false; |
178 | bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '['; |
179 | bool ends_right = (name[strlen(s: name) - 1] == ']'); |
180 | return (starts_right && ends_right); |
181 | } |
182 | |
183 | static bool IsPossibleObjCSelector(const char *name) { |
184 | if (!name) |
185 | return false; |
186 | |
187 | if (strchr(s: name, c: ':') == nullptr) |
188 | return true; |
189 | else if (name[strlen(s: name) - 1] == ':') |
190 | return true; |
191 | else |
192 | return false; |
193 | } |
194 | |
195 | llvm::StringRef GetInstanceVariableName() override { return "self" ; } |
196 | |
197 | // PluginInterface protocol |
198 | llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } |
199 | }; |
200 | |
201 | } // namespace lldb_private |
202 | |
203 | #endif // LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H |
204 | |