pyvbaanalysis 2.1.1__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 (213) hide show
  1. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/.gitignore +3 -0
  2. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/CHANGELOG.md +284 -0
  3. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/CONTRIBUTING.md +61 -7
  4. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/PKG-INFO +16 -3
  5. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/README.md +13 -0
  6. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/docs/api-reference.md +29 -11
  7. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/docs/diagnostics-catalogue.md +17 -5
  8. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/docs/usage.md +46 -2
  9. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyproject.toml +4 -2
  10. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/__init__.py +1 -1
  11. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/call/call_context.py +4 -1
  12. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/cli.py +41 -26
  13. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/completion/event_handlers.py +14 -8
  14. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/completion/member_access.py +408 -99
  15. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/conditional/conditional_compilation.py +8 -7
  16. pyvbaanalysis-2.2.1/pyvbaanalysis/data/access_host_model.json +1 -0
  17. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/diagnostic_influence_audit.json +159 -2
  18. pyvbaanalysis-2.2.1/pyvbaanalysis/data/excel_closed_types.json +31 -0
  19. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/excel_host_model.json +1 -1
  20. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/manifest.json +35 -10
  21. pyvbaanalysis-2.2.1/pyvbaanalysis/data/msforms_members.json +1 -0
  22. pyvbaanalysis-2.2.1/pyvbaanalysis/data/powerpoint_host_model.json +1 -0
  23. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/rule_metadata.json +139 -1
  24. pyvbaanalysis-2.2.1/pyvbaanalysis/data/vb6_host_model.json +1 -0
  25. pyvbaanalysis-2.2.1/pyvbaanalysis/data/vba_runtime_tables.json +1 -0
  26. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/vbe_oracle_cases.json +286 -0
  27. pyvbaanalysis-2.2.1/pyvbaanalysis/data/word_host_model.json +1 -0
  28. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/__init__.py +8 -0
  29. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/analyze_module.py +36 -8
  30. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/argument_inference.py +289 -14
  31. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/call_extraction.py +9 -5
  32. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/callable_signatures.py +255 -15
  33. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/const_expr.py +62 -4
  34. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/context.py +23 -0
  35. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/dataflow.py +101 -23
  36. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/model.py +36 -0
  37. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/registry.py +74 -7
  38. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rule_metadata.py +3 -1
  39. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/argument_types.py +19 -4
  40. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/arrays.py +32 -5
  41. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/assignments.py +50 -15
  42. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/call_arity.py +77 -8
  43. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/control_flow.py +33 -22
  44. pyvbaanalysis-2.2.1/pyvbaanalysis/diagnostics/rules/dead_code.py +568 -0
  45. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/declarations.py +139 -30
  46. pyvbaanalysis-2.2.1/pyvbaanalysis/diagnostics/rules/doc_comments.py +372 -0
  47. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/duplicates.py +55 -33
  48. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/expressions.py +16 -13
  49. pyvbaanalysis-2.2.1/pyvbaanalysis/diagnostics/rules/missing_reference.py +136 -0
  50. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/module_kind.py +5 -3
  51. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/object_state.py +56 -20
  52. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/parameter_defaults.py +8 -7
  53. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/runtime_values.py +7 -8
  54. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/shared.py +153 -12
  55. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/type_of_is.py +28 -64
  56. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/undeclared.py +95 -1
  57. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/walker.py +1 -1
  58. pyvbaanalysis-2.2.1/pyvbaanalysis/docs/__init__.py +19 -0
  59. pyvbaanalysis-2.2.1/pyvbaanalysis/docs/doc_comment.py +231 -0
  60. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/host/__init__.py +8 -0
  61. pyvbaanalysis-2.2.1/pyvbaanalysis/host/host_libraries.py +92 -0
  62. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/host/host_model.py +88 -3
  63. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/host/host_registry.py +76 -2
  64. pyvbaanalysis-2.2.1/pyvbaanalysis/host/msforms.py +91 -0
  65. pyvbaanalysis-2.2.1/pyvbaanalysis/host/type_extensibility.py +74 -0
  66. pyvbaanalysis-2.2.1/pyvbaanalysis/lexer/contextual_keywords.py +179 -0
  67. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/keyword_table.py +6 -2
  68. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/stripped_lines.py +11 -8
  69. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/token_helpers.py +76 -2
  70. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/token_kinds.py +9 -1
  71. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/tokenize.py +73 -16
  72. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/trivia.py +15 -9
  73. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/nodes.py +8 -0
  74. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/parse_expression.py +15 -8
  75. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/parse_module.py +19 -3
  76. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/parser_state.py +35 -7
  77. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/project.py +18 -3
  78. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/reader/__init__.py +4 -0
  79. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/reader/vbe_module.py +19 -5
  80. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/reader/workbook.py +103 -37
  81. pyvbaanalysis-2.2.1/pyvbaanalysis/references/__init__.py +10 -0
  82. pyvbaanalysis-2.2.1/pyvbaanalysis/references/reference_kinds.py +365 -0
  83. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/runtime/__init__.py +4 -0
  84. pyvbaanalysis-2.2.1/pyvbaanalysis/runtime/vba_runtime.py +190 -0
  85. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/__init__.py +2 -0
  86. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/build_module_symbols.py +2 -0
  87. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/project_index.py +241 -4
  88. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/symbol_model.py +30 -1
  89. pyvbaanalysis-2.2.1/pyvbaanalysis/symbols/user_form_controls.py +145 -0
  90. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/types/__init__.py +1 -1
  91. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/types/type_inference.py +2 -1
  92. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/types/type_names.py +3 -18
  93. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/oracle_support.py +11 -17
  94. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_cli.py +64 -1
  95. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_conditional_arms.py +3 -1
  96. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_dataflow.py +21 -14
  97. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_evidence.py +2 -2
  98. pyvbaanalysis-2.2.1/tests/test_host_libraries.py +176 -0
  99. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_host_seam.py +38 -10
  100. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_parser.py +19 -8
  101. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_reader.py +54 -2
  102. pyvbaanalysis-2.2.1/tests/test_reference_kinds.py +175 -0
  103. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_registry_parity.py +9 -2
  104. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rule_metadata.py +15 -5
  105. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_assignments_types.py +112 -4
  106. pyvbaanalysis-2.2.1/tests/test_rules_call_arity.py +102 -0
  107. pyvbaanalysis-2.2.1/tests/test_rules_dead_code.py +347 -0
  108. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_declarations.py +40 -0
  109. pyvbaanalysis-2.2.1/tests/test_rules_doc_comments.py +197 -0
  110. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_event_handler_module_scope.py +29 -1
  111. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_member_not_found.py +68 -43
  112. pyvbaanalysis-2.2.1/tests/test_rules_missing_reference.py +152 -0
  113. pyvbaanalysis-2.2.1/tests/test_upstream_sync_10_5_0.py +278 -0
  114. pyvbaanalysis-2.2.1/tests/test_upstream_sync_10_6_0.py +246 -0
  115. pyvbaanalysis-2.2.1/tests/test_upstream_sync_10_7_1.py +351 -0
  116. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_upstream_sync_6_1_2.py +3 -1
  117. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tools/extract_event_definitions.mjs +9 -7
  118. pyvbaanalysis-2.2.1/tools/extract_host_model.mjs +64 -0
  119. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tools/extract_rule_metadata.mjs +6 -3
  120. pyvbaanalysis-2.2.1/tools/extract_runtime_tables.mjs +20 -0
  121. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tools/generate_manifest.py +16 -6
  122. pyvbaanalysis-2.2.1/tools/pin_analyzer.py +127 -0
  123. pyvbaanalysis-2.2.1/tools/vendor_data.py +106 -0
  124. pyvbaanalysis-2.2.1/tools/xlide_source.mjs +52 -0
  125. pyvbaanalysis-2.1.1/pyvbaanalysis/data/access_host_model.json +0 -1
  126. pyvbaanalysis-2.1.1/pyvbaanalysis/data/powerpoint_host_model.json +0 -1
  127. pyvbaanalysis-2.1.1/pyvbaanalysis/data/vba_runtime_tables.json +0 -1
  128. pyvbaanalysis-2.1.1/pyvbaanalysis/data/word_host_model.json +0 -1
  129. pyvbaanalysis-2.1.1/pyvbaanalysis/runtime/vba_runtime.py +0 -329
  130. pyvbaanalysis-2.1.1/tests/test_rules_call_arity.py +0 -60
  131. pyvbaanalysis-2.1.1/tools/extract_host_model.mjs +0 -31
  132. pyvbaanalysis-2.1.1/tools/extract_runtime_tables.mjs +0 -10
  133. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/.gitattributes +0 -0
  134. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/.github/dependabot.yml +0 -0
  135. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/.github/workflows/ci.yml +0 -0
  136. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/.github/workflows/publish.yml +0 -0
  137. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/LICENSE +0 -0
  138. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/__main__.py +0 -0
  139. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/call/__init__.py +0 -0
  140. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/completion/__init__.py +0 -0
  141. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/completion/cursor_context.py +0 -0
  142. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/completion/type_completion.py +0 -0
  143. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/conditional/__init__.py +0 -0
  144. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/constants/__init__.py +0 -0
  145. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/constants/integer_constant_expression.py +0 -0
  146. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/data/event_definitions.json +0 -0
  147. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/exprwalk.py +0 -0
  148. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/inline_suppression.py +0 -0
  149. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/__init__.py +0 -0
  150. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/argument_shape.py +0 -0
  151. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/binary_operand_scalar.py +0 -0
  152. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/late_binding.py +0 -0
  153. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/lexical.py +0 -0
  154. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/diagnostics/rules/numeric_literals.py +0 -0
  155. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/evidence.py +0 -0
  156. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/flow/__init__.py +0 -0
  157. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/flow/procedure_labels.py +0 -0
  158. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/flow/procedure_unstructured.py +0 -0
  159. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/identity_cache.py +0 -0
  160. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/lexer/__init__.py +0 -0
  161. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/__init__.py +0 -0
  162. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/fixed_length_string.py +0 -0
  163. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/parser/type_declaration_suffix.py +0 -0
  164. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/py.typed +0 -0
  165. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/reader/loose_file.py +0 -0
  166. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/pyvbaanalysis/symbols/name_resolution.py +0 -0
  167. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/conftest.py +0 -0
  168. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_conditional_compilation.py +0 -0
  169. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_diagnostics_engine.py +0 -0
  170. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_host_model.py +0 -0
  171. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_inline_suppression.py +0 -0
  172. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_integer_constant_expression.py +0 -0
  173. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_language_matrix.py +0 -0
  174. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_lexer.py +0 -0
  175. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_member_access_chains.py +0 -0
  176. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_project.py +0 -0
  177. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_project_index.py +0 -0
  178. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_public_api.py +0 -0
  179. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_real_world_false_positives.py +0 -0
  180. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_ambiguous_enum_member.py +0 -0
  181. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_argument_shape.py +0 -0
  182. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_argument_types.py +0 -0
  183. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_arrays.py +0 -0
  184. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_assignments.py +0 -0
  185. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_binary_operand_scalar.py +0 -0
  186. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_control_flow.py +0 -0
  187. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_division_by_zero.py +0 -0
  188. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_duplicates.py +0 -0
  189. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_expression_calls.py +0 -0
  190. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_expressions.py +0 -0
  191. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_invalid_as_type_names.py +0 -0
  192. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_is_operator_non_object.py +0 -0
  193. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_late_binding.py +0 -0
  194. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_lexical.py +0 -0
  195. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_module_kind.py +0 -0
  196. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_numeric_literals.py +0 -0
  197. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_object_state.py +0 -0
  198. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_parameter_defaults.py +0 -0
  199. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_property_setter_value_parameters.py +0 -0
  200. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_runtime_values.py +0 -0
  201. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_scalar_and_foreach.py +0 -0
  202. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_type_of_is.py +0 -0
  203. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_typeof_is_always_false.py +0 -0
  204. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_rules_undeclared.py +0 -0
  205. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_runtime_tables.py +0 -0
  206. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_statement_token_derivation.py +0 -0
  207. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_stripped_lines.py +0 -0
  208. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_symbols.py +0 -0
  209. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_token_helpers.py +0 -0
  210. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_type_completion.py +0 -0
  211. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tests/test_type_names.py +0 -0
  212. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tools/generate_diagnostics_catalogue.py +0 -0
  213. {pyvbaanalysis-2.1.1 → pyvbaanalysis-2.2.1}/tools/oracle/build_combining_mark_probe.py +0 -0
