Skip to content
This repository was archived by the owner on Jan 25, 2024. It is now read-only.

Commit ec94196

Browse files
allevatoswiple-rules-gardener
authored andcommitted
Update the module name derivation algorithm to handle any sequence of non-identifier characters safely.
PiperOrigin-RevId: 368004995
1 parent bf8243d commit ec94196

File tree

1 file changed

+41
-8
lines changed

1 file changed

+41
-8
lines changed

swift/internal/compiling.bzl

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,14 +1162,44 @@ def _additional_inputs_configurator(prerequisites, args):
11621162
inputs = prerequisites.additional_inputs,
11631163
)
11641164

1165+
def _module_name_safe(string):
1166+
"""Returns a transformation of `string` that is safe for module names."""
1167+
result = ""
1168+
saw_non_identifier_char = False
1169+
for ch in string.elems():
1170+
if ch.isalnum() or ch == "_":
1171+
# If we're seeing an identifier character after a sequence of
1172+
# non-identifier characters, append an underscore and reset our
1173+
# tracking state before appending the identifier character.
1174+
if saw_non_identifier_char:
1175+
result += "_"
1176+
saw_non_identifier_char = False
1177+
result += ch
1178+
elif result:
1179+
# Only track this if `result` has content; this ensures that we
1180+
# (intentionally) drop leading non-identifier characters instead of
1181+
# adding a leading underscore.
1182+
saw_non_identifier_char = True
1183+
1184+
return result
1185+
11651186
def derive_module_name(*args):
11661187
"""Returns a derived module name from the given build label.
11671188
11681189
For targets whose module name is not explicitly specified, the module name
1169-
is computed by creating an underscore-delimited string from the components
1170-
of the label, replacing any non-identifier characters also with underscores.
1190+
is computed using the following algorithm:
1191+
1192+
* The package and name components of the label are considered separately.
1193+
All _interior_ sequences of non-identifier characters (anything other
1194+
than `a-z`, `A-Z`, `0-9`, and `_`) are replaced by a single underscore
1195+
(`_`). Any leading or trailing non-identifier characters are dropped.
1196+
* If the package component is non-empty after the above transformation,
1197+
it is joined with the transformed name component using an underscore.
1198+
Otherwise, the transformed name is used by itself.
1199+
* If this would result in a string that begins with a digit (`0-9`), an
1200+
underscore is prepended to make it identifier-safe.
11711201
1172-
This mapping is not intended to be reversible.
1202+
This mapping is intended to be fairly predictable, but not reversible.
11731203
11741204
Args:
11751205
*args: Either a single argument of type `Label`, or two arguments of
@@ -1194,12 +1224,15 @@ def derive_module_name(*args):
11941224
fail("derive_module_name may only be called with a single argument " +
11951225
"of type 'Label' or two arguments of type 'str'.")
11961226

1197-
package_part = (package.lstrip("//").replace("/", "_").replace("-", "_")
1198-
.replace(".", "_"))
1199-
name_part = name.replace("-", "_")
1227+
package_part = _module_name_safe(package.lstrip("//"))
1228+
name_part = _module_name_safe(name)
12001229
if package_part:
1201-
return package_part + "_" + name_part
1202-
return name_part
1230+
module_name = package_part + "_" + name_part
1231+
else:
1232+
module_name = name_part
1233+
if module_name[0].isdigit():
1234+
module_name = "_" + module_name
1235+
return module_name
12031236

12041237
def compile(
12051238
*,

0 commit comments

Comments
 (0)