Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions crates/fmt/src/state/sol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,9 @@ impl<'ast> State<'_, 'ast> {

self.print_assign_rhs(init, pre_init_size, init_space_left, Some(&ty.kind), cache);
} else {
if override_.is_some() {
self.end();
}
self.end();
}
self.end();
Expand Down
147 changes: 147 additions & 0 deletions crates/fmt/tests/formatter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,150 @@ contract ProofOfConcept {

assert_eq!(formatted, expected, "Formatting mismatch");
}

#[test]
fn test_override_state_variable_without_initializer_does_not_leak_indent() {
init_tracing();

let cases = [
(
"top-level items after override variable",
r#"pragma solidity ^0.8.28;

contract BaseStorage {
uint256 public total;
}

contract ChildStorage is BaseStorage {
uint256 public override total;
}

struct Info {
uint256 a;
}

function topLevel(uint256 value) pure returns (uint256) {
return value;
}
"#,
r#"pragma solidity ^0.8.28;

contract BaseStorage {
uint256 public total;
}

contract ChildStorage is BaseStorage {
uint256 public override total;
}

struct Info {
uint256 a;
}

function topLevel(uint256 value) pure returns (uint256) {
return value;
}
"#,
),
(
"contract member after override variable",
r#"pragma solidity ^0.8.28;

contract BaseStorage {
uint256 public total;
}

contract ChildStorage is BaseStorage {
uint256 public override total;
uint256 public next;
}
"#,
r#"pragma solidity ^0.8.28;

contract BaseStorage {
uint256 public total;
}

contract ChildStorage is BaseStorage {
uint256 public override total;
uint256 public next;
}
"#,
),
(
"override path list without initializer",
r#"pragma solidity ^0.8.28;

contract BaseA {
uint256 public total;
}

contract BaseB {
uint256 public total;
}

contract ChildStorage is BaseA, BaseB {
uint256 public override(BaseA, BaseB) total;
}

error AfterOverride(uint256 value);
"#,
r#"pragma solidity ^0.8.28;

contract BaseA {
uint256 public total;
}

contract BaseB {
uint256 public total;
}

contract ChildStorage is BaseA, BaseB {
uint256 public override(BaseA, BaseB) total;
}

error AfterOverride(uint256 value);
"#,
),
(
"override variable with initializer",
r#"pragma solidity ^0.8.28;

contract BaseStorage {
uint256 public total;
}

contract ChildStorage is BaseStorage {
uint256 public override total = 0;
}

struct AfterInitializer {
uint256 a;
}
"#,
r#"pragma solidity ^0.8.28;

contract BaseStorage {
uint256 public total;
}

contract ChildStorage is BaseStorage {
uint256 public override total = 0;
}

struct AfterInitializer {
uint256 a;
}
"#,
),
];

let fmt_config = Arc::new(FormatterConfig::default());
let path = Path::new("override-indent.sol");

for (case, source, expected) in cases {
let formatted = format(source, path, fmt_config.clone());
assert_eq!(formatted, expected, "{case}");
assert_eq!(format(&formatted, path, fmt_config.clone()), expected, "{case} idempotency");
}
}
Loading