PR #449: Add DataTypeReference to resolve multi-instance in one line
Fixes #421

GitHub PR https://github.com/google/verible/pull/449

Copybara import of the project:

  - d39390c257ad5a38f54911a73f67394a6b0664cf Add DataTypeReference to resolve multi-instance in one line by MinaToma <minatoma1999@gmail.com>

Closes #449

PiperOrigin-RevId: 331579978
diff --git a/verilog/tools/kythe/indexing_facts_tree_extractor.cc b/verilog/tools/kythe/indexing_facts_tree_extractor.cc
index 9e9afbc..28f23aa 100644
--- a/verilog/tools/kythe/indexing_facts_tree_extractor.cc
+++ b/verilog/tools/kythe/indexing_facts_tree_extractor.cc
@@ -277,23 +277,28 @@
 void IndexingFactsTreeExtractor::ExtractModuleInstantiation(
     const SyntaxTreeNode& data_declaration_node,
     const std::vector<TreeSearchMatch>& gate_instances) {
+  IndexingNodeData module_node_data(IndexingFactType::kDataTypeReference);
+  IndexingFactNode module_node(module_node_data);
+
   const verible::TokenInfo& type =
       GetTypeTokenInfoFromDataDeclaration(data_declaration_node);
   const Anchor type_anchor(type, context_.base);
 
+  module_node.Value().AppendAnchor(type_anchor);
+
   // Module instantiations (data declarations) may declare multiple instances
   // sharing the same type in a single statement e.g. bar b1(), b2().
   //
   // Loop through each instance and associate each declared id with the same
   // type and create its corresponding facts tree node.
   for (const TreeSearchMatch& instance : gate_instances) {
-    IndexingNodeData indexing_node_data(IndexingFactType::kModuleInstance);
+    IndexingNodeData module_instance_node_data(
+        IndexingFactType::kModuleInstance);
 
     const verible::TokenInfo& variable_name =
         GetModuleInstanceNameTokenInfoFromGateInstance(*instance.match);
     const Anchor variable_name_anchor(variable_name, context_.base);
-    indexing_node_data.AppendAnchor(type_anchor);
-    indexing_node_data.AppendAnchor(variable_name_anchor);
+    module_instance_node_data.AppendAnchor(variable_name_anchor);
 
     std::vector<TreeSearchMatch> port_names =
         FindAllUnqualifiedIds(*instance.match);
@@ -303,11 +308,13 @@
       const SyntaxTreeLeaf* leaf = GetIdentifier(*port.match);
       const Anchor port_name_anchor(leaf->get(), context_.base);
 
-      indexing_node_data.AppendAnchor(port_name_anchor);
+      module_instance_node_data.AppendAnchor(port_name_anchor);
     }
 
-    facts_tree_context_.top().NewChild(indexing_node_data);
+    module_node.NewChild(module_instance_node_data);
   }
+
+  facts_tree_context_.top().NewChild(module_node);
 }
 
 void IndexingFactsTreeExtractor::ExtractNetDeclaration(
@@ -530,10 +537,15 @@
 void IndexingFactsTreeExtractor::ExtractClassInstances(
     const SyntaxTreeNode& data_declaration_node,
     const std::vector<TreeSearchMatch>& register_variables) {
+  IndexingNodeData class_node_data(IndexingFactType::kDataTypeReference);
+  IndexingFactNode class_node(class_node_data);
+
   const verible::TokenInfo& type =
       GetTypeTokenInfoFromDataDeclaration(data_declaration_node);
   const Anchor type_anchor(type, context_.base);
 
+  class_node.Value().AppendAnchor(type_anchor);
+
   // Class instances may may appear as multiple instances sharing the same type
   // in a single statement e.g. myClass b1 = new, b2 = new.
   // LRM 8.8 Typed constructor calls
@@ -547,11 +559,12 @@
         GetInstanceNameTokenInfoFromRegisterVariable(*instance.match);
 
     const Anchor variable_name_anchor(variable_name, context_.base);
-    indexing_node_data.AppendAnchor(type_anchor);
     indexing_node_data.AppendAnchor(variable_name_anchor);
 
-    facts_tree_context_.top().NewChild(indexing_node_data);
+    class_node.NewChild(indexing_node_data);
   }
+
+  facts_tree_context_.top().NewChild(class_node);
 }
 
 void IndexingFactsTreeExtractor::ExtractPackageImport(
diff --git a/verilog/tools/kythe/indexing_facts_tree_extractor_test.cc b/verilog/tools/kythe/indexing_facts_tree_extractor_test.cc
index df96da6..968d57f 100644
--- a/verilog/tools/kythe/indexing_facts_tree_extractor_test.cc
+++ b/verilog/tools/kythe/indexing_facts_tree_extractor_test.cc
@@ -193,14 +193,21 @@
               },
               IndexingFactType::kModule,
           },
