pyvbaanalysis 2.2.1__tar.gz → 2.3.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.
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/.github/workflows/ci.yml +6 -6
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/.github/workflows/publish.yml +34 -4
- pyvbaanalysis-2.3.1/.github/workflows/security.yml +141 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/CHANGELOG.md +158 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/CONTRIBUTING.md +17 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/PKG-INFO +15 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/README.md +14 -0
- pyvbaanalysis-2.3.1/SECURITY.md +39 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/docs/diagnostics-catalogue.md +40 -6
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/docs/usage.md +3 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/__init__.py +1 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/cli.py +12 -2
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/completion/member_access.py +363 -86
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/conditional/__init__.py +2 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/conditional/conditional_compilation.py +50 -22
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/constants/integer_constant_expression.py +23 -9
- pyvbaanalysis-2.3.1/pyvbaanalysis/data/access_host_model.json +1 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/data/diagnostic_influence_audit.json +516 -3
- pyvbaanalysis-2.3.1/pyvbaanalysis/data/excel_host_model.json +1 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/data/host_closed_types.json +646 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/data/manifest.json +79 -11
- pyvbaanalysis-2.3.1/pyvbaanalysis/data/powerpoint_host_model.json +1 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/data/rule_metadata.json +395 -2
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/data/vba_runtime_tables.json +1 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/data/vbe_oracle_cases.json +2146 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/data/word_host_model.json +1 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/analyze_module.py +31 -8
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/argument_inference.py +73 -9
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/call_extraction.py +6 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/callable_signatures.py +37 -2
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/context.py +5 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/dataflow.py +101 -48
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/exprwalk.py +31 -30
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/known_locals.py +274 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/module_analysis.py +106 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/registry.py +48 -5
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/arrays.py +572 -86
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/assignments.py +176 -15
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/collection_state.py +399 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/control_flow.py +104 -81
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/dead_code.py +85 -73
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/declaration_forms.py +211 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/declarations.py +120 -46
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/directive_forms.py +105 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/duplicates.py +38 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/expressions.py +387 -17
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/file_statements.py +397 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/handler_flow.py +345 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/host_arguments.py +749 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/implements_members.py +275 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/late_bound_members.py +234 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/line_continuations.py +127 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/module_kind.py +28 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/numeric_literals.py +277 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/object_state.py +146 -14
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/overflow.py +1025 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/runtime_values.py +964 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/shared.py +27 -25
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/statement_forms.py +190 -0
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/stray_tokens.py +162 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/type_of_is.py +113 -22
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/undeclared.py +90 -10
- pyvbaanalysis-2.3.1/pyvbaanalysis/diagnostics/rules/variant_values.py +189 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/walker.py +18 -22
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/flow/procedure_labels.py +22 -11
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/flow/procedure_unstructured.py +6 -13
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/host/__init__.py +2 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/host/host_model.py +13 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/host/type_extensibility.py +36 -12
- pyvbaanalysis-2.3.1/pyvbaanalysis/js_compat.py +111 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/lexer/keyword_table.py +7 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/lexer/token_kinds.py +3 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/lexer/tokenize.py +20 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/parser/nodes.py +54 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/parser/parse_module.py +233 -39
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/parser/parser_state.py +49 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/runtime/vba_runtime.py +12 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/symbols/build_module_symbols.py +3 -7
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/symbols/name_resolution.py +25 -6
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/symbols/project_index.py +34 -6
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/symbols/symbol_model.py +5 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/types/type_inference.py +9 -5
- pyvbaanalysis-2.3.1/tests/test_analyzer_lexes_module_once.py +52 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_cli.py +18 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_conditional_arms.py +3 -2
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_dataflow.py +16 -0
- pyvbaanalysis-2.3.1/tests/test_deep_nesting.py +171 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_diagnostics_engine.py +3 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_evidence.py +2 -2
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_host_libraries.py +3 -1
- pyvbaanalysis-2.3.1/tests/test_member_access_chains.py +176 -0
- pyvbaanalysis-2.3.1/tests/test_module_analysis.py +122 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_registry_parity.py +12 -4
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rule_metadata.py +5 -5
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_argument_types.py +9 -2
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_assignments_types.py +5 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_control_flow.py +8 -3
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_declarations.py +3 -1
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_property_setter_value_parameters.py +10 -12
- pyvbaanalysis-2.3.1/tests/test_upstream_sync_10_12_0.py +721 -0
- pyvbaanalysis-2.3.1/tests/test_upstream_sync_10_13_0.py +45 -0
- pyvbaanalysis-2.3.1/tests/test_upstream_sync_10_14_0.py +294 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_upstream_sync_10_6_0.py +3 -3
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tools/extract_host_model.mjs +18 -6
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tools/generate_manifest.py +5 -2
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tools/vendor_data.py +8 -7
- pyvbaanalysis-2.2.1/pyvbaanalysis/data/access_host_model.json +0 -1
- pyvbaanalysis-2.2.1/pyvbaanalysis/data/excel_closed_types.json +0 -31
- pyvbaanalysis-2.2.1/pyvbaanalysis/data/excel_host_model.json +0 -1
- pyvbaanalysis-2.2.1/pyvbaanalysis/data/powerpoint_host_model.json +0 -1
- pyvbaanalysis-2.2.1/pyvbaanalysis/data/word_host_model.json +0 -1
- pyvbaanalysis-2.2.1/pyvbaanalysis/diagnostics/rules/numeric_literals.py +0 -49
- pyvbaanalysis-2.2.1/pyvbaanalysis/diagnostics/rules/runtime_values.py +0 -384
- pyvbaanalysis-2.2.1/tests/test_member_access_chains.py +0 -45
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/.gitattributes +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/.github/dependabot.yml +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/.gitignore +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/LICENSE +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/docs/api-reference.md +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyproject.toml +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/__main__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/call/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/call/call_context.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/completion/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/completion/cursor_context.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/completion/event_handlers.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/completion/type_completion.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/constants/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/data/event_definitions.json +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/data/msforms_members.json +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/data/vb6_host_model.json +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/const_expr.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/inline_suppression.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/model.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rule_metadata.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/argument_shape.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/argument_types.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/binary_operand_scalar.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/call_arity.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/doc_comments.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/late_binding.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/lexical.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/missing_reference.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/diagnostics/rules/parameter_defaults.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/docs/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/docs/doc_comment.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/evidence.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/flow/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/host/host_libraries.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/host/host_registry.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/host/msforms.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/identity_cache.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/lexer/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/lexer/contextual_keywords.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/lexer/stripped_lines.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/lexer/token_helpers.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/lexer/trivia.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/parser/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/parser/fixed_length_string.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/parser/parse_expression.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/parser/type_declaration_suffix.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/project.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/py.typed +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/reader/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/reader/loose_file.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/reader/vbe_module.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/reader/workbook.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/references/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/references/reference_kinds.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/runtime/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/symbols/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/symbols/user_form_controls.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/types/__init__.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/pyvbaanalysis/types/type_names.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/conftest.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/oracle_support.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_conditional_compilation.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_host_model.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_host_seam.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_inline_suppression.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_integer_constant_expression.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_language_matrix.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_lexer.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_parser.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_project.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_project_index.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_public_api.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_reader.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_real_world_false_positives.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_reference_kinds.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_ambiguous_enum_member.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_argument_shape.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_arrays.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_assignments.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_binary_operand_scalar.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_call_arity.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_dead_code.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_division_by_zero.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_doc_comments.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_duplicates.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_event_handler_module_scope.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_expression_calls.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_expressions.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_invalid_as_type_names.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_is_operator_non_object.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_late_binding.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_lexical.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_member_not_found.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_missing_reference.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_module_kind.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_numeric_literals.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_object_state.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_parameter_defaults.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_runtime_values.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_scalar_and_foreach.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_type_of_is.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_typeof_is_always_false.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_rules_undeclared.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_runtime_tables.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_statement_token_derivation.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_stripped_lines.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_symbols.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_token_helpers.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_type_completion.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_type_names.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_upstream_sync_10_5_0.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_upstream_sync_10_7_1.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tests/test_upstream_sync_6_1_2.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tools/extract_event_definitions.mjs +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tools/extract_rule_metadata.mjs +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tools/extract_runtime_tables.mjs +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tools/generate_diagnostics_catalogue.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tools/oracle/build_combining_mark_probe.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tools/pin_analyzer.py +0 -0
- {pyvbaanalysis-2.2.1 → pyvbaanalysis-2.3.1}/tools/xlide_source.mjs +0 -0
|
@@ -21,8 +21,8 @@ jobs:
|
|
|
21
21
|
name: Lint and type check
|
|
22
22
|
runs-on: ubuntu-latest
|
|
23
23
|
steps:
|
|
24
|
-
- uses: actions/checkout@v7
|
|
25
|
-
- uses: actions/setup-python@v7
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
25
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
26
26
|
with:
|
|
27
27
|
python-version: "3.12"
|
|
28
28
|
cache: pip
|
|
@@ -41,8 +41,8 @@ jobs:
|
|
|
41
41
|
matrix:
|
|
42
42
|
os: [ubuntu-latest, windows-latest]
|
|
43
43
|
steps:
|
|
44
|
-
- uses: actions/checkout@v7
|
|
45
|
-
- uses: actions/setup-python@v7
|
|
44
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
45
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
46
46
|
with:
|
|
47
47
|
python-version: "3.12"
|
|
48
48
|
cache: pip
|
|
@@ -62,8 +62,8 @@ jobs:
|
|
|
62
62
|
matrix:
|
|
63
63
|
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
64
64
|
steps:
|
|
65
|
-
- uses: actions/checkout@v7
|
|
66
|
-
- uses: actions/setup-python@v7
|
|
65
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
66
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
67
67
|
with:
|
|
68
68
|
python-version: ${{ matrix.python-version }}
|
|
69
69
|
cache: pip
|
|
@@ -20,8 +20,18 @@ permissions:
|
|
|
20
20
|
contents: read
|
|
21
21
|
|
|
22
22
|
jobs:
|
|
23
|
+
# CodeQL, Semgrep and pip-audit (security.yml). Any finding fails this job,
|
|
24
|
+
# and publishing waits on it.
|
|
25
|
+
security:
|
|
26
|
+
name: Security analysis
|
|
27
|
+
uses: ./.github/workflows/security.yml
|
|
28
|
+
permissions:
|
|
29
|
+
contents: read
|
|
30
|
+
security-events: write
|
|
31
|
+
|
|
23
32
|
publish:
|
|
24
33
|
name: Build and publish to PyPI
|
|
34
|
+
needs: security
|
|
25
35
|
runs-on: ubuntu-latest
|
|
26
36
|
environment:
|
|
27
37
|
name: pypi
|
|
@@ -29,8 +39,8 @@ jobs:
|
|
|
29
39
|
permissions:
|
|
30
40
|
id-token: write # OIDC token for PyPI Trusted Publishing
|
|
31
41
|
steps:
|
|
32
|
-
- uses: actions/checkout@v7
|
|
33
|
-
- uses: actions/setup-python@v7
|
|
42
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
43
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
34
44
|
with:
|
|
35
45
|
python-version: "3.12"
|
|
36
46
|
cache: pip
|
|
@@ -45,9 +55,29 @@ jobs:
|
|
|
45
55
|
- name: Build sdist + wheel
|
|
46
56
|
run: python -m build
|
|
47
57
|
- name: Upload build artifacts
|
|
48
|
-
uses: actions/upload-artifact@v7
|
|
58
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
49
59
|
with:
|
|
50
60
|
name: dist
|
|
51
61
|
path: dist/*
|
|
52
62
|
- name: Publish to PyPI
|
|
53
|
-
uses: pypa/gh-action-pypi-publish@release/v1
|
|
63
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
64
|
+
|
|
65
|
+
attach-security-report:
|
|
66
|
+
name: Attach the security report to the release
|
|
67
|
+
needs: [security, publish]
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
permissions:
|
|
70
|
+
contents: write
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
|
|
73
|
+
with:
|
|
74
|
+
name: security-report
|
|
75
|
+
path: report
|
|
76
|
+
- name: Upload to the release
|
|
77
|
+
env:
|
|
78
|
+
GH_TOKEN: ${{ github.token }}
|
|
79
|
+
TAG: ${{ github.event.release.tag_name }}
|
|
80
|
+
run: |
|
|
81
|
+
cd report
|
|
82
|
+
tar -czf security-sarif.tar.gz *.sarif *.json
|
|
83
|
+
gh release upload "$TAG" security-report.md security-sarif.tar.gz --clobber --repo "$GITHUB_REPOSITORY"
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
name: Security
|
|
2
|
+
|
|
3
|
+
# Static security analysis: CodeQL (Python and the workflows themselves),
|
|
4
|
+
# Semgrep, and pip-audit over the runtime dependency tree. Any finding fails
|
|
5
|
+
# the run. Results go to the repository's Security tab as SARIF and to a
|
|
6
|
+
# `security-report` artifact, which publish.yml attaches to every release.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
branches: [main]
|
|
11
|
+
pull_request:
|
|
12
|
+
schedule:
|
|
13
|
+
- cron: "17 6 * * 1" # weekly, so new advisories surface between pushes
|
|
14
|
+
workflow_call:
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
codeql:
|
|
21
|
+
name: CodeQL (${{ matrix.language }})
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
security-events: write
|
|
26
|
+
strategy:
|
|
27
|
+
fail-fast: false
|
|
28
|
+
matrix:
|
|
29
|
+
language: [python, actions]
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
32
|
+
- uses: github/codeql-action/init@1190a975f95ce23525efb6a3fc21ea29567c1b52 # v3
|
|
33
|
+
with:
|
|
34
|
+
languages: ${{ matrix.language }}
|
|
35
|
+
queries: security-extended
|
|
36
|
+
- uses: github/codeql-action/analyze@1190a975f95ce23525efb6a3fc21ea29567c1b52 # v3
|
|
37
|
+
with:
|
|
38
|
+
category: codeql-${{ matrix.language }}
|
|
39
|
+
output: sarif
|
|
40
|
+
- name: Fail on any finding
|
|
41
|
+
run: |
|
|
42
|
+
count=$(jq '[.runs[].results[]] | length' sarif/*.sarif)
|
|
43
|
+
echo "CodeQL ${{ matrix.language }}: $count finding(s)"
|
|
44
|
+
jq -r '.runs[].results[] | "\(.ruleId): \(.locations[0].physicalLocation.artifactLocation.uri):\(.locations[0].physicalLocation.region.startLine) \(.message.text)"' sarif/*.sarif
|
|
45
|
+
test "$count" -eq 0
|
|
46
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
47
|
+
if: always()
|
|
48
|
+
with:
|
|
49
|
+
name: sarif-codeql-${{ matrix.language }}
|
|
50
|
+
path: sarif/*.sarif
|
|
51
|
+
|
|
52
|
+
semgrep:
|
|
53
|
+
name: Semgrep
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
permissions:
|
|
56
|
+
contents: read
|
|
57
|
+
security-events: write
|
|
58
|
+
steps:
|
|
59
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
60
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
61
|
+
with:
|
|
62
|
+
python-version: "3.12"
|
|
63
|
+
- run: python -m pip install "semgrep>=1,<2"
|
|
64
|
+
- name: Scan (fails on any finding)
|
|
65
|
+
run: >
|
|
66
|
+
semgrep scan --metrics off --error
|
|
67
|
+
--config p/python --config p/security-audit
|
|
68
|
+
--config p/secrets --config p/github-actions
|
|
69
|
+
--sarif-output semgrep.sarif --text
|
|
70
|
+
- uses: github/codeql-action/upload-sarif@1190a975f95ce23525efb6a3fc21ea29567c1b52 # v3
|
|
71
|
+
if: always() && hashFiles('semgrep.sarif') != ''
|
|
72
|
+
with:
|
|
73
|
+
sarif_file: semgrep.sarif
|
|
74
|
+
category: semgrep
|
|
75
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
76
|
+
if: always()
|
|
77
|
+
with:
|
|
78
|
+
name: sarif-semgrep
|
|
79
|
+
path: semgrep.sarif
|
|
80
|
+
|
|
81
|
+
dependencies:
|
|
82
|
+
name: Dependency audit
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
86
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
|
|
87
|
+
with:
|
|
88
|
+
python-version: "3.12"
|
|
89
|
+
# The runtime tree without pyvbaanalysis itself, whose version is not on
|
|
90
|
+
# PyPI until the release that ships it; frozen before pip-audit is added.
|
|
91
|
+
- run: |
|
|
92
|
+
python -m pip install .
|
|
93
|
+
python -m pip freeze --exclude pyvbaanalysis > runtime.txt
|
|
94
|
+
cat runtime.txt
|
|
95
|
+
python -m pip install pip-audit
|
|
96
|
+
- name: Audit the runtime dependencies (fails on any known vulnerability)
|
|
97
|
+
run: pip-audit --strict --no-deps -r runtime.txt --format json --output pip-audit.json --progress-spinner off
|
|
98
|
+
- if: always()
|
|
99
|
+
run: pip-audit --strict --no-deps -r runtime.txt --progress-spinner off || true
|
|
100
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
101
|
+
if: always()
|
|
102
|
+
with:
|
|
103
|
+
name: pip-audit
|
|
104
|
+
path: pip-audit.json
|
|
105
|
+
|
|
106
|
+
report:
|
|
107
|
+
name: Security report
|
|
108
|
+
needs: [codeql, semgrep, dependencies]
|
|
109
|
+
if: always()
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
steps:
|
|
112
|
+
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
|
|
113
|
+
with:
|
|
114
|
+
path: results
|
|
115
|
+
merge-multiple: true
|
|
116
|
+
- name: Write the report
|
|
117
|
+
env:
|
|
118
|
+
CODEQL: ${{ needs.codeql.result }}
|
|
119
|
+
SEMGREP: ${{ needs.semgrep.result }}
|
|
120
|
+
DEPS: ${{ needs.dependencies.result }}
|
|
121
|
+
run: |
|
|
122
|
+
count() { if [ -f "$1" ]; then jq '[.runs[].results[]] | length' "$1"; else echo "not run"; fi; }
|
|
123
|
+
vulns=$(if [ -f results/pip-audit.json ]; then jq '[.dependencies[].vulns[]] | length' results/pip-audit.json; else echo "not run"; fi)
|
|
124
|
+
{
|
|
125
|
+
echo "# Security report"
|
|
126
|
+
echo
|
|
127
|
+
echo "Commit \`${GITHUB_SHA}\`, run ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
|
|
128
|
+
echo
|
|
129
|
+
echo "| Check | Result | Findings |"
|
|
130
|
+
echo "| --- | --- | --- |"
|
|
131
|
+
echo "| CodeQL (Python, security-extended) | $CODEQL | $(count results/python.sarif) |"
|
|
132
|
+
echo "| CodeQL (GitHub Actions) | $CODEQL | $(count results/actions.sarif) |"
|
|
133
|
+
echo "| Semgrep (python, security-audit, secrets, github-actions) | $SEMGREP | $(count results/semgrep.sarif) |"
|
|
134
|
+
echo "| pip-audit (runtime dependencies) | $DEPS | $vulns |"
|
|
135
|
+
} > security-report.md
|
|
136
|
+
mkdir -p report && cp security-report.md report/ && cp results/*.sarif results/*.json report/ 2>/dev/null || true
|
|
137
|
+
cat security-report.md >> "$GITHUB_STEP_SUMMARY"
|
|
138
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
139
|
+
with:
|
|
140
|
+
name: security-report
|
|
141
|
+
path: report/
|
|
@@ -5,6 +5,164 @@ 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.3.1 - 2026-09-28
|
|
9
|
+
|
|
10
|
+
Sync to XLIDE 10.14.1 (commit 67b844d), from 10.14.0, and a command-line flag
|
|
11
|
+
for projects that ship as one file.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
* `--whole-project` on the command line runs the whole-project checks
|
|
16
|
+
(`undeclared-variable`, `unknown-call`, `member-not-found`) on any input,
|
|
17
|
+
a single file included, such as a single-module distribution. It cannot be
|
|
18
|
+
combined with `--partial-project`, and the default is unchanged (#15).
|
|
19
|
+
* Security checks. CodeQL, Semgrep and pip-audit run on every push and pull
|
|
20
|
+
request and weekly, and any finding fails the run. A release reaches PyPI
|
|
21
|
+
only when all three pass, and it carries `security-report.md` and the raw
|
|
22
|
+
results as assets. `SECURITY.md` describes private vulnerability reporting.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
* `property-accessor-signature-mismatch` on a Property Set beside a Get of
|
|
27
|
+
another type, such as a Variant Get with an Object Set. Excel compiles it:
|
|
28
|
+
a Set's value is never compared with the Get. A Let must still match its Get
|
|
29
|
+
(XLIDE issue #152).
|
|
30
|
+
|
|
31
|
+
### Verified
|
|
32
|
+
|
|
33
|
+
* The oracle corpus (2251 diagnostics in 1289 modules), 16 real workbooks, 195
|
|
34
|
+
Office files, 693 further projects and 7 VB6 projects give identical findings
|
|
35
|
+
from both analyzers at 10.14.1. The recorded replay of upstream's test suite
|
|
36
|
+
did not run for this release.
|
|
37
|
+
|
|
38
|
+
## 2.3.0 - 2026-09-26
|
|
39
|
+
|
|
40
|
+
Sync to XLIDE 10.14.0 (commit 110c76e), from 10.7.1. Upstream measured the
|
|
41
|
+
analyzer against Excel, Word and PowerPoint 16.0 (build 20326) through
|
|
42
|
+
pyVBAharness and answered each finding (XLIDE issues #96 to #148): 34 new
|
|
43
|
+
diagnostics, 19 of them runtime errors in code the VBE compiles, and false
|
|
44
|
+
positives removed on code that compiles and runs. XLIDE 10.7.2, 10.8.0, 10.11.0
|
|
45
|
+
and 10.12.0 changed nothing the port reads.
|
|
46
|
+
|
|
47
|
+
The port now returns what XLIDE shows, not its raw rule list, and it analyzes
|
|
48
|
+
procedures nested past Python's recursion limit and long With blocks and member
|
|
49
|
+
chains in linear time.
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
* Nineteen runtime errors in code the VBE compiles, each reported as "This will
|
|
54
|
+
raise Run-time error ...":
|
|
55
|
+
* Overflow (#116): `arithmetic-overflow` for Integer arithmetic such as
|
|
56
|
+
`60 * 60 * 24`, an assignment that rounds past its target, and conversions
|
|
57
|
+
out of range; `for-counter-overflow` for `For i = 1 To 32767` on an Integer.
|
|
58
|
+
* Control flow (#117): `handler-fall-through` into an error handler that
|
|
59
|
+
re-raises, `resume-without-error`, `return-without-gosub`, and
|
|
60
|
+
`recursive-property-accessor`.
|
|
61
|
+
* Collections and Variants (#121): `collection-index-out-of-range`,
|
|
62
|
+
`collection-key-not-found`, `collection-key-in-use`, `variant-value-misuse`
|
|
63
|
+
and `runtime-member-not-found` (438 on a late-bound object).
|
|
64
|
+
* Host arguments (#122): `host-argument-out-of-range` for index 0 into a
|
|
65
|
+
1-based Office collection, `Cells(0, 1)` or an Offset off the sheet;
|
|
66
|
+
`multi-cell-range-as-scalar`; `sheet-name-invalid`.
|
|
67
|
+
* File statements (#123): `file-number-zero`, `file-used-after-close`,
|
|
68
|
+
`file-mode-mismatch`, `file-already-open` and `file-record-zero`.
|
|
69
|
+
* Fifteen compile errors: `const-overflow` (#116); `array-parameter-form`,
|
|
70
|
+
`bracketed-variable-name` and `duplicate-deftype` (#124);
|
|
71
|
+
`collection-operand`, `sub-used-as-value`, `implements-member-missing`,
|
|
72
|
+
`implements-member-signature` and `rem-after-then` (#125);
|
|
73
|
+
`directive-trailing-statement` and `duplicate-const-directive` (#130);
|
|
74
|
+
`stray-character` for characters VBA does not use and a no-break space
|
|
75
|
+
(#132); `line-too-long`, `date-literal-invalid` and `float-literal-overflow`
|
|
76
|
+
(#133).
|
|
77
|
+
* Existing rules report more of what the code states (#118 to #120, #124 to
|
|
78
|
+
#126): `Asc("")`, `Sqr(-1)`, `Log(0)`, `CLng("abc")`, `"abc" + 1` into a
|
|
79
|
+
Variant, a divisor local that holds 0, array bounds known from `Split`,
|
|
80
|
+
`Array` or a Range literal's `Value`, `ReDim a(-1)`, `Next i, j` out of
|
|
81
|
+
order, and the line continuations the VBE refuses.
|
|
82
|
+
* `AnalyzeModuleOptions.raw_rule_output`: the rules' own list, as upstream's
|
|
83
|
+
`analyzeModule` returns it, without the two steps below.
|
|
84
|
+
* `resolve_host_member` in `pyvbaanalysis.host`, and `declaredType` on a host
|
|
85
|
+
model member: the type its library declares, where the model's `returns`
|
|
86
|
+
is repaired from the reference documentation.
|
|
87
|
+
|
|
88
|
+
### Changed
|
|
89
|
+
|
|
90
|
+
* `analyze_module`, and everything built on it, returns what XLIDE shows. A
|
|
91
|
+
runtime-error finding under `On Error Resume Next`, from that statement to the
|
|
92
|
+
next `On Error` or the end of the procedure, is dropped, since the error is
|
|
93
|
+
raised and handled there (`n = UBound(a)` is the usual allocated-array
|
|
94
|
+
test, XLIDE issue #106). Findings with one code and span are merged, the later
|
|
95
|
+
one kept. `diagnostics/module_analysis.py` ports both from XLIDE's
|
|
96
|
+
`analyzeVbaModuleSource`.
|
|
97
|
+
* `member-not-found` works in Word, PowerPoint and Access: their models carry
|
|
98
|
+
the type libraries' hidden members and prove a member absent where the
|
|
99
|
+
library marks the interface NONEXTENSIBLE (#127). Document, Form, Report and
|
|
100
|
+
Control stay open. The data file `excel_closed_types.json` is replaced by
|
|
101
|
+
`host_closed_types.json`, which covers all four hosts.
|
|
102
|
+
* A host member the type library declares `As Object`, such as `ActiveSheet`
|
|
103
|
+
or a `Worksheets(1)` item, is late bound (#114).
|
|
104
|
+
* A hex or octal literal is the signed value of its bits: `&H8000` is -32768
|
|
105
|
+
and `&H80000000` is -2147483648 (#141). `parse_vba_integer_literal` returns
|
|
106
|
+
that value.
|
|
107
|
+
* The parser opens and closes a block written in a one-line If's tail (#128),
|
|
108
|
+
reads `Else:` as the If's Else (#129), counts a block keyword restated in both
|
|
109
|
+
arms of an `#If` once (#130), and reads a numbered one-line If with an `=`
|
|
110
|
+
condition as an If (#131).
|
|
111
|
+
* An Enum value or Optional default keeps its leading number, so `= 300 - 100`
|
|
112
|
+
is not the literal -100, and a module's Consts fold once with a procedure's
|
|
113
|
+
own Consts layered on top (XLIDE 10.13.0).
|
|
114
|
+
|
|
115
|
+
### Fixed
|
|
116
|
+
|
|
117
|
+
* False positives on code the VBE compiles and runs (#96 to #115): `Choose` and
|
|
118
|
+
`Switch` arity, `Open path` without `For`, `On Local Error`, a ReDim that
|
|
119
|
+
declares its array, `total&+1`, a library qualifier such as `Excel.`, a
|
|
120
|
+
`#Const` never defined, DAO constants in Access, `Left(Null, 1)`, a string
|
|
121
|
+
into a Byte array, a division the code guards, the Let and Set pairings of a
|
|
122
|
+
property, Nothing tracking past a GoSub or an early `Exit For`, two project
|
|
123
|
+
types sharing an instance, a Public Enum in a class, a Const or parenthesized
|
|
124
|
+
ByRef argument, `Len` in an Enum value, Option placement after a Deftype, and
|
|
125
|
+
a Function's return assigned by For, ReDim, `Line Input #` or `Get #`.
|
|
126
|
+
* False positives found by this port's own hunt and fixed upstream in 10.14.0
|
|
127
|
+
(#140 to #147): `If c Is Nothing Then Set c = New Collection`, `Set a(i) = c`
|
|
128
|
+
and `AddressOf` a Sub reported as compile errors; Win32 flag Enums such as
|
|
129
|
+
`GENERIC_READ = &H80000000` as Overflow; `Err.Raise vbObjectError + 513` as
|
|
130
|
+
error 5; the `;` of `If x Then Debug.Print a; b`; a string default holding a
|
|
131
|
+
comma in an Implements signature; `32000 \ 2 * 4` folded at the wrong
|
|
132
|
+
precedence; a For counter in a loop that leaves through `Exit For`; a file
|
|
133
|
+
reopened after `Reset` or a closing helper, an error handler's `Print #`,
|
|
134
|
+
and hex file numbers; and an item added through `Set o = c`.
|
|
135
|
+
* Misses from the same issues: `1 Mod 200 * 200` (error 6), `Resume Next`
|
|
136
|
+
after `On Error GoTo -1` (20), a `Print #` after `Reset` (52), a duplicate
|
|
137
|
+
key added through an alias (457), and a read-write interface property
|
|
138
|
+
implemented with its Get alone.
|
|
139
|
+
* `analyze_project` raised RecursionError on a procedure nested about 490 blocks
|
|
140
|
+
deep, where the VBE compiles a thousand. Every walk over a procedure body now
|
|
141
|
+
runs on an explicit stack, and `tests/test_deep_nesting.py` fails on one that
|
|
142
|
+
recurses per block.
|
|
143
|
+
|
|
144
|
+
### Performance
|
|
145
|
+
|
|
146
|
+
* A long With block and a long member chain are analyzed in linear time: the
|
|
147
|
+
pass keeps upstream's With-scan index (XLIDE issue #134) and receiver-chain
|
|
148
|
+
results (#135). A 500-line With block took 14.2 seconds in 2.2.1 and takes
|
|
149
|
+
0.19; a 3,000-member chain took 16 seconds and takes 0.56.
|
|
150
|
+
* Expression strings the parser carried on their own are lexed without
|
|
151
|
+
evicting the module from the token cache, and a test fails if one pass lexes
|
|
152
|
+
a module twice (#139). On two parts of the differential corpus's Office files
|
|
153
|
+
(66 modules), 2.3.0 is 12% faster than 2.2.1, new rules included.
|
|
154
|
+
|
|
155
|
+
### Verified
|
|
156
|
+
|
|
157
|
+
* Upstream's own 10.14.0 test suite, recorded and replayed through the port:
|
|
158
|
+
1419 standalone and 992 project calls, identical in code, span and message.
|
|
159
|
+
* The oracle corpus (2155 diagnostics in 1229 modules), 16 real workbooks, 195
|
|
160
|
+
Office files of every host, 693 further projects (948 modules) and 7 VB6
|
|
161
|
+
projects: identical findings from both analyzers, compared at what XLIDE
|
|
162
|
+
shows.
|
|
163
|
+
* Every expectation in the new sync tests was also run through the pinned
|
|
164
|
+
upstream analyzer.
|
|
165
|
+
|
|
8
166
|
## 2.2.1 - 2026-09-23
|
|
9
167
|
|
|
10
168
|
Sync to XLIDE 10.7.1 (commit 6ead73d), from 10.6.0. Upstream fixed how its
|
|
@@ -80,7 +80,8 @@ python tools/differential/harness.py projects artifacts/differential/cases/mine.
|
|
|
80
80
|
the port, rebuilding the project index behind a call made with project context,
|
|
81
81
|
and compares the diagnostics by code, span and message. It finds the gaps
|
|
82
82
|
nothing else exercises: whole checks never ported, fixes older than the last
|
|
83
|
-
sync point.
|
|
83
|
+
sync point. The recorded calls are the rules alone, so the port is asked for its
|
|
84
|
+
`raw_rule_output`.
|
|
84
85
|
* `corpus` runs the oracle corpus through both analyzers, each module standalone
|
|
85
86
|
and with its case's modules as a project.
|
|
86
87
|
* `cases` turns Office files, and folders searched for them and for exported
|
|
@@ -88,6 +89,16 @@ python tools/differential/harness.py projects artifacts/differential/cases/mine.
|
|
|
88
89
|
block of upstream's syntax corpus, and `--host` names a host for the cases no
|
|
89
90
|
file implies one for. `projects` runs a cases file through both analyzers.
|
|
90
91
|
|
|
92
|
+
`corpus` and `projects` compare what XLIDE shows. Upstream runs its rules
|
|
93
|
+
through `analyzeVbaModuleSource`, which drops a runtime-error finding under
|
|
94
|
+
`On Error Resume Next` and merges findings with one code and span, as
|
|
95
|
+
`analyze_module` does (`pyvbaanalysis/diagnostics/module_analysis.py`). Its own
|
|
96
|
+
additions the port leaves out, the structural block-balance pass and XLIDE's test
|
|
97
|
+
and suppression directives, are cut from its list by keeping only what its rules
|
|
98
|
+
produced (`tools/differential/upstream/shown.mjs`). One step the port lacks does
|
|
99
|
+
remove findings: a procedure marked `'@xlide-test expected-error=N` hides a runtime
|
|
100
|
+
finding for error N. No corpus has one.
|
|
101
|
+
|
|
91
102
|
`replay`, `corpus` and `projects` exit 1 when anything differs and print what only
|
|
92
103
|
one side reports. Where the port reports more, the port is wrong. Where upstream
|
|
93
104
|
reports more it may be an upstream false positive, so check before porting it.
|
|
@@ -104,6 +115,11 @@ run ends. `harness.py unpatch` restores a pin a run left patched, and
|
|
|
104
115
|
## Adding or changing a rule
|
|
105
116
|
|
|
106
117
|
* Port the rule from its XLIDE source; match the behavior, not just the shape.
|
|
118
|
+
* Walk a procedure body with `iter_body_nodes` or `iter_body_nodes_in_context`
|
|
119
|
+
(`pyvbaanalysis/parser/nodes.py`), not with a function that calls itself for
|
|
120
|
+
each nested block. XLIDE's walks recurse, which JavaScript's stack absorbs;
|
|
121
|
+
Python stops at 1,000 frames, and the VBE compiles blocks nested a thousand
|
|
122
|
+
deep. `tests/test_deep_nesting.py` fails on a walk that recurses per block.
|
|
107
123
|
* A rule ships only with oracle backing. Validate it against the vendored corpus
|
|
108
124
|
and add direct tests for the positive and the no-false-positive control cases.
|
|
109
125
|
* The diagnostic rule registry order is a contract: it is the diagnostic
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pyvbaanalysis
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.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
|
|
@@ -29,6 +29,12 @@ Description-Content-Type: text/markdown
|
|
|
29
29
|
|
|
30
30
|
# pyVBAanalysis
|
|
31
31
|
|
|
32
|
+
[](https://github.com/WilliamSmithEdward/pyVBAanalysis/actions/workflows/ci.yml)
|
|
33
|
+
[](https://github.com/WilliamSmithEdward/pyVBAanalysis/actions/workflows/security.yml)
|
|
34
|
+
[](https://pypi.org/project/pyvbaanalysis/)
|
|
35
|
+
[](https://pypi.org/project/pyvbaanalysis/)
|
|
36
|
+
[](LICENSE)
|
|
37
|
+
|
|
32
38
|
Static analysis for Office VBA. It reads your macros and reports likely bugs and the
|
|
33
39
|
errors the VBA compiler would catch, without opening Office or running any code.
|
|
34
40
|
|
|
@@ -135,6 +141,14 @@ an agent that changes a macro runs them afterwards and treats an error
|
|
|
135
141
|
as a failure rather than a suggestion, which is most of what stops a
|
|
136
142
|
model shipping VBA that does not compile.
|
|
137
143
|
|
|
144
|
+
## Security
|
|
145
|
+
|
|
146
|
+
Report a vulnerability privately through
|
|
147
|
+
[GitHub's advisory form](https://github.com/WilliamSmithEdward/pyVBAanalysis/security/advisories/new),
|
|
148
|
+
not a public issue. CodeQL, Semgrep and pip-audit run on every push and gate
|
|
149
|
+
every release, and each release carries its security report. See
|
|
150
|
+
[SECURITY.md](SECURITY.md).
|
|
151
|
+
|
|
138
152
|
## License
|
|
139
153
|
|
|
140
154
|
MIT. See [LICENSE](LICENSE).
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# pyVBAanalysis
|
|
2
2
|
|
|
3
|
+
[](https://github.com/WilliamSmithEdward/pyVBAanalysis/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/WilliamSmithEdward/pyVBAanalysis/actions/workflows/security.yml)
|
|
5
|
+
[](https://pypi.org/project/pyvbaanalysis/)
|
|
6
|
+
[](https://pypi.org/project/pyvbaanalysis/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
3
9
|
Static analysis for Office VBA. It reads your macros and reports likely bugs and the
|
|
4
10
|
errors the VBA compiler would catch, without opening Office or running any code.
|
|
5
11
|
|
|
@@ -106,6 +112,14 @@ an agent that changes a macro runs them afterwards and treats an error
|
|
|
106
112
|
as a failure rather than a suggestion, which is most of what stops a
|
|
107
113
|
model shipping VBA that does not compile.
|
|
108
114
|
|
|
115
|
+
## Security
|
|
116
|
+
|
|
117
|
+
Report a vulnerability privately through
|
|
118
|
+
[GitHub's advisory form](https://github.com/WilliamSmithEdward/pyVBAanalysis/security/advisories/new),
|
|
119
|
+
not a public issue. CodeQL, Semgrep and pip-audit run on every push and gate
|
|
120
|
+
every release, and each release carries its security report. See
|
|
121
|
+
[SECURITY.md](SECURITY.md).
|
|
122
|
+
|
|
109
123
|
## License
|
|
110
124
|
|
|
111
125
|
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Security fixes go into the latest release on PyPI. Upgrade to it before
|
|
6
|
+
reporting a problem.
|
|
7
|
+
|
|
8
|
+
## Reporting a vulnerability
|
|
9
|
+
|
|
10
|
+
Report privately through GitHub:
|
|
11
|
+
[Security > Report a vulnerability](https://github.com/WilliamSmithEdward/pyVBAanalysis/security/advisories/new).
|
|
12
|
+
Please do not open a public issue for a vulnerability.
|
|
13
|
+
|
|
14
|
+
Include the version, what you ran, the input that triggers the problem (a
|
|
15
|
+
minimal module or file if you can share one), and what happened. You will get a
|
|
16
|
+
reply within a week.
|
|
17
|
+
|
|
18
|
+
## What counts
|
|
19
|
+
|
|
20
|
+
pyVBAanalysis reads Office files and VBA source and never runs them. A file
|
|
21
|
+
that makes the reader or the analyzer crash, hang, use unbounded memory, write
|
|
22
|
+
outside where it was asked to, or run code is a vulnerability. A wrong or
|
|
23
|
+
missing diagnostic is an ordinary bug; open an issue for it.
|
|
24
|
+
|
|
25
|
+
## How the code is checked
|
|
26
|
+
|
|
27
|
+
Every push, pull request and release runs [security.yml](.github/workflows/security.yml):
|
|
28
|
+
|
|
29
|
+
- CodeQL with the `security-extended` queries, over the Python package and the
|
|
30
|
+
GitHub Actions workflows.
|
|
31
|
+
- Semgrep with the `python`, `security-audit`, `secrets` and `github-actions`
|
|
32
|
+
rule sets.
|
|
33
|
+
- pip-audit over the runtime dependencies.
|
|
34
|
+
|
|
35
|
+
Any finding fails the run, and a release is not published to PyPI until all
|
|
36
|
+
three pass. Each release carries the resulting `security-report.md` and the raw
|
|
37
|
+
SARIF and pip-audit output as assets. Dependabot keeps the dependencies and the
|
|
38
|
+
workflow actions current, and the run repeats weekly so new advisories surface
|
|
39
|
+
between releases.
|