CIRCT 22.0.0git
Loading...
Searching...
No Matches
VerilogTextFile.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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// VerilogTextFile.cpp
10//
11// This file implements the VerilogTextFile class, a lightweight wrapper around
12// VerilogDocument that represents the open text buffer for a single source file
13// managed by the CIRCT Verilog LSP server.
14//
15// Responsibilities:
16// * Manage the current text contents and version of an open Verilog file.
17// * Rebuild the associated VerilogDocument whenever the file is opened or
18// updated via LSP “didOpen” or “didChange” notifications.
19// * Apply incremental text changes as specified by the LSP protocol.
20// * Forward symbol-definition and reference queries to the underlying
21// VerilogDocument.
22//
23// The class acts as the LSP-facing façade for each active text document,
24// maintaining an editable in-memory copy of its contents while keeping the
25// corresponding Slang-based VerilogDocument synchronized for semantic analysis.
26//
27//===----------------------------------------------------------------------===//
28
29#include "slang/util/CommandLine.h"
30
31#include "../Utils/LSPUtils.h"
32#include "VerilogDocument.h"
34#include "VerilogTextFile.h"
36
37using namespace circt::lsp;
38using namespace llvm;
39using namespace llvm::lsp;
40
42 VerilogServerContext &context, const llvm::lsp::URIForFile &uri,
43 StringRef fileContents, int64_t version,
44 std::vector<llvm::lsp::Diagnostic> &diagnostics)
45 : context(context), contents(fileContents.str()) {
47 std::scoped_lock<std::shared_mutex> lk(contentMutex);
48 initialize(uri, version, diagnostics);
49}
50
52 const llvm::lsp::URIForFile &uri, int64_t newVersion,
53 ArrayRef<llvm::lsp::TextDocumentContentChangeEvent> changes,
54 std::vector<llvm::lsp::Diagnostic> &diagnostics) {
55
56 std::scoped_lock<std::shared_mutex> lk(contentMutex);
57 if (failed(llvm::lsp::TextDocumentContentChangeEvent::applyTo(changes,
58 contents))) {
59 circt::lsp::Logger::error(Twine("Failed to update contents of ") +
60 uri.file());
61 return failure();
62 }
63 // If the file contents were properly changed, reinitialize the text file.
64 initialize(uri, newVersion, diagnostics);
65 return success();
66}
67
69 if (context.options.commandFiles.empty())
70 return;
71
72 projectDriver = std::make_unique<slang::driver::Driver>();
73
74 // --- Apply project command files (the “-C”s) to this per-buffer driver ---
75 for (const std::string &cmdFile : context.options.commandFiles) {
76 if (!projectDriver->processCommandFiles(cmdFile, false, true)) {
77 circt::lsp::Logger::error(Twine("Failed to open command file ") +
78 cmdFile);
79 return;
80 }
81
82 // Open command file and parse it ourselves to get include dirs...
83 slang::CommandLine unitCmdLine;
84 std::vector<std::string> includes;
85 unitCmdLine.add("-I,--include-directory,+incdir", includes, "", "",
86 slang::CommandLineFlags::CommaList);
87 std::vector<std::string> defines;
88 unitCmdLine.add("-D,--define-macro,+define", defines, "");
89
90 std::optional<std::string> libraryName;
91 unitCmdLine.add("--library", libraryName, "");
92
93 std::vector<std::string> files;
94 unitCmdLine.setPositional(
95 [&](std::string_view value) {
96 files.emplace_back(value);
97 return "";
98 },
99 "");
100
101 slang::CommandLine::ParseOptions parseOpts;
102 parseOpts.expandEnvVars = true;
103 parseOpts.ignoreProgramName = true;
104 parseOpts.supportComments = true;
105 parseOpts.ignoreDuplicates = true;
106
107 slang::SmallVector<char> buffer;
108 if (auto readEc = slang::OS::readFile(cmdFile, buffer)) {
109 continue;
110 }
111 std::string_view argStr(buffer.data(), buffer.size());
112 if (!unitCmdLine.parse(argStr, parseOpts)) {
113 continue;
114 }
116 includes.begin(), includes.end());
117 }
118
119 projectDriver->options.compilationFlags.emplace(
120 slang::ast::CompilationFlags::LintMode, false);
121 projectDriver->options.compilationFlags.emplace(
122 slang::ast::CompilationFlags::DisableInstanceCaching, false);
123
124 if (!projectDriver->processOptions()) {
126 Twine("Failed to apply slang options on project "));
127 return;
128 }
129
130 if (!projectDriver->parseAllSources()) {
131 circt::lsp::Logger::error(Twine("Failed to parse Verilog project files "));
132 return;
133 }
134}
135
137 const llvm::lsp::URIForFile &uri, int64_t newVersion,
138 std::vector<llvm::lsp::Diagnostic> &diagnostics) {
139 std::shared_ptr<VerilogDocument> newDocument;
140 setDocument(std::make_shared<VerilogDocument>(
141 context, uri, contents, diagnostics, projectDriver.get(),
143 version = newVersion;
144}
145
147 const llvm::lsp::URIForFile &uri, llvm::lsp::Position defPos,
148 std::vector<llvm::lsp::Location> &locations) {
149 auto doc = getDocument();
150 doc->getLocationsOf(uri, defPos, locations);
151}
152
154 const llvm::lsp::URIForFile &uri, llvm::lsp::Position pos,
155 std::vector<llvm::lsp::Location> &references) {
156 auto doc = getDocument();
157 doc->findReferencesOf(uri, pos, references);
158}
159
160std::shared_ptr<VerilogDocument> VerilogTextFile::getDocument() {
161 std::scoped_lock<std::shared_mutex> lk(docMutex);
162 return document;
163}
164
165void VerilogTextFile::setDocument(std::shared_ptr<VerilogDocument> newDoc) {
166 std::scoped_lock<std::shared_mutex> lk(docMutex);
167 document = std::move(newDoc);
168}
void initialize(const llvm::lsp::URIForFile &uri, int64_t newVersion, std::vector< llvm::lsp::Diagnostic > &diagnostics)
Initialize the text file from the given file contents.
std::unique_ptr< slang::driver::Driver > projectDriver
The project-scale driver.
std::shared_ptr< VerilogDocument > getDocument()
Return document for read access.
VerilogServerContext & context
void getLocationsOf(const llvm::lsp::URIForFile &uri, llvm::lsp::Position defPos, std::vector< llvm::lsp::Location > &locations)
Return position of definition of an object pointed to by pos.
void findReferencesOf(const llvm::lsp::URIForFile &uri, llvm::lsp::Position pos, std::vector< llvm::lsp::Location > &references)
Return all references to an object pointed to by pos.
std::string contents
The full string contents of the file.
int64_t version
The version of this file.
llvm::LogicalResult update(const llvm::lsp::URIForFile &uri, int64_t newVersion, llvm::ArrayRef< llvm::lsp::TextDocumentContentChangeEvent > changes, std::vector< llvm::lsp::Diagnostic > &diagnostics)
Update the file to the new version using the provided set of content changes.
VerilogTextFile(VerilogServerContext &globalContext, const llvm::lsp::URIForFile &uri, llvm::StringRef fileContents, int64_t version, std::vector< llvm::lsp::Diagnostic > &diagnostics)
Initialize a new VerilogTextFile and its VerilogDocument.
std::shared_mutex contentMutex
A mutex to control updates of contents.
std::shared_mutex docMutex
A mutex to control updates of document; Acquire AFTER contentMutex.
std::vector< std::string > projectIncludeDirectories
std::shared_ptr< circt::lsp::VerilogDocument > document
The chunks of this file.
void setDocument(std::shared_ptr< VerilogDocument > newDoc)
Override document after update.
void error(Twine message)
Definition LSPUtils.cpp:16
const circt::lsp::VerilogServerOptions & options
const std::vector< std::string > & commandFiles
Additional list of command files that reference dependencies of the project.