-          // refers to bar b1().
-          T({
+          // refers to bar.
+          T(
               {
-                  Anchor(kTestCase.expected_tokens[7], kTestCase.code),
-                  Anchor(kTestCase.expected_tokens[9], kTestCase.code),
+                  {
+                      Anchor(kTestCase.expected_tokens[7], kTestCase.code),
+                  },
+                  IndexingFactType::kDataTypeReference,
               },
-              IndexingFactType ::kModuleInstance,
-          })));
+              // refers to bar b1().
+              T({
+                  {
+                      Anchor(kTestCase.expected_tokens[9], kTestCase.code),
+                  },
+                  IndexingFactType ::kModuleInstance,
+              }))));
 
   const auto facts_tree =
       ExtractOneFile(kTestCase.code, file_name, exit_status, parse_ok);
@@ -258,22 +265,36 @@
               },
               IndexingFactType::kModule,
           },
-          // refers to bar b1().
-          T({
+          // refers to bar.
+          T(
               {
-                  Anchor(kTestCase.expected_tokens[7], kTestCase.code),
-                  Anchor(kTestCase.expected_tokens[9], kTestCase.code),
+                  {
+                      Anchor(kTestCase.expected_tokens[7], kTestCase.code),
+                  },
+                  IndexingFactType ::kDataTypeReference,
               },
-              IndexingFactType ::kModuleInstance,
-          }),
-          // refers to bar b2().
-          T({
+              // refers to bar b1().
+              T({
+                  {
+                      Anchor(kTestCase.expected_tokens[9], kTestCase.code),
+                  },
+                  IndexingFactType ::kModuleInstance,
+              })),
+          // refers to bar.
+          T(
               {
-                  Anchor(kTestCase.expected_tokens[11], kTestCase.code),
-                  Anchor(kTestCase.expected_tokens[13], kTestCase.code),
+                  {
+                      Anchor(kTestCase.expected_tokens[11], kTestCase.code),
+                  },
+                  IndexingFactType ::kDataTypeReference,
               },
-              IndexingFactType ::kModuleInstance,
-          })));
+              // refers to bar b2().
+              T({
+                  {
+                      Anchor(kTestCase.expected_tokens[13], kTestCase.code),
+                  },
+                  IndexingFactType ::kModuleInstance,
+              }))));
 
   const auto facts_tree =
       ExtractOneFile(kTestCase.code, file_name, exit_status, parse_ok);
@@ -329,23 +350,28 @@
               },
               IndexingFactType::kModule,
           },
-          // refers to bar b1(), b2().
-          // bar b1().
-          T({
+          // refers to bar.
+          T(
               {
-                  Anchor(kTestCase.expected_tokens[7], kTestCase.code),
-                  Anchor(kTestCase.expected_tokens[9], kTestCase.code),
+                  {
+                      Anchor(kTestCase.expected_tokens[7], kTestCase.code),
+                  },
+                  IndexingFactType ::kDataTypeReference,
               },
-              IndexingFactType ::kModuleInstance,
-          }),
-          // bar b2().
-          T({
-              {
-                  Anchor(kTestCase.expected_tokens[7], kTestCase.code),
-                  Anchor(kTestCase.expected_tokens[11], kTestCase.code),
-              },
-              IndexingFactType ::kModuleInstance,
-          })));
+              // refers to b1().
+              T({
+                  {
+                      Anchor(kTestCase.expected_tokens[9], kTestCase.code),
+                  },
+                  IndexingFactType ::kModuleInstance,
+              }),
+              // refers to bar b2().
+              T({
+                  {
+                      Anchor(kTestCase.expected_tokens[11], kTestCase.code),
+                  },
+                  IndexingFactType ::kModuleInstance,
+              }))));
 
   const auto facts_tree =
       ExtractOneFile(kTestCase.code, file_name, exit_status, parse_ok);