@@ -34,3 +34,6 @@ Thumbs.db
34
34
 
35
35
  # Note: the vendored XLIDE data package under pyvbaanalysis/data/ is intentionally
36
36
  # committed (it is the version-pinned contract surface), so it is NOT ignored here.
37
+
38
+ # A pinned XLIDE checkout is a build input, reproducible from its ref at any time.
39
+ artifacts/
@@ -5,6 +5,290 @@ 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
+
76
+ ## 2.2.0 - 2026-09-22
77
+
78
+ Sync to XLIDE 10.6.0 (commit 5682c8f), from 6.2.0: twelve new diagnostics, early
79
+ binding checked against the libraries a project references, and member lookups
80
+ that follow the type library's own extensibility flags. The data is now vendored
81
+ from a pinned upstream commit, which the manifest records.
82
+
83
+ The sync also closes gaps earlier syncs left open. Replaying upstream's own test
84
+ suite through the port found checks that were never ported (member calls, typing
85
+ through the host model, constants from the host and the VBA library), fixes
86
+ older than 6.2.0 that were never taken, and false positives in 2.1.1 from that
87
+ drift. All of it is listed below.
88
+
89
+ ### Added
90
+
91
+ * `invalid-option-statement` (error): a malformed Option statement, such as
92
+ `Option Base 2`, `Option Explicit Foo` or a bare `Option Private`.
93
+ `Option Compare Database` is reported only when a host other than Access is
94
+ named: it is an Access directive, and a loose file names no host.
95
+ * `missing-library-reference` (error): a type or constant qualified with another
96
+ Office application's library the project does not reference, such as
97
+ `Dim doc As Word.Document` in a workbook with no reference to Word. The VBE
98
+ refuses it with "User-defined type not defined". Late binding through
99
+ `CreateObject` names nothing and stays silent. Reported once per library per
100
+ module, and only against a known reference list (see Changed).
101
+ * Four dead-code checks, all `information`: `unused-variable` (a local, or a
102
+ module-private variable or constant, that nothing uses), `variable-never-read`
103
+ (one that is only ever assigned), `unused-procedure` (a private procedure
104
+ nothing calls), and `unreachable-code` (statements after `Exit`, `End`, `GoTo`
105
+ or `Resume` that no label or `Case` arm reaches). A name in any module's
106
+ string literal counts as a use of a private procedure, because
107
+ `Application.Run "Poll"` reaches a private Sub. `unused-variable` and
108
+ `unreachable-code` findings carry the edit that removes the declaration or the
109
+ dead run.
110
+ * Six doc-comment checks, all `warning`: `doc-param-missing`,
111
+ `doc-param-unknown`, `doc-returns-missing`, `doc-returns-unexpected`,
112
+ `doc-tag-unclosed` and `doc-tag-duplicate` compare the XML tags of a `'''`
113
+ block with the declaration it documents, each with fixes that add, rename or
114
+ remove a tag. A `'''` block of plain prose is left alone.
115
+ * `referenced_hosts` on `analyze_project` and `analyze_module_options_for`: the
116
+ other Office libraries a project references, in declaration order. Their
117
+ types, constants and globals resolve against their own models, and the
118
+ project's own host wins a name two libraries share, as VBA resolves it.
119
+ `None`, the default, means the list is unknown; `[]` means it is known to name
120
+ nothing else.
121
+ * `read_office_project(path)` in `pyvbaanalysis.reader`, returning an
122
+ `OfficeProject`: a container's modules, the host its extension implies, and
123
+ the Office libraries its reference list names. `analyze_office_file` and the
124
+ CLI pass all three to the analysis.
125
+ * Member calls are checked for arity and argument types against the signature
126
+ the member resolves to, on host objects and project classes alike:
127
+ `Application.Calculate(1)`, a bare `Err.Raise`, `Workbooks.Open()`, and
128
+ `p.Save "bad"` on a class whose `Save` takes a Long. Earlier ports checked
129
+ calls to procedures only. A keyword before `:=` is a parameter name, so
130
+ `BreakLink Name:="x", Type:=xlLinkTypeExcelLinks` stays silent. A signature's
131
+ parameters end at their own closing parenthesis, so a member returning an
132
+ array, `Function Values() As Long()`, takes an empty argument list.
133
+ * Expressions are typed through the host model, the VBA runtime and the member
134
+ a chain resolves to, so `Set wb = ActiveSheet.Range("A1")` reports
135
+ `assignment-object-type-mismatch`, and a constant such as `vbFalse` or
136
+ `xlAbove` passed or assigned where an object is expected is reported.
137
+ * Constant expressions fold VBA and host constants: `1 / vbFalse` reports
138
+ `division-by-zero`, and `Left$(s, xlAbove - 1)` a negative length. A constant
139
+ qualified with a host (`Word.wdMainTextStory`) answers only in that host.
140
+ * A `vb6` host token and the VB6 object model: App, Screen, Printer, Form and
141
+ the intrinsic controls. It offers and describes, and never proves a member
142
+ absent.
143
+ * A UserForm's surface carries the MSForms UserForm members and the ones VBA
144
+ adds (Show, Hide, Name, ...). When the form's control list is authoritative,
145
+ supplied as `implicit_members` or spelled out by a `.frm` designer header, it
146
+ proves a member absent: `EntryForm.NoSuchControl` reports `member-not-found`
147
+ (XLIDE issue #26). A form nobody read the designer of proves nothing.
148
+ * The public pieces behind these: `classify_reference_kinds` in the new
149
+ `pyvbaanalysis.references`, the doc-comment grammar in `pyvbaanalysis.docs`,
150
+ `host_object_model_for_tokens`, `get_vb6_object_model` and the libid helpers
151
+ in `pyvbaanalysis.host`, the forms metadata in `pyvbaanalysis.host.msforms`,
152
+ `implicit_members`, `predeclared_id` and `designer_class` on `ModuleInput`
153
+ (with `ImplicitMember`), and the code-action payloads
154
+ `VbaAddLibraryReferenceData`, `VbaRemoveDeclarationData`,
155
+ `VbaRemoveUnreachableCodeData` and `VbaDocCommentFix`.
156
+ * `tools/vendor_data.py` vendors every data file from one pinned XLIDE commit,
157
+ after `tools/pin_analyzer.py` copies that commit out of the sibling checkout
158
+ (see CONTRIBUTING.md). The manifest gains `xlideCommit`.
159
+ * `tools/differential/harness.py` compares the port with the upstream analyzer
160
+ of the same pin. It records every `analyzeModule` call of upstream's own test
161
+ suite and replays each through the port, and it runs the oracle corpus, Office
162
+ files and folders of exported modules through both analyzers (see
163
+ CONTRIBUTING.md). It stays out of the published packages.
164
+
165
+ ### Changed
166
+
167
+ * `member-not-found` reports an absent member only on a closed Excel interface.
168
+ Upstream now reads each interface's TYPEFLAGS from the type library, and
169
+ Application, Workbook and Range are extensible: VBA compiles a member they do
170
+ not list and resolves it at run time. `Application.Match` and the other
171
+ worksheet functions reached through Application were reported and are now
172
+ silent. In a workbook, `ThisWorkbook` is the project's own document class,
173
+ which the VBE closes, so a member it lacks is still reported. Analyzed with no
174
+ ThisWorkbook module, as the oracle corpus runs its cases, it falls back to the
175
+ library's open Workbook, and three cases the VBE rejects go unreported by both
176
+ analyzers. `Worksheets` stays closed: the type library returns the closed
177
+ `Sheets` from it, so `Worksheets.NoSuchMemberXyz` is still reported and
178
+ `Worksheets(1)` is still a Worksheet (XLIDE issue #79, found by this sync).
179
+ * The host models carry the members each type library marks hidden, which the
180
+ reference documentation leaves out: 405 more in Excel's model, 332 in Word's
181
+ and 200 in PowerPoint's, each with `hidden` set. They resolve like any other
182
+ member (see Fixed). Where a Global interface answers for bare names, as in
183
+ Excel, Word and PowerPoint, Application's hidden members stay out of bare
184
+ scope, so a bare `Save` in Excel is still `unknown-call`.
185
+ * The project's own types outrank the host library's, as they do in VBA: a class
186
+ named `Font` or `Point` resolves to its own members rather than Excel's
187
+ (XLIDE issue #11). A project Enum is a value type, never an object receiver.
188
+ * The rules that read a statement's structure also read the statements a
189
+ single-line `If` carries: `If ok Then K = 2` reports `const-assignment`, and
190
+ `If ok Then Helper 1, 2, 3` its arity (XLIDE issue #46).
191
+ * The arms of one `#If` chain are alternatives, and a repeat inside one arm is a
192
+ repeat: two `Case Else`, two `Option Explicit`, or a duplicated Enum member or
193
+ Type field in the same arm are reported, where every undecidable branch used
194
+ to be skipped. A call that no arm's declaration accepts reports
195
+ `argument-count`, where a name declared once per arm used to turn the check
196
+ off (XLIDE issue #58).
197
+ * A module's own `Type` shadows another module's `Type` of the same name, as it
198
+ does in the VBE. A class with a private `Type JsonTextBuilder` was resolved
199
+ against a public one elsewhere, and its fields reported missing (oracle case
200
+ `private_type_shadows_public_type_compile`).
201
+ * A procedure closer ends the open procedure even from inside a block left open
202
+ in it, as the VBE does and upstream's parser now does too (XLIDE issue #81,
203
+ found by this sync). After `If x Then` with no `End If`, an `End Function`
204
+ reports the If as missing its `End If` and closes the procedure. It used to
205
+ read as an unmatched closer and leave the procedure open.
206
+ * `analyze_workbook` returns exactly what `analyze_office_file` returns for the
207
+ same file. It now reads the workbook's reference list and names Excel as the
208
+ host, so it can report `missing-library-reference` and
209
+ `Option Compare Database`, which it could not before.
210
+ * `missing-library-reference` is reported only against a known reference list:
211
+ one read from a container, or passed as `referenced_hosts`. Upstream treats an
212
+ absent list as "nothing referenced"; a loose `.bas` file has no list, and a
213
+ missing reference cannot be proven there.
214
+ * The four dead-code checks report at `information`, and the CLI's default
215
+ `--fail-level information` fails on any diagnostic, so a workbook with one
216
+ unused variable now exits 1. Pass `--fail-level warning` to gate on warnings
217
+ and errors only. Each of 16 real workbooks reports at least one of these.
218
+ * The vendored data moves to 10.6.0: 443 oracle cases (from 418), 134 audited
219
+ codes (from 122) and 131 catalogue rules (from 119). Two data files join it,
220
+ both extracted from the same commit: the VB6 object model and the Microsoft
221
+ Forms members.
222
+
223
+ ### Fixed
224
+
225
+ False positives 2.1.1 reported on code that compiles, each from a fix an earlier
226
+ sync did not carry over:
227
+
228
+ * `undeclared-variable` on a qualifier that names an enumeration or a VBA module
229
+ of constants: `XlDirection.xlUp`, `VbMsgBoxResult.vbYes`, `Strings.Left`,
230
+ `Constants.vbCrLf`.
231
+ * `undeclared-variable` on a UserForm's own controls in its code-behind, on a
232
+ bracketed name Excel evaluates (`[A1]`), on the field after `!` (`rs!Field`),
233
+ on `Line` in `Line Input #f, s`, and on a module name used as a qualifier
234
+ (`Module1.Limit`).
235
+ * `object-variable-not-set` on a variable declared `As New`, which VBA creates
236
+ on first use.
237
+ * `unallocated-dynamic-array-access` on an array read after a call that received
238
+ it, and may have allocated it: `If Fill(a) Then Debug.Print a(0)` (XLIDE issue
239
+ #70).
240
+ * `event-handler-module-scope` on each Document event handler in Word's
241
+ `ThisDocument`, such as `Document_Open`. The module was taken for a worksheet,
242
+ where upstream knows it as Word's document.
243
+
244
+ Three more, fixed upstream in 10.6.0:
245
+
246
+ * `readonly-member-assignment` on a comparison with a read-only property: in an
247
+ `ElseIf` or `Case` header, a single-line `If`'s condition, or a call given the
248
+ comparison, such as `Debug.Print w.Part = "a"`. The target of a member
249
+ assignment must be one receiver chain, which a keyword or a call before the
250
+ receiver breaks (XLIDE issue #78, found by this sync). An assignment that a
251
+ single-line `If` carries is still reported, named `w.Part` rather than
252
+ `If ok Then w.Part`.
253
+ * `member-not-found` on a member the type library hides, such as
254
+ `ThisWorkbook.Title` or `ws.OnEntry` on a Worksheet. Both compile, but the
255
+ models were built from the reference documentation, which leaves such members
256
+ out.
257
+ * `undeclared-variable` on a hidden global called bare, such as `Assistant` in
258
+ Word and PowerPoint, or PowerPoint's `Dialogs`.
259
+
260
+ ### Verified
261
+
262
+ * Upstream's own test suite, recorded: every `analyzeModule` call its 10.6.0
263
+ tests make, with the options they pass and the modules of any project index
264
+ behind them, replayed through the port: 1055 standalone calls and 929 with
265
+ project context, every result identical in code, span and message. With two
266
+ of the 10.6.0 fixes undone in the port, 7 of them differ, so the replay sees
267
+ what those fixes change.
268
+ * The oracle corpus, standalone and with project context: all 1818 diagnostics
269
+ identical in code, span and message. That is with the reference list given as
270
+ known and empty to both analyzers. Left unknown, the port stays silent on the
271
+ one case the upstream analyzer reports, the reference-list gate above.
272
+ * The 116 modules of 16 real workbooks: identical diagnostics from both
273
+ analyzers.
274
+ * 693 further projects, 627 of them the VBA blocks of upstream's syntax corpus
275
+ and 66 folders of exported modules: identical diagnostics from both analyzers
276
+ across 948 modules. The seven VB6 projects among them are identical under the
277
+ `vb6` host too.
278
+ * 195 distinct Office files from the same repositories, from Excel, Word,
279
+ PowerPoint and Access: identical diagnostics across 965 modules, once the
280
+ `ThisDocument` fix above was in. That fix is what this comparison found.
281
+ * Each new rule compared case by case with upstream 10.5.0, fix payloads
282
+ included: option statements 23, library references 11, reference kinds 18,
283
+ dead code 33 plus 8 removal edits, doc comments 21 with 25 fixes.
284
+ * Against 2.1.1, in interleaved runs measuring CPU time: a real workbook's
285
+ analysis takes about 3 percent longer, and the largest module (26,721 lines)
286
+ about 15 percent. The 10.6.0 changes measure under 2 points of that.
287
+ * The differential harness behind the 2.1.0 and 2.1.1 figures read each module's
288
+ kind from the wrong corpus field, so class and document modules were compared
289
+ as standard modules. It is corrected, and the figures above come from the
290
+ corrected harness, now `tools/differential/`.
291
+
8
292
  ## 2.1.1 - 2026-09-05
9
293
 
10
294
  Follows XLIDE 6.2.0. The vendored data is byte-identical to 6.1.2, so only the
@@ -14,8 +14,8 @@ pip install -e ".[dev]"
14
14
  ```
15
15
 
16
16
  The `dev` extra adds the test, lint, and type tools. pyOpenVBA (the one runtime
17
- dependency, used to read VBA out of Excel workbooks) is installed with the base
18
- package, so the workbook reader is exercised by the test suite.
17
+ dependency, used to read VBA out of Office files) is installed with the base
18
+ package, so the container reader is exercised by the test suite.
19
19
 
20
20
  ## Local checks
21
21
 
@@ -34,19 +34,73 @@ mypy pyvbaanalysis
34
34
  This repository ports XLIDE's TypeScript analyzer. XLIDE owns the language and
35
35
  host knowledge; pyVBAanalysis reproduces its behavior in Python.
36
36
 
37
- * The XLIDE source is expected as a sibling checkout at `../xlide_vscode`. The
38
- data-extraction tools reference it through that relative path.
37
+ * The XLIDE source is expected as a sibling checkout at `../xlide_vscode`, to read
38
+ while porting.
39
39
  * XLIDE also owns the oracle: the Excel/VBE evidence corpus and the provenance
40
40
  audit. pyVBAanalysis consumes the emitted evidence verbatim as both porting spec
41
41
  and test fixtures. Do not reimplement the oracle here.
42
- * The vendored data lives in `pyvbaanalysis/data/` (the host object model, the
42
+ * The vendored data lives in `pyvbaanalysis/data/` (the host object models, the
43
43
  runtime tables, the oracle cases, the rule metadata, and a manifest with
44
- checksums). It is regenerated by the `tools/extract_*.mjs` scripts (run with
45
- `npx tsx`) against the sibling XLIDE checkout, never hand-edited.
44
+ checksums). It is never hand-edited. A sync regenerates all of it from one XLIDE
45
+ commit:
46
+
47
+ ```
48
+ python tools/vendor_data.py --ref vX.Y.Z
49
+ ```
50
+
51
+ The commit is pinned first. `tools/pin_analyzer.py` copies the sibling
52
+ repository's history into `artifacts/analyzer-pin/<commit>` (not in source
53
+ control) and checks that commit out, so neither uncommitted work in the sibling
54
+ checkout nor the branch it happens to be on reaches the data. The
55
+ `tools/extract_*.mjs` scripts then read the pin through `XLIDE_ROOT`, and stop
56
+ rather than fall back to the sibling when it does not name an XLIDE checkout. The
57
+ manifest records both the version label and the full commit (`xlideVersion`,
58
+ `xlideCommit`).
46
59
 
47
60
  The build plan, parity inventory, and module-by-module port map are in
48
61
  [agent.md](agent.md).
49
62
 
63
+ ## Checking a sync against upstream
64
+
65
+ The port's own tests encode the behavior it had, so they stay green while upstream
66
+ widens a rule the port never took. A sync is checked by running both analyzers on
67
+ the same inputs, upstream from the pin of the vendored commit:
68
+
69
+ ```
70
+ python tools/differential/harness.py record
71
+ python tools/differential/harness.py replay
72
+ python tools/differential/harness.py corpus
73
+ python tools/differential/harness.py cases artifacts/differential/cases/mine.json PATH ...
74
+ python tools/differential/harness.py projects artifacts/differential/cases/mine.json
75
+ ```
76
+
77
+ * `record` runs upstream's own test suite with a recorder appended to its
78
+ `analyzeModule` and `ProjectIndex`, writing every call to
79
+ `artifacts/differential/<commit>/calls.jsonl`. `replay` runs each call through
80
+ the port, rebuilding the project index behind a call made with project context,
81
+ and compares the diagnostics by code, span and message. It finds the gaps
82
+ nothing else exercises: whole checks never ported, fixes older than the last
83
+ sync point.
84
+ * `corpus` runs the oracle corpus through both analyzers, each module standalone
85
+ and with its case's modules as a project.
86
+ * `cases` turns Office files, and folders searched for them and for exported
87
+ `.bas`/`.cls`/`.frm` modules, into project cases. `--markdown` adds every VBA
88
+ block of upstream's syntax corpus, and `--host` names a host for the cases no
89
+ file implies one for. `projects` runs a cases file through both analyzers.
90
+
91
+ `replay`, `corpus` and `projects` exit 1 when anything differs and print what only
92
+ one side reports. Where the port reports more, the port is wrong. Where upstream
93
+ reports more it may be an upstream false positive, so check before porting it.
94
+
95
+ The upstream halves (`tools/differential/upstream/*.mjs`) read the pin through
96
+ `tools/xlide_source.mjs`, as the extractors do, and need nothing installed. Only
97
+ `record` runs upstream's vitest suite, which needs the sibling checkout's
98
+ dependencies installed. The pin gets a `node_modules` folder of its own with one
99
+ link per package, so the caches Vite writes stay in the pin, and the run fails if
100
+ the sibling's folder changed. The recorder is removed with `git checkout` when the
101
+ run ends. `harness.py unpatch` restores a pin a run left patched, and
102
+ `tools/pin_analyzer.py` will not reuse a pin with local changes.
103
+
50
104
  ## Adding or changing a rule
51
105
 
52
106
  * Port the rule from its XLIDE source; match the behavior, not just the shape.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pyvbaanalysis
3
- Version: 2.1.1
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
@@ -22,9 +22,9 @@ Provides-Extra: build
22
22
  Requires-Dist: build>=1.2; extra == 'build'
23
23
  Requires-Dist: twine>=5; extra == 'build'
24
24
  Provides-Extra: dev
25
- Requires-Dist: mypy==2.3.0; extra == 'dev'
25
+ Requires-Dist: mypy==2.3.1; extra == 'dev'
26
26
  Requires-Dist: pytest==9.1.1; extra == 'dev'
27
- Requires-Dist: ruff==0.16.2; extra == 'dev'
27
+ Requires-Dist: ruff==0.16.8; extra == 'dev'
28
28
  Description-Content-Type: text/markdown
29
29
 
30
30
  # pyVBAanalysis
@@ -46,8 +46,13 @@ It looks for more than a hundred kinds of problem, including:
46
46
  - Undeclared variables and calls to procedures or members that do not exist.
47
47
  - Code the VBA compiler rejects: duplicate declarations, malformed statements, or a `Declare` that lacks `PtrSafe` on 64-bit
48
48
  Office.
49
+ - A type from another Office application's library the project does not
50
+ reference, such as `Dim doc As Word.Document` in a workbook with no reference to
51
+ Word.
49
52
  - Likely run-time failures, such as dividing by a constant zero or a type mismatch
50
53
  from a bad conversion.
54
+ - Dead code: variables nothing uses or nothing reads, private procedures nothing
55
+ calls, and statements no path reaches.
51
56
 
52
57
  It only reports a problem when it can prove one, and stays quiet otherwise, so the
53
58
  output does not bury you in false alarms.
@@ -122,6 +127,14 @@ a compressed record the reader does not open.
122
127
  - [API reference](docs/api-reference.md)
123
128
  - [Diagnostic catalogue](docs/diagnostics-catalogue.md)
124
129
 
130
+ ## Built with this
131
+
132
+ [xlide-mcp](https://github.com/WilliamSmithEdward/xlide_mcp)
133
+ is an MCP server built on this. The diagnostics here are its build gate:
134
+ an agent that changes a macro runs them afterwards and treats an error
135
+ as a failure rather than a suggestion, which is most of what stops a
136
+ model shipping VBA that does not compile.
137
+
125
138
  ## License
126
139
 
127
140
  MIT. See [LICENSE](LICENSE).
@@ -17,8 +17,13 @@ It looks for more than a hundred kinds of problem, including:
17
17
  - Undeclared variables and calls to procedures or members that do not exist.
18
18
  - Code the VBA compiler rejects: duplicate declarations, malformed statements, or a `Declare` that lacks `PtrSafe` on 64-bit
19
19
  Office.
20
+ - A type from another Office application's library the project does not
21
+ reference, such as `Dim doc As Word.Document` in a workbook with no reference to
22
+ Word.
20
23
  - Likely run-time failures, such as dividing by a constant zero or a type mismatch
21
24
  from a bad conversion.
25
+ - Dead code: variables nothing uses or nothing reads, private procedures nothing
26
+ calls, and statements no path reaches.
22
27
 
23
28
  It only reports a problem when it can prove one, and stays quiet otherwise, so the
24
29
  output does not bury you in false alarms.
@@ -93,6 +98,14 @@ a compressed record the reader does not open.
93
98
  - [API reference](docs/api-reference.md)
94
99
  - [Diagnostic catalogue](docs/diagnostics-catalogue.md)
95
100
 
101
+ ## Built with this
102
+
103
+ [xlide-mcp](https://github.com/WilliamSmithEdward/xlide_mcp)
104
+ is an MCP server built on this. The diagnostics here are its build gate:
105
+ an agent that changes a macro runs them afterwards and treats an error
106
+ as a failure rather than a suggestion, which is most of what stops a
107
+ model shipping VBA that does not compile.
108
+
96
109
  ## License
97
110
 
98
111
  MIT. See [LICENSE](LICENSE).
@@ -11,18 +11,18 @@ These are re-exported at the package root for convenience:
11
11
  | Symbol | Role |
12
12
  | --- | --- |
13
13
  | `analyze_module(source, opts=None)` | Analyze one module's source; returns `list[VbaDiagnostic]`. Never raises. |
14
- | `analyze_project(modules, *, only=None, severity_overrides=None, conditional_compilation=None, whole_project=True, inline_suppression=True, host=None)` | Analyze a set of `ModuleInput`s with cross-module context; returns `dict[str, list[VbaDiagnostic]]`. `whole_project=False` for a partial set. `host` names the Office host (absent means Excel). |
14
+ | `analyze_project(modules, *, only=None, severity_overrides=None, conditional_compilation=None, whole_project=True, inline_suppression=True, host=None, referenced_hosts=None)` | Analyze a set of `ModuleInput`s with cross-module context; returns `dict[str, list[VbaDiagnostic]]`. `whole_project=False` for a partial set. `host` names the Office host (absent means Excel). `referenced_hosts` names the other Office libraries the project references, in declaration order; `None` means the reference list is unknown, `[]` that it is known to name nothing else. |
15
15
  | `analyze_loose_file(path, *, severity_overrides=None, conditional_compilation=None, whole_project=False, inline_suppression=True)` | Analyze one `.bas`/`.cls`/`.frm` file (partial by default; the whole-project checks are skipped). |
16
16
  | `analyze_loose_files(paths, *, only=None, severity_overrides=None, conditional_compilation=None, whole_project=True, inline_suppression=True)` | Analyze several loose files as one project. |
17
- | `analyze_workbook(path, *, only=None, severity_overrides=None, conditional_compilation=None, inline_suppression=True)` | Analyze the VBA in an Excel workbook (via pyOpenVBA). |
18
- | `analyze_office_file(path, *, only=None, severity_overrides=None, conditional_compilation=None, inline_suppression=True)` | The same for any readable Office container (Excel, Word, PowerPoint, Access); the extension selects the host model. |
17
+ | `analyze_workbook(path, *, only=None, severity_overrides=None, conditional_compilation=None, inline_suppression=True)` | The Excel-only form of `analyze_office_file`: refuses any other extension, and otherwise returns exactly what it does. |
18
+ | `analyze_office_file(path, *, only=None, severity_overrides=None, conditional_compilation=None, inline_suppression=True)` | Analyze the VBA in any readable Office container (Excel, Word, PowerPoint, Access, via pyOpenVBA); the extension selects the host model, and the project's reference list is read with its modules. |
19
19
  | `host_token_for_file_name(name)` | The host a container implies (`excel`, `word`, `powerpoint`, `access`), or `None`. |
20
- | `host_object_model_for_token(host)` | The model a host token selects: `None` for Excel (the default), the host's own model, or the empty model when a named host has none. |
21
- | `analyze_module_options_for(index, name, kind, *, severity_overrides=None, conditional_compilation=None, whole_project=True, inline_suppression=True, host=None)` | Build per-module `AnalyzeModuleOptions` from a populated `ProjectIndex`. |
20
+ | `host_object_model_for_token(host)` | The model a host token selects: `None` for Excel (the default), the host's own model (`word`, `powerpoint`, `access`, `vb6`), or the empty model when a named host has none. |
21
+ | `analyze_module_options_for(index, name, kind, *, severity_overrides=None, conditional_compilation=None, whole_project=True, inline_suppression=True, host=None, referenced_hosts=None)` | Build per-module `AnalyzeModuleOptions` from a populated `ProjectIndex`. |
22
22
  | `build_project_index(modules)` | A `ProjectIndex` with every module registered. |
23
23
  | `AnalyzeModuleOptions` | Inputs for `analyze_module` (name, kind, project context, overrides). |
24
24
  | `VbaDiagnostic` | A single diagnostic (`code`, `message`, `severity`, `span`, `spec_reference`). |
25
- | `ModuleInput` | One module fed into a project (`module_name`, `module_kind`, `source`). |
25
+ | `ModuleInput` | One module fed into a project (`module_name`, `module_kind`, `source`), plus what a caller that read the module's designer or attribute header knows: `implicit_members` (a UserForm's controls, as `ImplicitMember`s), `predeclared_id` and `designer_class`. Left `None`, the index reads what the source itself carries. |
26
26
  | `ModuleSymbolKind` | `STANDARD`, `CLASS`, `DOCUMENT`, `USERFORM`. |
27
27
  | `ProjectIndex` | The cross-module symbol/type index. |
28
28
  | `__version__` | The package version string. |
@@ -34,6 +34,12 @@ These are re-exported at the package root for convenience:
34
34
  * Result model: `VbaDiagnostic`, `VbaDiagnosticData`, `VbaEdit`, and the enums
35
35
  `DiagnosticSeverity`, `DiagnosticCategory`, `DiagnosticEvidenceKind`,
36
36
  `DiagnosticSuppressionScope`.
37
+ * Code-action payloads, carried on `VbaDiagnosticData`:
38
+ `VbaMissingRequiredArgumentPlaceholderData`, `VbaCreateProcedureStubData`,
39
+ `VbaAddLibraryReferenceData` (the library a `missing-library-reference` finding
40
+ needs), `VbaRemoveDeclarationData` and `VbaRemoveUnreachableCodeData` (the edit
41
+ that deletes an unused declaration or an unreachable run), and `VbaDocCommentFix`
42
+ (each way to bring a doc comment in line with its declaration).
37
43
  * Registry and metadata: `DIAGNOSTIC_RULE_REGISTRY`, `DiagnosticRuleEntry`,
38
44
  `STRUCTURAL_DIAGNOSTIC_RULES`, `DIAGNOSTIC_RULES`, `DiagnosticRuleMetadata`,
39
45
  `diagnostic_metadata_for_code`, `rule_metadata_by_code`, `load_rule_metadata`,
@@ -42,15 +48,25 @@ These are re-exported at the package root for convenience:
42
48
  ## Readers (`pyvbaanalysis.reader`)
43
49
 
44
50
  * High level: `analyze_loose_file`, `analyze_loose_files`, `analyze_workbook`,
45
- `load_loose_module`, `read_workbook_modules`.
51
+ `analyze_office_file`, `load_loose_module`, `read_workbook_modules`,
52
+ `read_office_modules`, `read_office_project`.
53
+ * `read_office_project(path)` returns an `OfficeProject`: the container's
54
+ `modules`, the `host` its extension implies, and `referenced_hosts`, the other
55
+ Office libraries its project references (`None` when the reference list could
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).
46
60
  * Building blocks: `LoadedModule`, `strip_export_header`, `classify_module_kind`,
47
61
  `module_name_from_text`, `loaded_module_from_text`, `WorkbookReadError`,
48
- `LOOSE_EXTENSIONS`, `EXCEL_EXTENSIONS`.
62
+ `LooseFileReadError`, and the extension sets `LOOSE_EXTENSIONS`,
63
+ `EXCEL_EXTENSIONS`, `WORD_EXTENSIONS`, `POWERPOINT_EXTENSIONS`,
64
+ `ACCESS_EXTENSIONS`, `OFFICE_EXTENSIONS`.
49
65
 
50
66
  ## Project model (`pyvbaanalysis.symbols`)
51
67
 
52
- * Index: `ProjectIndex`, `ProjectIndexOptions`, `ModuleInput`, `ReferenceScope`,
53
- `ShadowedSpan`.
68
+ * Index: `ProjectIndex`, `ProjectIndexOptions`, `ModuleInput`, `ImplicitMember`,
69
+ `ReferenceScope`, `ShadowedSpan`.
54
70
  * Module symbols: `build_module_symbols`, `BuildModuleSymbolsOptions`,
55
71
  `ModuleSymbols`, `ModuleSymbolKind`, `SymbolVisibility`, `VbaSymbol`,
56
72
  `VbaSymbolKind`, `VbaSymbolAttribute`, `VbaProcedureSignature`,
@@ -72,7 +88,9 @@ them directly, but they are public and stable.
72
88
  | `pyvbaanalysis.conditional` | Conditional-compilation indexing and activity (`index_conditional_compilation`, `evaluate_conditional_expression`, ...). |
73
89
  | `pyvbaanalysis.types` | Type-name helpers: `normalize_type`, `is_known_scalar_type`, `is_numeric_type`, `numeric_literal_bounds`. |
74
90
  | `pyvbaanalysis.completion` | Member-completion surface and project-type resolution (`resolve_member_surface_at`, `resolve_type_name`, ...). |
75
- | `pyvbaanalysis.host` | The Excel, Word, PowerPoint and Access host object models and the host registry (`get_excel_object_model`, `host_object_model_for_token`, `resolve_host_alias`, ...). |
91
+ | `pyvbaanalysis.host` | The Excel, Word, PowerPoint, Access and VB6 object models and the host registry (`get_excel_object_model`, `get_vb6_object_model`, `host_object_model_for_token`, `resolve_host_alias`, ...). `host_object_model_for_tokens` merges the models for a project and its references, the first token winning a shared name; `host_token_for_libid`, `host_tokens_for_project` and `referenced_host_tokens` map a project's reference libids to host tokens. `pyvbaanalysis.host.msforms` carries the Microsoft Forms members of a UserForm and its controls (`msforms_control_members`, `resolve_msforms_type_name`). |
92
+ | `pyvbaanalysis.references` | `classify_reference_kinds`: whether each mention of a name reads it, writes it, or modifies it in place. |
93
+ | `pyvbaanalysis.docs` | The `'''` doc-comment grammar: `leading_doc_lines`, `scan_doc_tags`, `attached_comments_start`. |
76
94
  | `pyvbaanalysis.runtime` | VBA runtime functions, constants, and objects (`resolve_runtime_function`, ...). |
77
95
  | `pyvbaanalysis.call` | Call-statement shape helpers. |
78
96
  | `pyvbaanalysis.flow` | Procedure labels and unstructured-flow detection. |
@@ -1,12 +1,12 @@
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 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.
3
+ The diagnostic codes pyVBAanalysis can emit, generated from the rule metadata (`tools/generate_diagnostics_catalogue.py`). This table lists the 131 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 134 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
 
7
7
  Override a code's severity with `AnalyzeModuleOptions.severity_overrides` (or the `severity_overrides` argument of `analyze_project` / the reader functions), keyed by code. Use `"off"`, `"information"`, `"warning"`, or `"error"`; the allowed values per code are constrained by policy (some codes can be downgraded but not disabled). See [docs/usage.md](usage.md).
8
8
 
9
- ## Declaration (41)
9
+ ## Declaration (42)
10
10
 
11
11
  | Code | Title | Default | Kind | Spec reference |
12
12
  | --- | --- | --- | --- | --- |
@@ -29,6 +29,7 @@ Override a code's severity with `AnalyzeModuleOptions.severity_overrides` (or th
29
29
  | `invalid-identifier-character` | Invalid character in identifier | error | compile error | MS-VBAL 3.3.5 (identifier) / VBE compiler |
30
30
  | `invalid-identifier-start` | Invalid identifier start | error | compile error | MS-VBAL 3.3.5 |
31
31
  | `invalid-new-type-name` | Type cannot be created with New | error | compile error | MS-VBAL 5.2.3.1 / 5.6.9 |
32
+ | `invalid-option-statement` | Malformed Option statement | error | compile error | MS-VBAL 5.2.1 (module options) / VBE compiler |
32
33
  | `invalid-proc-header` | Invalid procedure declaration | error | compile error | MS-VBAL 5.3.1 |
33
34
  | `module-declaration-after-procedure` | Module-level declaration after procedure | error | compile error | MS-VBAL 5.2 / 5.3 |
34
35
  | `module-declaration-in-procedure` | Module-level declaration inside procedure | error | compile error | MS-VBAL 5.2 / 5.3 |
@@ -57,7 +58,7 @@ Override a code's severity with `AnalyzeModuleOptions.severity_overrides` (or th
57
58
  | Code | Title | Default | Kind | Spec reference |
58
59
  | --- | --- | --- | --- | --- |
59
60
  | `event-declaration-module-kind` | Event declaration is not valid in this module | error | compile error | MS-VBAL 5.2.5: Event declarations belong to object modules |
60
- | `event-handler-module-scope` | Event handler is not wired in this module | information | style-policy | Excel document-module event binding |
61
+ | `event-handler-module-scope` | Event handler is not wired in this module | information | style-policy | Office document-module event binding |
61
62
  | `friend-declaration` | Invalid Friend declaration | error | compile error | MS-VBAL Friend procedure visibility: object-module procedures only |
62
63
  | `implements-statement-placement` | Invalid Implements statement | error | compile error | MS-VBAL Implements statement: module-level object-module declaration |
63
64
  | `withevents-declaration` | Invalid WithEvents declaration | error | compile error | MS-VBAL 5.2.3: WithEvents object variable declarations |
@@ -69,7 +70,7 @@ Override a code's severity with `AnalyzeModuleOptions.severity_overrides` (or th
69
70
  | `undeclared-variable` | Variable not defined | error | compile error | MS-VBAL 5.2.4.1.1 |
70
71
  | `unknown-call` | Sub or Function not defined | error | compile error | MS-VBAL 5.4.2.1 |
71
72
 
72
- ## Semantic (51)
73
+ ## Semantic (52)
73
74
 
74
75
  | Code | Title | Default | Kind | Spec reference |
75
76
  | --- | --- | --- | --- | --- |
@@ -105,6 +106,7 @@ Override a code's severity with `AnalyzeModuleOptions.severity_overrides` (or th
105
106
  | `member-access-outside-with` | Leading member access outside With block | error | compile error | MS-VBAL 5.4.2.6 |
106
107
  | `member-not-found` | Object member not found | error | compile error | VBE compiler: Method or data member not found |
107
108
  | `mid-statement-literal-target` | Mid statement target must be a writable String variable | error | compile error | MS-VBAL 5.4.3.4 (Mid/MidB statement) |
109
+ | `missing-library-reference` | Type library not referenced | error | compile error | VBE compiler: User-defined type not defined |
108
110
  | `missing-return-assignment` | Function has no return assignment | warning | runtime risk | VBA Function return variable semantics |
109
111
  | `next-variable-mismatch` | Next variable does not match active For loop | error | compile error | MS-VBAL 5.4.2.5 |
110
112
  | `non-callable-call` | Identifier is not callable | error | compile error | MS-VBAL 5.4.2.1 |
@@ -125,12 +127,22 @@ Override a code's severity with `AnalyzeModuleOptions.severity_overrides` (or th
125
127
  | `unallocated-dynamic-array-access` | Dynamic array is not allocated | error | runtime error | VBE runtime error 9: Subscript out of range |
126
128
  | `undefined-label` | Label not defined | error | compile error | MS-VBAL 5.4.1 / VBE compiler: Label not defined |
127
129
 
128
- ## Style (3)
130
+ ## Style (13)
129
131
 
130
132
  | Code | Title | Default | Kind | Spec reference |
131
133
  | --- | --- | --- | --- | --- |
132
134
  | `analysis-suppression-directive` | Invalid analysis suppression directive | warning | style-policy | Analysis suppression directive comment syntax |
135
+ | `doc-param-missing` | Doc comment does not describe a parameter | warning | style-policy | Doc comment syntax |
136
+ | `doc-param-unknown` | Doc comment describes a parameter the declaration does not have | warning | style-policy | Doc comment syntax |
137
+ | `doc-returns-missing` | Doc comment does not describe the return value | warning | style-policy | Doc comment syntax |
138
+ | `doc-returns-unexpected` | Doc comment describes a return value the declaration does not have | warning | style-policy | Doc comment syntax |
139
+ | `doc-tag-duplicate` | Doc comment repeats a tag | warning | style-policy | Doc comment syntax |
140
+ | `doc-tag-unclosed` | Doc comment tag is not closed | warning | style-policy | Doc comment syntax |
133
141
  | `option-explicit-missing` | Option Explicit is not specified | warning | style-policy | MS-VBAL 5.2.4.1.1 |
142
+ | `unreachable-code` | Code is never reached | information | style-policy | MS-VBAL 5.4.1.3 (Exit), 5.4.1.4 (GoTo), 5.4.4 (Resume) plus dead-code policy |
143
+ | `unused-procedure` | Private procedure is never called | information | style-policy | MS-VBAL 5.3.1.1 (Private procedure visibility) plus dead-code policy |
144
+ | `unused-variable` | Variable or constant is never used | information | style-policy | MS-VBAL 5.2.3 / 5.4.3.1 (declaration scope) plus dead-code policy |
145
+ | `variable-never-read` | Variable is assigned but never read | information | style-policy | MS-VBAL 5.4.3 (assignment) plus dead-code policy |
134
146
  | `vba-test-directive` | Invalid VBA test directive | warning | style-policy | VBA test directive comment syntax |
135
147
 
136
148
  ## Syntax (17)