Copilot commented on code in PR #2097:
URL: https://github.com/apache/nifi-minifi-cpp/pull/2097#discussion_r2773860247


##########
minifi_main/AgentDocs.cpp:
##########
@@ -34,41 +34,34 @@
 #include "range/v3/range/conversion.hpp"
 #include "range/v3/view/join.hpp"
 #include "range/v3/view/transform.hpp"
+#include "utils/RegexUtils.h"

Review Comment:
   The include "utils/RegexUtils.h" appears to be unused in this file. There 
are no references to regex utilities in the code. Consider removing this 
include to avoid unnecessary dependencies.
   ```suggestion
   
   ```



##########
minifi_main/AgentDocs.cpp:
##########
@@ -177,58 +163,149 @@ std::string extractClassName(const std::string& 
full_class_name) {
 
 std::string lowercaseFirst(const std::pair<std::string, 
minifi::ClassDescription>& key_value) {
   return minifi::utils::string::toLower(key_value.first);
-};
+}
 
-}  // namespace
+void writeProcessor(std::ostream& os, const std::string_view name, const 
minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+  writeDynamicProperties(os, documentation);
+  writeRelationships(os, documentation);
+  writeOutputAttributes(os, documentation);
+}
 
-namespace org::apache::nifi::minifi::docs {
+void writeControllerService(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-void AgentDocs::generate(const std::filesystem::path& docs_dir) {
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
controller_services;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
parameter_providers;
+void writeParameterProvider(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-  for (const auto& [bundle_id, components]: 
ClassDescriptionRegistry::getClassDescriptions()) {
-    for (const auto &controller_service_description : 
components.controller_services) {
+class MonolithDocumentation {
+ public:
+  explicit MonolithDocumentation() {
+    for (const auto& [bundle_id, component]: 
minifi::ClassDescriptionRegistry::getClassDescriptions()) {
+      addComponents(component);
+    }
+    sort();
+  }
+
+  void write(const std::filesystem::path& docs_dir) {
+    std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
+    writeControllers(controllers_md);
+
+    std::ofstream processors_md(docs_dir / "PROCESSORS.md");

Review Comment:
   The ofstream is opened but its success is not verified. If the file fails to 
open, subsequent write operations will fail silently. Consider checking the 
stream state after opening, similar to how it's done in MiNiFiMain.cpp lines 
168-172.



##########
minifi_main/AgentDocs.cpp:
##########
@@ -177,58 +163,149 @@ std::string extractClassName(const std::string& 
full_class_name) {
 
 std::string lowercaseFirst(const std::pair<std::string, 
minifi::ClassDescription>& key_value) {
   return minifi::utils::string::toLower(key_value.first);
-};
+}
 
-}  // namespace
+void writeProcessor(std::ostream& os, const std::string_view name, const 
minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+  writeDynamicProperties(os, documentation);
+  writeRelationships(os, documentation);
+  writeOutputAttributes(os, documentation);
+}
 
-namespace org::apache::nifi::minifi::docs {
+void writeControllerService(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-void AgentDocs::generate(const std::filesystem::path& docs_dir) {
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
controller_services;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
parameter_providers;
+void writeParameterProvider(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-  for (const auto& [bundle_id, components]: 
ClassDescriptionRegistry::getClassDescriptions()) {
-    for (const auto &controller_service_description : 
components.controller_services) {
+class MonolithDocumentation {
+ public:
+  explicit MonolithDocumentation() {
+    for (const auto& [bundle_id, component]: 
minifi::ClassDescriptionRegistry::getClassDescriptions()) {
+      addComponents(component);
+    }
+    sort();
+  }
+
+  void write(const std::filesystem::path& docs_dir) {
+    std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
+    writeControllers(controllers_md);
+
+    std::ofstream processors_md(docs_dir / "PROCESSORS.md");
+    writeProcessors(processors_md);
+
+    std::ofstream parameter_providers_md(docs_dir / "PARAMETER_PROVIDERS.md");

Review Comment:
   The ofstream is opened but its success is not verified. If the file fails to 
open, subsequent write operations will fail silently. Consider checking the 
stream state after opening, similar to how it's done in MiNiFiMain.cpp lines 
168-172.



##########
minifi_main/AgentDocs.cpp:
##########
@@ -177,58 +163,149 @@ std::string extractClassName(const std::string& 
full_class_name) {
 
 std::string lowercaseFirst(const std::pair<std::string, 
minifi::ClassDescription>& key_value) {
   return minifi::utils::string::toLower(key_value.first);
-};
+}
 
-}  // namespace
+void writeProcessor(std::ostream& os, const std::string_view name, const 
minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+  writeDynamicProperties(os, documentation);
+  writeRelationships(os, documentation);
+  writeOutputAttributes(os, documentation);
+}
 
-namespace org::apache::nifi::minifi::docs {
+void writeControllerService(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-void AgentDocs::generate(const std::filesystem::path& docs_dir) {
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
controller_services;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
parameter_providers;
+void writeParameterProvider(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-  for (const auto& [bundle_id, components]: 
ClassDescriptionRegistry::getClassDescriptions()) {
-    for (const auto &controller_service_description : 
components.controller_services) {
+class MonolithDocumentation {
+ public:
+  explicit MonolithDocumentation() {
+    for (const auto& [bundle_id, component]: 
minifi::ClassDescriptionRegistry::getClassDescriptions()) {
+      addComponents(component);
+    }
+    sort();
+  }
+
+  void write(const std::filesystem::path& docs_dir) {
+    std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
+    writeControllers(controllers_md);
+
+    std::ofstream processors_md(docs_dir / "PROCESSORS.md");
+    writeProcessors(processors_md);
+
+    std::ofstream parameter_providers_md(docs_dir / "PARAMETER_PROVIDERS.md");
+    writeParameterProviders(parameter_providers_md);
+  }
+
+ private:
+  void addComponents(const minifi::Components& components) {
+    for (const auto& controller_service_description: 
components.controller_services) {
       
controller_services.emplace_back(extractClassName(controller_service_description.full_name_),
 controller_service_description);
     }
-    for (const auto &processor_description : components.processors) {
+    for (const auto& processor_description: components.processors) {
       
processors.emplace_back(extractClassName(processor_description.full_name_), 
processor_description);
     }
-    for (const auto& parameter_provider_description : 
components.parameter_providers) {
+    for (const auto& parameter_provider_description: 
components.parameter_providers) {
       
parameter_providers.emplace_back(extractClassName(parameter_provider_description.full_name_),
 parameter_provider_description);
     }
   }
-  std::ranges::sort(controller_services, std::less(), lowercaseFirst);
-  std::ranges::sort(processors, std::less(), lowercaseFirst);
-  std::ranges::sort(parameter_providers, std::less(), lowercaseFirst);
 
-  std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
-  writeHeader(controllers_md, controller_services);
-  for (const auto& [name, documentation] : controller_services) {
-    writeName(controllers_md, name);
-    writeDescription(controllers_md, documentation);
-    writeProperties(controllers_md, documentation);
+  void sort() {
+    std::ranges::sort(controller_services, std::less(), lowercaseFirst);
+    std::ranges::sort(processors, std::less(), lowercaseFirst);
+    std::ranges::sort(parameter_providers, std::less(), lowercaseFirst);
   }
 
-  std::ofstream processors_md(docs_dir / "PROCESSORS.md");
-  writeHeader(processors_md, processors);
-  for (const auto& [name, documentation] : processors) {
-    writeName(processors_md, name);
-    writeDescription(processors_md, documentation);
-    writeProperties(processors_md, documentation);
-    writeDynamicProperties(processors_md, documentation);
-    writeRelationships(processors_md, documentation);
-    writeOutputAttributes(processors_md, documentation);
+  void writeControllers(std::ostream& os) {
+    writeHeader(os, controller_services);
+    for (const auto& [name, documentation]: controller_services) {
+      writeControllerService(os, name, documentation);
+    }
   }
 
-  std::ofstream parameter_providers_md(docs_dir / "PARAMETER_PROVIDERS.md");
-  writeHeader(parameter_providers_md, parameter_providers);
-  for (const auto& [name, documentation] : parameter_providers) {
-    writeName(parameter_providers_md, name);
-    writeDescription(parameter_providers_md, documentation);
-    writeProperties(parameter_providers_md, documentation);
+  void writeProcessors(std::ostream& os) {
+    writeHeader(os, processors);
+    for (const auto& [name, documentation]: processors) {
+      writeProcessor(os, name, documentation);
+    }
   }
+
+  void writeParameterProviders(std::ostream& os) {
+    writeHeader(os, parameter_providers);
+    for (const auto& [name, documentation]: parameter_providers) {
+      writeParameterProvider(os, name, documentation);
+    }
+  }
+
+  std::vector<std::pair<std::string, minifi::ClassDescription>> 
controller_services;
+  std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
+  std::vector<std::pair<std::string, minifi::ClassDescription>> 
parameter_providers;
+};
+
+class ModularDocumentation {
+ public:
+  static void write(const std::filesystem::path& docs_dir) {
+    for (const auto& [bundle_id, component]: 
minifi::ClassDescriptionRegistry::getClassDescriptions()) {
+      writeModule(docs_dir, bundle_id.name, component);
+    }
+  }
+
+ private:
+  static void writeComponentParts(std::ostream& os, const 
std::vector<minifi::ClassDescription>& class_descriptions, const 
std::string_view h3) {
+    if (!class_descriptions.empty()) {
+      os << fmt::format("### {}\n\n", h3);
+      for (const auto& class_description: class_descriptions) {
+        const auto name = extractClassName(class_description.full_name_);
+        os << "- [" << name << "](#" << name << ")\n";
+      }
+    }
+  }
+
+  static void writeToC(std::ostream& os, const minifi::Components& components) 
{
+    os << "\n\n## Table of Contents\n\n";
+    writeComponentParts(os, components.processors, "Processors");
+    writeComponentParts(os, components.controller_services, "Controller 
Services");
+    writeComponentParts(os, components.parameter_providers, "Parameter 
Providers");
+  }
+
+  static void writeModule(const std::filesystem::path& docs_dir, const 
std::string_view module_name, const minifi::Components& components) {
+    minifi::utils::file::create_dir(docs_dir / "modules");

Review Comment:
   The return value of create_dir is not checked. If directory creation fails, 
the subsequent file operations will fail silently. Consider checking the return 
value and handling errors appropriately, similar to how it's done in 
MiNiFiMain.cpp line 145 where the return value is checked.



##########
minifi_main/AgentDocs.cpp:
##########
@@ -177,58 +163,149 @@ std::string extractClassName(const std::string& 
full_class_name) {
 
 std::string lowercaseFirst(const std::pair<std::string, 
minifi::ClassDescription>& key_value) {
   return minifi::utils::string::toLower(key_value.first);
-};
+}
 
-}  // namespace
+void writeProcessor(std::ostream& os, const std::string_view name, const 
minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+  writeDynamicProperties(os, documentation);
+  writeRelationships(os, documentation);
+  writeOutputAttributes(os, documentation);
+}
 
-namespace org::apache::nifi::minifi::docs {
+void writeControllerService(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-void AgentDocs::generate(const std::filesystem::path& docs_dir) {
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
controller_services;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
parameter_providers;
+void writeParameterProvider(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-  for (const auto& [bundle_id, components]: 
ClassDescriptionRegistry::getClassDescriptions()) {
-    for (const auto &controller_service_description : 
components.controller_services) {
+class MonolithDocumentation {
+ public:
+  explicit MonolithDocumentation() {
+    for (const auto& [bundle_id, component]: 
minifi::ClassDescriptionRegistry::getClassDescriptions()) {
+      addComponents(component);
+    }
+    sort();
+  }
+
+  void write(const std::filesystem::path& docs_dir) {
+    std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");

Review Comment:
   The ofstream is opened but its success is not verified. If the file fails to 
open, subsequent write operations will fail silently. Consider checking the 
stream state after opening, similar to how it's done in MiNiFiMain.cpp lines 
168-172.



##########
minifi_main/AgentDocs.cpp:
##########
@@ -177,58 +163,149 @@ std::string extractClassName(const std::string& 
full_class_name) {
 
 std::string lowercaseFirst(const std::pair<std::string, 
minifi::ClassDescription>& key_value) {
   return minifi::utils::string::toLower(key_value.first);
-};
+}
 
-}  // namespace
+void writeProcessor(std::ostream& os, const std::string_view name, const 
minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+  writeDynamicProperties(os, documentation);
+  writeRelationships(os, documentation);
+  writeOutputAttributes(os, documentation);
+}
 
-namespace org::apache::nifi::minifi::docs {
+void writeControllerService(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-void AgentDocs::generate(const std::filesystem::path& docs_dir) {
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
controller_services;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
-  std::vector<std::pair<std::string, minifi::ClassDescription>> 
parameter_providers;
+void writeParameterProvider(std::ostream& os, const std::string_view name, 
const minifi::ClassDescription& documentation) {
+  writeName(os, name);
+  writeDescription(os, documentation);
+  writeProperties(os, documentation);
+}
 
-  for (const auto& [bundle_id, components]: 
ClassDescriptionRegistry::getClassDescriptions()) {
-    for (const auto &controller_service_description : 
components.controller_services) {
+class MonolithDocumentation {
+ public:
+  explicit MonolithDocumentation() {
+    for (const auto& [bundle_id, component]: 
minifi::ClassDescriptionRegistry::getClassDescriptions()) {
+      addComponents(component);
+    }
+    sort();
+  }
+
+  void write(const std::filesystem::path& docs_dir) {
+    std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
+    writeControllers(controllers_md);
+
+    std::ofstream processors_md(docs_dir / "PROCESSORS.md");
+    writeProcessors(processors_md);
+
+    std::ofstream parameter_providers_md(docs_dir / "PARAMETER_PROVIDERS.md");
+    writeParameterProviders(parameter_providers_md);
+  }
+
+ private:
+  void addComponents(const minifi::Components& components) {
+    for (const auto& controller_service_description: 
components.controller_services) {
       
controller_services.emplace_back(extractClassName(controller_service_description.full_name_),
 controller_service_description);
     }
-    for (const auto &processor_description : components.processors) {
+    for (const auto& processor_description: components.processors) {
       
processors.emplace_back(extractClassName(processor_description.full_name_), 
processor_description);
     }
-    for (const auto& parameter_provider_description : 
components.parameter_providers) {
+    for (const auto& parameter_provider_description: 
components.parameter_providers) {
       
parameter_providers.emplace_back(extractClassName(parameter_provider_description.full_name_),
 parameter_provider_description);
     }
   }
-  std::ranges::sort(controller_services, std::less(), lowercaseFirst);
-  std::ranges::sort(processors, std::less(), lowercaseFirst);
-  std::ranges::sort(parameter_providers, std::less(), lowercaseFirst);
 
-  std::ofstream controllers_md(docs_dir / "CONTROLLERS.md");
-  writeHeader(controllers_md, controller_services);
-  for (const auto& [name, documentation] : controller_services) {
-    writeName(controllers_md, name);
-    writeDescription(controllers_md, documentation);
-    writeProperties(controllers_md, documentation);
+  void sort() {
+    std::ranges::sort(controller_services, std::less(), lowercaseFirst);
+    std::ranges::sort(processors, std::less(), lowercaseFirst);
+    std::ranges::sort(parameter_providers, std::less(), lowercaseFirst);
   }
 
-  std::ofstream processors_md(docs_dir / "PROCESSORS.md");
-  writeHeader(processors_md, processors);
-  for (const auto& [name, documentation] : processors) {
-    writeName(processors_md, name);
-    writeDescription(processors_md, documentation);
-    writeProperties(processors_md, documentation);
-    writeDynamicProperties(processors_md, documentation);
-    writeRelationships(processors_md, documentation);
-    writeOutputAttributes(processors_md, documentation);
+  void writeControllers(std::ostream& os) {
+    writeHeader(os, controller_services);
+    for (const auto& [name, documentation]: controller_services) {
+      writeControllerService(os, name, documentation);
+    }
   }
 
-  std::ofstream parameter_providers_md(docs_dir / "PARAMETER_PROVIDERS.md");
-  writeHeader(parameter_providers_md, parameter_providers);
-  for (const auto& [name, documentation] : parameter_providers) {
-    writeName(parameter_providers_md, name);
-    writeDescription(parameter_providers_md, documentation);
-    writeProperties(parameter_providers_md, documentation);
+  void writeProcessors(std::ostream& os) {
+    writeHeader(os, processors);
+    for (const auto& [name, documentation]: processors) {
+      writeProcessor(os, name, documentation);
+    }
   }
+
+  void writeParameterProviders(std::ostream& os) {
+    writeHeader(os, parameter_providers);
+    for (const auto& [name, documentation]: parameter_providers) {
+      writeParameterProvider(os, name, documentation);
+    }
+  }
+
+  std::vector<std::pair<std::string, minifi::ClassDescription>> 
controller_services;
+  std::vector<std::pair<std::string, minifi::ClassDescription>> processors;
+  std::vector<std::pair<std::string, minifi::ClassDescription>> 
parameter_providers;
+};
+
+class ModularDocumentation {
+ public:
+  static void write(const std::filesystem::path& docs_dir) {
+    for (const auto& [bundle_id, component]: 
minifi::ClassDescriptionRegistry::getClassDescriptions()) {
+      writeModule(docs_dir, bundle_id.name, component);
+    }
+  }
+
+ private:
+  static void writeComponentParts(std::ostream& os, const 
std::vector<minifi::ClassDescription>& class_descriptions, const 
std::string_view h3) {
+    if (!class_descriptions.empty()) {
+      os << fmt::format("### {}\n\n", h3);
+      for (const auto& class_description: class_descriptions) {
+        const auto name = extractClassName(class_description.full_name_);
+        os << "- [" << name << "](#" << name << ")\n";
+      }
+    }
+  }
+
+  static void writeToC(std::ostream& os, const minifi::Components& components) 
{
+    os << "\n\n## Table of Contents\n\n";
+    writeComponentParts(os, components.processors, "Processors");
+    writeComponentParts(os, components.controller_services, "Controller 
Services");
+    writeComponentParts(os, components.parameter_providers, "Parameter 
Providers");
+  }
+
+  static void writeModule(const std::filesystem::path& docs_dir, const 
std::string_view module_name, const minifi::Components& components) {
+    minifi::utils::file::create_dir(docs_dir / "modules");
+    std::ofstream os(docs_dir / "modules" / (std::string(module_name) + 
".md"));

Review Comment:
   The ofstream is opened but its success is not verified. If the file fails to 
open (e.g., due to permissions or the directory not existing), subsequent write 
operations will fail silently. Consider checking the stream state after 
opening, similar to how it's done in MiNiFiMain.cpp lines 168-172.
   ```suggestion
       const auto module_path = docs_dir / "modules" / 
(std::string(module_name) + ".md");
       std::ofstream os(module_path);
       if (!os.is_open()) {
         std::cerr << "Failed to open agent documentation file for writing: " 
<< module_path << '\n';
         return;
       }
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to