1//===-- SourceManager.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_CORE_SOURCEMANAGER_H
10#define LLDB_CORE_SOURCEMANAGER_H
11
12#include "lldb/Utility/FileSpec.h"
13#include "lldb/lldb-defines.h"
14#include "lldb/lldb-forward.h"
15
16#include "llvm/Support/Chrono.h"
17
18#include <cstddef>
19#include <cstdint>
20#include <map>
21#include <memory>
22#include <optional>
23#include <string>
24#include <vector>
25
26namespace lldb_private {
27class RegularExpression;
28class Stream;
29class SymbolContextList;
30class Target;
31
32class SourceManager {
33public:
34  class File {
35    friend bool operator==(const SourceManager::File &lhs,
36                           const SourceManager::File &rhs);
37
38  public:
39    File(const FileSpec &file_spec, Target *target);
40    File(const FileSpec &file_spec, lldb::DebuggerSP debugger_sp);
41    ~File() = default;
42
43    void UpdateIfNeeded();
44
45    size_t DisplaySourceLines(uint32_t line, std::optional<size_t> column,
46                              uint32_t context_before, uint32_t context_after,
47                              Stream *s);
48    void FindLinesMatchingRegex(RegularExpression &regex, uint32_t start_line,
49                                uint32_t end_line,
50                                std::vector<uint32_t> &match_lines);
51
52    bool GetLine(uint32_t line_no, std::string &buffer);
53
54    uint32_t GetLineOffset(uint32_t line);
55
56    bool LineIsValid(uint32_t line);
57
58    const FileSpec &GetFileSpec() { return m_file_spec; }
59
60    uint32_t GetSourceMapModificationID() const { return m_source_map_mod_id; }
61
62    const char *PeekLineData(uint32_t line);
63
64    uint32_t GetLineLength(uint32_t line, bool include_newline_chars);
65
66    uint32_t GetNumLines();
67
68  protected:
69    bool CalculateLineOffsets(uint32_t line = UINT32_MAX);
70
71    FileSpec m_file_spec_orig; // The original file spec that was used (can be
72                               // different from m_file_spec)
73    FileSpec m_file_spec; // The actually file spec being used (if the target
74                          // has source mappings, this might be different from
75                          // m_file_spec_orig)
76
77    // Keep the modification time that this file data is valid for
78    llvm::sys::TimePoint<> m_mod_time;
79
80    // If the target uses path remappings, be sure to clear our notion of a
81    // source file if the path modification ID changes
82    uint32_t m_source_map_mod_id = 0;
83    lldb::DataBufferSP m_data_sp;
84    typedef std::vector<uint32_t> LineOffsets;
85    LineOffsets m_offsets;
86    lldb::DebuggerWP m_debugger_wp;
87
88  private:
89    void CommonInitializer(const FileSpec &file_spec, Target *target);
90  };
91
92  typedef std::shared_ptr<File> FileSP;
93
94  // The SourceFileCache class separates the source manager from the cache of
95  // source files, so the cache can be stored in the Debugger, but the source
96  // managers can be per target.
97  class SourceFileCache {
98  public:
99    SourceFileCache() = default;
100    ~SourceFileCache() = default;
101
102    void AddSourceFile(const FileSP &file_sp);
103    FileSP FindSourceFile(const FileSpec &file_spec) const;
104
105    // Removes all elements from the cache.
106    void Clear() { m_file_cache.clear(); }
107
108  protected:
109    typedef std::map<FileSpec, FileSP> FileCache;
110    FileCache m_file_cache;
111  };
112
113  // Constructors and Destructors
114  // A source manager can be made with a non-null target, in which case it can
115  // use the path remappings to find
116  // source files that are not in their build locations.  With no target it
117  // won't be able to do this.
118  SourceManager(const lldb::DebuggerSP &debugger_sp);
119  SourceManager(const lldb::TargetSP &target_sp);
120
121  ~SourceManager();
122
123  FileSP GetLastFile() { return GetFile(m_last_file_spec); }
124
125  size_t
126  DisplaySourceLinesWithLineNumbers(const FileSpec &file, uint32_t line,
127                                    uint32_t column, uint32_t context_before,
128                                    uint32_t context_after,
129                                    const char *current_line_cstr, Stream *s,
130                                    const SymbolContextList *bp_locs = nullptr);
131
132  // This variant uses the last file we visited.
133  size_t DisplaySourceLinesWithLineNumbersUsingLastFile(
134      uint32_t start_line, uint32_t count, uint32_t curr_line, uint32_t column,
135      const char *current_line_cstr, Stream *s,
136      const SymbolContextList *bp_locs = nullptr);
137
138  size_t DisplayMoreWithLineNumbers(Stream *s, uint32_t count, bool reverse,
139                                    const SymbolContextList *bp_locs = nullptr);
140
141  bool SetDefaultFileAndLine(const FileSpec &file_spec, uint32_t line);
142
143  bool GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line);
144
145  bool DefaultFileAndLineSet() {
146    return (GetFile(m_last_file_spec).get() != nullptr);
147  }
148
149  void FindLinesMatchingRegex(FileSpec &file_spec, RegularExpression &regex,
150                              uint32_t start_line, uint32_t end_line,
151                              std::vector<uint32_t> &match_lines);
152
153  FileSP GetFile(const FileSpec &file_spec);
154
155protected:
156  FileSpec m_last_file_spec;
157  uint32_t m_last_line;
158  uint32_t m_last_count;
159  bool m_default_set;
160  lldb::TargetWP m_target_wp;
161  lldb::DebuggerWP m_debugger_wp;
162
163private:
164  SourceManager(const SourceManager &) = delete;
165  const SourceManager &operator=(const SourceManager &) = delete;
166};
167
168bool operator==(const SourceManager::File &lhs, const SourceManager::File &rhs);
169
170} // namespace lldb_private
171
172#endif // LLDB_CORE_SOURCEMANAGER_H
173