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