forked from chipsalliance/verible
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lsp-parse-buffer.h
159 lines (138 loc) · 6.33 KB
/
lsp-parse-buffer.h
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
// Copyright 2021 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef VERILOG_TOOLS_LS_LSP_PARSE_BUFFER_H
#define VERILOG_TOOLS_LS_LSP_PARSE_BUFFER_H
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include "absl/strings/string_view.h"
#include "common/analysis/lint_rule_status.h"
#include "common/lsp/lsp-text-buffer.h"
#include "common/util/logging.h"
#include "verilog/analysis/verilog_analyzer.h"
// ParseBuffer and BufferTrackerContainer are tracking fully parsed content
// and are corresponding to verible::lsp::EditTextBuffer and
// verible::lsp::BufferCollection that are responsible for tracking the
// bare editor text.
namespace verilog {
// A parsed buffer collects all the artifacts generated from a text buffer
// from parsing or running the linter.
//
// Right now, the ParsedBuffer is synchronously filling its internal structure
// on construction, but plan is to do that on-demand and possibly with
// std::future<>s evaluated in separate threads.
class ParsedBuffer {
public:
ParsedBuffer(int64_t version, absl::string_view uri,
absl::string_view content);
bool parsed_successfully() const {
return parser_->LexStatus().ok() && parser_->ParseStatus().ok();
}
const verilog::VerilogAnalyzer &parser() const { return *parser_; }
const std::vector<verible::LintRuleStatus> &lint_result() const {
return lint_statuses_;
}
int64_t version() const { return version_; }
const std::string &uri() const { return uri_; }
private:
const int64_t version_;
const std::string uri_;
const std::unique_ptr<verilog::VerilogAnalyzer> parser_;
std::vector<verible::LintRuleStatus> lint_statuses_;
};
// A buffer tracker tracks of a single file EditTextBuffer content and stores
// a parsed version.
// It keeps up to two versions of ParsedBuffers - the latest, that might have
// parse errors, and the last known good that parsed without errors
// (if available).
class BufferTracker {
public:
// Update with a changed text buffer from the LSP subsystem. Triggers
// re-parsing and updating our current() and potentially last_good().
void Update(const std::string &uri, const verible::lsp::EditTextBuffer &txt);
// ---
// Thread guarantee for the following functions.
// As long as the caller (typically some operation) holds on to the returned
// shared pointer, the object is alive and well, but there is no guarantee
// that if called multiple times it returns the same object (as it might
// be replaced asynchronously).
// ---
// Get the current ParsedBuffer from the last text update we received
// from the editor.
//
// Use in operations that only really makes sense on the latest view,
// e.g. suggesting edits.
std::shared_ptr<const ParsedBuffer> current() const { return current_; }
// Get the ParsedBuffer that represents that last time we were able to
// parse the document from the editor correctly. This can be the same
// as current() if the last text update was fully parseable, or nullptr
// if we never received a buffer that was parseable.
//
// Use in operations that focus on returning something that requires a
// valid parsed file even it it is slightly outdated, e.g. finding
// a particular symbol.
std::shared_ptr<const ParsedBuffer> last_good() const { return last_good_; }
private:
// The same ParsedBuffer can in both, current and last_good, or last_good can
// be an older version. So the very same object can be in both of them.
// Use shared_ptr to keep track of the reference count.
//
// Also: We want to be able to replace contents asynchronously which means
// we need a thread-safe way to hand out a copy that survives while we
// replace this one.
std::shared_ptr<const ParsedBuffer> current_;
std::shared_ptr<const ParsedBuffer> last_good_;
};
// Container holding a buffer tracker per file uri.
// This is the correspondent to verible::lsp::BufferCollection that
// internally stores file content by uri. Here we keep parsed files per uri,
// whenever we're informed of a change in the buffer collection.
class BufferTrackerContainer {
public:
// Return a callback that allows to subscribe to an lsp::BufferCollection
// to update our internal state whenever the editor state changes.
// (internally, they exercise Update() and Remove())
verible::lsp::BufferCollection::UriBufferCallback GetSubscriptionCallback();
// type for buffer change callback function
// The callback takes uri of the file, and the pointer to the BufferTracker
// The pointer can be nullptr, meaning that e.g. the file was closed.
// The nullptr case should be handled by callback.
using ChangeCallback =
std::function<void(const std::string &uri, const BufferTracker *tracker)>;
// Add a change listener for clients of ours interested in updated fresly
// parsed content.
// The callback takes uri of the file, and the pointer to the BufferTracker
// The pointer can be nullptr, meaning that e.g. the file was closed.
// The nullptr case should be handled by callback.
void AddChangeListener(const ChangeCallback &cb) {
change_listeners_.push_back(ABSL_DIE_IF_NULL(cb));
}
// Given the URI, find the associated parse buffer if it exists.
const BufferTracker *FindBufferTrackerOrNull(const std::string &uri) const;
private:
// Update internal state of the given "uri" with the content of the text
// buffer. Return the buffer tracker.
BufferTracker *Update(const std::string &uri,
const verible::lsp::EditTextBuffer &txt);
// Remove the buffer tracker for the given "uri".
void Remove(const std::string &uri) { buffers_.erase(uri); }
std::vector<ChangeCallback> change_listeners_;
std::unordered_map<std::string, std::unique_ptr<BufferTracker>> buffers_;
};
} // namespace verilog
#endif // VERILOG_TOOLS_LS_LSP_PARSE_BUFFER_H