Skip to content

Commit

Permalink
feat(validation): Initializers of struct fields (PLC-lang#1032)
Browse files Browse the repository at this point in the history
This commit validates the initializers of struct fields
  • Loading branch information
volsa authored Nov 29, 2023
1 parent ff4027c commit 23e6139
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/typesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,10 @@ impl DataTypeInformation {
let inner_type_size = inner_type_info.get_size_in_bits(index);
let arr_size = self.get_size_in_bits(index);

if inner_type_size == 0 {
return None;
}

Some((arr_size / inner_type_size) as usize)
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ impl<'s, T: AnnotationMap> ValidationContext<'s, T> {
}
}

fn with_optional_qualifier(&self, qualifier: Option<&'s str>) -> Self {
ValidationContext {
annotations: self.annotations,
index: self.index,
qualifier,
is_call: self.is_call,
}
}

fn find_pou(&self, stmt: &AstNode) -> Option<&PouIndexEntry> {
self.annotations.get_call_name(stmt).and_then(|pou_name| {
self.index
Expand Down
4 changes: 4 additions & 0 deletions src/validation/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ fn validate_array<T: AnnotationMap>(
let len_lhs = lhs_type.get_array_length(context.index).unwrap_or(0);
let len_rhs = statement_to_array_length(stmt_rhs);

if len_lhs == 0 {
return;
}

if len_lhs < len_rhs {
let name = lhs_type.get_name();
let location = stmt_rhs.get_location();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
source: src/validation/tests/variable_validation_tests.rs
expression: diagnostics
---
error: Could not resolve reference to xxx
┌─ <internal>:7:41
7 │ unknown_reference : foo := (xxx := 1);
│ ^^^ Could not resolve reference to xxx

error: Array assignments must be surrounded with `[]`
┌─ <internal>:8:62
8 │ invalid_array_assignment : ARRAY[0..1] OF INT := 0;
│ ^ Array assignments must be surrounded with `[]`


20 changes: 20 additions & 0 deletions src/validation/tests/variable_validation_tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::test_utils::tests::parse_and_validate_buffered;
use crate::{assert_validation_snapshot, test_utils::tests::parse_and_validate};
use insta::assert_snapshot;

#[test]
fn uninitialized_constants_fall_back_to_the_default() {
Expand Down Expand Up @@ -360,3 +362,21 @@ mod overflows {
assert_validation_snapshot!(diagnostics);
}
}

#[test]
fn type_initializers_in_structs_are_validated() {
let diagnostics = parse_and_validate_buffered(
"
TYPE foo : STRUCT
x : DINT;
END_STRUCT END_TYPE
TYPE MyStruct: STRUCT
unknown_reference : foo := (xxx := 1);
invalid_array_assignment : ARRAY[0..1] OF INT := 0;
END_STRUCT END_TYPE
",
);

assert_snapshot!(diagnostics);
}
1 change: 1 addition & 0 deletions src/validation/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub fn visit_data_type<T: AnnotationMap>(
) {
validate_data_type(validator, data_type, location);

let context = &context.with_optional_qualifier(data_type.get_name());
match data_type {
DataType::StructType { variables, .. } => {
variables.iter().for_each(|v| visit_variable(validator, v, context))
Expand Down
1 change: 0 additions & 1 deletion src/validation/variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ pub fn visit_variable<T: AnnotationMap>(
context: &ValidationContext<T>,
) {
validate_variable(validator, variable, context);

visit_data_type_declaration(validator, &variable.data_type_declaration, context);
}

Expand Down

0 comments on commit 23e6139

Please sign in to comment.