hashicorp / hcl2

Former temporary home for experimental new version of HCL
https://github.com/hashicorp/hcl
Mozilla Public License 2.0
373 stars 66 forks source link

hclwrite: Allow body to set attributes in blocks #126

Closed minamijoyo closed 4 years ago

minamijoyo commented 4 years ago

The current implementation can set attributes in top-level, but not attributes in blocks. To do this, add the (*Body).GetBlock() method that selects a block by typeName and labels.

Related to #88


UPDATE: The original proposal has changed as a result of the suggestion:

codecov-io commented 4 years ago

Codecov Report

Merging #126 into master will increase coverage by 0.15%. The diff coverage is 94.11%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #126      +/-   ##
==========================================
+ Coverage   69.02%   69.18%   +0.15%     
==========================================
  Files          98       98              
  Lines       10258    10288      +30     
==========================================
+ Hits         7081     7118      +37     
+ Misses       2858     2852       -6     
+ Partials      319      318       -1
Impacted Files Coverage Δ
hcl/hclsyntax/parser_template.go 65.99% <100%> (ø) :arrow_up:
hclwrite/ast_body.go 89.87% <100%> (+9.31%) :arrow_up:
hcl/hclsyntax/parser.go 67.33% <66.66%> (ø) :arrow_up:
hclwrite/ast_block.go 91.8% <95.65%> (+2.32%) :arrow_up:
hclwrite/node.go 72.38% <0%> (+1.9%) :arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 66c59f9...def1c4e. Read the comment docs.

apparentlymart commented 4 years ago

Hi @minamijoyo! Thanks for working on this.

The way I'd intended this to be done is for the caller to call Body.Blocks and then iterate over the list to find the one they want to add to, because blocks within a body are not necessarily unique even by block type and labels, depending on how the application has defined its schema. However, currently there isn't a good way to actually match on the labels because they are represented as opaque nodes.

This GetBlock method is, I suppose, a shorthand for that in the case where the blocks are unique by type and labels, which is a common design choice. Therefore I'd like to merge this, but I'd suggest the following changes:

If you don't have time to respond to these changes please let me know and I'd be happy to do it myself when I have some spare time. And please also let me know if anything above is unclear or seems surprising. Thanks again for working on this!

minamijoyo commented 4 years ago

@apparentlymart Thank you for your comments! I don't know much about the internal implementation, so it might take some time for me to fix it, but I'm interested in the hcl2, so I'll try to fix it.

minamijoyo commented 4 years ago

@apparentlymart I fixed it. How about this? If it looks almost good, I will add more tests.

minamijoyo commented 4 years ago

@apparentlymart I've added tests. Please review this.

If my understanding is correct, I found a bug in the existing implementation. If label is unquoted, we expect to get a TokenIdent as *identifier, but the current implementation seems to wrap it in *quoted. Please let me know if I am wrong.

minamijoyo commented 4 years ago

Looking at the parser implementation, I may have found the cause. https://github.com/hashicorp/hcl2/blob/1aba4ac822ee0b54f729b458191f9f069d68af28/hclwrite/parser.go#L310

(*hclwrite.node)(0xc000118570)({
 content: (*hclwrite.quoted)(0xc0000b3000)({
  leafNode: (hclwrite.leafNode) {
  },
  parent: (*hclwrite.node)(<nil>),
  tokens: (hclwrite.Tokens) (len=1 cap=1) {
   (*hclwrite.Token)(0xc000106690)({
    Type: (hclsyntax.TokenType) TokenIdent,
    Bytes: ([]uint8) (len=6 cap=6) {
     00000000  6c 61 62 65 6c 31                                 |label1|
    },
    SpacesBefore: (int) 1
   })
  }
 }),
 list: (*hclwrite.nodes)(<nil>),
 before: (*hclwrite.node)(<nil>),
 after: (*hclwrite.node)(<nil>)
})
minamijoyo commented 4 years ago

I've opened PR #130 to fix it.

minamijoyo commented 4 years ago

I rebased this branch on the latest master and removed the workaround. All tests are now passed. It's ready to be merged. Please check this again! @apparentlymart

apparentlymart commented 4 years ago

Thanks @minamijoyo!

We're currently working on moving the code from this repository into the hashicorp/hcl repository as major version 2, so I'm going to wait to merge this just to avoid conflicting with that work, and then I'll apply your changeset to the new branch in the other repository in order to merge it.

Thanks again for working on this!

minamijoyo commented 4 years ago

@apparentlymart OK. I'll be waiting for it.

apparentlymart commented 4 years ago

Hi again! Sorry for the delay.

This is now merged over in the hcl2 branch in hashicorp/hcl, and included in the v2.0.0 release there. The commit in the other repository is 9d1235a5b4e8.