@@ -304,14 +304,14 @@ impl TypeAnnotator<'_> {
304
304
} else {
305
305
vec ! [ ]
306
306
} ;
307
- let operator_qualifier = & self . get_call_name ( operator) ;
308
307
309
308
let mut generics_candidates: FxHashMap < String , Vec < String > > = FxHashMap :: default ( ) ;
310
309
let mut params = vec ! [ ] ;
311
310
let mut parameters = parameters. into_iter ( ) ;
312
311
313
312
// If we are dealing with an action call statement, we need to get the declared parameters from the parent POU in order
314
313
// to annotate them with the correct type hint.
314
+ let operator_qualifier = & self . get_call_name ( operator) ;
315
315
let implementation = self . index . find_implementation_by_name ( operator_qualifier) ;
316
316
let operator_qualifier = implementation. map ( |it| it. get_type_name ( ) ) . unwrap_or ( operator_qualifier) ;
317
317
for m in self . index . get_declared_parameters ( operator_qualifier) . into_iter ( ) {
@@ -322,7 +322,7 @@ impl TypeAnnotator<'_> {
322
322
{
323
323
generics_candidates. entry ( key. to_string ( ) ) . or_default ( ) . push ( candidate. to_string ( ) )
324
324
} else {
325
- params. push ( ( p, type_name. to_string ( ) ) )
325
+ params. push ( ( p, type_name. to_string ( ) , m . get_location_in_parent ( ) ) )
326
326
}
327
327
}
328
328
}
@@ -331,9 +331,8 @@ impl TypeAnnotator<'_> {
331
331
match self . index . find_pou ( operator_qualifier) {
332
332
Some ( pou) if pou. is_variadic ( ) => {
333
333
//get variadic argument type, if it is generic, update the generic candidates
334
- if let Some ( type_name) =
335
- self . index . get_variadic_member ( pou. get_name ( ) ) . map ( VariableIndexEntry :: get_type_name)
336
- {
334
+ if let Some ( variadic) = self . index . get_variadic_member ( pou. get_name ( ) ) {
335
+ let type_name = variadic. get_type_name ( ) ;
337
336
for parameter in parameters {
338
337
if let Some ( ( key, candidate) ) = TypeAnnotator :: get_generic_candidate (
339
338
self . index ,
@@ -383,17 +382,23 @@ impl TypeAnnotator<'_> {
383
382
type_name
384
383
} ;
385
384
386
- params. push ( ( parameter, type_name. to_string ( ) ) ) ;
385
+ params. push ( (
386
+ parameter,
387
+ type_name. to_string ( ) ,
388
+ variadic. get_location_in_parent ( ) ,
389
+ ) ) ;
387
390
}
388
391
}
389
392
}
390
393
}
391
394
_ => { }
392
395
}
393
- for ( p, name) in params {
394
- self . annotate_parameters ( p, & name) ;
396
+
397
+ for ( p, name, position) in params {
398
+ self . annotate_parameters ( p, & name, position as usize ) ;
395
399
}
396
- //Attempt to resolve the generic signature here
400
+
401
+ // Attempt to resolve the generic signature here
397
402
self . update_generic_call_statement (
398
403
generics_candidates,
399
404
operator_qualifier,
@@ -437,6 +442,14 @@ pub enum StatementAnnotation {
437
442
Value {
438
443
resulting_type : String ,
439
444
} ,
445
+ /// An argument of a call statement
446
+ Argument {
447
+ /// The resulting type of this argument
448
+ resulting_type : String ,
449
+
450
+ /// The position of the parameter this argument is assigned to
451
+ position : usize ,
452
+ } ,
440
453
/// a reference that resolves to a declared variable (e.g. `a` --> `PLC_PROGRAM.a`)
441
454
Variable {
442
455
/// the name of the variable's type (e.g. `"INT"`)
@@ -717,6 +730,27 @@ impl StatementAnnotation {
717
730
_ => None ,
718
731
}
719
732
}
733
+
734
+ /// Returns the location of a parameter in some POU the argument is assigned to, for example
735
+ /// `foo(a, b, c)` will return `0` for `a`, `1` for `b` and `3` for c if `foo` has the following variable
736
+ /// blocks
737
+ /// ```norun
738
+ /// VAR_INPUT
739
+ /// a, b : DINT;
740
+ /// END_VAR
741
+ /// VAR
742
+ /// placeholder: DINT;
743
+ /// END_VAR
744
+ /// VAR_INPUT
745
+ /// c : DINT;
746
+ /// END_VAR`
747
+ /// ```
748
+ pub ( crate ) fn get_location_in_parent ( & self ) -> Option < u32 > {
749
+ match self {
750
+ StatementAnnotation :: Argument { position, .. } => Some ( * position as u32 ) ,
751
+ _ => None ,
752
+ }
753
+ }
720
754
}
721
755
722
756
impl From < & PouIndexEntry > for StatementAnnotation {
@@ -807,6 +841,7 @@ pub trait AnnotationMap {
807
841
fn get_type_name_for_annotation < ' a > ( & ' a self , annotation : & ' a StatementAnnotation ) -> Option < & ' a str > {
808
842
match annotation {
809
843
StatementAnnotation :: Value { resulting_type } => Some ( resulting_type. as_str ( ) ) ,
844
+ StatementAnnotation :: Argument { resulting_type, .. } => Some ( resulting_type. as_str ( ) ) ,
810
845
StatementAnnotation :: Variable { resulting_type, .. } => Some ( resulting_type. as_str ( ) ) ,
811
846
StatementAnnotation :: ReplacementAst { statement } => self
812
847
. get_hint ( statement)
@@ -2133,10 +2168,9 @@ impl<'i> TypeAnnotator<'i> {
2133
2168
}
2134
2169
StatementAnnotation :: Program { qualified_name } => Some ( qualified_name. clone ( ) ) ,
2135
2170
StatementAnnotation :: Variable { resulting_type, .. } => {
2136
- //lets see if this is a FB
2137
2171
self . index
2138
2172
. find_pou ( resulting_type. as_str ( ) )
2139
- . filter ( |it| matches ! ( it, PouIndexEntry :: FunctionBlock { .. } ) )
2173
+ . filter ( |it| matches ! ( it, PouIndexEntry :: FunctionBlock { .. } | PouIndexEntry :: Program { .. } ) )
2140
2174
. map ( |it| it. get_name ( ) . to_string ( ) )
2141
2175
}
2142
2176
// call statements on array access "arr[1]()" will return a StatementAnnotation::Value
@@ -2158,18 +2192,17 @@ impl<'i> TypeAnnotator<'i> {
2158
2192
operator_qualifier
2159
2193
}
2160
2194
2161
- pub ( crate ) fn annotate_parameters ( & mut self , p : & AstNode , type_name : & str ) {
2162
- if !matches ! (
2163
- p. get_stmt( ) ,
2164
- AstStatement :: Assignment ( ..)
2165
- | AstStatement :: OutputAssignment ( ..)
2166
- | AstStatement :: RefAssignment ( ..)
2167
- ) {
2168
- if let Some ( effective_member_type) = self . index . find_effective_type_by_name ( type_name) {
2169
- //update the type hint
2170
- self . annotation_map
2171
- . annotate_type_hint ( p, StatementAnnotation :: value ( effective_member_type. get_name ( ) ) )
2172
- }
2195
+ pub ( crate ) fn annotate_parameters ( & mut self , p : & AstNode , type_name : & str , position : usize ) {
2196
+ if let Some ( effective_member_type) = self . index . find_effective_type_by_name ( type_name) {
2197
+ //update the type hint
2198
+ // self.annotation_map.annotate_type_hint(p, StatementAnnotation::value(effective_member_type.get_name()))
2199
+ self . annotation_map . annotate_type_hint (
2200
+ p,
2201
+ StatementAnnotation :: Argument {
2202
+ resulting_type : effective_member_type. get_name ( ) . to_string ( ) ,
2203
+ position,
2204
+ } ,
2205
+ ) ;
2173
2206
}
2174
2207
}
2175
2208
0 commit comments