aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
blob: a68ea41c723de7aae4fef0e0f7af59ea86fcbe60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
//===-- ObjCLanguage.h ------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H
#define LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H

#include <cstring>
#include <vector>

#include "Plugins/Language/ClangCommon/ClangHighlighter.h"
#include "lldb/Target/Language.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"

namespace lldb_private {

class ObjCLanguage : public Language {
  ClangHighlighter m_highlighter;

public:
  class ObjCMethodName {
  public:
    /// The static factory method for creating a ObjCMethodName.
    ///
    /// \param[in] name
    ///   The name of the method.
    ///
    /// \param[in] strict
    ///   Control whether or not the name parser is strict about +/- in the
    ///   front of the name.
    ///
    /// \return If the name failed to parse as a valid Objective-C method name,
    /// returns std::nullopt. Otherwise returns a const ObjCMethodName.
    static std::optional<const ObjCMethodName> Create(llvm::StringRef name,
                                                      bool strict);

    /// Determines if this method is a class method
    ///
    /// \return Returns true if the method is a class method. False otherwise.
    bool IsClassMethod() const { return m_type == eTypeClassMethod; }

    /// Determines if this method is an instance method
    ///
    /// \return Returns true if the method is an instance method. False
    /// otherwise.
    bool IsInstanceMethod() const { return m_type == eTypeInstanceMethod; }

    /// Returns the full name of the method.
    ///
    /// This includes the class name, the category name (if applicable), and the
    /// selector name.
    ///
    /// \return The name of the method in the form of a const std::string
    /// reference.
    const std::string &GetFullName() const { return m_full; }

    /// Creates a variation of this method without the category.
    /// If this method has no category, it returns an empty string.
    ///
    /// Example:
    ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
    ///   becomes "+[NSString myStringWithCString:]"
    ///
    /// \return The method name without the category or an empty string if there
    /// was no category to begin with.
    std::string GetFullNameWithoutCategory() const;

    /// Returns a reference to the class name.
    ///
    /// Example:
    ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
    ///   will give you "NSString"
    ///
    /// \return A StringRef to the class name of this method.
    llvm::StringRef GetClassName() const;

    /// Returns a reference to the class name with the category.
    ///
    /// Example:
    ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
    ///   will give you "NSString(my_additions)"
    ///
    /// Note: If your method has no category, this will give the same output as
    /// `GetClassName`.
    ///
    /// \return A StringRef to the class name (including the category) of this
    /// method. If there was no category, returns the same as `GetClassName`.
    llvm::StringRef GetClassNameWithCategory() const;

    /// Returns a reference to the category name.
    ///
    /// Example:
    ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
    ///   will give you "my_additions"
    /// \return A StringRef to the category name of this method. If no category
    /// is present, the StringRef is empty.
    llvm::StringRef GetCategory() const;

    /// Returns a reference to the selector name.
    ///
    /// Example:
    ///   Full name: "+[NSString(my_additions) myStringWithCString:]"
    ///   will give you "myStringWithCString:"
    /// \return A StringRef to the selector of this method.
    llvm::StringRef GetSelector() const;

  protected:
    enum Type { eTypeUnspecified, eTypeClassMethod, eTypeInstanceMethod };

    ObjCMethodName(llvm::StringRef name, Type type)
        : m_full(name.str()), m_type(type) {}

    const std::string m_full;
    Type m_type;
  };

  ObjCLanguage() = default;

  ~ObjCLanguage() override = default;

  lldb::LanguageType GetLanguageType() const override {
    return lldb::eLanguageTypeObjC;
  }

  llvm::StringRef GetUserEntryPointName() const override { return "main"; }

  // Get all possible names for a method. Examples:
  // If method_name is "+[NSString(my_additions) myStringWithCString:]"
  //   variant_names[0] => "+[NSString myStringWithCString:]"
  // If name is specified without the leading '+' or '-' like
  // "[NSString(my_additions) myStringWithCString:]"
  //  variant_names[0] => "+[NSString(my_additions) myStringWithCString:]"
  //  variant_names[1] => "-[NSString(my_additions) myStringWithCString:]"
  //  variant_names[2] => "+[NSString myStringWithCString:]"
  //  variant_names[3] => "-[NSString myStringWithCString:]"
  // Also returns the FunctionNameType of each possible name.
  std::vector<Language::MethodNameVariant>
  GetMethodNameVariants(ConstString method_name) const override;

  std::pair<lldb::FunctionNameType, std::optional<ConstString>>
  GetFunctionNameInfo(ConstString name) const override;

  bool SymbolNameFitsToLanguage(Mangled mangled) const override;

  lldb::TypeCategoryImplSP GetFormatters() override;

  std::vector<FormattersMatchCandidate>
  GetPossibleFormattersMatches(ValueObject &valobj,
                               lldb::DynamicValueType use_dynamic) override;

  std::unique_ptr<TypeScavenger> GetTypeScavenger() override;

  std::pair<llvm::StringRef, llvm::StringRef>
  GetFormatterPrefixSuffix(llvm::StringRef type_hint) override;

  bool IsNilReference(ValueObject &valobj) override;

  llvm::StringRef GetNilReferenceSummaryString() override { return "nil"; }

  bool IsSourceFile(llvm::StringRef file_path) const override;

  const Highlighter *GetHighlighter() const override { return &m_highlighter; }

  // Static Functions
  static void Initialize();

  static void Terminate();

  static lldb_private::Language *CreateInstance(lldb::LanguageType language);

  static llvm::StringRef GetPluginNameStatic() { return "objc"; }

  static bool IsPossibleObjCMethodName(const char *name) {
    if (!name)
      return false;
    bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
    bool ends_right = (name[strlen(name) - 1] == ']');
    return (starts_right && ends_right);
  }

  static bool IsPossibleObjCSelector(const char *name) {
    if (!name)
      return false;

    if (strchr(name, ':') == nullptr)
      return true;
    else if (name[strlen(name) - 1] == ':')
      return true;
    else
      return false;
  }

  llvm::StringRef GetInstanceVariableName() override { return "self"; }

  virtual std::optional<bool>
  GetBooleanFromString(llvm::StringRef str) const override;

  bool SupportsExceptionBreakpointsOnThrow() const override { return true; }

  // PluginInterface protocol
  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
};

} // namespace lldb_private

#endif // LLDB_SOURCE_PLUGINS_LANGUAGE_OBJC_OBJCLANGUAGE_H