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
25namespace lldb_private {
26class RegularExpression;
27class Stream;
28class SymbolContextList;
29class Target;
30
31class SourceManager {
32public:
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
154protected:
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
162private:
163 SourceManager(const SourceManager &) = delete;
164 const SourceManager &operator=(const SourceManager &) = delete;
165};
166
167bool operator==(const SourceManager::File &lhs, const SourceManager::File &rhs);
168
169} // namespace lldb_private
170
171#endif // LLDB_CORE_SOURCEMANAGER_H
172