Skip to content

Commit b2885ba

Browse files
authored
ifaces: warn about repeated field name in iimpl (RGB-WG#223)
1 parent a7296e3 commit b2885ba

File tree

1 file changed

+94
-3
lines changed

1 file changed

+94
-3
lines changed

src/interface/iimpl.rs

+94-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
// See the License for the specific language governing permissions and
2020
// limitations under the License.
2121

22+
use std::collections::HashMap;
2223
use std::fmt::{self, Display, Formatter};
2324
use std::str::FromStr;
2425

@@ -374,13 +375,37 @@ pub enum ImplInconsistency {
374375

375376
/// implementation references unknown interface error '{0}'.
376377
IfaceErrorAbsent(VariantName),
378+
379+
/// metadata field '{0}' is repeated {1} times
380+
RepeatedMetaData(FieldName, i32),
381+
382+
/// global state field '{0}' is repeated {1} times
383+
RepeatedGlobalState(FieldName, i32),
384+
385+
/// assignments field '{0}' is repeated {1} times
386+
RepeatedAssignments(FieldName, i32),
387+
388+
/// valencies field '{0}' is repeated {1} times
389+
RepeatedValencies(FieldName, i32),
390+
391+
/// transition field '{0}' is repeated {1} times
392+
RepeatedTransitions(FieldName, i32),
393+
394+
/// extension field '{0}' is repeated {1} times
395+
RepeatedExtensions(FieldName, i32),
377396
}
378397

379398
impl IfaceImpl {
380399
pub fn check(&self, iface: &Iface, schema: &Schema) -> Result<(), Vec<ImplInconsistency>> {
381400
let mut errors = vec![];
382-
383401
let now = Utc::now();
402+
let mut dup_metadata = HashMap::new();
403+
let mut dup_global_state = HashMap::new();
404+
let mut dup_assignments = HashMap::new();
405+
let mut dup_valencies = HashMap::new();
406+
let mut dup_transitions = HashMap::new();
407+
let mut dup_extensions = HashMap::new();
408+
384409
match Utc.timestamp_opt(self.timestamp, 0).single() {
385410
Some(ts) if ts > now => errors.push(ImplInconsistency::FutureTimestamp(ts)),
386411
None => errors.push(ImplInconsistency::InvalidTimestamp(self.timestamp)),
@@ -393,76 +418,142 @@ impl IfaceImpl {
393418
}
394419
}
395420
for field in &self.metadata {
421+
dup_metadata
422+
.entry(field.name.clone())
423+
.and_modify(|counter| *counter += 1)
424+
.or_insert(0);
396425
if !schema.meta_types.contains_key(&field.id) {
397426
errors.push(ImplInconsistency::SchemaMetaAbsent(field.name.clone(), field.id));
398427
}
399428
}
400429

430+
dup_metadata
431+
.iter()
432+
.filter(|(_, &count)| count > 1)
433+
.for_each(|(field_name, &count)| {
434+
errors.push(ImplInconsistency::RepeatedMetaData(field_name.clone(), count));
435+
});
436+
401437
for name in iface.global_state.keys() {
402438
if self.global_state.iter().all(|field| &field.name != name) {
403439
errors.push(ImplInconsistency::IfaceGlobalAbsent(name.clone()));
404440
}
405441
}
406442
for field in &self.global_state {
443+
dup_global_state
444+
.entry(field.name.clone())
445+
.and_modify(|counter| *counter += 1)
446+
.or_insert(0);
407447
if !schema.global_types.contains_key(&field.id) {
408448
errors.push(ImplInconsistency::SchemaGlobalAbsent(field.name.clone(), field.id));
409449
}
410450
}
411451

452+
dup_global_state
453+
.iter()
454+
.filter(|(_, &count)| count > 1)
455+
.for_each(|(field_name, &count)| {
456+
errors.push(ImplInconsistency::RepeatedGlobalState(field_name.clone(), count));
457+
});
458+
412459
for name in iface.assignments.keys() {
413460
if self.assignments.iter().all(|field| &field.name != name) {
414461
errors.push(ImplInconsistency::IfaceAssignmentAbsent(name.clone()));
415462
}
416463
}
417464
for field in &self.assignments {
465+
dup_assignments
466+
.entry(field.name.clone())
467+
.and_modify(|counter| *counter += 1)
468+
.or_insert(0);
418469
if !schema.owned_types.contains_key(&field.id) {
419470
errors
420471
.push(ImplInconsistency::SchemaAssignmentAbsent(field.name.clone(), field.id));
421472
}
422473
}
423474

475+
dup_assignments
476+
.iter()
477+
.filter(|(_, &count)| count > 1)
478+
.for_each(|(field_name, &count)| {
479+
errors.push(ImplInconsistency::RepeatedAssignments(field_name.clone(), count));
480+
});
481+
424482
for name in iface.valencies.keys() {
425483
if self.valencies.iter().all(|field| &field.name != name) {
426484
errors.push(ImplInconsistency::IfaceValencyAbsent(name.clone()));
427485
}
428486
}
429487
for field in &self.valencies {
488+
dup_valencies
489+
.entry(field.name.clone())
490+
.and_modify(|counter| *counter += 1)
491+
.or_insert(0);
492+
430493
if !schema.valency_types.contains(&field.id) {
431494
errors.push(ImplInconsistency::SchemaValencyAbsent(field.name.clone(), field.id));
432495
}
433496
}
497+
dup_valencies
498+
.iter()
499+
.filter(|(_, &count)| count > 1)
500+
.for_each(|(field_name, &count)| {
501+
errors.push(ImplInconsistency::RepeatedValencies(field_name.clone(), count));
502+
});
434503

435504
for name in iface.transitions.keys() {
436505
if self.transitions.iter().all(|field| &field.name != name) {
437506
errors.push(ImplInconsistency::IfaceTransitionAbsent(name.clone()));
438507
}
439508
}
440509
for field in &self.transitions {
510+
dup_transitions
511+
.entry(field.name.clone())
512+
.and_modify(|counter| *counter += 1)
513+
.or_insert(0);
514+
441515
if !schema.transitions.contains_key(&field.id) {
442516
errors
443517
.push(ImplInconsistency::SchemaTransitionAbsent(field.name.clone(), field.id));
444518
}
445519
}
446520

521+
dup_transitions
522+
.iter()
523+
.filter(|(_, &count)| count > 1)
524+
.for_each(|(field_name, &count)| {
525+
errors.push(ImplInconsistency::RepeatedTransitions(field_name.clone(), count));
526+
});
527+
447528
for name in iface.extensions.keys() {
448529
if self.extensions.iter().all(|field| &field.name != name) {
449530
errors.push(ImplInconsistency::IfaceExtensionAbsent(name.clone()));
450531
}
451532
}
452533
for field in &self.extensions {
534+
dup_extensions
535+
.entry(field.name.clone())
536+
.and_modify(|counter| *counter += 1)
537+
.or_insert(0);
538+
453539
if !schema.extensions.contains_key(&field.id) {
454540
errors.push(ImplInconsistency::SchemaExtensionAbsent(field.name.clone(), field.id));
455541
}
456542
}
457543

544+
dup_extensions
545+
.iter()
546+
.filter(|(_, &count)| count > 1)
547+
.for_each(|(field_name, &count)| {
548+
errors.push(ImplInconsistency::RepeatedExtensions(field_name.clone(), count));
549+
});
550+
458551
for var in &self.errors {
459552
if iface.errors.keys().all(|name| name != &var.name) {
460553
errors.push(ImplInconsistency::IfaceErrorAbsent(var.name.clone()));
461554
}
462555
}
463556

464-
// TODO: Warn about repeated field names
465-
466557
if errors.is_empty() {
467558
Ok(())
468559
} else {

0 commit comments

Comments
 (0)