neo_devpack_solidity/solidity/validate/contract/
entry.rs1pub fn validate_contract(metadata: &ContractMetadata) -> Vec<Diagnostic> {
2 let mut diagnostics = Vec::new();
3
4 let method_name_counts = build_method_name_counts(metadata);
5 let constructor_count = validate_methods(metadata, &mut diagnostics);
6
7 if constructor_count > 1 {
8 diagnostics.push(Diagnostic::error(format!("multiple constructors defined ({constructor_count} total)")));
9 }
10
11 validate_state_variables(metadata, &method_name_counts, &mut diagnostics);
12 validate_events(metadata, &mut diagnostics);
13 validate_return_types(metadata, &mut diagnostics);
14 validate_erc_nep_patterns(metadata, &mut diagnostics);
15 validate_using_directives(metadata, &mut diagnostics);
16 validate_type_definitions(metadata, &mut diagnostics);
17 validate_library(metadata, &mut diagnostics);
18 validate_abstract_contract(metadata, &mut diagnostics);
19 validate_flatten_warnings(metadata, &mut diagnostics);
20
21 diagnostics
22}
23
24fn validate_using_directives(_metadata: &ContractMetadata, _diagnostics: &mut [Diagnostic]) {
25 }
29
30fn validate_type_definitions(_metadata: &ContractMetadata, _diagnostics: &mut [Diagnostic]) {
31 }
34
35fn validate_abstract_contract(metadata: &ContractMetadata, diagnostics: &mut Vec<Diagnostic>) {
36 let unimplemented: Vec<&str> = metadata
37 .methods
38 .iter()
39 .filter(|m| {
40 matches!(m.kind, FunctionKind::Regular)
41 && m.body.is_none()
42 })
43 .map(|m| m.name.as_str())
44 .collect();
45
46 if unimplemented.is_empty() {
47 return;
48 }
49
50 if metadata.is_interface {
51 return;
52 }
53
54 if metadata.is_abstract {
55 diagnostics.push(
58 Diagnostic::warning(format!(
59 "abstract contract '{}' has {} unimplemented function(s): [{}]",
60 metadata.name,
61 unimplemented.len(),
62 unimplemented.join(", "),
63 ))
64 .with_suggestion(
65 "derived contracts must implement these functions or also be declared abstract"
66 ),
67 );
68 } else {
69 diagnostics.push(
71 Diagnostic::error(format!(
72 "contract '{}' has {} unimplemented function(s) [{}] but is not declared abstract; \
73 either provide implementations or declare the contract as 'abstract contract {}'",
74 metadata.name,
75 unimplemented.len(),
76 unimplemented.join(", "),
77 metadata.name,
78 ))
79 .with_suggestion(
80 "add 'abstract' before 'contract', or provide function bodies for all declared functions"
81 ),
82 );
83 }
84}
85
86fn validate_flatten_warnings(metadata: &ContractMetadata, diagnostics: &mut Vec<Diagnostic>) {
87 for warning in &metadata.flatten_warnings {
88 diagnostics.push(
89 Diagnostic::warning(warning.clone())
90 .with_code("W200")
91 .with_suggestion(
92 "mark the base function 'virtual' and the overriding function 'override'",
93 ),
94 );
95 }
96}