CIRCT 24.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::lsp;
39
41 VerilogServerContext &context, const llvm::lsp::URIForFile &uri,
42 StringRef fileContents, int64_t version,
43 std::vector<llvm::lsp::Diagnostic> &diagnostics)
44 : context(context), contents(fileContents.str()) {
46 std::scoped_lock<std::shared_mutex> lk(contentMutex);
47 initialize(uri, version, diagnostics);
48}
49
50llvm::LogicalResult VerilogTextFile::update(
51 const llvm::lsp::URIForFile &uri, int64_t newVersion,
52 ArrayRef<llvm::lsp::TextDocumentContentChangeEvent> changes,
53 std::vector<llvm::lsp::Diagnostic> &diagnostics) {
54
55 std::scoped_lock<std::shared_mutex> lk(contentMutex);
56 if (failed(llvm::lsp::TextDocumentContentChangeEvent::applyTo(changes,
57 contents))) {
58 circt::lsp::Logger::error(Twine("Failed to update contents of ") +
59 uri.file());
60 return llvm::failure();
61 }
62 // If the file contents were properly changed, reinitialize the text file.
63 initialize(uri, newVersion, diagnostics);
64 return llvm::success();
65}
66
68 if (context.options.commandFiles.empty())
69 return;
70
71 projectDriver = std::make_unique<slang::driver::Driver>();
72
73 // --- Apply project command files (the “-C”s) to this per-buffer driver ---
74 for (const std::string &cmdFile : context.options.commandFiles) {
75 if (!projectDriver->processCommandFiles(cmdFile, false, true)) {
76 circt::lsp::Logger::error(Twine("Failed to open command file ") +
77 cmdFile);
78 return;
79 }
80
81 // Open command file and parse it ourselves to get include dirs...
82 slang::CommandLine unitCmdLine;
83 std::vector<std::string> includes;
84 unitCmdLine.add("-I,--include-directory,+incdir", includes, "", "",
85 slang::CommandLineFlags::CommaList);
86 std::vector<std::string> defines;
87 unitCmdLine.add("-D,--define-macro,+define", defines, "");
88
89 std::optional<std::string> libraryName;
90 unitCmdLine.add("--library", libraryName, "");
91
92 std::vector<std::string> files;
93 unitCmdLine.setPositional(
94 [&](std::string_view value) {
95 files.emplace_back(value);
96 return "";
97 },
98 "");
99
100 slang::CommandLine::ParseOptions parseOpts;
101 parseOpts.expandEnvVars = true;
102 parseOpts.ignoreProgramName = true;
103 parseOpts.supportComments = true;
104 parseOpts.ignoreDuplicates = true;
105
106 slang::SmallVector<char> buffer;
107 if (auto readEc = slang::OS::readFile(cmdFile, buffer)) {
108 continue;
109 }
110 std::string_view argStr(buffer.data(), buffer.size());
111 if (!unitCmdLine.parse(argStr, parseOpts)) {
112 continue;
113 }
115 includes.begin(), includes.end());
116 }
117
118 projectDriver->options.compilationFlags.emplace(
119 slang::ast::CompilationFlags::LintMode, false);
120 projectDriver->options.compilationFlags.emplace(
121 slang::ast::CompilationFlags::DisableInstanceCaching, false);
122
123 if (!projectDriver->processOptions()) {
125 Twine("Failed to apply slang options on project "));
126 return;
127 }
128
129 if (!projectDriver->parseAllSources()) {
130 circt::lsp::Logger::error(Twine("Failed to parse Verilog project files "));
131 return;
132 }
133}
134
136 const llvm::lsp::URIForFile &uri, int64_t newVersion,
137 std::vector<llvm::lsp::Diagnostic> &diagnostics) {
138 std::shared_ptr<VerilogDocument> newDocument;
139 setDocument(std::make_shared<VerilogDocument>(
140 context, uri, contents, diagnostics, projectDriver.get(),
142 version = newVersion;
143}
144
146 const llvm::lsp::URIForFile &uri, llvm::lsp::Position defPos,
147 std::vector<llvm::lsp::Location> &locations) {
148 auto doc = getDocument();
149 doc->getLocationsOf(uri, defPos, locations);
150}
151
153 const llvm::lsp::URIForFile &uri, llvm::lsp::Position pos,
154 std::vector<llvm::lsp::Location> &references) {
155 auto doc = getDocument();
156 doc->findReferencesOf(uri, pos, references);
157}
158
159std::shared_ptr<VerilogDocument> VerilogTextFile::getDocument() {
160 std::scoped_lock<std::shared_mutex> lk(docMutex);
161 return document;
162}
163
164void VerilogTextFile::setDocument(std::shared_ptr<VerilogDocument> newDoc) {
165 std::scoped_lock<std::shared_mutex> lk(docMutex);
166 document = std::move(newDoc);
167}
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
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.
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.
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