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 liblldb_SourceManager_h_
10 #define liblldb_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   protected:
105     typedef std::map<FileSpec, FileSP> FileCache;
106     FileCache m_file_cache;
107   };
108 
109   // Constructors and Destructors
110   // A source manager can be made with a non-null target, in which case it can
111   // use the path remappings to find
112   // source files that are not in their build locations.  With no target it
113   // won't be able to do this.
114   SourceManager(const lldb::DebuggerSP &debugger_sp);
115   SourceManager(const lldb::TargetSP &target_sp);
116 
117   ~SourceManager();
118 
119   FileSP GetLastFile() { return m_last_file_sp; }
120 
121   size_t
122   DisplaySourceLinesWithLineNumbers(const FileSpec &file, uint32_t line,
123                                     uint32_t column, uint32_t context_before,
124                                     uint32_t context_after,
125                                     const char *current_line_cstr, Stream *s,
126                                     const SymbolContextList *bp_locs = nullptr);
127 
128   // This variant uses the last file we visited.
129   size_t DisplaySourceLinesWithLineNumbersUsingLastFile(
130       uint32_t start_line, uint32_t count, uint32_t curr_line, uint32_t column,
131       const char *current_line_cstr, Stream *s,
132       const SymbolContextList *bp_locs = nullptr);
133 
134   size_t DisplayMoreWithLineNumbers(Stream *s, uint32_t count, bool reverse,
135                                     const SymbolContextList *bp_locs = nullptr);
136 
137   bool SetDefaultFileAndLine(const FileSpec &file_spec, uint32_t line);
138 
139   bool GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line);
140 
141   bool DefaultFileAndLineSet() { return (m_last_file_sp.get() != nullptr); }
142 
143   void FindLinesMatchingRegex(FileSpec &file_spec, RegularExpression &regex,
144                               uint32_t start_line, uint32_t end_line,
145                               std::vector<uint32_t> &match_lines);
146 
147   FileSP GetFile(const FileSpec &file_spec);
148 
149 protected:
150   FileSP m_last_file_sp;
151   uint32_t m_last_line;
152   uint32_t m_last_count;
153   bool m_default_set;
154   lldb::TargetWP m_target_wp;
155   lldb::DebuggerWP m_debugger_wp;
156 
157 private:
158   DISALLOW_COPY_AND_ASSIGN(SourceManager);
159 };
160 
161 bool operator==(const SourceManager::File &lhs, const SourceManager::File &rhs);
162 
163 } // namespace lldb_private
164 
165 #endif // liblldb_SourceManager_h_
166