pyvbaanalysis 2.0.0__tar.gz → 2.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/CHANGELOG.md +63 -0
  2. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/PKG-INFO +1 -1
  3. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/docs/diagnostics-catalogue.md +3 -2
  4. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/__init__.py +1 -1
  5. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/conditional/conditional_compilation.py +80 -3
  6. pyvbaanalysis-2.1.0/pyvbaanalysis/data/access_host_model.json +1 -0
  7. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/data/diagnostic_influence_audit.json +14 -0
  8. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/data/event_definitions.json +1 -1
  9. pyvbaanalysis-2.1.0/pyvbaanalysis/data/excel_host_model.json +1 -0
  10. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/data/manifest.json +12 -10
  11. pyvbaanalysis-2.1.0/pyvbaanalysis/data/powerpoint_host_model.json +1 -0
  12. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/data/rule_metadata.json +11 -0
  13. pyvbaanalysis-2.1.0/pyvbaanalysis/data/vba_runtime_tables.json +1 -0
  14. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/data/vbe_oracle_cases.json +64 -0
  15. pyvbaanalysis-2.1.0/pyvbaanalysis/data/word_host_model.json +1 -0
  16. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/context.py +4 -0
  17. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/registry.py +16 -4
  18. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/assignments.py +91 -15
  19. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/control_flow.py +54 -20
  20. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/declarations.py +28 -6
  21. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/duplicates.py +186 -56
  22. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/module_kind.py +10 -3
  23. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/walker.py +18 -1
  24. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/parser/nodes.py +6 -0
  25. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/parser/parse_module.py +25 -1
  26. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/project.py +1 -0
  27. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/symbols/project_index.py +11 -0
  28. pyvbaanalysis-2.1.0/tests/test_conditional_arms.py +212 -0
  29. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_evidence.py +2 -2
  30. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rule_metadata.py +5 -5
  31. pyvbaanalysis-2.1.0/tests/test_upstream_sync_6_1_2.py +169 -0
  32. pyvbaanalysis-2.0.0/pyvbaanalysis/data/access_host_model.json +0 -1
  33. pyvbaanalysis-2.0.0/pyvbaanalysis/data/excel_host_model.json +0 -1
  34. pyvbaanalysis-2.0.0/pyvbaanalysis/data/powerpoint_host_model.json +0 -1
  35. pyvbaanalysis-2.0.0/pyvbaanalysis/data/vba_runtime_tables.json +0 -1
  36. pyvbaanalysis-2.0.0/pyvbaanalysis/data/word_host_model.json +0 -1
  37. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/.gitattributes +0 -0
  38. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/.github/dependabot.yml +0 -0
  39. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/.github/workflows/ci.yml +0 -0
  40. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/.github/workflows/publish.yml +0 -0
  41. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/.gitignore +0 -0
  42. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/CONTRIBUTING.md +0 -0
  43. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/LICENSE +0 -0
  44. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/README.md +0 -0
  45. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/docs/api-reference.md +0 -0
  46. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/docs/usage.md +0 -0
  47. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyproject.toml +0 -0
  48. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/__main__.py +0 -0
  49. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/call/__init__.py +0 -0
  50. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/call/call_context.py +0 -0
  51. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/cli.py +0 -0
  52. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/completion/__init__.py +0 -0
  53. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/completion/cursor_context.py +0 -0
  54. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/completion/event_handlers.py +0 -0
  55. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/completion/member_access.py +0 -0
  56. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/completion/type_completion.py +0 -0
  57. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/conditional/__init__.py +0 -0
  58. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/constants/__init__.py +0 -0
  59. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/constants/integer_constant_expression.py +0 -0
  60. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/__init__.py +0 -0
  61. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/analyze_module.py +0 -0
  62. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/argument_inference.py +0 -0
  63. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/call_extraction.py +0 -0
  64. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/callable_signatures.py +0 -0
  65. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/const_expr.py +0 -0
  66. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/dataflow.py +0 -0
  67. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/exprwalk.py +0 -0
  68. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/inline_suppression.py +0 -0
  69. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/model.py +0 -0
  70. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rule_metadata.py +0 -0
  71. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/__init__.py +0 -0
  72. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/argument_shape.py +0 -0
  73. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/argument_types.py +0 -0
  74. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/arrays.py +0 -0
  75. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/binary_operand_scalar.py +0 -0
  76. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/call_arity.py +0 -0
  77. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/expressions.py +0 -0
  78. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/late_binding.py +0 -0
  79. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/lexical.py +0 -0
  80. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/numeric_literals.py +0 -0
  81. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/object_state.py +0 -0
  82. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/parameter_defaults.py +0 -0
  83. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/runtime_values.py +0 -0
  84. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/shared.py +0 -0
  85. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/type_of_is.py +0 -0
  86. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/diagnostics/rules/undeclared.py +0 -0
  87. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/evidence.py +0 -0
  88. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/flow/__init__.py +0 -0
  89. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/flow/procedure_labels.py +0 -0
  90. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/flow/procedure_unstructured.py +0 -0
  91. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/host/__init__.py +0 -0
  92. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/host/host_model.py +0 -0
  93. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/host/host_registry.py +0 -0
  94. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/identity_cache.py +0 -0
  95. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/lexer/__init__.py +0 -0
  96. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/lexer/keyword_table.py +0 -0
  97. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/lexer/stripped_lines.py +0 -0
  98. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/lexer/token_helpers.py +0 -0
  99. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/lexer/token_kinds.py +0 -0
  100. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/lexer/tokenize.py +0 -0
  101. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/lexer/trivia.py +0 -0
  102. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/parser/__init__.py +0 -0
  103. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/parser/fixed_length_string.py +0 -0
  104. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/parser/parse_expression.py +0 -0
  105. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/parser/parser_state.py +0 -0
  106. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/parser/type_declaration_suffix.py +0 -0
  107. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/py.typed +0 -0
  108. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/reader/__init__.py +0 -0
  109. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/reader/loose_file.py +0 -0
  110. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/reader/vbe_module.py +0 -0
  111. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/reader/workbook.py +0 -0
  112. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/runtime/__init__.py +0 -0
  113. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/runtime/vba_runtime.py +0 -0
  114. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/symbols/__init__.py +0 -0
  115. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/symbols/build_module_symbols.py +0 -0
  116. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/symbols/name_resolution.py +0 -0
  117. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/symbols/symbol_model.py +0 -0
  118. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/types/__init__.py +0 -0
  119. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/types/type_inference.py +0 -0
  120. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/pyvbaanalysis/types/type_names.py +0 -0
  121. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/conftest.py +0 -0
  122. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/oracle_support.py +0 -0
  123. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_cli.py +0 -0
  124. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_conditional_compilation.py +0 -0
  125. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_dataflow.py +0 -0
  126. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_diagnostics_engine.py +0 -0
  127. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_host_model.py +0 -0
  128. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_host_seam.py +0 -0
  129. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_inline_suppression.py +0 -0
  130. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_integer_constant_expression.py +0 -0
  131. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_language_matrix.py +0 -0
  132. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_lexer.py +0 -0
  133. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_member_access_chains.py +0 -0
  134. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_parser.py +0 -0
  135. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_project.py +0 -0
  136. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_project_index.py +0 -0
  137. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_public_api.py +0 -0
  138. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_reader.py +0 -0
  139. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_real_world_false_positives.py +0 -0
  140. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_registry_parity.py +0 -0
  141. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_ambiguous_enum_member.py +0 -0
  142. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_argument_shape.py +0 -0
  143. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_argument_types.py +0 -0
  144. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_arrays.py +0 -0
  145. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_assignments.py +0 -0
  146. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_assignments_types.py +0 -0
  147. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_binary_operand_scalar.py +0 -0
  148. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_call_arity.py +0 -0
  149. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_control_flow.py +0 -0
  150. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_declarations.py +0 -0
  151. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_division_by_zero.py +0 -0
  152. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_duplicates.py +0 -0
  153. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_event_handler_module_scope.py +0 -0
  154. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_expression_calls.py +0 -0
  155. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_expressions.py +0 -0
  156. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_invalid_as_type_names.py +0 -0
  157. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_is_operator_non_object.py +0 -0
  158. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_late_binding.py +0 -0
  159. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_lexical.py +0 -0
  160. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_member_not_found.py +0 -0
  161. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_module_kind.py +0 -0
  162. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_numeric_literals.py +0 -0
  163. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_object_state.py +0 -0
  164. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_parameter_defaults.py +0 -0
  165. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_property_setter_value_parameters.py +0 -0
  166. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_runtime_values.py +0 -0
  167. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_scalar_and_foreach.py +0 -0
  168. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_type_of_is.py +0 -0
  169. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_typeof_is_always_false.py +0 -0
  170. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_rules_undeclared.py +0 -0
  171. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_runtime_tables.py +0 -0
  172. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_statement_token_derivation.py +0 -0
  173. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_stripped_lines.py +0 -0
  174. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_symbols.py +0 -0
  175. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_token_helpers.py +0 -0
  176. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_type_completion.py +0 -0
  177. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tests/test_type_names.py +0 -0
  178. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tools/extract_event_definitions.mjs +0 -0
  179. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tools/extract_host_model.mjs +0 -0
  180. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tools/extract_rule_metadata.mjs +0 -0
  181. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tools/extract_runtime_tables.mjs +0 -0
  182. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tools/generate_diagnostics_catalogue.py +0 -0
  183. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tools/generate_manifest.py +0 -0
  184. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.0}/tools/oracle/build_combining_mark_probe.py +0 -0
