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
20namespace lldb_private {
21
22class ObjCLanguage : public Language {
23  ClangHighlighter m_highlighter;
24
25public:
26  class MethodName {
27  public:
28    enum Type { eTypeUnspecified, eTypeClassMethod, eTypeInstanceMethod };
29
30    MethodName() : m_full(), m_class(), m_category(), m_selector() {}
31
32    MethodName(const char *name, bool strict)
33        : m_full(), m_class(), m_category(), m_selector(),
34          m_type(eTypeUnspecified), m_category_is_valid(false) {
35      SetName(name, strict);
36    }
37    MethodName(llvm::StringRef name, bool strict)
38        : m_full(), m_class(), m_category(), m_selector(),
39          m_type(eTypeUnspecified), m_category_is_valid(false) {
40      SetName(name, strict);
41    }
42
43    void Clear();
44
45    bool IsValid(bool strict) const {
46      // If "strict" is true, the name must have everything specified including
47      // the leading "+" or "-" on the method name
48      if (strict && m_type == eTypeUnspecified)
49        return false;
50      // Other than that, m_full will only be filled in if the objective C
51      // name is valid.
52      return (bool)m_full;
53    }
54
55    bool HasCategory() { return !GetCategory().IsEmpty(); }
56
57    Type GetType() const { return m_type; }
58
59    ConstString GetFullName() const { return m_full; }
60
61    ConstString GetFullNameWithoutCategory(bool empty_if_no_category);
62
63    bool SetName(const char *name, bool strict);
64    bool SetName(llvm::StringRef name, bool strict);
65
66    ConstString GetClassName();
67
68    ConstString GetClassNameWithCategory();
69
70    ConstString GetCategory();
71
72    ConstString GetSelector();
73
74  protected:
75    ConstString
76        m_full; // Full name:   "+[NSString(my_additions) myStringWithCString:]"
77    ConstString m_class; // Class name:  "NSString"
78    ConstString
79        m_class_category;   // Class with category: "NSString(my_additions)"
80    ConstString m_category; // Category:    "my_additions"
81    ConstString m_selector; // Selector:    "myStringWithCString:"
82    Type m_type = eTypeUnspecified;
83    bool m_category_is_valid = false;
84  };
85
86  ObjCLanguage() = default;
87
88  ~ObjCLanguage() override = default;
89
90  lldb::LanguageType GetLanguageType() const override {
91    return lldb::eLanguageTypeObjC;
92  }
93
94  // Get all possible names for a method. Examples:
95  // If method_name is "+[NSString(my_additions) myStringWithCString:]"
96  //   variant_names[0] => "+[NSString myStringWithCString:]"
97  // If name is specified without the leading '+' or '-' like
98  // "[NSString(my_additions) myStringWithCString:]"
99  //  variant_names[0] => "+[NSString(my_additions) myStringWithCString:]"
100  //  variant_names[1] => "-[NSString(my_additions) myStringWithCString:]"
101  //  variant_names[2] => "+[NSString myStringWithCString:]"
102  //  variant_names[3] => "-[NSString myStringWithCString:]"
103  // Also returns the FunctionNameType of each possible name.
104  std::vector<Language::MethodNameVariant>
105  GetMethodNameVariants(ConstString method_name) const override;
106
107  bool SymbolNameFitsToLanguage(Mangled mangled) const override;
108
109  lldb::TypeCategoryImplSP GetFormatters() override;
110
111  std::vector<FormattersMatchCandidate>
112  GetPossibleFormattersMatches(ValueObject &valobj,
113                               lldb::DynamicValueType use_dynamic) override;
114
115  std::unique_ptr<TypeScavenger> GetTypeScavenger() override;
116
117  bool GetFormatterPrefixSuffix(ValueObject &valobj, ConstString type_hint,
118                                std::string &prefix,
119                                std::string &suffix) override;
120
121  bool IsNilReference(ValueObject &valobj) override;
122
123  llvm::StringRef GetNilReferenceSummaryString() override { return "nil"; }
124
125  bool IsSourceFile(llvm::StringRef file_path) const override;
126
127  const Highlighter *GetHighlighter() const override { return &m_highlighter; }
128
129  // Static Functions
130  static void Initialize();
131
132  static void Terminate();
133
134  static lldb_private::Language *CreateInstance(lldb::LanguageType language);
135
136  static llvm::StringRef GetPluginNameStatic() { return "objc"; }
137
138  static bool IsPossibleObjCMethodName(const char *name) {
139    if (!name)
140      return false;
141    bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
142    bool ends_right = (name[strlen(name) - 1] == ']');
143    return (starts_right && ends_right);
144  }
145
146  static bool IsPossibleObjCSelector(const char *name) {
147    if (!name)
148      return false;
149
150    if (strchr(name, ':') == nullptr)
151      return true;
152    else if (name[strlen(name) - 1] == ':')
153      return true;
154    else
155      return false;
156  }
157
158  // PluginInterface protocol
159  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
160};
161
162} // namespace lldb_private
163
164#endif // LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H
165