Repository: martinohmann/hcl-rs (rust)

Issue:
hcl-edit: attribute key has no span information
```rust
#[test]
fn parsed_body_attribute_has_span_information() {
    use hcl_edit::Span;
    
    let body = hcl_edit::parser::parse_body("foo = bar").unwrap();
    let first_attr = body.into_attributes().next().unwrap();
    assert!(first_attr.key.span().is_some());
}
```

Is this assertion correct? (it fails)

_If this is confirmed and still open in about 2 weeks then i'll provide a PR with a fix attempt_

Pull request description:
fix(parser): attach missing span information to identifiers
Fixes #294

Patch:
diff --git a/crates/hcl-edit/src/parser/structure.rs b/crates/hcl-edit/src/parser/structure.rs
index ab3fbb7..3f149a8 100644
--- a/crates/hcl-edit/src/parser/structure.rs
+++ b/crates/hcl-edit/src/parser/structure.rs
@@ -60,7 +60,7 @@ fn structure<'i, 's>(
         let start = input.location();
         let checkpoint = input.checkpoint();
         peek(one_of(is_id_start)).parse_next(input)?;
-        let ident = cut_str_ident.parse_next(input)?;
+        let (ident, ident_span) = cut_str_ident.with_span().parse_next(input)?;
         let suffix = raw_string(sp).parse_next(input)?;
 
         let mut structure = match peek(any).parse_next(input)? {
@@ -78,6 +78,7 @@ fn structure<'i, 's>(
                 let expr = attribute_expr(input)?;
                 let mut ident = Decorated::new(Ident::new_unchecked(ident));
                 ident.decor_mut().set_suffix(suffix);
+                ident.set_span(ident_span);
                 let attr = Attribute::new(ident, expr);
                 Structure::Attribute(attr)
             }
@@ -85,6 +86,7 @@ fn structure<'i, 's>(
                 let body = block_body(input)?;
                 let mut ident = Decorated::new(Ident::new_unchecked(ident));
                 ident.decor_mut().set_suffix(suffix);
+                ident.set_span(ident_span);
                 let mut block = Block::new(ident);
                 block.body = body;
                 Structure::Block(block)
@@ -94,6 +96,7 @@ fn structure<'i, 's>(
                 let body = block_body(input)?;
                 let mut ident = Decorated::new(Ident::new_unchecked(ident));
                 ident.decor_mut().set_suffix(suffix);
+                ident.set_span(ident_span);
                 let mut block = Block::new(ident);
                 block.body = body;
                 block.labels = labels;


Test patch:
diff --git a/crates/hcl-edit/tests/regressions.rs b/crates/hcl-edit/tests/regressions.rs
index 0c82d2c..400aa31 100644
--- a/crates/hcl-edit/tests/regressions.rs
+++ b/crates/hcl-edit/tests/regressions.rs
@@ -1,7 +1,7 @@
 use hcl_edit::expr::Expression;
-use hcl_edit::structure::{Attribute, Block, Body};
+use hcl_edit::structure::{Attribute, Block, Body, Structure};
 use hcl_edit::template::{Element, Interpolation, Template};
-use hcl_edit::Ident;
+use hcl_edit::{Ident, Span};
 use pretty_assertions::assert_eq;
 
 // https://github.com/martinohmann/hcl-rs/issues/248
@@ -58,6 +58,7 @@ fn issue_270() {
     assert_eq!(body.to_string(), no_trailing_newline);
 }
 
+// https://github.com/martinohmann/hcl-rs/issues/284
 #[test]
 fn issue_284() {
     let input = r#"
@@ -72,3 +73,29 @@ fn issue_284() {
     let res: Result<Body, _> = input.parse();
     assert!(res.is_ok());
 }
+
+// https://github.com/martinohmann/hcl-rs/issues/294
+#[test]
+fn issue_294() {
+    let input = r#"
+        foo = bar
+        block {}
+        labeled_block "label" {}
+    "#;
+
+    let body: Body = input.parse().unwrap();
+
+    assert_eq!(body.len(), 3);
+
+    for structure in &body {
+        let ident = match structure {
+            Structure::Attribute(attr) => &attr.key,
+            Structure::Block(block) => &block.ident,
+        };
+
+        assert!(
+            ident.span().is_some(),
+            "ident `{ident}` misses span information in {structure:?}"
+        );
+    }
+}