blob: 70e3cd219f986958fa576d823b3de7df30bc5346 [file]
// Copyright 2017-2020 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.
#include "verible/verilog/tools/kythe/indexing-facts-tree-extractor.h"
#include <functional>
#include <string>
#include <string_view>
#include <vector>
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "gtest/gtest.h"
#include "verible/common/analysis/syntax-tree-search-test-utils.h"
#include "verible/common/util/file-util.h"
#include "verible/common/util/logging.h"
#include "verible/common/util/tree-operations.h"
#include "verible/verilog/analysis/verilog-project.h"
#include "verible/verilog/tools/kythe/indexing-facts-tree.h"
#include "verible/verilog/tools/kythe/verilog-extractor-indexing-fact-type.h"
#undef EXPECT_OK
#define EXPECT_OK(value) EXPECT_TRUE((value).ok())
namespace verilog {
namespace kythe {
namespace {
using verible::file::testing::ScopedTestFile;
using T = IndexingFactNode;
using D = IndexingNodeData;
// This class exists, solely to store the temp dir name in a variable that
// outlives its uses. Do not pass TempDir() directly anywhere that expects a
// string_view to be owned elsewhere, because it returns a temporary string,
// which would leave a dangling reference.
class TempDir {
protected:
TempDir() : temp_dir_(::testing::TempDir()) {}
protected:
const std::string temp_dir_;
};
// Groups information for a single temporary source file together.
struct TestFileEntry {
// The original source code of the translation.
const std::string_view origin_text;
// One file in project, will be given randomly generated name.
const ScopedTestFile temp_file;
// Points to a successfully opened source file that corresponds to test_file_
// opened as a translation unit.
const VerilogSourceFile *const source_file = nullptr;
TestFileEntry(std::string_view code_text, std::string_view temp_dir,
const std::function<const VerilogSourceFile *(std::string_view)>
&file_opener,
std::string_view override_basename = "")
: origin_text(code_text),
temp_file(temp_dir, origin_text, override_basename),
// Open this file from inside 'project', save pointer here.
source_file(file_opener(temp_file.filename())) {}
// Returns the string_view of text owned by this->source_file.
std::string_view SourceText() const {
CHECK(source_file != nullptr);
return source_file->GetContent();
}
T::value_type ExpectedFileData() const {
CHECK(source_file != nullptr);
return {
IndexingFactType::kFile,
Anchor(source_file->ResolvedPath()),
Anchor(SourceText()),
};
}
};
// SimpleTestProject create a single-file project for testing.
// No include files supported in this base class.
class SimpleTestProject : public TempDir, public VerilogProject {
public:
// 'code_text' is the contents of the single translation unit in this project
explicit SimpleTestProject(std::string_view code_text,
const std::vector<std::string> &include_paths = {})
: VerilogProject(temp_dir_, include_paths, /*corpus=*/"unittest",
/*provide_lookup_file_origin=*/false),
code_text_(code_text),
translation_unit_(code_text, temp_dir_,
[this](std::string_view full_file_name)
-> const VerilogSourceFile * {
/* VerilogProject base class is already fully
* initialized */
return *OpenTranslationUnit(
verible::file::Basename(full_file_name));
}) {}
const TestFileEntry &XUnit() const { return translation_unit_; }
std::string_view OnlyFileName() const {
return translation_unit_.temp_file.filename();
}
T Extract() {
return ExtractFiles(
/* file_list_path= */ temp_dir_, // == Dirname(OnlyFileName()),
/* project= */ this,
/* file_names= */
{std::string(verible::file::Basename(OnlyFileName()))}, &errors_);
}
T::value_type ExpectedFileListData() const {
return {
IndexingFactType::kFileList, //
Anchor(std::string_view(temp_dir_)),
// file_list is co-located with the files it references
Anchor(TranslationUnitRoot()),
// TranslationUnitRoot() == verible::file::Dirname(OnlyFileName())
// but in a different string_view range.
};
}
std::vector<absl::Status> &Errors() { return errors_; }
// This printer only works well for tests cases with one translation unit.
PrintableIndexingFactNode TreePrinter(const IndexingFactNode &n) const {
return PrintableIndexingFactNode(n, code_text_);
}
private:
std::string code_text_;
// The one and only translation unit under test.
TestFileEntry translation_unit_;
// Processing errors.
std::vector<absl::Status> errors_;
};
// Test project with one source translation unit, one included file.
class IncludeTestProject : protected SimpleTestProject {
public:
// 'code_text' is the contents of the single translation unit in this project.
// 'include_text' is the contents of the single included file in this project.
IncludeTestProject(std::string_view code_text,
std::string_view include_file_basename,
std::string_view include_text,
const std::vector<std::string> &include_paths = {})
: SimpleTestProject(code_text, include_paths),
include_file_(
include_text, temp_dir_,
[this](
std::string_view full_file_name) -> const VerilogSourceFile * {
/* VerilogProject base class is already fully initialized */
return *OpenIncludedFile(verible::file::Basename(full_file_name));
},
include_file_basename) {}
using SimpleTestProject::Errors;
using SimpleTestProject::ExpectedFileListData;
using SimpleTestProject::Extract;
using SimpleTestProject::XUnit;
const TestFileEntry &IncludeFile() const { return include_file_; }
private:
// The one and only one included file in the test.
TestFileEntry include_file_;
};
TEST(FactsTreeExtractor, EqualOperatorTest) {
constexpr std::string_view code_text = "some other code";
constexpr std::string_view file_name = "verilog.v";
constexpr std::string_view file_name_other = "other.v";
const IndexingFactNode expected(D{
IndexingFactType::kFile,
Anchor(file_name),
});
// same as expected
const IndexingFactNode tree(D{
IndexingFactType::kFile,
Anchor(file_name),
});
// different filename
const IndexingFactNode tree2(D{
IndexingFactType::kFile,
Anchor(file_name_other),
});
// different number of anchors
const IndexingFactNode tree3(D{
IndexingFactType::kFile,
Anchor(file_name),
Anchor(file_name),
});
// completely different string_view ranges
const IndexingFactNode tree4(
D{
IndexingFactType::kFile,
Anchor(file_name),
},
T(D{
IndexingFactType::kModule,
Anchor(std::string_view("foo")),
Anchor(std::string_view("foo")),
}));
const auto P = [&code_text](const IndexingFactNode &n) {
return PrintableIndexingFactNode(n, code_text);
};
{
const auto result_pair = DeepEqual(tree, expected);
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
{
const auto result_pair2 = DeepEqual(tree2, expected);
EXPECT_NE(result_pair2.left, nullptr) << P(*result_pair2.left);
EXPECT_NE(result_pair2.right, nullptr) << P(*result_pair2.right);
}
{
const auto result_pair3 = DeepEqual(tree3, expected);
EXPECT_NE(result_pair3.left, nullptr) << P(*result_pair3.left);
EXPECT_NE(result_pair3.right, nullptr) << P(*result_pair3.right);
}
{
const auto result_pair4 = DeepEqual(tree4, expected);
EXPECT_NE(result_pair4.left, nullptr) << P(*result_pair4.left);
EXPECT_NE(result_pair4.right, nullptr) << P(*result_pair4.right);
}
}
TEST(FactsTreeExtractor, EmptyCSTTest) {
constexpr std::string_view code_text;
SimpleTestProject project(code_text);
const IndexingFactNode expected( //
project.ExpectedFileListData(), //
T(project.XUnit().ExpectedFileData()));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ParseErrorTest) {
// These inputs are lexically or syntactically invalid.
constexpr std::string_view code_texts[] = {
"9badid foo;\n", // lexical error
"final v;\n", // syntax error
"module unfinished", // syntax error
};
for (const auto &code_text : code_texts) {
SimpleTestProject project(code_text);
const auto facts_tree = project.Extract();
const std::vector<absl::Status> errors(project.Errors());
EXPECT_FALSE(errors.empty()) << "code\n" << code_text;
}
}
TEST(FactsTreeExtractor, EmptyModuleTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ", {kTag, "foo"}, ";\n endmodule: ", {kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo.
T(D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, PropagatedUserDefinedTypeInModulePort) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{
"module ",
{kTag, "foo"},
"(",
{kTag, "My_type"},
" ",
{kTag, "x"},
", ",
{kTag, "y"},
");\n endmodule",
}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to My_type.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to y.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, OneLocalNetTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase{{
"module ",
{kTag, "bar"},
";\n"
"wire ",
{kTag, "w"},
";\n"
"tri ",
{kTag, "`x"},
";\n"
"endmodule",
}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module bar.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to w.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to `x
// TODO(minatoma): suppress declarations that use macro
// identifiers because they evaluate to something unknown.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, OneModuleInstanceTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{"module ",
{kTag, "bar"},
";\n endmodule: ",
{kTag, "bar"},
"\nmodule ",
{kTag, "foo"},
";\n ",
{kTag, "bar"},
" ",
{kTag, "b1"},
"();\n endmodule: ",
{kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module bar.
T(D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to bar b1().
T(D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, TwoModuleInstanceTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{"module ",
{kTag, "bar"},
";\n endmodule: ",
{kTag, "bar"},
"\nmodule ",
{kTag, "foo"},
"; ",
{kTag, "bar"},
" ",
{kTag, "b1"},
"();\n",
{kTag, "bar"},
" ",
{kTag, "b2"},
"();\nendmodule: ",
{kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module bar.
T(D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
},
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to bar b1().
T(D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
})),
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to bar b2().
T(D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
} // namespace
TEST(FactsTreeExtractor, MultipleModuleInstancesInTheSameDeclarationTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{"module ",
{kTag, "bar"},
";\nendmodule: ",
{kTag, "bar"},
"\nmodule ",
{kTag, "foo"},
";\n",
{kTag, "bar"},
" ",
{kTag, "b1"},
"(), ",
{kTag, "b2"},
"();\nendmodule: ",
{kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module bar.
T(D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
},
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to b1().
T(D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}),
// refers to bar b2().
T(D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
} // namespace
TEST(FactsTreeExtractor, ModuleWithPortsTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{"module ",
{kTag, "foo"},
"(input ",
{kTag, "a"},
", output ",
{kTag, "b"},
");\nendmodule: ",
{kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to input a.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to output b.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ModuleDimensionTypePortsTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ",
{kTag, "foo"},
"(input ",
{kTag, "a"},
", output [",
{kTag, "x"},
":",
{kTag, "y"},
"] ",
{kTag, "b"},
" [",
{kTag, "x"},
":",
{kTag, "y"},
"]);\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to input a.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to output b.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}),
// refers to input x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to input y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to input x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}),
// refers to input y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ModuleWithPortsNonANSIStyleTest) {
constexpr int kTag = 1; // value doesn't matter
// Normally, tools will reject non-ANSI port declarations that are missing
// their full definitions inside the body like "input a", but here we don't
// care and are just checking for references, even if they are dangling.
const verible::SyntaxTreeSearchTestCase kTestCase = {{"module ",
{kTag, "foo"},
"(",
{kTag, "a"},
", ",
{kTag, "b"},
", input wire ",
{kTag, "z"},
", ",
{kTag, "h"},
");\nendmodule: ",
{kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to a.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to b.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to input z.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to h.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ClassParams) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "my_class"},
" #(parameter ",
{kTag, "x"},
" = 4, ",
{kTag, "y"},
" = 4); endclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class my_class.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to parameter x
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to y
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, QualifiedVariableType) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ",
{kTag, "m"},
";\n ",
{kTag, "pkg"},
"::",
{kTag, "X"},
" ",
{kTag, "y"},
";\n ",
{kTag, "pkg"},
"::",
{kTag, "H"},
" ",
{kTag, "j"},
" = new();\nendmodule"}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module m.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to pkg::X
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to y
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})),
// refers to pkg::H
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to j
T(D{
IndexingFactType::kClassInstance,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ClassTypeParams) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "my_class"},
" #(type ",
{kTag, "x"},
" = int, ",
{kTag, "y"},
" = int); endclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class my_class.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to parameter x
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to y
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ModuleInstanceWithActualNamedPorts) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ", // 0
{kTag, "foo"}, // 1
"(input ", // 2
{kTag, "a"}, // 3
", input ", // 4
{kTag, "b"}, // 5
", input wire ", // 6
{kTag, "z"}, // 7
", output ", // 8
{kTag, "h"}, // 9
");\nendmodule: ", // 10
{kTag, "foo"}, // 11
"\nmodule ", // 12
{kTag, "bar"}, // 13
"(input ", // 14
{kTag, "a"}, // 15
", ", // 16
{kTag, "b"}, // 17
", ", // 18
{kTag, "c"}, // 19
", ", // 20
{kTag, "h"}, // 21
");\n", // 22
{kTag, "foo"}, // 23
" ", // 24
{kTag, "f1"}, // 25
"(.", // 26
{kTag, "a"}, // 27
"(", // 28
{kTag, "a"}, // 29
"), .", // 30
{kTag, "b"}, // 31
"(", // 32
{kTag, "b"}, // 33
"), .", // 34
{kTag, "z"}, // 35
"(", // 36
{kTag, "c"}, // 37
"), .", // 38
{kTag, "h"}, // 39
");\nendmodule"}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to a.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to b.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to input z.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to h.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
})),
// refers to module bar.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
},
// refers to input a.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
}),
// refers to b.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
}),
// refers to c.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
}),
// refers to h.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
}),
// refers to foo.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[23], kTestCase.code),
},
// refers to f1(.a(a), .b(b), .z(c), .h).
T(
D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[25], kTestCase.code),
},
// refers to .a
T(
D{
IndexingFactType::kModuleNamedPort,
Anchor(kTestCase.expected_tokens[27],
kTestCase.code),
},
// refers to a
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[29],
kTestCase.code),
})),
// refers to .b
T(
D{
IndexingFactType::kModuleNamedPort,
Anchor(kTestCase.expected_tokens[31],
kTestCase.code),
},
// refers to b
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[33],
kTestCase.code),
})),
// refers to .z
T(
D{
IndexingFactType::kModuleNamedPort,
Anchor(kTestCase.expected_tokens[35],
kTestCase.code),
},
// refers to c
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[37],
kTestCase.code),
})),
// refers to .h
T(D{
IndexingFactType::kModuleNamedPort,
Anchor(kTestCase.expected_tokens[39], kTestCase.code),
}))))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ModuleInstanceWitStarExpandedPorts) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ", // 00
{kTag, "foo"}, // 01
"(input ", // 02
{kTag, "a"}, // 03
");\nendmodule\n", // 04
"\nmodule ", // 05
{kTag, "bar"}, // 06
"(input ", // 07
{kTag, "a"}, // 08
");\n", // 09
{kTag, "foo"}, // 10
" ", // 11
{kTag, "f1"}, // 12
"(.", // 13
{kTag, "*"}, // 14
");\nendmodule"}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to a.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})),
// refers to module bar.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[6], kTestCase.code),
},
// refers to input a.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[8], kTestCase.code),
}),
// refers to foo.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[10], kTestCase.code),
},
// refers to f1(.*)
T(D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[12], kTestCase.code),
} // The .* is not recorded as named module port.
)))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ModuleWithPortsDataTypeForwarding) {
constexpr int kTag = 1; // value doesn't matter
// Normally, tools will reject non-ANSI port declarations that are missing
// their full definitions inside the body like "input a", but here we don't
// care and are just checking for references, even if they are dangling.
const verible::SyntaxTreeSearchTestCase kTestCase = {{"module ",
{kTag, "foo"},
"(input wire ",
{kTag, "a"},
", ",
{kTag, "b"},
", output wire ",
{kTag, "z"},
", ",
{kTag, "h"},
");\nendmodule: ",
{kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to a.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to b.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to input z.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to h.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, PrimitiveTypeExtraction) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"package ",
{kTag, "pkg"},
";\n int ",
{kTag, "x"},
", ",
{kTag, "y"},
";\nlogic ",
{kTag, "l1"},
", ",
{kTag, "l2"},
";\nbit ",
{kTag, "b1"},
", ",
{kTag, "b2"},
";\nstring ",
{kTag, "s1"},
", ",
{kTag, "s2"},
";\nendpackage\nclass ",
{kTag, "cla"},
";\n int ",
{kTag, "x"},
", ",
{kTag, "y"},
";\nlogic ",
{kTag, "l1"},
", ",
{kTag, "l2"},
";\nbit ",
{kTag, "b1"},
", ",
{kTag, "b2"},
";\nstring ",
{kTag, "s1"},
", ",
{kTag, "s2"},
";\nendclass\nfunction int ",
{kTag, "fun"},
"();\n int ",
{kTag, "x"},
" = 5, ",
{kTag, "y"},
" = ",
{kTag, "my_fun"},
"(",
{kTag, "o"},
", ",
{kTag, "l"},
");\nlogic ",
{kTag, "l1"},
", ",
{kTag, "l2"},
";\nbit ",
{kTag, "b1"},
", ",
{kTag, "b2"},
";\nstring ",
{kTag, "s1"},
", ",
{kTag, "s2"},
";\nreturn ",
{kTag, "x"},
";\nendfunction"}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package pkg.
T(
D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to x;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to y;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to l1;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to l2;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}),
// refers to b1;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}),
// refers to b2;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
}),
// refers to s1;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
}),
// refers to s2;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
})),
// refers to class cla.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
},
// refers to x;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
}),
// refers to y;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[23], kTestCase.code),
}),
// refers to l1;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[25], kTestCase.code),
}),
// refers to l2;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[27], kTestCase.code),
}),
// refers to b1;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[29], kTestCase.code),
}),
// refers to b2;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[31], kTestCase.code),
}),
// refers to s1;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[33], kTestCase.code),
}),
// refers to s2;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[35], kTestCase.code),
})),
// refers to function fun.
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[37], kTestCase.code),
},
// refers to x;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[39], kTestCase.code),
}),
// refers to y;
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[41], kTestCase.code),
},
// refers to my_fun;
T(
D{
IndexingFactType::kFunctionCall,
Anchor(kTestCase.expected_tokens[43], kTestCase.code),
},
// refers to o;
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[45], kTestCase.code),
}),
// refers to l;
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[47], kTestCase.code),
}))),
// refers to l1;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[49], kTestCase.code),
}),
// refers to l2;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[51], kTestCase.code),
}),
// refers to b1;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[53], kTestCase.code),
}),
// refers to b2;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[55], kTestCase.code),
}),
// refers to s1;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[57], kTestCase.code),
}),
// refers to s2;
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[59], kTestCase.code),
}),
// refers to return x;
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[61], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, MultiSignalDeclaration) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{"module ",
{kTag, "foo"},
"(",
"input ",
{kTag, "in"},
");\n",
"input ",
{kTag, "x"},
", ",
{kTag, "y"},
";\noutput ",
{kTag, "z"},
";\nendmodule: ",
{kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
},
// refers to input in.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[4], kTestCase.code),
}),
// refers to output x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to output y
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}),
// refers to output z.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ModuleInstanceWithPortsTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{"module ",
{kTag, "bar"},
"(input ",
{kTag, "x"},
", output ",
{kTag, "y"},
");\nendmodule: ",
{kTag, "bar"},
"\nmodule ",
{kTag, "foo"},
"(input ",
{kTag, "x"},
", output ",
{kTag, "y"},
");\n ",
{kTag, "bar"},
" ",
{kTag, "b1"},
"(",
{kTag, "x"},
", ",
{kTag, "y"},
");\nendmodule: ",
{kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module bar.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to input x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to output y.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
})),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
Anchor(kTestCase.expected_tokens[23], kTestCase.code),
},
// refers to input x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}),
// refers to output y.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
}),
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
},
// refers to b1(x, y).
T(
D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
},
// refers to x
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
}),
// refers to y
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
}))))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
} // namespace
TEST(FactsTreeExtractor, WireTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{"module ",
{kTag, "foo"},
"();\nwire ",
{kTag, "a"},
";\nendmodule: ",
{kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to "wire a"
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ClassTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ", {kTag, "foo"}, ";\nendclass: ", {kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class foo
T(D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, CLassWithinModuleTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{"module ",
{kTag, "m"},
"();\nclass ",
{kTag, "foo"},
";\nendclass:",
{kTag, "foo"},
";\nendmodule: ",
{kTag, "m"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module foo
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to "class foo"
T(D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, NestedClassTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{
"class ",
{kTag, "foo"},
";\nclass ",
{kTag, "bar"},
";\nendclass: ",
{kTag, "bar"},
"\nendclass: ",
{kTag, "foo"},
}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class foo
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to class bar
T(D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, OneClassInstanceTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{"class ",
{kTag, "bar"},
";\n endclass: ",
{kTag, "bar"},
"\nmodule ",
{kTag, "foo"},
"();\n ",
{kTag, "bar"},
" ",
{kTag, "b1"},
"= new(), ",
{kTag, "b2"},
" = new(",
{kTag, "x"},
", ",
{kTag, "y"},
");\n endmodule: ",
{kTag, "foo"}}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class bar.
T(D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
},
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to b1.
T(D{
IndexingFactType::kClassInstance,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}),
// refers to b2.
T(
D{
IndexingFactType::kClassInstance,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
}),
// refers to y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
}))))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ClassMemberAccess) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{
"class ", {kTag, "inner"},
";\n static int ", {kTag, "x"},
";\nendclass\n", "class ",
{kTag, "bar"}, ";\n static ",
{kTag, "inner"}, " ",
{kTag, "in1"}, " = new();\nendclass: ",
{kTag, "bar"}, "\nmodule ",
{kTag, "foo"}, "();\n ",
{kTag, "bar"}, " ",
{kTag, "b1"}, "= new();\n initial $display(",
{kTag, "bar"}, "::",
{kTag, "in"}, "::",
{kTag, "x"}, ");\nendmodule: ",
{kTag, "foo"},
}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class inner.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to int x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})),
// refers to class bar.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[6], kTestCase.code),
Anchor(kTestCase.expected_tokens[12], kTestCase.code),
},
// refers to inner in1.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[8], kTestCase.code),
},
// refers to in1.
T(D{
IndexingFactType::kClassInstance,
Anchor(kTestCase.expected_tokens[10], kTestCase.code),
}))),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[14], kTestCase.code),
Anchor(kTestCase.expected_tokens[26], kTestCase.code),
},
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[16], kTestCase.code),
},
// refers to b1.
T(D{
IndexingFactType::kClassInstance,
Anchor(kTestCase.expected_tokens[18], kTestCase.code),
})),
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-0"),
},
// refers to bar::in::x.
T(D{
IndexingFactType::kMemberReference,
Anchor(kTestCase.expected_tokens[20], kTestCase.code),
Anchor(kTestCase.expected_tokens[22], kTestCase.code),
Anchor(kTestCase.expected_tokens[24], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, FunctionAndTaskDeclarationNoArgs) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{
"function int ",
{kTag, "foo"},
"();",
";\nendfunction ",
"task ",
{kTag, "bar"},
"();",
";\nendtask ",
}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function foo
T(D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
}),
// refers to task bar
T(D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
})));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, FunctionAndTaskDeclarationWithArgs) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{
"function int ", {kTag, "foo"}, "(int ", {kTag, "arg1"},
", input ", {kTag, "arg2"}, ", ", {kTag, "arg3"},
", bit ", {kTag, "arg4"}, ");", ";\nendfunction ",
"task ", {kTag, "bar"}, "(int ", {kTag, "arg1"},
", input ", {kTag, "arg2"}, ", ", {kTag, "arg3"},
", bit ", {kTag, "arg4"}, ");", ";\nendtask ",
}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function foo
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
})),
// refers to task bar
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
},
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
}),
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
}),
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
}),
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ClassMember) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{
"module ",
{kTag, "m"},
"();\ninitial begin\n$display(",
{kTag, "my_class"},
".",
{kTag, "x"},
");\n$display(",
{kTag, "my_class"},
".",
{kTag, "instance1"},
".",
{kTag, "y"},
");\nend\nendmodule",
}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module m
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-0"),
},
// refers to my_class.x
T(D{
IndexingFactType::kMemberReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to my_class.instance1.x
T(D{
IndexingFactType::kMemberReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, FunctionAndTaskCallNoArgs) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{
"function int ",
{kTag, "foo"},
"();",
";\nendfunction\n ",
"task ",
{kTag, "bar"},
"();",
";\nendtask ",
"\nmodule ",
{kTag, "m"},
"();\ninitial begin\n",
{kTag, "foo"},
"();\n",
{kTag, "bar"},
"();\nend\nendmodule: ",
{kTag, "m"},
}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function foo
T(D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
}),
// refers to task bar
T(D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
},
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-0"),
},
T(D{
IndexingFactType::kFunctionCall,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}),
T(D{
IndexingFactType::kFunctionCall,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, FunctionClassCall) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {{
"class ",
{kTag, "inner"},
";\n static function int ",
{kTag, "my_fun"},
"();\nreturn 1;\nendfunction\nfunction int ",
{kTag, "fun_2"},
"(int ",
{kTag, "x"},
", int ",
{kTag, "y"},
");\nreturn ",
{kTag, "x"},
" + ",
{kTag, "y"},
";\nendfunction\nendclass\n",
"class ",
{kTag, "bar"},
";\n static ",
{kTag, "inner"},
" ",
{kTag, "in1"},
" = new();\nendclass: ",
{kTag, "bar"},
"\nmodule ",
{kTag, "foo"},
"();\n ",
{kTag, "bar"},
" ",
{kTag, "b1"},
"= new();\n initial $display(",
{kTag, "bar"},
"::",
{kTag, "in"},
"::",
{kTag, "my_fun"},
"());\ninitial $display(",
{kTag, "bar"},
"::",
{kTag, "in"},
".",
{kTag, "my_fun"},
"());\n",
{kTag, "inner"},
" ",
{kTag, "in1"},
" = new();\nint ",
{kTag, "x"},
", ",
{kTag, "y"},
";\ninitial $display(",
{kTag, "in1"},
".",
{kTag, "fun_2"},
"(",
{kTag, "x"},
", ",
{kTag, "y"},
"));\nendmodule",
}};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class inner.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to function my_fun.
T(D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to function fun_2.
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x arg in fun_2.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to y arg in fun_2.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}),
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}),
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
}))),
// refers to class bar.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[16], kTestCase.code),
Anchor(kTestCase.expected_tokens[22], kTestCase.code),
},
// refers to inner in1.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[18], kTestCase.code),
},
// refers to in1.
T(D{
IndexingFactType::kClassInstance,
Anchor(kTestCase.expected_tokens[20], kTestCase.code),
}))),
// refers to module foo.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[24], kTestCase.code),
},
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[26], kTestCase.code),
},
// refers to b1.
T(D{
IndexingFactType::kClassInstance,
Anchor(kTestCase.expected_tokens[28], kTestCase.code),
})),
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-0"),
},
// refers to bar::in::my_fun().
T(D{
IndexingFactType::kFunctionCall,
Anchor(kTestCase.expected_tokens[30], kTestCase.code),
Anchor(kTestCase.expected_tokens[32], kTestCase.code),
Anchor(kTestCase.expected_tokens[34], kTestCase.code),
})),
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-1"),
},
// refers to bar::in.my_fun().
T(D{
IndexingFactType::kFunctionCall,
Anchor(kTestCase.expected_tokens[36], kTestCase.code),
Anchor(kTestCase.expected_tokens[38], kTestCase.code),
Anchor(kTestCase.expected_tokens[40], kTestCase.code),
})),
// refers to inner in1.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[42], kTestCase.code),
},
// refers to in1.
T(D{
IndexingFactType::kClassInstance,
Anchor(kTestCase.expected_tokens[44], kTestCase.code),
})),
// refers to int x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[46], kTestCase.code),
}),
// refers to int y.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[48], kTestCase.code),
}),
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-2"),
},
// refers to in1.my_fun().
T(
D{
IndexingFactType::kFunctionCall,
Anchor(kTestCase.expected_tokens[50], kTestCase.code),
Anchor(kTestCase.expected_tokens[52], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[54], kTestCase.code),
}),
// refers to y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[56], kTestCase.code),
}))))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ThisAsFunctionCall) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase{
// Note: this test case is also significant in that it exercises
// short-string-optimization, where by sufficiently short strings live
// directly in the object, rather than in heap memory.
{
{kTag, "r"},
"=this();",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to r.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[0], kTestCase.code),
})));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, MacroDefinitionTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"`define ",
{kTag, "PRINT_STRING"},
"(",
{kTag, "str1"},
") $display(\"%s\\n\", str1)\n",
"`define ",
{kTag, "PRINT_3_STRING"},
"(",
{kTag, "str1"},
", ",
{kTag, "str2"},
", ",
{kTag, "str3"},
")",
R"( \
`PRINT_STRING(str1); \
`PRINT_STRING(str2); \
`PRINT_STRING(str3);)",
"\n`define ",
{kTag, "TEN"},
" 10",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to macro PRINT_STRING.
T(
D{
IndexingFactType::kMacro,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to str1 arg in PRINT_STRING.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})),
// refers to macro PRINT_3_STRING.
T(
D{
IndexingFactType::kMacro,
Anchor(kTestCase.expected_tokens[6], kTestCase.code),
},
// refers to str1 arg in PRINT_3_STRING.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[8], kTestCase.code),
}),
// refers to str2 arg in PRINT_3_STRING.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[10], kTestCase.code),
}),
// refers to str3 arg in PRINT_3_STRING.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[12], kTestCase.code),
})),
// refers to macro TEN.
T(D{
IndexingFactType::kMacro,
Anchor(kTestCase.expected_tokens[16], kTestCase.code),
})));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, MacroCallTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
"`define ",
{kTag, "PRINT_STRING"},
"(",
{kTag, "str1"},
") $display(\"%s\\n\", str1)\n",
"`define ",
{kTag, "PRINT_3_STRING"},
"(",
{kTag, "str1"},
", ",
{kTag, "str2"},
", ",
{kTag, "str3"},
")",
R"( \
`PRINT_STRING(str1); \
`PRINT_STRING(str2); \
`PRINT_STRING(str3);)",
"\n`define ",
{kTag, "TEN"},
" 10\n",
"\n`define ",
{kTag, "NUM"},
"(",
{kTag, "i"},
") i\n",
"module ",
{kTag, "macro"},
";\ninitial begin\n`",
{kTag, "PRINT_3_STRINGS"},
"(\"Grand\", \"Tour\", \"S4\");\n",
"$display(\"%d\\n\", `",
{kTag, "TEN"},
");\n",
"$display(\"%d\\n\", `",
{kTag, "NUM"},
"(`",
{kTag, "TEN"},
"));\n",
"parameter int ",
{kTag, "x"},
" = `",
{kTag, "TEN"},
";\n"
"end\nendmodule",
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to macro PRINT_STRING.
T(
D{
IndexingFactType::kMacro,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to str1 in PRINT_STRING.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})),
// refers to macro PRINT_3_STRING.
T(
D{
IndexingFactType::kMacro,
Anchor(kTestCase.expected_tokens[6], kTestCase.code),
},
// refers to str1 in PRINT_3_STRING.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[8], kTestCase.code),
}),
// refers to str2 in PRINT_3_STRING.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[10], kTestCase.code),
}),
// refers to str3 in PRINT_3_STRING.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[12], kTestCase.code),
})),
// refers to macro TEN.
T(D{
IndexingFactType::kMacro,
Anchor(kTestCase.expected_tokens[16], kTestCase.code),
}),
// refers to macro NUM.
T(
D{
IndexingFactType::kMacro,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
},
// refers to i in macro NUM.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
})),
// refers to module macro.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[24], kTestCase.code),
},
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-0"),
},
// refers to macro call PRINT_3_STRINGS.
T(D{
IndexingFactType::kMacroCall,
Anchor(kTestCase.expected_tokens[26], kTestCase.code),
}),
// refers to macro call TEN.
T(D{
IndexingFactType::kMacroCall,
Anchor(kTestCase.expected_tokens[29], kTestCase.code),
}),
// refers to macro call NUM.
T(
D{
IndexingFactType::kMacroCall,
Anchor(kTestCase.expected_tokens[32], kTestCase.code),
}, // refers to macro call TEN.
T(D{
IndexingFactType::kMacroCall,
Anchor(kTestCase.expected_tokens[34], kTestCase.code),
})),
// refers to parm x
T(
D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[37], kTestCase.code),
},
// refers to macro call TEN.
T(D{
IndexingFactType::kMacroCall,
Anchor(kTestCase.expected_tokens[39], kTestCase.code),
}))))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(PackageImportTest, PackageAndImportedItemName) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"package ",
{kTag, "pkg1"},
";\nendpackage\npackage ",
{kTag, "pkg"},
";\nclass ",
{kTag, "my_class"},
";\nendclass\nfunction ",
{kTag, "my_function"},
"();\nendfunction\nendpackage\nmodule ",
{kTag, "m"},
"();\nimport ",
{kTag, "pkg1"},
"::*;\nimport ",
{kTag, "pkg"},
"::",
{kTag, "my_function"},
";\nimport ",
{kTag, "pkg"},
"::",
{kTag, "my_class"},
";\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package pkg1.
T(D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
}),
// refers to package pkg.
T(
D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to class my_class.
T(D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to function my_function.
T(D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})),
// refers to module m..
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
},
// refers to import pkg1::*.
T(D{
IndexingFactType::kPackageImport,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}),
// refers to import pkg::my_function.
T(D{
IndexingFactType::kPackageImport,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
}),
// refers to import pkg::my_class.
T(D{
IndexingFactType::kPackageImport,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(PackageImportTest, PackageDirectMemberReference) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"package ",
{kTag, "pkg"},
";\nclass ",
{kTag, "my_class"},
";\nendclass\nwire ",
{kTag, "x"},
";\nendpackage\nmodule ",
{kTag, "m"},
"();\n",
"initial $display(",
{kTag, "pkg"},
"::",
{kTag, "x"},
");\n",
";\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package pkg.
T(
D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to class my_class.
T(D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to wire x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
})),
// refers to module m..
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-0"),
},
// refers to $display(pkg::x).
T(D{
IndexingFactType::kMemberReference,
Anchor(kTestCase.expected_tokens[10], kTestCase.code),
Anchor(kTestCase.expected_tokens[12], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(PackageImportTest, ClassInstanceWithMultiParams) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"function ",
{kTag, "m"},
"();\n",
{kTag, "foo"},
"#(.",
{kTag, "A"},
"(",
{kTag, "var1"},
"), .",
{kTag, "B"},
"(",
{kTag, "var2"},
"))::",
{kTag, "barc"},
"#(.",
{kTag, "X"},
"(",
{kTag, "var1"},
"), .",
{kTag, "W"},
"(",
{kTag, "var2"},
"))::",
{kTag, "get2"},
"();\nendfunction",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function m.
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers foo(.A, .B).
T(
D{
IndexingFactType::kMemberReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers A.
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers var1.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})),
// refers B.
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
},
// refers var2.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}))),
// refers barc(.X, .W).
T(
D{
IndexingFactType::kMemberReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
},
// refers X.
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
},
// refers var1.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
})),
// refers W.
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
},
// refers var2.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
}))),
// refers var2.
T(D{
IndexingFactType::kFunctionCall,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
Anchor(kTestCase.expected_tokens[23], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(PackageImportTest, UserDefinedType) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "Stack"},
";\ntypedef int ",
{kTag, "some_type"},
";\nendclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class stack.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to some_type.
T(D{
IndexingFactType::kTypeDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(PackageImportTest, SelectVariableDimension) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"task ",
{kTag, "t"},
"(int ",
{kTag, "y"},
");\n@",
{kTag, "x"},
"[",
{kTag, "y"},
"];\nendtask",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to task t.
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to y.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(PackageImportTest, ClassParameterType) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "Stack"},
" #(parameter type ",
{kTag, "T"},
"=int);\nendclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class stack.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to T.
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(PackageImportTest, ClassInstanceWithParams) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"module ",
{kTag, "m"},
"();\n",
{kTag, "clt"},
"#(",
{kTag, "x"},
") ",
{kTag, "v1"},
" = new();\nendmodule",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module m.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to clt#(x) v1.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to v1.
T(D{
IndexingFactType::kClassInstance,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(PackageImportTest, PackageTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"package ",
{kTag, "pkg"},
";\nendpackage: ",
{kTag, "pkg"},
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package pkg.
T(D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ForLoopInitializations) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"function int ",
{kTag, "foo"},
"();\n for (int ",
{kTag, "i"},
" = 0, bit ",
{kTag, "j"},
" = 0, bit[",
{kTag, "l"},
":",
{kTag, "r"},
"] ",
{kTag, "tm"},
" = 0; ",
{kTag, "i"},
" < 50; ",
{kTag, "i"},
"++) begin\n",
{kTag, "x"},
"+=",
{kTag, "i"},
";\nend\nreturn ",
{kTag, "x"},
";\n\nendfunction "},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function foo
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-0"),
},
// refers to i
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to j
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to tm
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}),
// refers to l
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to r
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}),
// refers to i
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
}),
// refers to i
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
}),
// refers to x
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
}),
// refers to i
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
})),
// refers to x
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ClassExtends) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "X"},
" extends ",
{kTag, "Y"},
";\nendclass\nclass ",
{kTag, "H"},
" extends ",
{kTag, "G"},
"::",
{kTag, "K"},
";\nendclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class X.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to Y.
T(D{
IndexingFactType::kExtends,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})),
// refers to H.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to G::K.
T(D{
IndexingFactType::kExtends,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ParameterExtraction) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ",
{kTag, "m"},
"#(parameter ",
{kTag, "x"},
" = 1, parameter ",
{kTag, "y"},
" = 2) (input ",
{kTag, "z"},
");\n ",
{kTag, "bar"},
" #(.",
{kTag, "p1"},
"(",
{kTag, "x"},
"), .",
{kTag, "p2"},
"(",
{kTag, "y"},
")) ",
{kTag, "b1"},
"(",
{kTag, "z"},
");\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module m.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to module parameter x.
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to class parameter y.
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to class input x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
},
// refers to .p1(x).
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
})),
// refers to .p2(y).
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
},
// refers to y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
})),
// refers to b1.
T(
D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
},
// refers to z.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
}))))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, InterfaceParameterExtraction) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"interface ",
{kTag, "m"},
"#(parameter ",
{kTag, "x"},
" = 1, parameter ",
{kTag, "y"},
" = 2) (input ",
{kTag, "z"},
");\n ",
{kTag, "bar"},
" #(.",
{kTag, "p1"},
"(",
{kTag, "x"},
"), .",
{kTag, "p2"},
"(",
{kTag, "y"},
")) ",
{kTag, "b1"},
"(",
{kTag, "z"},
");\nendinterface"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to interface m.
T(
D{
IndexingFactType::kInterface,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to module parameter x.
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to class parameter y.
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to class input x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
},
// refers to .p1(x).
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
})),
// refers to .p2(y).
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
},
// refers to y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
})),
// refers to b1.
T(
D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
},
// refers to z.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
}))))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ClassAsPort) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ",
{kTag, "m"},
"(",
{kTag, "class_type"},
" ",
{kTag, "x"},
");\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module m.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to class_type.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ProgramParameterExtraction) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"program ",
{kTag, "m"},
"#(parameter ",
{kTag, "x"},
" = 1, parameter ",
{kTag, "y"},
" = 2) (input ",
{kTag, "z"},
");\n ",
{kTag, "bar"},
" #(.",
{kTag, "p1"},
"(",
{kTag, "x"},
"), .",
{kTag, "p2"},
"(",
{kTag, "y"},
")) ",
{kTag, "b1"},
"(",
{kTag, "z"},
");\nendprogram"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to program m.
T(
D{
IndexingFactType::kProgram,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to module parameter x.
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to class parameter y.
T(D{
IndexingFactType::kParamDeclaration,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to class input x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
}),
// refers to bar.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
},
// refers to .p1(x).
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
})),
// refers to .p2(y).
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
},
// refers to y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
})),
// refers to b1.
T(
D{
IndexingFactType::kModuleInstance,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
},
// refers to z.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
}))))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, PackedAndUnpackedDimension) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"package ",
{kTag, "pkg"},
";\nint [",
{kTag, "k"},
":",
{kTag, "y"},
"] ",
{kTag, "x"},
" [",
{kTag, "l"},
":",
{kTag, "r"},
"];\nendpackage\nmodule ",
{kTag, "m"},
";\nint [",
{kTag, "j"},
":",
{kTag, "o"},
"] ",
{kTag, "v"},
" [",
{kTag, "e"},
":",
{kTag, "t"},
"];\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package pkg.
T(
D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to k.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to x.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to l.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}),
// refers to r.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}))),
// refers to module m.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
},
// refers to j.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
}),
// refers to o.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
}),
// refers to v.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
},
// refers to e.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
}),
// refers to t.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[23], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, FileIncludes) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase0 = {
{"class ",
{kTag, "my_class"},
";\n static int ",
{kTag, "var5"},
";\n endclass"},
};
const std::string included_file_basename(
verible::file::testing::RandomFileBasename("include-this"));
const std::string quoted_included_file =
absl::StrCat("\"", included_file_basename, "\"");
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"`include ",
{kTag, quoted_included_file},
"\n module ",
{kTag, "my_module"},
"();\n initial begin\n$display(",
{kTag, "my_class"},
"::",
{kTag, "var5"},
");\n "
"end\nendmodule"},
};
IncludeTestProject project(kTestCase.code, included_file_basename,
kTestCase0.code, {::testing::TempDir()});
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.IncludeFile().ExpectedFileData(),
// refers to class my_class.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase0.expected_tokens[1], kTestCase0.code),
},
// refers to int var5.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase0.expected_tokens[3], kTestCase0.code),
}))),
T(project.XUnit().ExpectedFileData(),
// refers to include.
T(D{
IndexingFactType::kInclude,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(project.IncludeFile().source_file->ResolvedPath()),
}),
// refers to module my_module.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-0"),
},
// refers to $display(my_class::var5).
T(D{
IndexingFactType::kMemberReference,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
// Print showing raw addresses instead of in-file byte-offsets.
EXPECT_EQ(result_pair.left, nullptr) << *result_pair.left;
EXPECT_EQ(result_pair.right, nullptr) << *result_pair.right;
}
TEST(FactsTreeExtractor, IncludedFileContainsParseError) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase0{
{"parameter 7;"}, // parse error
};
const std::string included_file_basename(
verible::file::testing::RandomFileBasename("include-this"));
const std::string quoted_included_file =
absl::StrCat("\"", included_file_basename, "\"");
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"`include ",
{kTag, quoted_included_file},
"\n module ",
{kTag, "my_module"},
";\nendmodule"},
};
IncludeTestProject project(kTestCase.code, included_file_basename,
kTestCase0.code, {::testing::TempDir()});
const IndexingFactNode expected( //
project.ExpectedFileListData(),
// No subtree from project.IncludeFile(), due to parse error.
T(project.XUnit().ExpectedFileData(),
// refers to include.
T(D{
IndexingFactType::kInclude,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(project.IncludeFile().source_file->ResolvedPath()),
}),
// refers to module my_module.
T(D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})));
const auto facts_tree = project.Extract();
// Check that a parse error was recorded.
const auto statuses(project.Errors());
ASSERT_EQ(statuses.size(), 1);
EXPECT_EQ(statuses.front().code(), absl::StatusCode::kInvalidArgument);
const auto result_pair = DeepEqual(facts_tree, expected);
// Print showing raw addresses instead of in-file byte-offsets.
EXPECT_EQ(result_pair.left, nullptr) << *result_pair.left;
EXPECT_EQ(result_pair.right, nullptr) << *result_pair.right;
}
TEST(FactsTreeExtractor, IncludedFileNotFound) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase0{
{"parameter int foo = 7;"}, // parse error
};
const std::string included_file_basename(
verible::file::testing::RandomFileBasename("include-this"));
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"`include ",
{kTag, "\"wrong-wrong.wrong-file\""},
"\n module ",
{kTag, "my_module"},
";\nendmodule"},
};
IncludeTestProject project(kTestCase.code, included_file_basename,
kTestCase0.code, {::testing::TempDir()});
const IndexingFactNode expected( //
project.ExpectedFileListData(),
// included file was not found, and ignored
T(project.XUnit().ExpectedFileData(),
// No include node created.
T(
// refers to module my_module.
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})));
const auto facts_tree = project.Extract();
// Confirm that we have an error status.
const auto statuses(project.Errors());
ASSERT_EQ(statuses.size(), 1);
EXPECT_EQ(statuses.front().code(), absl::StatusCode::kNotFound);
const auto result_pair = DeepEqual(facts_tree, expected);
// Print showing raw addresses instead of in-file byte-offsets.
EXPECT_EQ(result_pair.left, nullptr) << *result_pair.left;
EXPECT_EQ(result_pair.right, nullptr) << *result_pair.right;
}
TEST(FactsTreeExtractor, FileIncludeSameFileTwice) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase0 = {
{"class ",
{kTag, "my_class"},
";\n static int ",
{kTag, "var5"},
";\n endclass"},
};
const std::string included_file_basename(
verible::file::testing::RandomFileBasename("include-this"));
const std::string quoted_included_file =
absl::StrCat("\"", included_file_basename, "\"");
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"`include ",
{kTag, quoted_included_file},
"\n `include ",
{kTag, quoted_included_file}, // repeated
"\n module ",
{kTag, "my_module"},
"();\n initial begin\n$display(",
{kTag, "my_class"},
"::",
{kTag, "var5"},
");\n "
"end\nendmodule"},
};
IncludeTestProject project(kTestCase.code, included_file_basename,
kTestCase0.code, {::testing::TempDir()});
const IndexingFactNode expected( //
project.ExpectedFileListData(), //
T(project.IncludeFile().ExpectedFileData(), //
// refers to class my_class.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase0.expected_tokens[1], kTestCase0.code),
},
// refers to int var5.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase0.expected_tokens[3], kTestCase0.code),
}))),
T(project.XUnit().ExpectedFileData(), //
// refers to include.
T(D{
IndexingFactType::kInclude,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(project.IncludeFile().source_file->ResolvedPath()),
}),
// refers to include (duplicate).
T(D{
IndexingFactType::kInclude,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
Anchor(project.IncludeFile().source_file->ResolvedPath()),
}),
// refers to module my_module.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// anonymous scope for initial.
T(
D{
IndexingFactType::kAnonymousScope,
Anchor("anonymous-scope-0"),
},
// refers to $display(my_class::var5).
T(D{
IndexingFactType::kMemberReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
// Print showing raw addresses instead of in-file byte-offsets.
EXPECT_EQ(result_pair.left, nullptr) << *result_pair.left;
EXPECT_EQ(result_pair.right, nullptr) << *result_pair.right;
}
TEST(FactsTreeExtractor, EnumTest) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"package ",
{kTag, "pkg"},
";\nenum {",
{kTag, "AA"},
"} ",
{kTag, "m_var"},
";\ntypedef enum {",
{kTag, "BB"},
"} ",
{kTag, "var2"},
";\nendpackage\nmodule ",
{kTag, "m"},
"();\nenum {",
{kTag, "CC"},
"} ",
{kTag, "m_var"},
";\ntypedef enum {",
{kTag, "DD"},
"} ",
{kTag, "var3"},
";\nenum {",
{kTag, "GG"},
"=",
{kTag, "y"},
"[",
{kTag, "idx"},
"]} ",
{kTag, "var6"},
";\ntypedef enum {",
{kTag, "HH"},
"=",
{kTag, "yh"},
"[",
{kTag, "idx2"},
"]} ",
{kTag, "var5"},
";\n"
"endmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package pkg.
T(
D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to AA.
T(D{
IndexingFactType::kConstant,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to enum m_var.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to enum var.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}),
// refers to BB.
T(D{
IndexingFactType::kConstant,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})),
// refers to module m.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
},
// refers to CC.
T(D{
IndexingFactType::kConstant,
Anchor(kTestCase.expected_tokens[13], kTestCase.code),
}),
// refers to enum m_var.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[15], kTestCase.code),
}),
// refers to enum var2.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[19], kTestCase.code),
}),
// refers to DD.
T(D{
IndexingFactType::kConstant,
Anchor(kTestCase.expected_tokens[17], kTestCase.code),
}),
// refers to GG.
T(
D{
IndexingFactType::kConstant,
Anchor(kTestCase.expected_tokens[21], kTestCase.code),
},
// refers to y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[23], kTestCase.code),
}),
// refers to idx.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[25], kTestCase.code),
})),
// refers to enum var3.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[27], kTestCase.code),
}),
// refers to enum var5.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[35], kTestCase.code),
}),
// refers to HH.
T(
D{
IndexingFactType::kConstant,
Anchor(kTestCase.expected_tokens[29], kTestCase.code),
},
// refers to yh.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[31], kTestCase.code),
}),
// refers to idx2.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[33], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, NonLiteralIncludeSafeFail) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
// no facts should be extracted for this include.
{"`include `c\nmodule ",
{kTag, "pkg"},
";\n struct {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module pkg.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to var1.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, StructInModule) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ",
{kTag, "pkg"},
";\n struct {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module pkg.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to var1.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ClassConstructor) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "my_class"},
";\nfunction ",
{kTag, "new"},
"(int ",
{kTag, "x"},
");\n",
{kTag, "x"},
" = 1;\nendfunction\nendclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class my_class.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to new.
T(
D{
IndexingFactType::kConstructor,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, StructInPackage) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"package ",
{kTag, "pkg"},
";\n struct {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";\nendpackage"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package pkg.
T(
D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to var1.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, UnionInModule) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ",
{kTag, "pkg"},
";\n union {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module pkg.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to var1.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, UnionInPackage) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"package ",
{kTag, "pkg"},
";\n union {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";\nendpackage"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package pkg.
T(
D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to var1.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, UnionTypeInPackage) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"package ",
{kTag, "pkg"},
";\n typedef union {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";\nendpackage"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package pkg.
T(
D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to var1.
T(
D{
IndexingFactType::kStructOrUnion,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, UnionTypenModule) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ",
{kTag, "pkg"},
";\n typedef union {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module pkg.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to var1.
T(
D{
IndexingFactType::kStructOrUnion,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, StructTypeInPackage) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"package ",
{kTag, "pkg"},
";\n typedef struct {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";\nendpackage"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package pkg.
T(
D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to var1.
T(
D{
IndexingFactType::kStructOrUnion,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, StructTypedefModule) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"module ",
{kTag, "pkg"},
";\n typedef struct {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";\nendmodule"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to module pkg.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to var1.
T(
D{
IndexingFactType::kStructOrUnion,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, DataTypeReferenceInUnionType) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"typedef struct {\n ",
{kTag, "some_type"},
" ",
{kTag, "var1"},
";}",
{kTag, "var2"},
";"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to struct var1.
T(
D{
IndexingFactType::kStructOrUnion,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to some_type var1.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to var1.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, StructInUnionType) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"typedef union {\n struct {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";}",
{kTag, "var2"},
";"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to union var1.
T(
D{
IndexingFactType::kStructOrUnion,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to struct var2.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, StructInUnion) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"union {\n struct {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";}",
{kTag, "var2"},
";"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to union var1.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to struct var2.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, UnionInStructType) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"typedef struct {\n union {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";}",
{kTag, "var2"},
";"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to union var1.
T(
D{
IndexingFactType::kStructOrUnion,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to struct var2.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, UnionInStruct) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"struct {\n union {int ",
{kTag, "xx"},
";} ",
{kTag, "var1"},
";}",
{kTag, "var2"},
";"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to union var1.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to struct var2.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, TypedVariable) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"package ",
{kTag, "m"},
";\n",
{kTag, "some_type"},
" ",
{kTag, "var1"},
";\nendpackage\nmodule ",
{kTag, "m"},
"();\n",
{kTag, "some_type1"},
" ",
{kTag, "var2"},
";\nendmodule",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to package m.
T(
D{
IndexingFactType::kPackage,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to some_type.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to var1.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}))),
// refers to module m.
T(
D{
IndexingFactType::kModule,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to some_type1.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
},
// refers to var2.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, FunctionNameAsQualifiedId) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"function ",
{kTag, "pkg"},
"::",
{kTag, "f"},
";\nendfunction\ntask ",
{kTag, "pkg"},
"::",
{kTag, "t"},
";\nendtask",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function pkg::f.
T(D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to task pkg::t.
T(D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, PureVirtualFunction) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "env"},
";\npure virtual function int ",
{kTag, "mod_if"},
"( ",
{kTag, "x"},
");\nendclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class env.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to function mod_if.
T(
D{
IndexingFactType::kFunctionOrTaskForwardDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ExternFunction) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "env"},
";\nextern function int ",
{kTag, "mod_if"},
"( ",
{kTag, "x"},
");\nendclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class env.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to function mod_if.
T(
D{
IndexingFactType::kFunctionOrTaskForwardDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, ExternTask) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "env"},
";\nextern task ",
{kTag, "mod_if"},
"( ",
{kTag, "x"},
");\nendclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class env.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to function mod_if.
T(
D{
IndexingFactType::kFunctionOrTaskForwardDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, PureVirtualTask) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "env"},
";\npure virtual task ",
{kTag, "mod_if"},
"( ",
{kTag, "x"},
");\nendclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class env.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to task mod_if.
T(
D{
IndexingFactType::kFunctionOrTaskForwardDeclaration,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, VirtualDataDeclaration) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{"class ",
{kTag, "env"},
" extends ",
{kTag, "uvm_env"},
";\nvirtual ",
{kTag, "mod_if"},
" ",
{kTag, "m_if"},
";\nendclass"},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to class env.
T(
D{
IndexingFactType::kClass,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to extends uvm_env.
T(D{
IndexingFactType::kExtends,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to mod_if.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to m_if.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, FunctionNamedArgument) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"function void ",
{kTag, "f1"},
"();\n",
{kTag, "f2"},
"(.",
{kTag, "a"},
"(",
{kTag, "x"},
"), .",
{kTag, "b"},
"(",
{kTag, "y"},
"));\nendfunction",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function f1.
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to f2.
T(
D{
IndexingFactType::kFunctionCall,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to a.
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
})),
// refers to b.
T(
D{
IndexingFactType::kNamedParam,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
},
// refers to y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
}))))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, FunctionPortPackedAndUnpackedDimsensions) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"function void ",
{kTag, "f1"},
"(int [",
{kTag, "x"},
":",
{kTag, "y"},
"] ",
{kTag, "t"},
" [",
{kTag, "l"},
":",
{kTag, "r"},
"]);\nendfunction",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function f1.
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to t.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to x.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}),
// refers to y.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
}),
// refers to l.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[9], kTestCase.code),
}),
// refers to r.
T(D{
IndexingFactType::kVariableReference,
Anchor(kTestCase.expected_tokens[11], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, UserDefinedTypeFunctionPort) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"function void ",
{kTag, "f1"},
"(",
{kTag, "foo"},
" ",
{kTag, "bar"},
");\nendfunction",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function f1.
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to foo.
T(
D{
IndexingFactType::kDataTypeReference,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
},
// refers to bar.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, StructFunctionPort) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"function void ",
{kTag, "f1"},
"(struct {int ",
{kTag, "foo"},
";} ",
{kTag, "bar"},
");\nendfunction",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function f1.
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to bar.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to foo.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
})))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
TEST(FactsTreeExtractor, NestedStructFunctionPort) {
constexpr int kTag = 1; // value doesn't matter
const verible::SyntaxTreeSearchTestCase kTestCase = {
{
"function void ",
{kTag, "f1"},
"(struct {struct {int ",
{kTag, "y"},
";} ",
{kTag, "foo"},
";} ",
{kTag, "bar"},
");\nendfunction",
},
};
SimpleTestProject project(kTestCase.code);
const IndexingFactNode expected( //
project.ExpectedFileListData(),
T(project.XUnit().ExpectedFileData(),
// refers to function f1.
T(
D{
IndexingFactType::kFunctionOrTask,
Anchor(kTestCase.expected_tokens[1], kTestCase.code),
},
// refers to bar.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[7], kTestCase.code),
},
// refers to foo.
T(
D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[5], kTestCase.code),
},
// refers to y.
T(D{
IndexingFactType::kVariableDefinition,
Anchor(kTestCase.expected_tokens[3], kTestCase.code),
}))))));
const auto facts_tree = project.Extract();
const auto result_pair = DeepEqual(facts_tree, expected);
const auto P = [&project](const T &t) { return project.TreePrinter(t); };
EXPECT_EQ(result_pair.left, nullptr) << P(*result_pair.left);
EXPECT_EQ(result_pair.right, nullptr) << P(*result_pair.right);
}
} // namespace
} // namespace kythe
} // namespace verilog