pyvbaanalysis 2.0.0__tar.gz → 2.1.1__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.1}/CHANGELOG.md +93 -0
  2. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/PKG-INFO +1 -1
  3. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/docs/diagnostics-catalogue.md +3 -2
  4. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/__init__.py +1 -1
  5. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/completion/member_access.py +26 -1
  6. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/conditional/conditional_compilation.py +80 -3
  7. pyvbaanalysis-2.1.1/pyvbaanalysis/data/access_host_model.json +1 -0
  8. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/data/diagnostic_influence_audit.json +14 -0
  9. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/data/event_definitions.json +1 -1
  10. pyvbaanalysis-2.1.1/pyvbaanalysis/data/excel_host_model.json +1 -0
  11. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/data/manifest.json +12 -10
  12. pyvbaanalysis-2.1.1/pyvbaanalysis/data/powerpoint_host_model.json +1 -0
  13. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/data/rule_metadata.json +11 -0
  14. pyvbaanalysis-2.1.1/pyvbaanalysis/data/vba_runtime_tables.json +1 -0
  15. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/data/vbe_oracle_cases.json +64 -0
  16. pyvbaanalysis-2.1.1/pyvbaanalysis/data/word_host_model.json +1 -0
  17. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/context.py +4 -0
  18. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/registry.py +16 -4
  19. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/assignments.py +91 -15
  20. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/control_flow.py +54 -20
  21. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/declarations.py +28 -6
  22. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/duplicates.py +186 -56
  23. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/module_kind.py +10 -3
  24. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/walker.py +18 -1
  25. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/parser/nodes.py +6 -0
  26. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/parser/parse_module.py +25 -1
  27. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/project.py +1 -0
  28. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/symbols/project_index.py +11 -0
  29. pyvbaanalysis-2.1.1/tests/test_conditional_arms.py +212 -0
  30. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_evidence.py +2 -2
  31. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rule_metadata.py +5 -5
  32. pyvbaanalysis-2.1.1/tests/test_upstream_sync_6_1_2.py +219 -0
  33. pyvbaanalysis-2.0.0/pyvbaanalysis/data/access_host_model.json +0 -1
  34. pyvbaanalysis-2.0.0/pyvbaanalysis/data/excel_host_model.json +0 -1
  35. pyvbaanalysis-2.0.0/pyvbaanalysis/data/powerpoint_host_model.json +0 -1
  36. pyvbaanalysis-2.0.0/pyvbaanalysis/data/vba_runtime_tables.json +0 -1
  37. pyvbaanalysis-2.0.0/pyvbaanalysis/data/word_host_model.json +0 -1
  38. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/.gitattributes +0 -0
  39. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/.github/dependabot.yml +0 -0
  40. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/.github/workflows/ci.yml +0 -0
  41. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/.github/workflows/publish.yml +0 -0
  42. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/.gitignore +0 -0
  43. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/CONTRIBUTING.md +0 -0
  44. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/LICENSE +0 -0
  45. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/README.md +0 -0
  46. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/docs/api-reference.md +0 -0
  47. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/docs/usage.md +0 -0
  48. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyproject.toml +0 -0
  49. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/__main__.py +0 -0
  50. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/call/__init__.py +0 -0
  51. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/call/call_context.py +0 -0
  52. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/cli.py +0 -0
  53. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/completion/__init__.py +0 -0
  54. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/completion/cursor_context.py +0 -0
  55. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/completion/event_handlers.py +0 -0
  56. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/completion/type_completion.py +0 -0
  57. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/conditional/__init__.py +0 -0
  58. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/constants/__init__.py +0 -0
  59. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/constants/integer_constant_expression.py +0 -0
  60. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/__init__.py +0 -0
  61. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/analyze_module.py +0 -0
  62. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/argument_inference.py +0 -0
  63. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/call_extraction.py +0 -0
  64. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/callable_signatures.py +0 -0
  65. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/const_expr.py +0 -0
  66. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/dataflow.py +0 -0
  67. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/exprwalk.py +0 -0
  68. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/inline_suppression.py +0 -0
  69. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/model.py +0 -0
  70. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rule_metadata.py +0 -0
  71. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/__init__.py +0 -0
  72. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/argument_shape.py +0 -0
  73. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/argument_types.py +0 -0
  74. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/arrays.py +0 -0
  75. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/binary_operand_scalar.py +0 -0
  76. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/call_arity.py +0 -0
  77. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/expressions.py +0 -0
  78. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/late_binding.py +0 -0
  79. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/lexical.py +0 -0
  80. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/numeric_literals.py +0 -0
  81. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/object_state.py +0 -0
  82. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/parameter_defaults.py +0 -0
  83. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/runtime_values.py +0 -0
  84. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/shared.py +0 -0
  85. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/type_of_is.py +0 -0
  86. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/diagnostics/rules/undeclared.py +0 -0
  87. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/evidence.py +0 -0
  88. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/flow/__init__.py +0 -0
  89. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/flow/procedure_labels.py +0 -0
  90. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/flow/procedure_unstructured.py +0 -0
  91. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/host/__init__.py +0 -0
  92. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/host/host_model.py +0 -0
  93. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/host/host_registry.py +0 -0
  94. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/identity_cache.py +0 -0
  95. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/lexer/__init__.py +0 -0
  96. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/lexer/keyword_table.py +0 -0
  97. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/lexer/stripped_lines.py +0 -0
  98. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/lexer/token_helpers.py +0 -0
  99. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/lexer/token_kinds.py +0 -0
  100. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/lexer/tokenize.py +0 -0
  101. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/lexer/trivia.py +0 -0
  102. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/parser/__init__.py +0 -0
  103. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/parser/fixed_length_string.py +0 -0
  104. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/parser/parse_expression.py +0 -0
  105. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/parser/parser_state.py +0 -0
  106. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/parser/type_declaration_suffix.py +0 -0
  107. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/py.typed +0 -0
  108. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/reader/__init__.py +0 -0
  109. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/reader/loose_file.py +0 -0
  110. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/reader/vbe_module.py +0 -0
  111. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/reader/workbook.py +0 -0
  112. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/runtime/__init__.py +0 -0
  113. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/runtime/vba_runtime.py +0 -0
  114. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/symbols/__init__.py +0 -0
  115. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/symbols/build_module_symbols.py +0 -0
  116. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/symbols/name_resolution.py +0 -0
  117. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/symbols/symbol_model.py +0 -0
  118. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/types/__init__.py +0 -0
  119. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/types/type_inference.py +0 -0
  120. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/pyvbaanalysis/types/type_names.py +0 -0
  121. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/conftest.py +0 -0
  122. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/oracle_support.py +0 -0
  123. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_cli.py +0 -0
  124. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_conditional_compilation.py +0 -0
  125. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_dataflow.py +0 -0
  126. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_diagnostics_engine.py +0 -0
  127. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_host_model.py +0 -0
  128. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_host_seam.py +0 -0
  129. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_inline_suppression.py +0 -0
  130. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_integer_constant_expression.py +0 -0
  131. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_language_matrix.py +0 -0
  132. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_lexer.py +0 -0
  133. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_member_access_chains.py +0 -0
  134. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_parser.py +0 -0
  135. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_project.py +0 -0
  136. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_project_index.py +0 -0
  137. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_public_api.py +0 -0
  138. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_reader.py +0 -0
  139. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_real_world_false_positives.py +0 -0
  140. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_registry_parity.py +0 -0
  141. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_ambiguous_enum_member.py +0 -0
  142. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_argument_shape.py +0 -0
  143. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_argument_types.py +0 -0
  144. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_arrays.py +0 -0
  145. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_assignments.py +0 -0
  146. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_assignments_types.py +0 -0
  147. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_binary_operand_scalar.py +0 -0
  148. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_call_arity.py +0 -0
  149. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_control_flow.py +0 -0
  150. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_declarations.py +0 -0
  151. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_division_by_zero.py +0 -0
  152. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_duplicates.py +0 -0
  153. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_event_handler_module_scope.py +0 -0
  154. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_expression_calls.py +0 -0
  155. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_expressions.py +0 -0
  156. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_invalid_as_type_names.py +0 -0
  157. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_is_operator_non_object.py +0 -0
  158. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_late_binding.py +0 -0
  159. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_lexical.py +0 -0
  160. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_member_not_found.py +0 -0
  161. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_module_kind.py +0 -0
  162. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_numeric_literals.py +0 -0
  163. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_object_state.py +0 -0
  164. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_parameter_defaults.py +0 -0
  165. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_property_setter_value_parameters.py +0 -0
  166. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_runtime_values.py +0 -0
  167. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_scalar_and_foreach.py +0 -0
  168. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_type_of_is.py +0 -0
  169. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_typeof_is_always_false.py +0 -0
  170. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_rules_undeclared.py +0 -0
  171. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_runtime_tables.py +0 -0
  172. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_statement_token_derivation.py +0 -0
  173. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_stripped_lines.py +0 -0
  174. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_symbols.py +0 -0
  175. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_token_helpers.py +0 -0
  176. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_type_completion.py +0 -0
  177. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tests/test_type_names.py +0 -0
  178. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tools/extract_event_definitions.mjs +0 -0
  179. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tools/extract_host_model.mjs +0 -0
  180. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tools/extract_rule_metadata.mjs +0 -0
  181. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tools/extract_runtime_tables.mjs +0 -0
  182. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tools/generate_diagnostics_catalogue.py +0 -0
  183. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tools/generate_manifest.py +0 -0
  184. {pyvbaanalysis-2.0.0 → pyvbaanalysis-2.1.1}/tools/oracle/build_combining_mark_probe.py +0 -0
