pyvbaanalysis 2.2.0__tar.gz → 2.2.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 (205) hide show
  1. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/CHANGELOG.md +68 -0
  2. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/PKG-INFO +1 -1
  3. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/docs/api-reference.md +3 -0
  4. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/docs/usage.md +13 -1
  5. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/__init__.py +1 -1
  6. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/call/call_context.py +4 -1
  7. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/cli.py +36 -22
  8. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/conditional/conditional_compilation.py +8 -7
  9. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/excel_host_model.json +1 -1
  10. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/manifest.json +2 -2
  11. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/vba_runtime_tables.json +1 -1
  12. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/dataflow.py +48 -5
  13. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/dead_code.py +6 -0
  14. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/expressions.py +11 -6
  15. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/object_state.py +14 -3
  16. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/type_of_is.py +13 -0
  17. pyvbaanalysis-2.2.1/pyvbaanalysis/lexer/contextual_keywords.py +179 -0
  18. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/keyword_table.py +6 -2
  19. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/stripped_lines.py +11 -8
  20. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/token_helpers.py +33 -0
  21. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/token_kinds.py +9 -1
  22. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/tokenize.py +73 -16
  23. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/trivia.py +15 -9
  24. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/nodes.py +8 -0
  25. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/parse_expression.py +15 -8
  26. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/parse_module.py +12 -2
  27. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/parser_state.py +35 -7
  28. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/reader/vbe_module.py +19 -5
  29. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_cli.py +60 -0
  30. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_reader.py +20 -0
  31. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_assignments_types.py +44 -0
  32. pyvbaanalysis-2.2.1/tests/test_upstream_sync_10_7_1.py +351 -0
  33. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/.gitattributes +0 -0
  34. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/.github/dependabot.yml +0 -0
  35. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/.github/workflows/ci.yml +0 -0
  36. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/.github/workflows/publish.yml +0 -0
  37. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/.gitignore +0 -0
  38. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/CONTRIBUTING.md +0 -0
  39. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/LICENSE +0 -0
  40. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/README.md +0 -0
  41. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/docs/diagnostics-catalogue.md +0 -0
  42. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyproject.toml +0 -0
  43. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/__main__.py +0 -0
  44. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/call/__init__.py +0 -0
  45. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/completion/__init__.py +0 -0
  46. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/completion/cursor_context.py +0 -0
  47. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/completion/event_handlers.py +0 -0
  48. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/completion/member_access.py +0 -0
  49. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/completion/type_completion.py +0 -0
  50. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/conditional/__init__.py +0 -0
  51. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/constants/__init__.py +0 -0
  52. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/constants/integer_constant_expression.py +0 -0
  53. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/access_host_model.json +0 -0
  54. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/diagnostic_influence_audit.json +0 -0
  55. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/event_definitions.json +0 -0
  56. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/excel_closed_types.json +0 -0
  57. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/msforms_members.json +0 -0
  58. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/powerpoint_host_model.json +0 -0
  59. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/rule_metadata.json +0 -0
  60. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/vb6_host_model.json +0 -0
  61. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/vbe_oracle_cases.json +0 -0
  62. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/word_host_model.json +0 -0
  63. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/__init__.py +0 -0
  64. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/analyze_module.py +0 -0
  65. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/argument_inference.py +0 -0
  66. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/call_extraction.py +0 -0
  67. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/callable_signatures.py +0 -0
  68. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/const_expr.py +0 -0
  69. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/context.py +0 -0
  70. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/exprwalk.py +0 -0
  71. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/inline_suppression.py +0 -0
  72. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/model.py +0 -0
  73. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/registry.py +0 -0
  74. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rule_metadata.py +0 -0
  75. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/__init__.py +0 -0
  76. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/argument_shape.py +0 -0
  77. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/argument_types.py +0 -0
  78. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/arrays.py +0 -0
  79. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/assignments.py +0 -0
  80. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/binary_operand_scalar.py +0 -0
  81. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/call_arity.py +0 -0
  82. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/control_flow.py +0 -0
  83. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/declarations.py +0 -0
  84. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/doc_comments.py +0 -0
  85. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/duplicates.py +0 -0
  86. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/late_binding.py +0 -0
  87. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/lexical.py +0 -0
  88. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/missing_reference.py +0 -0
  89. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/module_kind.py +0 -0
  90. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/numeric_literals.py +0 -0
  91. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/parameter_defaults.py +0 -0
  92. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/runtime_values.py +0 -0
  93. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/shared.py +0 -0
  94. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/undeclared.py +0 -0
  95. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/walker.py +0 -0
  96. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/docs/__init__.py +0 -0
  97. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/docs/doc_comment.py +0 -0
  98. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/evidence.py +0 -0
  99. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/flow/__init__.py +0 -0
  100. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/flow/procedure_labels.py +0 -0
  101. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/flow/procedure_unstructured.py +0 -0
  102. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/host/__init__.py +0 -0
  103. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/host/host_libraries.py +0 -0
  104. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/host/host_model.py +0 -0
  105. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/host/host_registry.py +0 -0
  106. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/host/msforms.py +0 -0
  107. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/host/type_extensibility.py +0 -0
  108. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/identity_cache.py +0 -0
  109. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/__init__.py +0 -0
  110. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/__init__.py +0 -0
  111. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/fixed_length_string.py +0 -0
  112. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/type_declaration_suffix.py +0 -0
  113. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/project.py +0 -0
  114. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/py.typed +0 -0
  115. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/reader/__init__.py +0 -0
  116. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/reader/loose_file.py +0 -0
  117. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/reader/workbook.py +0 -0
  118. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/references/__init__.py +0 -0
  119. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/references/reference_kinds.py +0 -0
  120. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/runtime/__init__.py +0 -0
  121. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/runtime/vba_runtime.py +0 -0
  122. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/__init__.py +0 -0
  123. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/build_module_symbols.py +0 -0
  124. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/name_resolution.py +0 -0
  125. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/project_index.py +0 -0
  126. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/symbol_model.py +0 -0
  127. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/user_form_controls.py +0 -0
  128. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/types/__init__.py +0 -0
  129. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/types/type_inference.py +0 -0
  130. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/pyvbaanalysis/types/type_names.py +0 -0
  131. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/conftest.py +0 -0
  132. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/oracle_support.py +0 -0
  133. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_conditional_arms.py +0 -0
  134. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_conditional_compilation.py +0 -0
  135. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_dataflow.py +0 -0
  136. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_diagnostics_engine.py +0 -0
  137. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_evidence.py +0 -0
  138. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_host_libraries.py +0 -0
  139. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_host_model.py +0 -0
  140. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_host_seam.py +0 -0
  141. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_inline_suppression.py +0 -0
  142. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_integer_constant_expression.py +0 -0
  143. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_language_matrix.py +0 -0
  144. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_lexer.py +0 -0
  145. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_member_access_chains.py +0 -0
  146. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_parser.py +0 -0
  147. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_project.py +0 -0
  148. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_project_index.py +0 -0
  149. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_public_api.py +0 -0
  150. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_real_world_false_positives.py +0 -0
  151. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_reference_kinds.py +0 -0
  152. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_registry_parity.py +0 -0
  153. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rule_metadata.py +0 -0
  154. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_ambiguous_enum_member.py +0 -0
  155. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_argument_shape.py +0 -0
  156. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_argument_types.py +0 -0
  157. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_arrays.py +0 -0
  158. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_assignments.py +0 -0
  159. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_binary_operand_scalar.py +0 -0
  160. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_call_arity.py +0 -0
  161. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_control_flow.py +0 -0
  162. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_dead_code.py +0 -0
  163. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_declarations.py +0 -0
  164. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_division_by_zero.py +0 -0
  165. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_doc_comments.py +0 -0
  166. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_duplicates.py +0 -0
  167. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_event_handler_module_scope.py +0 -0
  168. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_expression_calls.py +0 -0
  169. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_expressions.py +0 -0
  170. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_invalid_as_type_names.py +0 -0
  171. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_is_operator_non_object.py +0 -0
  172. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_late_binding.py +0 -0
  173. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_lexical.py +0 -0
  174. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_member_not_found.py +0 -0
  175. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_missing_reference.py +0 -0
  176. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_module_kind.py +0 -0
  177. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_numeric_literals.py +0 -0
  178. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_object_state.py +0 -0
  179. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_parameter_defaults.py +0 -0
  180. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_property_setter_value_parameters.py +0 -0
  181. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_runtime_values.py +0 -0
  182. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_scalar_and_foreach.py +0 -0
  183. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_type_of_is.py +0 -0
  184. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_typeof_is_always_false.py +0 -0
  185. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_rules_undeclared.py +0 -0
  186. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_runtime_tables.py +0 -0
  187. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_statement_token_derivation.py +0 -0
  188. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_stripped_lines.py +0 -0
  189. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_symbols.py +0 -0
  190. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_token_helpers.py +0 -0
  191. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_type_completion.py +0 -0
  192. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_type_names.py +0 -0
  193. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_upstream_sync_10_5_0.py +0 -0
  194. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_upstream_sync_10_6_0.py +0 -0
  195. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tests/test_upstream_sync_6_1_2.py +0 -0
  196. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tools/extract_event_definitions.mjs +0 -0
  197. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tools/extract_host_model.mjs +0 -0
  198. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tools/extract_rule_metadata.mjs +0 -0
  199. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tools/extract_runtime_tables.mjs +0 -0
  200. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tools/generate_diagnostics_catalogue.py +0 -0
  201. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tools/generate_manifest.py +0 -0
  202. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tools/oracle/build_combining_mark_probe.py +0 -0
  203. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tools/pin_analyzer.py +0 -0
  204. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tools/vendor_data.py +0 -0
  205. {pyvbaanalysis-2.2.0 → pyvbaanalysis-2.2.1}/tools/xlide_source.mjs +0 -0
