Skip to content

Commit

Permalink
Add begin_line and add_line meta parameters. Migrate tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
htorianik-amplify committed Jan 13, 2023
1 parent ac6d89f commit fc8805e
Show file tree
Hide file tree
Showing 16 changed files with 134 additions and 47 deletions.
3 changes: 1 addition & 2 deletions hcl2/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from lark import UnexpectedCharacters, UnexpectedToken

from . import load
from .parser import hcl2
from .version import __version__


Expand Down Expand Up @@ -53,7 +52,7 @@ def main():
else open(args.OUT_PATH, "w", encoding="utf-8")
)
print(args.PATH, file=sys.stderr, flush=True)
json.dump(hcl2.parse(in_file.read()), out_file)
json.dump(load(in_file), out_file)
if args.OUT_PATH is None:
out_file.write("\n")
out_file.close()
Expand Down
7 changes: 3 additions & 4 deletions hcl2/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import TextIO

from hcl2.parser import hcl2
from hcl2.transformer import DictTransformer


def load(file: TextIO) -> dict:
Expand All @@ -15,7 +16,5 @@ def loads(text: str) -> dict:
# Lark doesn't support a EOF token so our grammar can't look for "new line or end of file"
# This means that all blocks must end in a new line even if the file ends
# Append a new line as a temporary fix
# Ignoring type as the type-annotation of Lark.parse() claims that it always returns a Tree,
# but in the docs of the parse() said that it returns whatever the supplied transformer returns.
# We supply DictTransformer so the return type is Dict.
return hcl2.parse(text + "\n") # type: ignore
tree = hcl2.parse(text + "\n")
return DictTransformer().transform(tree)
4 changes: 1 addition & 3 deletions hcl2/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

from lark import Lark

from hcl2.transformer import DictTransformer


PARSER_FILE = Path(__file__).absolute().resolve().parent / ".lark_cache.bin"

Expand All @@ -14,5 +12,5 @@
parser="lalr",
cache=str(PARSER_FILE), # Disable/Delete file to effect changes to the grammar
rel_to=__file__,
transformer=DictTransformer(),
propagate_positions=True,
)
33 changes: 28 additions & 5 deletions hcl2/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,21 @@
from collections import namedtuple
from typing import List, Dict, Any

from lark.visitors import Transformer, Discard, _DiscardType
from lark.tree import Meta
from lark.visitors import Transformer, Discard, _DiscardType, v_args


HEREDOC_PATTERN = re.compile(r"<<([a-zA-Z][a-zA-Z0-9._-]+)\n([\s\S]*)\1", re.S)
HEREDOC_TRIM_PATTERN = re.compile(r"<<-([a-zA-Z][a-zA-Z0-9._-]+)\n([\s\S]*)\1", re.S)

START_LINE = "__start_line__"
END_LINE = "__end_line__"

NO_BLOCK_LABEL_TYPES = {"locals", "terraform"}
ONE_BLOCK_LABEL_TYPES = {"module", "provider", "variable"}
TWO_BLOCK_LABEL_TYPES = {"data", "resource"}


Attribute = namedtuple("Attribute", ("key", "value"))


Expand Down Expand Up @@ -96,7 +106,8 @@ def arguments(self, args: List) -> List:
def new_line_and_or_comma(self, args: List) -> _DiscardType:
return Discard

def block(self, args: List) -> Dict:
@v_args(meta=True)
def block(self, meta: Meta, args: List) -> Dict:
args = self.strip_new_line_tokens(args)

# if the last token is a string instead of an object then the block is empty
Expand All @@ -113,10 +124,22 @@ def block(self, args: List) -> Dict:

current_level[self.strip_quotes(args[-2])] = args[-1]

return result
if args[0] in TWO_BLOCK_LABEL_TYPES:
label_1 = self.strip_quotes(args[1])
label_2 = self.strip_quotes(args[2])
result[args[0]][label_1][label_2][START_LINE] = meta.line
result[args[0]][label_1][label_2][END_LINE] = meta.end_line

