xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- ObjCLanguage.h ------------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
95ffd83dbSDimitry Andric #ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H
105ffd83dbSDimitry Andric #define LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include <cstring>
130b57cec5SDimitry Andric #include <vector>
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "Plugins/Language/ClangCommon/ClangHighlighter.h"
160b57cec5SDimitry Andric #include "lldb/Target/Language.h"
170b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
180b57cec5SDimitry Andric #include "lldb/lldb-private.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace lldb_private {
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric class ObjCLanguage : public Language {
230b57cec5SDimitry Andric   ClangHighlighter m_highlighter;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric public:
260b57cec5SDimitry Andric   class MethodName {
270b57cec5SDimitry Andric   public:
2806c3fb27SDimitry Andric     /// The static factory method for creating a MethodName.
2906c3fb27SDimitry Andric     ///
3006c3fb27SDimitry Andric     /// \param[in] name
3106c3fb27SDimitry Andric     ///   The name of the method.
3206c3fb27SDimitry Andric     ///
3306c3fb27SDimitry Andric     /// \param[in] strict
3406c3fb27SDimitry Andric     ///   Control whether or not the name parser is strict about +/- in the
3506c3fb27SDimitry Andric     ///   front of the name.
3606c3fb27SDimitry Andric     ///
3706c3fb27SDimitry Andric     /// \return If the name failed to parse as a valid Objective-C method name,
3806c3fb27SDimitry Andric     /// returns std::nullopt. Otherwise returns a const MethodName.
3906c3fb27SDimitry Andric     static std::optional<const MethodName> Create(llvm::StringRef name,
4006c3fb27SDimitry Andric                                                   bool strict);
410b57cec5SDimitry Andric 
4206c3fb27SDimitry Andric     /// Determines if this method is a class method
4306c3fb27SDimitry Andric     ///
4406c3fb27SDimitry Andric     /// \return Returns true if the method is a class method. False otherwise.
4506c3fb27SDimitry Andric     bool IsClassMethod() const { return m_type == eTypeClassMethod; }
460b57cec5SDimitry Andric 
4706c3fb27SDimitry Andric     /// Determines if this method is an instance method
4806c3fb27SDimitry Andric     ///
4906c3fb27SDimitry Andric     /// \return Returns true if the method is an instance method. False
5006c3fb27SDimitry Andric     /// otherwise.
5106c3fb27SDimitry Andric     bool IsInstanceMethod() const { return m_type == eTypeInstanceMethod; }
520b57cec5SDimitry Andric 
5306c3fb27SDimitry Andric     /// Returns the full name of the method.
5406c3fb27SDimitry Andric     ///
5506c3fb27SDimitry Andric     /// This includes the class name, the category name (if applicable), and the
5606c3fb27SDimitry Andric     /// selector name.
5706c3fb27SDimitry Andric     ///
5806c3fb27SDimitry Andric     /// \return The name of the method in the form of a const std::string
5906c3fb27SDimitry Andric     /// reference.
6006c3fb27SDimitry Andric     const std::string &GetFullName() const { return m_full; }
610b57cec5SDimitry Andric 
6206c3fb27SDimitry Andric     /// Creates a variation of this method without the category.
6306c3fb27SDimitry Andric     /// If this method has no category, it returns an empty string.
6406c3fb27SDimitry Andric     ///
6506c3fb27SDimitry Andric     /// Example:
6606c3fb27SDimitry Andric     ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
6706c3fb27SDimitry Andric     ///   becomes "+[NSString myStringWithCString:]"
6806c3fb27SDimitry Andric     ///
6906c3fb27SDimitry Andric     /// \return The method name without the category or an empty string if there
7006c3fb27SDimitry Andric     /// was no category to begin with.
7106c3fb27SDimitry Andric     std::string GetFullNameWithoutCategory() const;
720b57cec5SDimitry Andric 
7306c3fb27SDimitry Andric     /// Returns a reference to the class name.
7406c3fb27SDimitry Andric     ///
7506c3fb27SDimitry Andric     /// Example:
7606c3fb27SDimitry Andric     ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
7706c3fb27SDimitry Andric     ///   will give you "NSString"
7806c3fb27SDimitry Andric     ///
7906c3fb27SDimitry Andric     /// \return A StringRef to the class name of this method.
8006c3fb27SDimitry Andric     llvm::StringRef GetClassName() const;
810b57cec5SDimitry Andric 
8206c3fb27SDimitry Andric     /// Returns a reference to the class name with the category.
8306c3fb27SDimitry Andric     ///
8406c3fb27SDimitry Andric     /// Example:
8506c3fb27SDimitry Andric     ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
8606c3fb27SDimitry Andric     ///   will give you "NSString(my_additions)"
8706c3fb27SDimitry Andric     ///
8806c3fb27SDimitry Andric     /// Note: If your method has no category, this will give the same output as
8906c3fb27SDimitry Andric     /// `GetClassName`.
9006c3fb27SDimitry Andric     ///
9106c3fb27SDimitry Andric     /// \return A StringRef to the class name (including the category) of this
9206c3fb27SDimitry Andric     /// method. If there was no category, returns the same as `GetClassName`.
9306c3fb27SDimitry Andric     llvm::StringRef GetClassNameWithCategory() const;
940b57cec5SDimitry Andric 
9506c3fb27SDimitry Andric     /// Returns a reference to the category name.
9606c3fb27SDimitry Andric     ///
9706c3fb27SDimitry Andric     /// Example:
9806c3fb27SDimitry Andric     ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
9906c3fb27SDimitry Andric     ///   will give you "my_additions"
10006c3fb27SDimitry Andric     /// \return A StringRef to the category name of this method. If no category
10106c3fb27SDimitry Andric     /// is present, the StringRef is empty.
10206c3fb27SDimitry Andric     llvm::StringRef GetCategory() const;
1030b57cec5SDimitry Andric 
10406c3fb27SDimitry Andric     /// Returns a reference to the selector name.
10506c3fb27SDimitry Andric     ///
10606c3fb27SDimitry Andric     /// Example:
10706c3fb27SDimitry Andric     ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
10806c3fb27SDimitry Andric     ///   will give you "myStringWithCString:"
10906c3fb27SDimitry Andric     /// \return A StringRef to the selector of this method.
11006c3fb27SDimitry Andric     llvm::StringRef GetSelector() const;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   protected:
11306c3fb27SDimitry Andric     enum Type { eTypeUnspecified, eTypeClassMethod, eTypeInstanceMethod };
11406c3fb27SDimitry Andric 
11506c3fb27SDimitry Andric     MethodName(llvm::StringRef name, Type type)
11606c3fb27SDimitry Andric         : m_full(name.str()), m_type(type) {}
11706c3fb27SDimitry Andric 
11806c3fb27SDimitry Andric     const std::string m_full;
11906c3fb27SDimitry Andric     Type m_type;
1200b57cec5SDimitry Andric   };
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   ObjCLanguage() = default;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   ~ObjCLanguage() override = default;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   lldb::LanguageType GetLanguageType() const override {
1270b57cec5SDimitry Andric     return lldb::eLanguageTypeObjC;
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric 
1305f757f3fSDimitry Andric   llvm::StringRef GetUserEntryPointName() const override { return "main"; }
1315f757f3fSDimitry Andric 
1320b57cec5SDimitry Andric   // Get all possible names for a method. Examples:
1330b57cec5SDimitry Andric   // If method_name is "+[NSString(my_additions) myStringWithCString:]"
1340b57cec5SDimitry Andric   //   variant_names[0] => "+[NSString myStringWithCString:]"
1350b57cec5SDimitry Andric   // If name is specified without the leading '+' or '-' like
1360b57cec5SDimitry Andric   // "[NSString(my_additions) myStringWithCString:]"
1370b57cec5SDimitry Andric   //  variant_names[0] => "+[NSString(my_additions) myStringWithCString:]"
1380b57cec5SDimitry Andric   //  variant_names[1] => "-[NSString(my_additions) myStringWithCString:]"
1390b57cec5SDimitry Andric   //  variant_names[2] => "+[NSString myStringWithCString:]"
1400b57cec5SDimitry Andric   //  variant_names[3] => "-[NSString myStringWithCString:]"
141fe6060f1SDimitry Andric   // Also returns the FunctionNameType of each possible name.
142fe6060f1SDimitry Andric   std::vector<Language::MethodNameVariant>
1430b57cec5SDimitry Andric   GetMethodNameVariants(ConstString method_name) const override;
1440b57cec5SDimitry Andric 
145fe6060f1SDimitry Andric   bool SymbolNameFitsToLanguage(Mangled mangled) const override;
146fe6060f1SDimitry Andric 
1470b57cec5SDimitry Andric   lldb::TypeCategoryImplSP GetFormatters() override;
1480b57cec5SDimitry Andric 
149bdd1243dSDimitry Andric   std::vector<FormattersMatchCandidate>
1500b57cec5SDimitry Andric   GetPossibleFormattersMatches(ValueObject &valobj,
1510b57cec5SDimitry Andric                                lldb::DynamicValueType use_dynamic) override;
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   std::unique_ptr<TypeScavenger> GetTypeScavenger() override;
1540b57cec5SDimitry Andric 
15506c3fb27SDimitry Andric   std::pair<llvm::StringRef, llvm::StringRef>
15606c3fb27SDimitry Andric   GetFormatterPrefixSuffix(llvm::StringRef type_hint) override;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   bool IsNilReference(ValueObject &valobj) override;
1590b57cec5SDimitry Andric 
160e8d8bef9SDimitry Andric   llvm::StringRef GetNilReferenceSummaryString() override { return "nil"; }
161e8d8bef9SDimitry Andric 
1620b57cec5SDimitry Andric   bool IsSourceFile(llvm::StringRef file_path) const override;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   const Highlighter *GetHighlighter() const override { return &m_highlighter; }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   // Static Functions
1670b57cec5SDimitry Andric   static void Initialize();
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   static void Terminate();
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   static lldb_private::Language *CreateInstance(lldb::LanguageType language);
1720b57cec5SDimitry Andric 
173349cc55cSDimitry Andric   static llvm::StringRef GetPluginNameStatic() { return "objc"; }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   static bool IsPossibleObjCMethodName(const char *name) {
1760b57cec5SDimitry Andric     if (!name)
1770b57cec5SDimitry Andric       return false;
1780b57cec5SDimitry Andric     bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
1790b57cec5SDimitry Andric     bool ends_right = (name[strlen(name) - 1] == ']');
1800b57cec5SDimitry Andric     return (starts_right && ends_right);
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   static bool IsPossibleObjCSelector(const char *name) {
1840b57cec5SDimitry Andric     if (!name)
1850b57cec5SDimitry Andric       return false;
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric     if (strchr(name, ':') == nullptr)
1880b57cec5SDimitry Andric       return true;
1890b57cec5SDimitry Andric     else if (name[strlen(name) - 1] == ':')
1900b57cec5SDimitry Andric       return true;
1910b57cec5SDimitry Andric     else
1920b57cec5SDimitry Andric       return false;
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric 
19506c3fb27SDimitry Andric   llvm::StringRef GetInstanceVariableName() override { return "self"; }
19606c3fb27SDimitry Andric 
197*0fca6ea1SDimitry Andric   bool SupportsExceptionBreakpointsOnThrow() const override { return true; }
198*0fca6ea1SDimitry Andric 
1990b57cec5SDimitry Andric   // PluginInterface protocol
200349cc55cSDimitry Andric   llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
2010b57cec5SDimitry Andric };
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric } // namespace lldb_private
2040b57cec5SDimitry Andric 
2055ffd83dbSDimitry Andric #endif // LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H
206