@@ -629,16 +655,23 @@
               },
               IndexingFactType ::kVariableDefinition,
           }),
-          // refers to bar b1(x, y).
-          T({
+          // refers to bar.
+          T(
               {
-                  Anchor(kTestCase.expected_tokens[15], kTestCase.code),
-                  Anchor(kTestCase.expected_tokens[17], kTestCase.code),
-                  Anchor(kTestCase.expected_tokens[19], kTestCase.code),
-                  Anchor(kTestCase.expected_tokens[21], kTestCase.code),
+                  {
+                      Anchor(kTestCase.expected_tokens[15], kTestCase.code),
+                  },
+                  IndexingFactType ::kDataTypeReference,
               },
-              IndexingFactType ::kModuleInstance,
-          })));
+              // refers to b1(x, y).
+              T({
+                  {
+                      Anchor(kTestCase.expected_tokens[17], kTestCase.code),
+                      Anchor(kTestCase.expected_tokens[19], kTestCase.code),
+                      Anchor(kTestCase.expected_tokens[21], kTestCase.code),
+                  },
+                  IndexingFactType ::kModuleInstance,
+              }))));
 
   const auto facts_tree =
       ExtractOneFile(kTestCase.code, file_name, exit_status, parse_ok);
@@ -873,14 +906,21 @@
               },
               IndexingFactType::kModule,
           },
-          // refers to bar b1().
-          T({
+          // refers to bar.
+          T(
               {
-                  Anchor(kTestCase.expected_tokens[7], kTestCase.code),
-                  Anchor(kTestCase.expected_tokens[9], kTestCase.code),
+                  {
+                      Anchor(kTestCase.expected_tokens[7], kTestCase.code),
+                  },
+                  IndexingFactType ::kDataTypeReference,
               },
-              IndexingFactType ::kClassInstance,
-          })));
+              // refers to b1.
+              T({
+                  {
+                      Anchor(kTestCase.expected_tokens[9], kTestCase.code),
+                  },
+                  IndexingFactType ::kClassInstance,
+              }))));
 
   const auto facts_tree =
       ExtractOneFile(kTestCase.code, file_name, exit_status, parse_ok);
diff --git a/verilog/tools/kythe/kythe_facts_extractor.cc b/verilog/tools/kythe/kythe_facts_extractor.cc
index 3ec8761..0b9f37d 100644
--- a/verilog/tools/kythe/kythe_facts_extractor.cc
+++ b/verilog/tools/kythe/kythe_facts_extractor.cc
@@ -93,6 +93,10 @@
       scope_context_.top().push_back(vname);
       break;
     }
+    case IndexingFactType::kDataTypeReference: {
+      vname = ExtractDataTypeReference(node);
+      break;
+    }
     case IndexingFactType::kModuleInstance: {
       vname = ExtractModuleInstanceFact(node);
       scope_context_.top().push_back(vname);
@@ -229,42 +233,41 @@
   return module_vname;
 }
 
