Skip to content

Commit

Permalink
verilog/analysis: Add ParsedVerilogSourceFile class
Browse files Browse the repository at this point in the history
This class is an extended version of InMemoryVerilogSourceFile.
It wraps a TextStructureView object and allows to skip loading and
parsing phase.

This class may be used in e.g. TextStructureLinterRules.

Signed-off-by: Lukasz Dalek <[email protected]>
  • Loading branch information
Lukasz Dalek committed Apr 5, 2021
1 parent d46e152 commit 47e9bf0
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
17 changes: 17 additions & 0 deletions verilog/analysis/verilog_project.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,23 @@ absl::Status InMemoryVerilogSourceFile::Open() {
return status_;
}

absl::Status ParsedVerilogSourceFile::Open() {
state_ = State::kOpened;
status_ = absl::OkStatus();
return status_;
}

absl::Status ParsedVerilogSourceFile::Parse() {
state_ = State::kParsed;
status_ = absl::OkStatus();
return status_;
}

const verible::TextStructureView* ParsedVerilogSourceFile::GetTextStructure()
const {
return &text_structure_;
}

absl::StatusOr<VerilogSourceFile*> VerilogProject::OpenFile(
absl::string_view referenced_filename, absl::string_view resolved_filename,
absl::string_view corpus) {
Expand Down
28 changes: 26 additions & 2 deletions verilog/analysis/verilog_project.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ class VerilogSourceFile {
// Attempts to lex and parse the file (without preprocessing).
// Will Open() if the file is not already opened.
// Depending on context, not all files are suitable for standalone parsing.
absl::Status Parse();
virtual absl::Status Parse();

// After Open(), the underlying text structure contains at least the file's
// contents. After Parse(), it may contain other analyzed structural forms.
// Before Open(), this returns nullptr.
const verible::TextStructureView* GetTextStructure() const;
virtual const verible::TextStructureView* GetTextStructure() const;

// Returns the first non-Ok status if there is one, else OkStatus().
absl::Status Status() const { return status_; }
Expand Down Expand Up @@ -165,6 +165,30 @@ class InMemoryVerilogSourceFile : public VerilogSourceFile {
const absl::string_view contents_for_open_;
};

// Source file that was already parsed and got its own TextStructure.
// Doesn't require file-system access, nor create temporary files.
class ParsedVerilogSourceFile : public VerilogSourceFile {
public:
// filename can be fake, it is not used to open any file.
ParsedVerilogSourceFile(absl::string_view filename,
const verible::TextStructureView& text_structure,
absl::string_view corpus = "")
: VerilogSourceFile(filename, filename, corpus),
text_structure_(text_structure) {}

// Do nothing (file contents already loaded)
absl::Status Open() override;

// Do nothing (contents already parsed)
absl::Status Parse() override;

// Return TextStructureView provided previously in constructor
const verible::TextStructureView* GetTextStructure() const override;

private:
const verible::TextStructureView& text_structure_;
};

// VerilogProject represents a set of files as a cohesive unit of compilation.
// Files can include top-level translation units and preprocessor included
// files. This is responsible for owning string memory that corresponds
Expand Down
30 changes: 30 additions & 0 deletions verilog/analysis/verilog_project_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,36 @@ TEST(InMemoryVerilogSourceFileTest, ParseInvalidFile) {
EXPECT_EQ(&text_structure->SyntaxTree(), tree);
}

TEST(ParsedVerilogSourceFileTest, ParseValidFile) {
constexpr absl::string_view text("localparam int p = 1;\n");
std::unique_ptr<VerilogAnalyzer> analyzed_structure =
absl::make_unique<VerilogAnalyzer>(text, "internal");
absl::Status status = analyzed_structure->Analyze();
EXPECT_TRUE(status.ok());
const TextStructureView& input_text_structure = analyzed_structure->Data();

ParsedVerilogSourceFile file("internal", input_text_structure);
// Parse automatically opens.
EXPECT_TRUE(file.Parse().ok());
EXPECT_TRUE(file.Status().ok());
const TextStructureView* text_structure =
ABSL_DIE_IF_NULL(file.GetTextStructure());
EXPECT_EQ(&input_text_structure, text_structure);
const absl::string_view owned_string_range(text_structure->Contents());
EXPECT_EQ(owned_string_range, text);
const auto* tokens = &text_structure->TokenStream();
EXPECT_NE(tokens, nullptr);
const auto* tree = &text_structure->SyntaxTree();
EXPECT_NE(tree, nullptr);

// Re-parsing doesn't change anything
EXPECT_TRUE(file.Parse().ok());
EXPECT_TRUE(file.Status().ok());
EXPECT_EQ(file.GetTextStructure(), text_structure);
EXPECT_EQ(&text_structure->TokenStream(), tokens);
EXPECT_EQ(&text_structure->SyntaxTree(), tree);
}

TEST(VerilogProjectTest, Initialization) {
const auto tempdir = ::testing::TempDir();
VerilogProject project(tempdir, {tempdir});
Expand Down

0 comments on commit 47e9bf0

Please sign in to comment.