Skip to content

Commit 86eb38e

Browse files
authored
Add Formatting Capabilities (#321)
This PR enables the initial support for formatting VHDL language elements and files. The formatter is transforms the AST representation into a string. It is capable of formatting any AST element and preserving comments as well as newlines.
1 parent f5546fa commit 86eb38e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+7746
-993
lines changed

clippy.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ignore-interior-mutability = ["vhdl_lang::data::source::UniqueSource"]

vhdl_lang/src/analysis/assignment.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
3838
self.analyze_expression_for_target(scope, ttyp, item, diagnostics)?;
3939
self.boolean_expr(scope, condition, diagnostics)?;
4040
}
41-
if let Some(expr) = else_item {
41+
if let Some((expr, _)) = else_item {
4242
self.analyze_expression_for_target(scope, ttyp, expr, diagnostics)?;
4343
}
4444
}
@@ -48,7 +48,12 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
4848
alternatives,
4949
} = selection;
5050
let ctyp = as_fatal(self.expr_unambiguous_type(scope, expression, diagnostics))?;
51-
for Alternative { choices, item } in alternatives.iter_mut() {
51+
for Alternative {
52+
choices,
53+
item,
54+
span: _,
55+
} in alternatives.iter_mut()
56+
{
5257
self.analyze_expression_for_target(scope, ttyp, item, diagnostics)?;
5358
self.choice_with_ttyp(scope, ctyp, choices, diagnostics)?;
5459
}
@@ -83,7 +88,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
8388
self.analyze_waveform(scope, ttyp, item, diagnostics)?;
8489
self.boolean_expr(scope, condition, diagnostics)?;
8590
}
86-
if let Some(wavf) = else_item {
91+
if let Some((wavf, _)) = else_item {
8792
self.analyze_waveform(scope, ttyp, wavf, diagnostics)?;
8893
}
8994
}
@@ -93,7 +98,12 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
9398
alternatives,
9499
} = selection;
95100
let ctyp = as_fatal(self.expr_unambiguous_type(scope, expression, diagnostics))?;
96-
for Alternative { choices, item } in alternatives.iter_mut() {
101+
for Alternative {
102+
choices,
103+
item,
104+
span: _,
105+
} in alternatives.iter_mut()
106+
{
97107
self.analyze_waveform(scope, ttyp, item, diagnostics)?;
98108
self.choice_with_ttyp(scope, ctyp, choices, diagnostics)?;
99109
}
@@ -119,7 +129,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
119129
}
120130
}
121131
}
122-
Waveform::Unaffected => {}
132+
Waveform::Unaffected(_) => {}
123133
}
124134
Ok(())
125135
}

vhdl_lang/src/analysis/association.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
184184
// it must be a type conversion or a single parameter function call
185185