+VName KytheFactsExtractor::ExtractDataTypeReference(
+    const IndexingFactNode& data_type_reference) {
+  const auto& anchors = data_type_reference.Value().Anchors();
+  const Anchor& type = anchors[0];
+
+  const VName type_vname = *ABSL_DIE_IF_NULL(
+      scope_context_.SearchForDefinition(CreateModuleSignature(type.Value())));
+  const VName type_anchor = PrintAnchorVName(type);
+  GenerateEdgeString(type_anchor, kEdgeRef, type_vname);
+
+  return type_vname;
+}
+
 VName KytheFactsExtractor::ExtractModuleInstanceFact(
     const IndexingFactNode& module_instance_fact_node) {
   const auto& anchors = module_instance_fact_node.Value().Anchors();
-  const Anchor& module_type = anchors[0];
-  const Anchor& instance_name = anchors[1];
+  const Anchor& instance_name = anchors[0];
 
   const VName module_instance_vname(
       file_path_, CreateScopeRelativeSignature(
                       CreateVariableSignature(instance_name.Value())));
   const VName module_instance_anchor = PrintAnchorVName(instance_name);
 
-  const VName module_type_vname =
-      *ABSL_DIE_IF_NULL(scope_context_.SearchForDefinition(
-          CreateModuleSignature(module_type.Value())));
-
-  const VName module_type_anchor = PrintAnchorVName(module_type);
-
   GenerateFactString(module_instance_vname, kFactNodeKind, kNodeVariable);
   GenerateFactString(module_instance_vname, kFactComplete, kCompleteDefinition);
-
-  GenerateEdgeString(module_type_anchor, kEdgeRef, module_type_vname);
-  GenerateEdgeString(module_instance_vname, kEdgeTyped, module_type_vname);
   GenerateEdgeString(module_instance_anchor, kEdgeDefinesBinding,
                      module_instance_vname);
 
   for (const auto& anchor :
-       verible::make_range(anchors.begin() + 2, anchors.end())) {
-    const VName port_vname_reference(
-        file_path_,
-        CreateScopeRelativeSignature(CreateVariableSignature(anchor.Value())));
+       verible::make_range(anchors.begin() + 1, anchors.end())) {
     const VName port_vname_definition =
         *ABSL_DIE_IF_NULL(scope_context_.SearchForDefinition(
             CreateVariableSignature(anchor.Value())));
 
     const VName port_vname_anchor = PrintAnchorVName(anchor);
-
     GenerateEdgeString(port_vname_anchor, kEdgeRef, port_vname_definition);
   }
 
@@ -423,25 +426,15 @@
 VName KytheFactsExtractor::ExtractClassInstances(
     const IndexingFactNode& class_instance_fact_node) {
   const auto& anchors = class_instance_fact_node.Value().Anchors();
-  const Anchor& class_type = anchors[0];
-  const Anchor& instance_name = anchors[1];
+  const Anchor& instance_name = anchors[0];
 
   const VName class_instance_vname(
       file_path_, CreateScopeRelativeSignature(
                       CreateVariableSignature(instance_name.Value())));
   const VName class_instance_anchor = PrintAnchorVName(instance_name);
 
-  const VName class_type_vname =
-      *ABSL_DIE_IF_NULL(scope_context_.SearchForDefinition(
-          CreateClassSignature(class_type.Value())));
-
-  const VName class_type_anchor = PrintAnchorVName(class_type);
-
   GenerateFactString(class_instance_vname, kFactNodeKind, kNodeVariable);
   GenerateFactString(class_instance_vname, kFactComplete, kCompleteDefinition);
-
-  GenerateEdgeString(class_type_anchor, kEdgeRef, class_type_vname);
-  GenerateEdgeString(class_instance_vname, kEdgeTyped, class_type_vname);
   GenerateEdgeString(class_instance_anchor, kEdgeDefinesBinding,
                      class_instance_vname);
 
diff --git a/verilog/tools/kythe/kythe_facts_extractor.h b/verilog/tools/kythe/kythe_facts_extractor.h
index 5c09a9e..847fee9 100644
--- a/verilog/tools/kythe/kythe_facts_extractor.h
+++ b/verilog/tools/kythe/kythe_facts_extractor.h
@@ -155,6 +155,10 @@
   // Extracts kythe facts from file node and returns it VName.
   VName ExtractFileFact(const IndexingFactNode&);
 
+  // Extracts kythe facts a reference to a user defined data type like class or
+  // module.
+  VName ExtractDataTypeReference(const IndexingFactNode&);
+
   // Extracts kythe facts from module instance node and returns it VName.
   VName ExtractModuleInstanceFact(const IndexingFactNode&);
 
diff --git a/verilog/tools/kythe/verilog_extractor_indexing_fact_type.h b/verilog/tools/kythe/verilog_extractor_indexing_fact_type.h
index f01d0c3..476e3fc 100644
--- a/verilog/tools/kythe/verilog_extractor_indexing_fact_type.h
+++ b/verilog/tools/kythe/verilog_extractor_indexing_fact_type.h
@@ -32,6 +32,7 @@
   kClass,
   kClassInstance,
   kModuleInstance,
+  kDataTypeReference,
   kVariableDefinition,
   kVariableReference,
   kFunctionOrTask,