Skip to content

Commit 118168d

Browse files
NullVoxPopuliclaude
andcommitted
fix: element.path loc uses tag name span, not whole element
build_element_path was receiving the entire element's location, so <section>'s path loc spanned the whole element (open+children+close) instead of just the tag name 'section'. The head loc was the same. Now build_normal_element / build_self_closing_element / build_void_element capture the TagName / VoidTagName pair's span separately and pass it through as tag_loc. build_element_path takes that and produces path and head locs that span just the tag name text. Fixes many Location Info tests that check element.path.loc and element.path.head.loc. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
1 parent af4dc49 commit 118168d

3 files changed

Lines changed: 27 additions & 12 deletions

File tree

Binary file not shown.

packages/@glimmer/syntax/pkg/wasm-bytes.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

packages/@glimmer/syntax/src/builder.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,6 +1082,7 @@ fn build_normal_element(
10821082
loc: SourceLocation,
10831083
) -> ElementNode {
10841084
let mut tag_name = String::new();
1085+
let mut tag_loc = loc.clone();
10851086
let mut attributes = vec![];
10861087
let mut modifiers = vec![];
10871088
let mut comments = vec![];
@@ -1096,7 +1097,10 @@ fn build_normal_element(
10961097
open_tag = span_to_loc(source, &child);
10971098
for sub in child.into_inner() {
10981099
match sub.as_rule() {
1099-
Rule::TagName => tag_name = sub.as_str().to_string(),
1100+
Rule::TagName => {
1101+
tag_name = sub.as_str().to_string();
1102+
tag_loc = span_to_loc(source, &sub);
1103+
}
11001104
Rule::Splattributes => {
11011105
let attr_loc = span_to_loc(source, &sub);
11021106
attributes.push(AttrNode {
@@ -1142,7 +1146,7 @@ fn build_normal_element(
11421146
}
11431147
}
11441148

1145-
let path = build_element_path(&tag_name, &loc);
1149+
let path = build_element_path(&tag_name, &tag_loc);
11461150

11471151
ElementNode {
11481152
node_type: "ElementNode",
@@ -1167,14 +1171,18 @@ fn build_self_closing_element(
11671171
loc: SourceLocation,
11681172
) -> ElementNode {
11691173
let mut tag_name = String::new();
1174+
let mut tag_loc = loc.clone();
11701175
let mut attributes = vec![];
11711176
let mut modifiers = vec![];
11721177
let mut comments = vec![];
11731178
let mut block_params: Vec<String> = vec![];
11741179

11751180
for child in pair.into_inner() {
11761181
match child.as_rule() {
1177-
Rule::TagName => tag_name = child.as_str().to_string(),
1182+
Rule::TagName => {
1183+
tag_name = child.as_str().to_string();
1184+
tag_loc = span_to_loc(source, &child);
1185+
}
11781186
Rule::Splattributes => {
11791187
let attr_loc = span_to_loc(source, &child);
11801188
attributes.push(AttrNode {
@@ -1207,7 +1215,7 @@ fn build_self_closing_element(
12071215
}
12081216
}
12091217

1210-
let path = build_element_path(&tag_name, &loc);
1218+
let path = build_element_path(&tag_name, &tag_loc);
12111219

12121220
ElementNode {
12131221
node_type: "ElementNode",
@@ -1232,14 +1240,18 @@ fn build_void_element(
12321240
loc: SourceLocation,
12331241
) -> ElementNode {
12341242
let mut tag_name = String::new();
1243+
let mut tag_loc = loc.clone();
12351244
let mut attributes = vec![];
12361245
let mut modifiers = vec![];
12371246
let mut comments = vec![];
12381247
let mut self_closing = false;
12391248

12401249
for child in pair.into_inner() {
12411250
match child.as_rule() {
1242-
Rule::VoidTagName => tag_name = child.as_str().to_string(),
1251+
Rule::VoidTagName => {
1252+
tag_name = child.as_str().to_string();
1253+
tag_loc = span_to_loc(source, &child);
1254+
}
12431255
Rule::TagEnd => {
12441256
// `/>` marks a self-closing void element like <br />
12451257
if child.as_str() == "/>" {
@@ -1275,7 +1287,7 @@ fn build_void_element(
12751287
}
12761288
}
12771289

1278-
let path = build_element_path(&tag_name, &loc);
1290+
let path = build_element_path(&tag_name, &tag_loc);
12791291

12801292
ElementNode {
12811293
node_type: "ElementNode",
@@ -1294,16 +1306,19 @@ fn build_void_element(
12941306
}
12951307
}
12961308

1297-
fn build_element_path(tag_name: &str, loc: &SourceLocation) -> PathExpression {
1309+
/// Build an element path from the tag name source span.
1310+
/// `tag_loc` must be the location of just the tag name in the source
1311+
/// (NOT the whole element).
1312+
fn build_element_path(tag_name: &str, tag_loc: &SourceLocation) -> PathExpression {
12981313
let segments: Vec<&str> = tag_name.split('.').collect();
12991314
let head_name = segments[0];
13001315
let tail: Vec<String> = segments[1..].iter().map(|s| s.to_string()).collect();
13011316

13021317
let head_loc = SourceLocation {
1303-
start: loc.start.clone(),
1318+
start: tag_loc.start.clone(),
13041319
end: SourcePosition {
1305-
line: loc.start.line,
1306-
column: loc.start.column + head_name.len(),
1320+
line: tag_loc.start.line,
1321+
column: tag_loc.start.column + head_name.len(),
13071322
},
13081323
};
13091324

@@ -1335,7 +1350,7 @@ fn build_element_path(tag_name: &str, loc: &SourceLocation) -> PathExpression {
13351350
original: tag_name.to_string(),
13361351
head,
13371352
tail,
1338-
loc: loc.clone(),
1353+
loc: tag_loc.clone(),
13391354
}
13401355
}
13411356

0 commit comments

Comments
 (0)