186186
let (pos, resolved_formal) = if let Some((inner_pos, inner_name)) =
187-
to_formal_conversion_argument(&mut fcall.parameters)
187+
to_formal_conversion_argument(&mut fcall.parameters.items)
188188
{
189189
(
190190
inner_pos,
@@ -250,7 +250,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
250250
bail!(
251251
diagnostics,
252252
Diagnostic::new(
253-
&fcall.name.pos(self.ctx),
253+
fcall.name.pos(self.ctx),
254254
format!(
255255
"No function '{}' accepting {}",
256256
fcall.name,
@@ -372,7 +372,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
372372
result.push((actual.span, Some(formal)));
373373
} else {
374374
diagnostics.add(
375-
&actual.pos(self.ctx),
375+
actual.pos(self.ctx),
376376
"Unexpected extra argument",
377377
ErrorCode::TooManyArguments,
378378
);

vhdl_lang/src/analysis/concurrent.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
119119
..
120120
} = process;
121121
if let Some(sensitivity_list) = sensitivity_list {
122-
match sensitivity_list {
122+
match &mut sensitivity_list.item {
123123
SensitivityList::Names(names) => {
124124
self.sensitivity_list_check(scope, names, diagnostics)?;
125125
}
@@ -165,7 +165,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
165165
let nested = scope.nested();
166166
self.analyze_generate_body(&nested, parent, item, src_span, diagnostics)?;
167167
}
168-
if let Some(ref mut else_item) = else_item {
168+
if let Some((ref mut else_item, _)) = else_item {
169169
let nested = scope.nested();
170170
self.analyze_generate_body(&nested, parent, else_item, src_span, diagnostics)?;
171171
}
@@ -186,6 +186,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
186186
let Alternative {
187187
ref mut choices,
188188
ref mut item,
189+
span: _,
189190
} = alternative;
190191
self.choice_with_ttyp(scope, ctyp, choices, diagnostics)?;
191192
let nested = scope.nested();
@@ -258,7 +259,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
258259
// Pre-declare labels
259260
self.define_labels_for_concurrent_part(scope, parent, statements, diagnostics)?;
260261

261-
if let Some(ref mut decl) = decl {
262+
if let Some((ref mut decl, _)) = decl {
262263
self.analyze_declarative_part(scope, parent, decl, diagnostics)?;
263264
}
264265
self.analyze_concurrent_part(scope, inner_parent, statements, diagnostics)?;
@@ -456,7 +457,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
456457
))? {
457458
if object_name.base.class() != ObjectClass::Signal {
458459
diagnostics.add(
459-
&name.pos(self.ctx),
460+
name.pos(self.ctx),
460461
format!(
461462
"{} is not a signal and cannot be in a sensitivity list",
462463
object_name.base.describe_class()
@@ -467,7 +468,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
467468
&& !object_name.base.is_port()
468469
{
469470
diagnostics.add(
470-
&name.pos(self.ctx),
471+
name.pos(self.ctx),
471472
format!(
472473
"{} cannot be in a sensitivity list",
473474
object_name.base.describe_class()

vhdl_lang/src/analysis/declarative.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
234234
name,
235235
subtype_indication,
236236
signature,
237+
is_token: _,
237238
} = alias;
238239

239240
let resolved_name = self.name_resolve(scope, name.span, &mut name.item, diagnostics);
@@ -283,7 +284,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
283284
));
284285
}
285286
diagnostics.add(
286-
&name.pos(self.ctx),
287+
name.pos(self.ctx),
287288
format!("{} cannot be aliased", resolved_name.describe_type()),
288289
ErrorCode::MismatchedKinds,
289290
);
@@ -447,7 +448,8 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
447448
}
448449
Declaration::File(ref mut file) => {
449450
let FileDeclaration {
450-
ident,
451+
idents,
452+
colon_token: _,
451453
subtype_indication,
452454
open_info,
453455
file_name,
@@ -459,18 +461,20 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
459461
diagnostics,
460462
))?;
461463

462-
if let Some(ref mut expr) = open_info {
464+
if let Some((_, ref mut expr)) = open_info {
463465
self.expr_unknown_ttyp(scope, expr, diagnostics)?;
464466
}
465-
if let Some(ref mut expr) = file_name {
467+
if let Some((_, ref mut expr)) = file_name {
466468
self.expr_unknown_ttyp(scope, expr, diagnostics)?;
467469
}
468470

469471
if let Some(subtype) = subtype {
470-
scope.add(
471-
self.define(ident, parent, AnyEntKind::File(subtype), src_span),
472-
diagnostics,
473-
);
472+
for ident in idents {
473+
scope.add(
474+
self.define(ident, parent, AnyEntKind::File(subtype), src_span),
475+
diagnostics,
476+
);
477+
}
474478
}
475479
}
476480
Declaration::Component(ref mut component) => {
@@ -625,7 +629,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
625629
Type::Record(region) => region,
626630
_ => {
627631
let diag = Diagnostic::new(
628-
&view.typ.type_mark.pos(self.ctx),
632+
view.typ.type_mark.pos(self.ctx),
629633
format!(
630634
"The type of a view must be a record type, not {}",
631635
typ.type_mark().describe()
@@ -641,17 +645,17 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
641645
};
642646
let mut unassociated: HashSet<_> = record_region.elems.iter().collect();
643647
for element in view.elements.iter_mut() {
644-
for name in element.names.items.iter_mut() {
645-
let desi = Designator::Identifier(name.item.item.clone());
648+
for name in element.names.iter_mut() {
649+
let desi = Designator::Identifier(name.tree.item.clone());
646650
let Some(record_element) = record_region.lookup(&desi) else {
647651
diagnostics.push(Diagnostic::new(
648-
name.item.pos(self.ctx),
652+
name.pos(self.ctx),
649653
format!("Not a part of {}", typ.type_mark().describe()),
650654
ErrorCode::Unresolved,
651655
));
652656
continue;
653657
};
654-
name.set_unique_reference(&record_element);
658+
name.decl.set_unique_reference(&record_element);
655659
unassociated.remove(&record_element);
656660
}
657661
}
@@ -690,6 +694,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
690694
entity_name,
691695
entity_class,
692696
expr,
697+
colon_token: _,
693698
} = attr_spec;
694699

695700
let attr_ent = match scope.lookup(
@@ -744,7 +749,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
744749
if let Some(signature) = signature {
745750
diagnostics.push(Diagnostic::should_not_have_signature(
746751
"Attribute specification",
747-
&signature.pos(self.ctx),
752+
signature.pos(self.ctx),
748753
));
749754
}
750755
ent
@@ -954,7 +959,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
954959
class,
955960
iface: Some(ObjectInterface::simple(
956961
object_decl.list_type,
957-
mode.mode.unwrap_or_default(),
962+
mode.mode.as_ref().map(|mode| mode.item).unwrap_or_default(),
958963
)),
959964
subtype,
960965
has_default: mode.expression.is_some(),
@@ -968,14 +973,14 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
968973
let resolved =
969974
self.name_resolve(scope, view.name.span, &mut view.name.item, diagnostics)?;
970975
let view_ent = self.resolve_view_ent(&resolved, diagnostics, view.name.span)?;
971-
if let Some(ast_declared_subtype) = &mut view.subtype_indication {
976+
if let Some((_, ast_declared_subtype)) = &mut view.subtype_indication {
972977
let declared_subtype =
973978
self.resolve_subtype_indication(scope, ast_declared_subtype, diagnostics)?;
974979
if declared_subtype.type_mark() != view_ent.subtype().type_mark() {
975980
bail!(
976981
diagnostics,
977982
Diagnostic::new(
978-
&ast_declared_subtype.type_mark.pos(self.ctx),
983+
ast_declared_subtype.type_mark.pos(self.ctx),
979984
"Specified subtype must match the subtype declared for the view",
980985
ErrorCode::TypeMismatch
981986
)
@@ -1061,7 +1066,9 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
10611066
ArrayIndex::IndexSubtypeDefintion(ref mut type_mark) => self
10621067
.type_name(scope, type_mark.span, &mut type_mark.item, diagnostics)
10631068
.map(|typ| typ.base()),
1064-
ArrayIndex::Discrete(ref mut drange) => self.drange_type(scope, drange, diagnostics),
1069+
ArrayIndex::Discrete(ref mut drange) => {
1070+
self.drange_type(scope, &mut drange.item, diagnostics)
1071+
}
10651072
}
10661073
}
10671074
}

vhdl_lang/src/analysis/design_unit.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
420420
ResolvedName::Library(ref library_name) => {
421421
if library_name != self.work_library_name() {
422422
diagnostics.add(
423-
&prefix.pos(self.ctx),
423+
prefix.pos(self.ctx),
424424
format!("Configuration must be within the same library '{}' as the corresponding entity", self.work_library_name()), ErrorCode::ConfigNotInSameLibrary);
425425
Err(EvalError::Unknown)
426426
} else {
@@ -451,14 +451,14 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
451451
}
452452
}
453453
other => {
454-
diagnostics.push(other.kind_error(&prefix.pos(self.ctx), "library"));
454+
diagnostics.push(other.kind_error(prefix.pos(self.ctx), "library"));
455455
Err(EvalError::Unknown)
456456
}
457457
}
458458
}
459459
_ => {
460460
diagnostics.add(
461-
&ent_name.pos(self.ctx),
461+
ent_name.pos(self.ctx),
462462
"Expected selected name",
463463
ErrorCode::MismatchedKinds,
464464
);
@@ -480,7 +480,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
480480
bail!(
481481
diagnostics,
482482
Diagnostic::mismatched_kinds(
483-
&prefix.pos(self.ctx),
483+
prefix.pos(self.ctx),
484484
"Invalid prefix of a selected name",
485485
)
486486
);
@@ -490,7 +490,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
490490
bail!(
491491
diagnostics,
492492
Diagnostic::mismatched_kinds(
493-
&prefix.pos(self.ctx),
493+
prefix.pos(self.ctx),
494494
"'.all' may not be the prefix of a selected name",
495495
)
496496
);
@@ -531,7 +531,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
531531
| Name::External(..) => {
532532
bail!(
533533
diagnostics,
534-
Diagnostic::mismatched_kinds(&name.pos(self.ctx), "Invalid selected name",)
534+
Diagnostic::mismatched_kinds(name.pos(self.ctx), "Invalid selected name",)
535535
);
536536
}
537537
}
@@ -548,7 +548,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
548548
ContextItem::Library(LibraryClause {
549549
ref mut name_list, ..
550550
}) => {
551-
for library_name in name_list.items.iter_mut() {
551+
for library_name in name_list.iter_mut() {
552552
if self.work_sym == library_name.item.item {
553553
library_name.set_unique_reference(self.work_library());
554554
diagnostics.add(
@@ -577,12 +577,12 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
577577
ContextItem::Context(ContextReference {
578578
ref mut name_list, ..
579579
}) => {
580-
for name in name_list.items.iter_mut() {
580+
for name in name_list.iter_mut() {
581581
match name.item {
582582
Name::Selected(..) => {}
583583
_ => {
584584
diagnostics.add(
585-
&name.pos(self.ctx),
585+
name.pos(self.ctx),
586586
"Context reference must be a selected name",
587587
ErrorCode::MismatchedKinds,
588588
);
@@ -639,13 +639,13 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
639639
use_clause: &mut UseClause,
640640
diagnostics: &mut dyn DiagnosticHandler,
641641
) -> FatalResult {
642-
for name in use_clause.name_list.items.iter_mut() {
642+
for name in use_clause.name_list.iter_mut() {
643643
match name.item {
644644
Name::Selected(..) => {}
645645
Name::SelectedAll(..) => {}
646646
_ => {
647647
diagnostics.add(
648-
&name.pos(self.ctx),
648+
name.pos(self.ctx),
649649
"Use clause must be a selected name",
650650
ErrorCode::MismatchedKinds,
651651
);
@@ -729,7 +729,7 @@ impl<'a, 't> AnalyzeContext<'a, 't> {
729729
}
730730
}
731731
diagnostics.add(
732-
&package_name.pos(self.ctx),
732+
package_name.pos(self.ctx),
733733
format!("'{package_name}' is not an uninstantiated generic package"),
734734
ErrorCode::MismatchedKinds,
735735
);

0 commit comments

Comments
 (0)