if args[0] in ONE_BLOCK_LABEL_TYPES:
label_1 = self.strip_quotes(args[1])
result[args[0]][label_1][START_LINE] = meta.line
result[args[0]][label_1][END_LINE] = meta.end_line

def one_line_block(self, args: List) -> Dict:
return self.block(args)
if args[0] in NO_BLOCK_LABEL_TYPES:
result[args[0]][START_LINE] = meta.line
result[args[0]][END_LINE] = meta.end_line

return result

def attribute(self, args: List) -> Attribute:
key = str(args[0])
Expand Down
16 changes: 12 additions & 4 deletions test/helpers/terraform-config-json/backend.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@
"provider": [
{
"aws": {
"region": "${var.region}"
"region": "${var.region}",
"__start_line__": 2,
"__end_line__": 7
}
},
{
"aws": {
"region": "${var.backup_region}",
"alias": "backup"
"alias": "backup",
"__start_line__": 7,
"__end_line__": 15
}
}
],
"terraform": [
{
"required_version": "0.12"
"required_version": "0.12",
"__start_line__": 15,
"__end_line__": 17
},
{
"backend": [
Expand All @@ -34,7 +40,9 @@
"source": "hashicorp/template"
}
}
]
],
"__start_line__": 17,
"__end_line__": 32
}
]
}
12 changes: 9 additions & 3 deletions test/helpers/terraform-config-json/cloudwatch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,29 @@
"aws_cloudwatch_event_rule": {
"aws_cloudwatch_event_rule": {
"name": "name",
"event_pattern": " {\n \"foo\": \"bar\"\n }"
"event_pattern": " {\n \"foo\": \"bar\"\n }",
"__start_line__": 1,
"__end_line__": 10
}
}
},
{
"aws_cloudwatch_event_rule": {
"aws_cloudwatch_event_rule2": {
"name": "name",
"event_pattern": "{\n \"foo\": \"bar\"\n}"
"event_pattern": "{\n \"foo\": \"bar\"\n}",
"__start_line__": 10,
"__end_line__": 19
}
}
},
{
"aws_cloudwatch_event_rule": {
"aws_cloudwatch_event_rule2": {
"name": "name",
"event_pattern": "${jsonencode(var.cloudwatch_pattern_deploytool)}"
"event_pattern": "${jsonencode(var.cloudwatch_pattern_deploytool)}",
"__start_line__": 19,
"__end_line__": 24
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion test/helpers/terraform-config-json/data_sources.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"terraform_remote_state": {
"map": {
"for_each": "${{for s3_bucket_key in data.aws_s3_bucket_objects.remote_state_objects.keys : regex(local.remote_state_regex, s3_bucket_key)[\"account_alias\"] => s3_bucket_key if length(regexall(local.remote_state_regex, s3_bucket_key)) > 0}}",
"backend": "s3"
"backend": "s3",
"__start_line__": 1,
"__end_line__": 10
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion test/helpers/terraform-config-json/empty-heredoc.json
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
{"bar": ""}
{
"bar": ""
}
8 changes: 6 additions & 2 deletions test/helpers/terraform-config-json/iam.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
],
"resources": "${aws_s3_bucket.bucket.*.arn.bar}"
}
]
],
"__start_line__": 1,
"__end_line__": 21
}
}
},
Expand All @@ -33,7 +35,9 @@
],
"resources": "${[for bucket_name in local.buckets_to_proxy : \"arn:aws:s3:::${bucket_name}/*\" if substr(bucket_name, 0, 1) == \"l\"]}"
}
]
],
"__start_line__": 21,
"__end_line__": 39
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"locals": [
{
"function_test": "${var.basename}-${var.forwarder_function_name}_${md5(\"${var.vpc_id}${data.aws_region.current.name}\")}"
"function_test": "${var.basename}-${var.forwarder_function_name}_${md5(\"${var.vpc_id}${data.aws_region.current.name}\")}",
"__start_line__": 1,
"__end_line__": 5
}
]
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"locals": [
{
"embedded_interpolation": "${module.special_constants.aws_accounts[\"aaa-${local.foo}-${local.bar}\"]}/us-west-2/key_foo"
"embedded_interpolation": "${module.special_constants.aws_accounts[\"aaa-${local.foo}-${local.bar}\"]}/us-west-2/key_foo",
"__start_line__": 1,
"__end_line__": 5
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"locals": [
{
"multi_function": "${substr(split(\"-\", \"us-west-2\")[0], 0, 1)}",
"multi_function_embedded": "${substr(split(\"-\", \"us-west-2\")[0], 0, 1)}"
"multi_function_embedded": "${substr(split(\"-\", \"us-west-2\")[0], 0, 1)}",
"__start_line__": 3,
"__end_line__": 8
}
]
}
28 changes: 21 additions & 7 deletions test/helpers/terraform-config-json/multiline_expressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,36 @@
{
"null_resource": {
"multiline_comment_multiline": {
"triggers": []
"triggers": [],
"__start_line__": 1,
"__end_line__": 8
}
}
},
{
"null_resource": {
"multiline_comment_single_line_before_closing_bracket": {
"triggers": []
"triggers": [],
"__start_line__": 8,
"__end_line__": 13
}
}
},
{
"null_resource": {
"multiline_comment_single_line_between_brackets": {
"triggers": []
"triggers": [],
"__start_line__": 13,
"__end_line__": 19
}
}
},
{
"null_resource": {
"multiline_comment_single_line_after_opening_bracket": {
"triggers": []
"triggers": [],
"__start_line__": 19,
"__end_line__": 24
}
}
},
Expand All @@ -33,7 +41,9 @@
"multiline_comment_multiple_single_element": {
"triggers": [
2
]
],
"__start_line__": 24,
"__end_line__": 32
}
}
}
Expand All @@ -43,13 +53,17 @@
"some_var2": {
"description": "description",
"type": "${string}",
"default": "${cidrsubnets(\"10.0.0.0/24\", 2, 2)}"
"default": "${cidrsubnets(\"10.0.0.0/24\", 2, 2)}",
"__start_line__": 32,
"__end_line__": 50
}
},
{
"some_var2": {
"description": "description",
"default": "${concat([{'1': '1'}], [{'2': '2'}])}"
"default": "${concat([{'1': '1'}], [{'2': '2'}])}",
"__start_line__": 50,
"__end_line__": 62
}
}
]
Expand Down
8 changes: 6 additions & 2 deletions test/helpers/terraform-config-json/route_table.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"count": "${var.tgw_name == \"\" ? 0 : var.number_of_az}",
"route_table_id": "${aws_route_table.rt[count.index].id}",
"destination_cidr_block": "10.0.0.0/8",
"transit_gateway_id": "${data.aws_ec2_transit_gateway.tgw[0].id}"
"transit_gateway_id": "${data.aws_ec2_transit_gateway.tgw[0].id}",
"__start_line__": 1,
"__end_line__": 13
}
}
},
Expand All @@ -16,7 +18,9 @@
"count": "${var.tgw_name == \"\" ? 0 : var.number_of_az}",
"route_table_id": "${aws_route_table.rt[count.index].id}",
"destination_cidr_block": "10.0.0.0/8",
"transit_gateway_id": "${data.aws_ec2_transit_gateway.tgw[0].id}"
"transit_gateway_id": "${data.aws_ec2_transit_gateway.tgw[0].id}",
"__start_line__": 13,
"__end_line__": 20
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions test/helpers/terraform-config-json/s3.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
{
"enabled": true
}
]
],
"__start_line__": 1,
"__end_line__": 25
}
}
}
Expand All @@ -36,7 +38,9 @@
"source": "s3_bucket_name",
"name": "audit",
"account": "${var.account}",
"region": "${var.region}"
"region": "${var.region}",
"__start_line__": 25,
"__end_line__": 33
}
}
]
Expand Down
Loading

0 comments on commit fc8805e

Please sign in to comment.