@@ -5,6 +5,69 @@ All notable changes to pyVBAanalysis are recorded here. The format follows
5
5
  follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html): a minor version
6
6
  per milestone.
7
7
 
8
+ ## 2.1.0 - 2026-09-05
9
+
10
+ Sync to XLIDE 6.1.2, the analyzer's first re-pin since 3.1.4. Verified by a
11
+ differential against the upstream analyzer over the whole oracle corpus: 418 of
12
+ 418 cases identical, in both directions.
13
+
14
+ ### Added
15
+
16
+ * `ambiguousProjectProcedure`: VBA is content for two modules to export the same
17
+ public procedure name, but it refuses to compile an UNQUALIFIED call to that
18
+ name from a module declaring neither. The finding sits at the call site, not
19
+ the declarations, because a project that exports a name twice and always
20
+ qualifies its calls is legal VBA and common. Silent when the call is
21
+ qualified, when the calling module declares the name itself, when a local or
22
+ parameter shadows it, or when only one module exports it.
23
+ * `ConditionalActivityTracker.mutually_exclusive` and `in_same_branch`, the
24
+ primitive the arm-aware rules below need, plus
25
+ `ProjectIndex.implemented_interface_names()` and the
26
+ `AnalyzeModuleOptions.implemented_interfaces` option it feeds.
27
+
28
+ ### Fixed
29
+
30
+ * Rules no longer pair declarations from mutually exclusive `#If` arms. Only one
31
+ arm of a chain is ever built, so two declarations in different arms are
32
+ alternatives rather than duplicates. With a compiler constant the analyzer
33
+ cannot evaluate, the ordinary `#If VBA7 / #Else` idiom reported
34
+ `duplicate-procedure` and `duplicate-module-variable` on legal code. The same
35
+ reasoning now covers duplicate declarations and labels, undefined labels,
36
+ `For`/`Next` pairing, `Else` branch order, `Option` placement, and `Implements`
37
+ placement (XLIDE issue #58).
38
+ * A `#Const` directive may precede `Option Explicit`. A conditional-compilation
39
+ directive is not a declaration, and the live VBE compiles it there
40
+ (oracle case `const_directive_before_option_explicit_compile`).
41
+ * Three gaps in return-assignment detection, each of which the widened rule below
42
+ would otherwise have turned into a false positive:
43
+ assigning a field of the returned value (`MsToSystemTime.wYear = ...`) is a
44
+ return assignment; so is an assignment inside a single-line `If`, whose
45
+ branches the statement walk never entered; and a name that SPELLS a keyword is
46
+ still an assignment target, so `Function Read()` assigning `Read = True` was
47
+ read as never assigning its return. Measured on one real workbook these three
48
+ accounted for nine false findings.
49
+
50
+ ### Changed
51
+
52
+ * `missingReturnAssignment` now covers every Function and Property Get, not only
53
+ untyped ones, so a typed Function that never assigns its return reports. An
54
+ empty member of a module some other module declares with `Implements` stays
55
+ silent: that is a contract for an implementer to fill in, not unfinished code.
56
+ A body whose work is to raise stays silent too. **This reports on code that was
57
+ previously quiet**; the rule is warning severity and can be turned off through
58
+ `severity_overrides`.
59
+ * The vendored host models grew with upstream's move to the whole documented
60
+ object model: Excel 229 to 651 types, Word 364 to 627, PowerPoint 201 to 464,
61
+ Access 188 to 451. The wheel grows from 0.94 MB to 1.84 MB; the models still
62
+ load lazily, so import cost is unchanged.
63
+ * Data re-pinned to XLIDE 6.1.2: 418 oracle cases (was 415), 122 audited codes
64
+ (was 121), 119 rules (was 118).
65
+
66
+ ### Known limits
67
+
68
+ * Upstream's form-control member work is not ported, and the oracle corpus has no
69
+ UserForm designer cases, so that area is untested here rather than verified.
70
+
8
71
  ## 2.0.0 - 2026-08-19
9
72
 
10
73
  Multi-host analysis: VBA is now measured against the object model of the Office
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pyvbaanalysis
3
- Version: 2.0.0
3
+ Version: 2.1.0
4
4
  Summary: Pure-Python static analysis for Excel VBA
5
5
  Project-URL: Homepage, https://github.com/WilliamSmithEdward/pyVBAanalysis
6
6
  Project-URL: Repository, https://github.com/WilliamSmithEdward/pyVBAanalysis
@@ -1,6 +1,6 @@
1
1
  # Diagnostic catalogue
2
2
 
3
- The diagnostic codes pyVBAanalysis can emit, generated from the rule metadata (`tools/generate_diagnostics_catalogue.py`). This table lists the 118 rule-metadata codes across 6 categories. A further 3 structural block-balance codes (`mismatched-end-keyword`, `missing-block-closer`, `unmatched-block-closer`) are emitted by the parser pass and are not in the metadata table, for a full set of 121 codes.
3
+ The diagnostic codes pyVBAanalysis can emit, generated from the rule metadata (`tools/generate_diagnostics_catalogue.py`). This table lists the 119 rule-metadata codes across 6 categories. A further 3 structural block-balance codes (`mismatched-end-keyword`, `missing-block-closer`, `unmatched-block-closer`) are emitted by the parser pass and are not in the metadata table, for a full set of 122 codes.
4
4
 
5
5
  Each code is reported only when it is provably correct; anything unknown or ambiguous stays quiet (the no-false-positive discipline). The **kind** column says what a code means: a *compile error* is rejected by the VBE compiler, a *runtime error* is a deterministic Run-time error, a *runtime risk* is a likely fault, and *style* is advisory.
6
6
 
@@ -69,11 +69,12 @@ Override a code's severity with `AnalyzeModuleOptions.severity_overrides` (or th
69
69
  | `undeclared-variable` | Variable not defined | error | compile error | MS-VBAL 5.2.4.1.1 |
70
70
  | `unknown-call` | Sub or Function not defined | error | compile error | MS-VBAL 5.4.2.1 |
71
71
 
72
- ## Semantic (50)
72
+ ## Semantic (51)
73
73
 
74
74
  | Code | Title | Default | Kind | Spec reference |
75
75
  | --- | --- | --- | --- | --- |
76
76
  | `ambiguous-enum-member` | Ambiguous Enum member reference | error | compile error | VBE compiler: Ambiguous name detected |
77
+ | `ambiguous-project-procedure` | Ambiguous unqualified call to a name two modules export | error | compile error | VBE compiler: Ambiguous name detected |
77
78
  | `argument-count` | Wrong number of arguments | error | compile error | MS-VBAL 5.4.2.1 |
78
79
  | `argument-object-type-mismatch` | Object argument type mismatch | error | compile error | MS-VBAL 5.3.1 |
79
80
  | `argument-shape-mismatch` | Argument shape (array/Type vs scalar) mismatch | error | compile error | MS-VBAL 5.3.1 (argument passing) / VBE compiler: ByRef argument type mismatch; array or user-defined type expected |
@@ -41,7 +41,7 @@ from .reader import (
41
41
  )
42
42
  from .symbols import ModuleInput, ModuleSymbolKind, ProjectIndex, ProjectIndexOptions
43
43
 
44
- __version__ = "2.0.0"
44
+ __version__ = "2.1.0"
45
45
 
46
46
  __all__ = [
47
47
  "AnalyzeModuleOptions",
@@ -114,10 +114,42 @@ class _ConditionalFrame:
114
114
  seen_unknown: bool
115
115
 
116
116
 
117
+ @dataclass(frozen=True, slots=True)
118
+ class _ConditionalArm:
119
+ """One arm of one `#If` chain, as a persistent stack.
120
+
121
+ ``parent`` is the enclosing chain's arm. Immutable, so an event can keep the
122
+ arm that was in effect when it was recorded without copying the stack, and
123
+ one arm is one object, which makes identity the comparison for
124
+ ``in_same_branch``.
125
+ """
126
+
127
+ chain: int
128
+ #: 0 for the `#If`, then one per `#ElseIf` / `#Else`.
129
+ index: int
130
+ parent: "_ConditionalArm | None"
131
+
132
+
133
+ def _arms_diverge(a: _ConditionalArm | None, b: _ConditionalArm | None) -> bool:
134
+ """Whether two arm stacks disagree about which arm of a shared chain they are
135
+ in. The branches then exclude each other whatever the constants are worth.
136
+ Stacks are as deep as the source nests directives, so the walk is short."""
137
+ outer = a
138
+ while outer is not None:
139
+ inner = b
140
+ while inner is not None:
141
+ if outer.chain == inner.chain:
142
+ return outer.index != inner.index
143
+ inner = inner.parent
144
+ outer = outer.parent
145
+ return False
146
+
147
+
117
148
  @dataclass(slots=True)
118
149
  class _ConditionalActivityEvent:
119
150
  start: int
120
151
  activity: ConditionalActivity
152
+ branch: _ConditionalArm | None = None
121
153
 
122
154
 
123
155
  class ConditionalActivityTracker:
@@ -128,7 +160,7 @@ class ConditionalActivityTracker:
128
160
  def __init__(self, events: list[_ConditionalActivityEvent]) -> None:
129
161
  self._events = events
130
162
 
131
- def activity_for_span(self, span: Span) -> ConditionalActivity:
163
+ def _event_for_span(self, span: Span) -> _ConditionalActivityEvent | None:
132
164
  # Directives starting at or after the queried offset are not applied.
133
165
  lo = -1
134
166
  hi = len(self._events) - 1
@@ -138,11 +170,41 @@ class ConditionalActivityTracker:
138
170
  lo = mid
139
171
  else:
140
172
  hi = mid - 1
141
- return self._events[lo].activity if lo >= 0 else ConditionalActivity.ACTIVE
173
+ return self._events[lo] if lo >= 0 else None
174
+
175
+ def activity_for_span(self, span: Span) -> ConditionalActivity:
176
+ event = self._event_for_span(span)
177
+ return event.activity if event is not None else ConditionalActivity.ACTIVE
142
178
 
143
179
  def is_inactive(self, span: Span) -> bool:
144
180
  return self.activity_for_span(span) is ConditionalActivity.INACTIVE
145
181
 
182
+ def mutually_exclusive(self, a: Span, b: Span) -> bool:
183
+ """Whether the two spans sit in different arms of one `#If` chain, and so
184
+ are never compiled together however the constants evaluate."""
185
+ left = self._event_for_span(a)
186
+ right = self._event_for_span(b)
187
+ return _arms_diverge(
188
+ left.branch if left is not None else None,
189
+ right.branch if right is not None else None,
190
+ )
191
+
192
+ def in_same_branch(self, a: Span, b: Span) -> bool:
193
+ """Whether the two spans sit under exactly the same arms, so every build
194
+ either compiles both or neither.
195
+
196
+ Stricter than "not mutually exclusive": spans in two SEPARATE chains are
197
+ neither exclusive nor in the same branch, because a build may take one and
198
+ not the other. Rules that pair two pieces of one construct need this, since
199
+ a pairing made across different chains is a guess about a build that may
200
+ never exist.
201
+ """
202
+ left = self._event_for_span(a)
203
+ right = self._event_for_span(b)
204
+ return (left.branch if left is not None else None) is (
205
+ right.branch if right is not None else None
206
+ )
207
+
146
208
 
147
209
  def create_conditional_activity_tracker(
148
210
  module: ModuleNode, env: ConditionalCompilationEnvironment | None = None
@@ -162,10 +224,25 @@ def _collect_conditional_activity_events(
162
224
  project_constants = _lowercased(effective_env.project_constants)
163
225
  stack: list[_ConditionalFrame] = []
164
226
  current = ConditionalActivity.ACTIVE
227
+ branch: _ConditionalArm | None = None
228
+ chains = 0
165
229
  events: list[_ConditionalActivityEvent] = []
166
230
  for occ in directives:
167
231
  current = _apply_conditional_directive(occ.directive, effective_env, project_constants, stack, current)
168
- events.append(_ConditionalActivityEvent(start=occ.directive.span.start, activity=current))
232
+ kind = occ.directive.directive_kind
233
+ if kind is ConditionalDirectiveKind.IF:
234
+ branch = _ConditionalArm(chain=chains, index=0, parent=branch)
235
+ chains += 1
236
+ elif kind in (ConditionalDirectiveKind.ELSE_IF, ConditionalDirectiveKind.ELSE):
237
+ # An `#ElseIf` with no open `#If` is a parse-level error; leave the
238
+ # stack alone rather than inventing an arm for it.
239
+ if branch is not None:
240
+ branch = _ConditionalArm(chain=branch.chain, index=branch.index + 1, parent=branch.parent)
241
+ elif kind is ConditionalDirectiveKind.END_IF:
242
+ branch = branch.parent if branch is not None else None
243
+ events.append(
244
+ _ConditionalActivityEvent(start=occ.directive.span.start, activity=current, branch=branch)
245
+ )
169
246
  return events
170
247
 
171
248