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