Repository: lbl-srg/BuildingsPy

Issue:
Package.order is misses to include constants that are arrays
This issue is to correct the generation of `package.order` for packages that have constant arrays, such as
```modelica
  final constant Real A[:] = {-1.721781e2, 2.381558e-1, -4.329207e-4, -6.241072e-7}
    "Coefficients A for Martin-Hou equation of state";
```

This is required for https://github.com/ibpsa/modelica-ibpsa/pull/1415 to be loaded in OMEdit without a warning.

Comments:

Patch:
diff --git a/buildingspy/CHANGES.txt b/buildingspy/CHANGES.txt
index ac2406f..e4bb144 100644
--- a/buildingspy/CHANGES.txt
+++ b/buildingspy/CHANGES.txt
@@ -4,6 +4,7 @@ BuildingsPy Changelog
 Version 2.2.0, xxx, 2020 -- Release 2.2
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 - xxx
+- Corrected generation of package.order for constant arrays (https://github.com/lbl-srg/BuildingsPy/issues/387)
 - Refactored class buildingspy.simulate.Dymola, and added buildingspy.simulate.Optimica
 - Added check for wrong derivative implementation that is reported by Dymola 2021x (https://github.com/lbl-srg/BuildingsPy/issues/376).
 
diff --git a/buildingspy/development/refactor.py b/buildingspy/development/refactor.py
index 216d16c..314f131 100644
--- a/buildingspy/development/refactor.py
+++ b/buildingspy/development/refactor.py
@@ -491,6 +491,25 @@ def write_package_order(directory=".", recursive=False):
                 filPac.write(p[1] + "\n")
 
 
+def _get_constants(lines):
+    """ Get a list with all constants.
+
+    :param: lines All lines of the Modelica file.
+    """
+    import re
+    # Constants can be "constant Real n = ..." or "constant someClass n(..."
+    # or "constant Real n[:] = ..." or or "constant Real n[4] = ..."
+    # See also https://regex101.com/r/cD5nE0/2 for testing
+    f = re.findall(
+        r"\s*constant\s+[\w+\.]+\s+(\w+)(\[\w+\]|\[\s*[\w:]\s*(,\s*[\w:]\s*)*\])?\s*[=\(]",
+        lines,
+        re.MULTILINE)
+    r = []
+    for ele in f:
+        r.append(ele[0])
+    return r
+
+
 def _get_package_list_for_file(directory, file_name):
     """ Gets the package list for the file `directory/file_name`
     """
@@ -509,10 +528,7 @@ def _get_package_list_for_file(directory, file_name):
         # They need to be added to the package.order as well.
         with open(os.path.join(directory, file_name), mode="r", encoding="utf-8-sig") as fil:
             lines = fil.read()
-            # Constants can be 'constant Real n = ..." or "constant someClass n(..."
-            con = re.findall(
-                r"\s*constant\s+[a-zA-Z0-9_\.]+\s+(\w+)\s*[=\(]", lines, re.MULTILINE)
-#                        con=re.search(r"constant\s+\w+\s+(\w+)\s*=", lines, re.MULTILINE);
+            con = _get_constants(lines)
             for ele in con:
                 # Found a constant whose name is in con.group(1)
                 pacLis.append([__CON, ele])


Test patch:
diff --git a/buildingspy/tests/test_development_refactor.py b/buildingspy/tests/test_development_refactor.py
index 7e15a5b..0d81f4f 100644
--- a/buildingspy/tests/test_development_refactor.py
+++ b/buildingspy/tests/test_development_refactor.py
@@ -69,6 +69,36 @@ class Test_development_refactor(unittest.TestCase):
 
         self.assertEqual(pac_lis, correct, "Parsing package.order failed.")
 
+    def test_get_constants_non_empty(self):
+        import buildingspy.development.refactor as r
+
+        lines = """
+        constant Real a = 1 "some text";
+        constant Real b = 1;
+        constant Real A = 1;
+        constant Real B[2] = {1, 2};
+        constant Real C[:] = {1, 2};
+        constant Real D[1,2] = {{1}, {1, 2}};
+        constant Real E[:,:] = {{1}, {1, 2}};
+        not_a_constant f = 1;
+        """
+        con = r._get_constants(lines)
+        self.assertEqual(con, ['a', 'b', 'A', 'B', 'C', 'D', 'E'], "Failed to get all constants.")
+
+    def test_get_constants_empty(self):
+        import buildingspy.development.refactor as r
+
+        lines = """
+
+        """
+        con = r._get_constants(lines)
+        for ele in con:
+            print(f"--{ele}--")
+        self.assertEqual(
+            con,
+            [],
+            "Failed to get all constants for a file content with no constants.")
+
     def test_get_modelica_file_name(self):
         import os
         import buildingspy.development.refactor as r