Skip to content

Commit

Permalink
Fix method name collisions for getProperties() (#434)
Browse files Browse the repository at this point in the history
* Fix method name collisions for getProperties()

* Add a specialized method to fix name collisions for getProperties().
  • Loading branch information
mrinaudo-aws committed Jan 10, 2024
1 parent ae56c9d commit 219872f
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 2 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ source env/bin/activate
pip3 install -e /path/to/cloudformation-cli-java-plugin
```

Install `pytest-cov`, used when running unit tests for this plugin:

```shell
pip3 install pytest-cov
```

You may also want to check out the [CloudFormation CLI](https://github.com/aws-cloudformation/cloudformation-cli) if you wish to make edits to that. In this case, installing them in one operation works well:

```shell
Expand Down
8 changes: 7 additions & 1 deletion python/rpdk/java/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@

from . import __version__
from .resolver import UNDEFINED, translate_type
from .utils import safe_reserved, validate_codegen_model, validate_namespace
from .utils import (
safe_reserved,
safe_reserved_hook_target,
validate_codegen_model,
validate_namespace,
)

LOG = logging.getLogger(__name__)

Expand Down Expand Up @@ -86,6 +91,7 @@ def __init__(self):
self.codegen_template_path = None
self.env.filters["translate_type"] = translate_type
self.env.filters["safe_reserved"] = safe_reserved
self.env.filters["safe_reserved_hook_target"] = safe_reserved_hook_target
self.namespace = None
self.package_name = None

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class {{ model_name|uppercase_first_letter }} extends ResourceHookTarget

{% for name, type in properties.items() %}
@JsonProperty("{{ name }}")
private {{ type|translate_type }} {{ name|lowercase_first_letter|safe_reserved }};
private {{ type|translate_type }} {{ name|lowercase_first_letter|safe_reserved_hook_target }};

{% endfor %}
@JsonIgnore
Expand Down
36 changes: 36 additions & 0 deletions python/rpdk/java/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,48 @@
}


# Keywords used in the context of AWS CloudFormation Hooks, when
# classes are generated, by this plugin, for target resource
# types. For example, the `properties` item below is marked as a
# keyword because if a target resource type has a property called
# `Properties` (see the `AWS::ApiGateway::DocumentationPart` resource
# type as one of the examples), the generated class code for the
# target resource type will contain a getter, `getProperties()`, that
# will collide with `getProperties()` that is already defined for
# `ResourceHookTarget`. By marking `properties` as a keyword, the
# generated code for the class will still have a relevant, private
# variable for the resource type target's property, but whose name
# will contain an underscore as a suffix: the Lombok-generated getter
# (and setter) for that private variable will, in turn, contain an
# underscore suffix as well; see `safe_reserved_hook_target()` below
# for more information (`safe_reserved_hook_target()` is, in turn,
# consumed by other parts of a hook's code generation logic in this
# plugin).
HOOK_TARGET_KEYWORDS = {
"properties",
}


def safe_reserved(token):
if token in LANGUAGE_KEYWORDS:
return token + "_"
return token


# This is a specialized method for hooks only. In addition to using
# LANGUAGE_KEYWORDS (used by safe_reserved()), this function uses
# HOOK_TARGET_KEYWORDS: the reason for having such a specialized
# method is that since excluding `properties` will alter an affected
# target's getters and setters (see this specific case explained in
# comments for `HOOK_TARGET_KEYWORDS`), we do not want to have the
# same behavior for resource type extensions, that you also model with
# this plugin of the CloudFormation CLI.
def safe_reserved_hook_target(token):
if token in LANGUAGE_KEYWORDS or token in HOOK_TARGET_KEYWORDS:
return token + "_"
return token


def validate_namespace(default):
pattern = r"^[_a-z][_a-z0-9]+$"

Expand Down
9 changes: 9 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from rpdk.core.exceptions import WizardValidationError
from rpdk.java.utils import (
safe_reserved,
safe_reserved_hook_target,
validate_codegen_model as validate_codegen_model_factory,
validate_namespace as validate_namespace_factory,
)
Expand All @@ -29,6 +30,14 @@ def test_safe_reserved_unsafe_string():
assert safe_reserved("class") == "class_"


def test_safe_reserved_hook_target_safe_string():
assert safe_reserved_hook_target("foo") == "foo"


def test_safe_reserved_hook_target_unsafe_string():
assert safe_reserved_hook_target("properties") == "properties_"


def test_validate_namespace_empty(validate_namespace):
assert validate_namespace("") == DEFAULT

Expand Down

0 comments on commit 219872f

Please sign in to comment.