@@ -5,6 +5,99 @@ 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.1 - 2026-09-05
9
+
10
+ Follows XLIDE 6.2.0. The vendored data is byte-identical to 6.1.2, so only the
11
+ manifest's version moves; the analyzer change is the one fix below.
12
+
13
+ ### Fixed
14
+
15
+ * A module's own procedures now shadow the host's globals when used as a
16
+ receiver. A module VARIABLE named `rows` already resolved from its
17
+ declaration, but `Public Property Get rows() As Widget` fell through to
18
+ Excel's global `Rows`, so `rows.Where(p)` was measured against `Excel.Range`.
19
+ The names that collide are the ones every workbook uses: rows, columns,
20
+ cells, selection, names, sheets, application. A Function or Property Get now
21
+ yields its return type; a Sub, or a Property with only Let/Set, yields nothing
22
+ readable but still shadows the global rather than letting the host answer
23
+ (XLIDE issue #68, which this port reported upstream and which 6.2.0 fixed).
24
+
25
+ This port never emitted the false positive, because it resolved such a
26
+ receiver to nothing at all rather than to the wrong type. The fix replaces
27
+ that silence with a correct binding, so a receiver that used to go unchecked
28
+ is now checked: with project context, a genuinely absent member on one of
29
+ these names reports `member-not-found` where it previously passed. Analyzed
30
+ standalone, without project context, behaviour is unchanged.
31
+
32
+ ### Verified
33
+
34
+ * Differential against the upstream 6.2.0 analyzer: 418 of 418 oracle cases
35
+ identical in both directions, and identical on a real workbook's modules.
36
+ 16 real workbooks stay silent.
37
+
38
+ ## 2.1.0 - 2026-09-05
39
+
40
+ Sync to XLIDE 6.1.2, the analyzer's first re-pin since 3.1.4. Verified by a
41
+ differential against the upstream analyzer over the whole oracle corpus: 418 of
42
+ 418 cases identical, in both directions.
43
+
44
+ ### Added
45
+
46
+ * `ambiguousProjectProcedure`: VBA is content for two modules to export the same
47
+ public procedure name, but it refuses to compile an UNQUALIFIED call to that
48
+ name from a module declaring neither. The finding sits at the call site, not
49
+ the declarations, because a project that exports a name twice and always
50
+ qualifies its calls is legal VBA and common. Silent when the call is
51
+ qualified, when the calling module declares the name itself, when a local or
52
+ parameter shadows it, or when only one module exports it.
53
+ * `ConditionalActivityTracker.mutually_exclusive` and `in_same_branch`, the
54
+ primitive the arm-aware rules below need, plus
55
+ `ProjectIndex.implemented_interface_names()` and the
56
+ `AnalyzeModuleOptions.implemented_interfaces` option it feeds.
57
+
58
+ ### Fixed
59
+
60
+ * Rules no longer pair declarations from mutually exclusive `#If` arms. Only one
61
+ arm of a chain is ever built, so two declarations in different arms are
62
+ alternatives rather than duplicates. With a compiler constant the analyzer
63
+ cannot evaluate, the ordinary `#If VBA7 / #Else` idiom reported
64
+ `duplicate-procedure` and `duplicate-module-variable` on legal code. The same
65
+ reasoning now covers duplicate declarations and labels, undefined labels,
66
+ `For`/`Next` pairing, `Else` branch order, `Option` placement, and `Implements`
67
+ placement (XLIDE issue #58).
68
+ * A `#Const` directive may precede `Option Explicit`. A conditional-compilation
69
+ directive is not a declaration, and the live VBE compiles it there
70
+ (oracle case `const_directive_before_option_explicit_compile`).
71
+ * Three gaps in return-assignment detection, each of which the widened rule below
72
+ would otherwise have turned into a false positive:
73
+ assigning a field of the returned value (`MsToSystemTime.wYear = ...`) is a
74
+ return assignment; so is an assignment inside a single-line `If`, whose
75
+ branches the statement walk never entered; and a name that SPELLS a keyword is
76
+ still an assignment target, so `Function Read()` assigning `Read = True` was
77
+ read as never assigning its return. Measured on one real workbook these three
78
+ accounted for nine false findings.
79
+
80
+ ### Changed
81
+
82
+ * `missingReturnAssignment` now covers every Function and Property Get, not only
83
+ untyped ones, so a typed Function that never assigns its return reports. An
84
+ empty member of a module some other module declares with `Implements` stays
85
+ silent: that is a contract for an implementer to fill in, not unfinished code.
86
+ A body whose work is to raise stays silent too. **This reports on code that was
87
+ previously quiet**; the rule is warning severity and can be turned off through
88
+ `severity_overrides`.
89
+ * The vendored host models grew with upstream's move to the whole documented
90
+ object model: Excel 229 to 651 types, Word 364 to 627, PowerPoint 201 to 464,
91
+ Access 188 to 451. The wheel grows from 0.94 MB to 1.84 MB; the models still
92
+ load lazily, so import cost is unchanged.
93
+ * Data re-pinned to XLIDE 6.1.2: 418 oracle cases (was 415), 122 audited codes
94
+ (was 121), 119 rules (was 118).
95
+
96
+ ### Known limits
97
+
98
+ * Upstream's form-control member work is not ported, and the oracle corpus has no
99
+ UserForm designer cases, so that area is untested here rather than verified.
100
+
8
101
  ## 2.0.0 - 2026-08-19
9
102
 
10
103
  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.1
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.1"
45
45
 
46
46
  __all__ = [
47
47
  "AnalyzeModuleOptions",
@@ -42,6 +42,7 @@ from ..parser.nodes import (
42
42
  LeafStatementNode,
43
43
  ModuleNode,
44
44
  ProcedureNode,
45
+ ProcKind,
45
46
  VariableGroupNode,
46
47
  is_leaf_statement,
47
48
  )
@@ -1088,7 +1089,31 @@ def _find_declared_binding(
1088
1089
  hit = _match_group(mem, lower)
1089
1090
  if hit is not None:
1090
1091
  return hit
1091
- return None
1092
+ return _module_procedure_binding(module, lower)
1093
+
1094
+
1095
+ def _module_procedure_binding(module: ModuleNode, lower: str) -> _DeclaredBinding | None:
1096
+ """A module-level procedure of this name, as a receiver.
1097
+
1098
+ The module's own members shadow the host's globals, and this is where the two
1099
+ used to disagree: a module VARIABLE named `rows` resolved from the declaration
1100
+ above, while `Public Property Get rows() As Widget` fell through to Excel's
1101
+ global `Rows`, so `rows.Where(p)` was measured against `Excel.Range`
1102
+ (XLIDE issue #68). The names that collide are the ones every workbook uses:
1103
+ rows, columns, cells, selection, names, sheets, application.
1104
+
1105
+ A Function or Property Get yields its return type. A Sub, or a Property with
1106
+ only Let/Set, yields nothing readable, but it still shadows the global, so it
1107
+ binds with no type rather than letting the host answer for it.
1108
+ """
1109
+ shadow: _DeclaredBinding | None = None
1110
+ for mem in module.members:
1111
+ if not isinstance(mem, ProcedureNode) or mem.name.lower() != lower:
1112
+ continue
1113
+ if mem.proc_kind in (ProcKind.FUNCTION, ProcKind.PROPERTY_GET):
1114
+ return _DeclaredBinding(as_type=mem.return_type or None)
1115
+ shadow = _DeclaredBinding(as_type=None)
1116
+ return shadow
1092
1117
 
1093
1118
 
1094
1119
  def _find_in_body(body: Sequence[BodyNode], lower: str) -> _DeclaredBinding | None:
@@ -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