@@ -5,6 +5,74 @@ 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.2.1 - 2026-09-23
9
+
10
+ Sync to XLIDE 10.7.1 (commit 6ead73d), from 10.6.0. Upstream fixed how its
11
+ lexer and parser read a handful of lines the VBE compiles (XLIDE issues #82 to
12
+ #90), and the port takes each fix. XLIDE 10.7.0 changed nothing the port reads.
13
+
14
+ ### Added
15
+
16
+ * `LoadedModule.designer_block`: the export header a reader stripped ahead of
17
+ `source`, empty when there was none. `designer_block + source` is the module
18
+ text as read, so a span in the analyzed body can be placed in the file.
19
+
20
+ ### Changed
21
+
22
+ * A contextual keyword is a `KEYWORD` token only inside the statement that
23
+ makes it one: `Text` after `Option Compare`, `Step` in a `For` header,
24
+ `Output` in an `Open` statement. Elsewhere, as in `Dim text As String`, it is
25
+ an `IDENTIFIER` (XLIDE issue #86). `PtrSafe` joins these words, as it did
26
+ upstream with issue #41.
27
+ * A comment ending in ` _` runs on through the next line, so its token can span
28
+ physical lines (#82). A line continuation may have whitespace after its `_`
29
+ (#83).
30
+ * `1.` lexes as a float and `&17` as an octal literal. `=>`, `=<` and `><` are
31
+ one operator token, whose `canonical_text` gives the standard spelling (#87).
32
+
33
+ ### Fixed
34
+
35
+ False positives 2.2.0 reported on code that compiles, and two errors it missed:
36
+
37
+ * `unreachable-code` on the line after
38
+ `If conn Is Nothing Then ACCT = CVErr(xlErrNA): Exit Function`. Every
39
+ statement a one-line `If` runs after a colon belongs to the If (MS-VBAL
40
+ 5.4.2.9). After a `Set x = Nothing` or an `Erase` there, the next line no
41
+ longer reports an unset object or an unallocated array. A `Set` inside a
42
+ one-line `If` no longer leaves the object reported as Nothing after it.
43
+ * Findings on the line after a comment ending in ` _` (#82), and a missing
44
+ `Then` or a call to a variable on the line after a continuation with spaces
45
+ after its `_` (#83).
46
+ * `If x Then:` read as a block If (#84), and a one-word `EndIf` read as no
47
+ closer, so the lines after it reported as unreachable (#88).
48
+ * `invalid-expression-syntax` on `1.`, `&17`, `a => b`, `a < > b` and the other
49
+ spellings the VBE reads (#87). `s = "a" &1`, which the VBE refuses, is now
50
+ reported, and `s = "a" &9` is still a concatenation.
51
+ * `argument-count` missed on `Needs, 2`: a comma touching the callee opens its
52
+ argument list, as the VBE reads it (#85).
53
+ * `assignment-object-type-mismatch` on `Shape.Duplicate` assigned to a `Shape`,
54
+ on `SparklineGroup.SeriesColor` assigned to a `FormatColor`, and on a
55
+ `Charts` or `Worksheets` collection assigned to a `Sheets` variable (#90).
56
+ * `Err.LastDllError` is spelled the way the VBE writes it (#89).
57
+ * The command line counted lines in a `.cls` or `.frm` export from the end of
58
+ its designer header (the `VERSION` line and `Begin ... End` block the reader
59
+ strips before analysis), so a class module's findings printed four lines
60
+ early and a UserForm's early by the height of its form block. Lines, and the
61
+ JSON `start` and `end` offsets, now count the file as saved. Modules read
62
+ from an Office container are numbered as before, since pyOpenVBA reads them
63
+ without a designer header. The library's spans still index the code body.
64
+
65
+ ### Verified
66
+
67
+ * Upstream's own 10.7.1 test suite, recorded and replayed through the port:
68
+ 1081 standalone and 936 project calls, every result identical in code, span
69
+ and message. Before the port changes 24 of them differed, so the replay sees
70
+ what this release changes.
71
+ * The oracle corpus (1820 diagnostics), 16 real workbooks, 195 Office files of
72
+ every host, 693 further projects (948 modules) and 7 VB6 projects: identical
73
+ diagnostics from both analyzers.
74
+ * Against 2.2.0, the largest module (26,721 lines) takes the same CPU time.
75
+
8
76
  ## 2.2.0 - 2026-09-22
9
77
 
10
78
  Sync to XLIDE 10.6.0 (commit 5682c8f), from 6.2.0: twelve new diagnostics, early
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pyvbaanalysis
3
- Version: 2.2.0
3
+ Version: 2.2.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
@@ -54,6 +54,9 @@ These are re-exported at the package root for convenience:
54
54
  `modules`, the `host` its extension implies, and `referenced_hosts`, the other
55
55
  Office libraries its project references (`None` when the reference list could
56
56
  not be read).
57
+ * A `LoadedModule` carries a module's `name`, `kind`, and `source` (the code body
58
+ the analyzer reads), plus `designer_block`, the export header the reader stripped
59
+ ahead of `source` (empty when there was none).
57
60
  * Building blocks: `LoadedModule`, `strip_export_header`, `classify_module_kind`,
58
61
  `module_name_from_text`, `loaded_module_from_text`, `WorkbookReadError`,
59
62
  `LooseFileReadError`, and the extension sets `LOOSE_EXTENSIONS`,
@@ -136,6 +136,11 @@ analyze_loose_files(["Module1.bas", "Widget.cls"]) # several, as one project
136
136
  skipped for it (see "Whole project vs a single file" below). Use `analyze_loose_files`
137
137
  to analyze several files together with shared cross-module context.
138
138
 
139
+ Spans index the code body the analyzer reads, which starts after the stripped header.
140
+ `load_loose_module` returns a `LoadedModule` whose `designer_block` holds that header,
141
+ so `line_col(module.designer_block + module.source, len(module.designer_block) + span.start)`
142
+ places a span in the file. The command line reports positions this way.
143
+
139
144
  ### Office macro containers
140
145
 
141
146
  The container reader reads VBA directly out of an Office file via pyOpenVBA (the one
@@ -291,6 +296,12 @@ project), or an Office macro container, whose extension selects the host model.
291
296
  `pyvbaanalysis --version` prints the version, and `python -m pyvbaanalysis` is
292
297
  equivalent to the `pyvbaanalysis` command.
293
298
 
299
+ Each diagnostic is placed by line and column in the module text as read. For a loose
300
+ file that is the file itself, so the `VERSION` and `Begin ... End` header of a `.cls`
301
+ or `.frm` export counts and the numbers match an editor. For an Office container it
302
+ is the module's stored text, which begins at its `Attribute` lines; the VBE hides
303
+ those lines, so its line numbers run lower by their count.
304
+
294
305
  Flags:
295
306
 
296
307
  | Flag | Effect |
@@ -336,7 +347,8 @@ diagnostics are reported or a file cannot be read, and `2` for a usage error.
336
347
  ]
337
348
  ```
338
349
 
339
- `start` and `end` are character offsets; `line` and `column` are 1-based.
350
+ `start` and `end` are character offsets and `line` and `column` are 1-based, all in
351
+ the module text as read (see above).
340
352
 
341
353
  ## Use in CI
342
354
 
@@ -41,7 +41,7 @@ from .reader import (
41
41
  )
42
42
  from .symbols import ModuleInput, ModuleSymbolKind, ProjectIndex, ProjectIndexOptions
43
43
 
44
- __version__ = "2.2.0"
44
+ __version__ = "2.2.1"
45
45
 
46
46
  __all__ = [
47
47
  "AnalyzeModuleOptions",
@@ -142,7 +142,10 @@ def bare_call_statement_target(source: str, span: Span) -> BareCallStatementTarg
142
142
  after_close = toks[close + 1] if 0 <= close and close + 1 < len(toks) else None
143
143
  if after_close is None or after_close.raw_text in (".", "("):
144
144
  return None
145
- elif not explicit_call:
145
+ elif not explicit_call and r != ",":
146
+ # A comma cannot continue the callee, so it opens the argument list with
147
+ # or without a space: the VBE reads `Needs, 2` as `Needs , 2`, a missing
148
+ # first argument and 2 (XLIDE issue #85).
146
149
  gap = source[span.start + callee.end : span.start + next_tok.start]
147
150
  if _WHITESPACE.search(gap) is None:
148
151
  return None
@@ -33,6 +33,7 @@ from .project import analyze_project
33
33
  from .reader import (
34
34
  LOOSE_EXTENSIONS,
35
35
  OFFICE_EXTENSIONS,
36
+ LoadedModule,
36
37
  LooseFileReadError,
37
38
  WorkbookReadError,
38
39
  load_loose_module,
@@ -137,8 +138,7 @@ def _analyze_loose_group(
137
138
  whole_project=whole_project,
138
139
  inline_suppression=inline_suppression,
139
140
  )
140
- sources = {m.name: m.source for m in unique}
141
- return [_ProjectResult("(loose files)", diagnostics, sources)], warnings, errors
141
+ return [_ProjectResult("(loose files)", diagnostics, unique)], warnings, errors
142
142
 
143
143
 
144
144
  def _analyze_workbook_group(
@@ -167,8 +167,7 @@ def _analyze_workbook_group(
167
167
  host=project.host,
168
168
  referenced_hosts=project.referenced_hosts,
169
169
  )
170
- sources = {m.name: m.source for m in modules}
171
- results.append(_ProjectResult(str(path), diagnostics, sources))
170
+ results.append(_ProjectResult(str(path), diagnostics, modules))
172
171
  return results, errors
173
172
 
174
173
 
@@ -179,11 +178,23 @@ class _ProjectResult:
179
178
  self,
180
179
  label: str,
181
180
  diagnostics: dict[str, list[VbaDiagnostic]],
182
- sources: dict[str, str],
181
+ modules: Sequence[LoadedModule],
183
182
  ) -> None:
184
183
  self.label = label
185
184
  self.diagnostics = diagnostics
186
- self.sources = sources
185
+ self.modules = {module.name: module for module in modules}
186
+
187
+
188
+ def _text_as_read(module: LoadedModule | None) -> tuple[str, int]:
189
+ """A module's text as read, and where the body the analyzer saw starts in it.
190
+
191
+ The reader strips a .cls or .frm export's designer block before analysis, so a
192
+ span indexes the body; shifting it by the block's length places it in the file
193
+ as saved, which is where a user will look for it.
194
+ """
195
+ if module is None:
196
+ return "", 0
197
+ return module.designer_block + module.source, len(module.designer_block)
187
198
 
188
199
 
189
200
  def _render_text(results: Sequence[_ProjectResult]) -> str:
@@ -195,10 +206,10 @@ def _render_text(results: Sequence[_ProjectResult]) -> str:
195
206
  if not diagnostics:
196
207
  continue
197
208
  any_in_project = True
198
- source = result.sources.get(module_name, "")
209
+ text, shift = _text_as_read(result.modules.get(module_name))
199
210
  lines.append(f" {module_name}")
200
211
  for diag in diagnostics:
201
- line, column = line_col(source, diag.span.start)
212
+ line, column = line_col(text, shift + diag.span.start)
202
213
  lines.append(
203
214
  f" {line}:{column} {diag.severity.value} {diag.code} {diag.message}"
204
215
  )
@@ -207,28 +218,31 @@ def _render_text(results: Sequence[_ProjectResult]) -> str:
207
218
  return "\n".join(lines)
208
219
 
209
220
 
221
+ def _diagnostic_json(diag: VbaDiagnostic, text: str, shift: int) -> dict[str, object]:
222
+ start = shift + diag.span.start
223
+ line, column = line_col(text, start)
224
+ return {
225
+ "code": diag.code,
226
+ "severity": diag.severity.value,
227
+ "message": diag.message,
228
+ "start": start,
229
+ "end": shift + diag.span.end,
230
+ "line": line,
231
+ "column": column,
232
+ "spec_reference": diag.spec_reference,
233
+ }
234
+
235
+
210
236
  def _render_json(results: Sequence[_ProjectResult]) -> str:
211
237
  payload = []
212
238
  for result in results:
213
239
  modules = []
214
240
  for module_name, diagnostics in result.diagnostics.items():
215
- source = result.sources.get(module_name, "")
241
+ text, shift = _text_as_read(result.modules.get(module_name))
216
242
  modules.append(
217
243
  {
218
244
  "module": module_name,
219
- "diagnostics": [
220
- {
221
- "code": diag.code,
222
- "severity": diag.severity.value,
223
- "message": diag.message,
224
- "start": diag.span.start,
225
- "end": diag.span.end,
226
- "line": line_col(source, diag.span.start)[0],
227
- "column": line_col(source, diag.span.start)[1],
228
- "spec_reference": diag.spec_reference,
229
- }
230
- for diag in diagnostics
231
- ],
245
+ "diagnostics": [_diagnostic_json(diag, text, shift) for diag in diagnostics],
232
246
  }
233
247
  )
234
248
  payload.append({"project": result.label, "modules": modules})
@@ -16,7 +16,7 @@ from collections.abc import Mapping
16
16
  from dataclasses import dataclass
17
17
  from typing import Union
18
18
 
19
- from ..lexer.token_helpers import token_word
19
+ from ..lexer.token_helpers import relational_operator_at, token_word
20
20
  from ..lexer.token_kinds import TokenKind, VbaToken
21
21
  from ..lexer.tokenize import tokenize
22
22
  from ..parser.nodes import (
@@ -593,14 +593,15 @@ class _ConditionalExpressionParser:
593
593
 
594
594
  def _parse_comparison(self) -> ConditionalValue | None:
595
595
  left = self._parse_unary()
596
- op_token = self._peek()
597
- op = op_token.raw_text if op_token is not None else None
598
596
  # Relational operators (<, >, <=, >=) join the existing equality (=, <>)
599
- # handling so `#If Win64 >= 1 Then` and friends evaluate. Anything else
600
- # (Like, etc.) is left to the caller as an unmodeled remainder.
601
- if op not in ("=", "<>", "<", ">", "<=", ">="):
597
+ # handling so `#If Win64 >= 1 Then` and friends evaluate, in any of the
598
+ # spellings MS-VBAL 5.6.9.5 allows (`=>`, `< >`). Anything else (Like,
599
+ # etc.) is left to the caller as an unmodeled remainder.
600
+ relational = relational_operator_at(self._tokens, self._index)
601
+ if relational is None:
602
602
  return left
603
- self._index += 1
603
+ op, length = relational
604
+ self._index += length
604
605
  right = self._parse_unary()
605
606
  if left is None or right is None:
606
607
  return None