pyvbaanalysis 1.0.0__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-1.0.0/.gitattributes +3 -0
- pyvbaanalysis-1.0.0/.github/dependabot.yml +13 -0
- pyvbaanalysis-1.0.0/.github/workflows/ci.yml +52 -0
- pyvbaanalysis-1.0.0/.github/workflows/publish.yml +53 -0
- pyvbaanalysis-1.0.0/.gitignore +36 -0
- pyvbaanalysis-1.0.0/CHANGELOG.md +47 -0
- pyvbaanalysis-1.0.0/CONTRIBUTING.md +105 -0
- pyvbaanalysis-1.0.0/LICENSE +21 -0
- pyvbaanalysis-1.0.0/PKG-INFO +120 -0
- pyvbaanalysis-1.0.0/README.md +91 -0
- pyvbaanalysis-1.0.0/docs/api-reference.md +86 -0
- pyvbaanalysis-1.0.0/docs/diagnostics-catalogue.md +152 -0
- pyvbaanalysis-1.0.0/docs/usage.md +225 -0
- pyvbaanalysis-1.0.0/pyproject.toml +80 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/__init__.py +59 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/__main__.py +8 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/call/__init__.py +23 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/call/call_context.py +296 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/cli.py +352 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/completion/__init__.py +49 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/completion/cursor_context.py +26 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/completion/event_handlers.py +82 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/completion/member_access.py +1097 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/completion/type_completion.py +228 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/conditional/__init__.py +41 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/conditional/conditional_compilation.py +531 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/constants/__init__.py +21 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/constants/integer_constant_expression.py +226 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/data/diagnostic_influence_audit.json +1786 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/data/event_definitions.json +1 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/data/excel_host_model.json +1 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/data/manifest.json +257 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/data/rule_metadata.json +1287 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/data/vba_runtime_tables.json +1 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/data/vbe_oracle_cases.json +4578 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/__init__.py +59 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/analyze_module.py +177 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/argument_inference.py +706 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/call_extraction.py +380 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/callable_signatures.py +443 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/const_expr.py +134 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/context.py +130 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/dataflow.py +242 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/exprwalk.py +110 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/model.py +108 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/registry.py +263 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rule_metadata.py +243 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/__init__.py +2 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/argument_shape.py +204 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/argument_types.py +80 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/arrays.py +1000 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/assignments.py +650 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/binary_operand_scalar.py +75 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/call_arity.py +114 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/control_flow.py +651 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/declarations.py +1642 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/duplicates.py +311 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/expressions.py +679 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/lexical.py +185 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/module_kind.py +389 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/numeric_literals.py +49 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/object_state.py +327 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/parameter_defaults.py +92 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/runtime_values.py +382 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/shared.py +441 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/type_of_is.py +312 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/rules/undeclared.py +503 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/diagnostics/walker.py +347 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/evidence.py +111 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/flow/__init__.py +21 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/flow/procedure_labels.py +274 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/flow/procedure_unstructured.py +65 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/host/__init__.py +41 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/host/host_model.py +209 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/lexer/__init__.py +43 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/lexer/keyword_table.py +141 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/lexer/stripped_lines.py +41 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/lexer/token_helpers.py +115 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/lexer/token_kinds.py +113 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/lexer/tokenize.py +413 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/lexer/trivia.py +65 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/parser/__init__.py +22 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/parser/fixed_length_string.py +58 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/parser/nodes.py +721 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/parser/parse_expression.py +621 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/parser/parse_module.py +1472 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/parser/parser_state.py +110 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/parser/type_declaration_suffix.py +29 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/project.py +146 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/py.typed +0 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/reader/__init__.py +49 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/reader/loose_file.py +104 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/reader/vbe_module.py +137 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/reader/workbook.py +104 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/runtime/__init__.py +29 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/runtime/vba_runtime.py +314 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/symbols/__init__.py +60 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/symbols/build_module_symbols.py +379 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/symbols/name_resolution.py +252 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/symbols/project_index.py +942 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/symbols/symbol_model.py +371 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/types/__init__.py +17 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/types/type_inference.py +278 -0
- pyvbaanalysis-1.0.0/pyvbaanalysis/types/type_names.py +105 -0
- pyvbaanalysis-1.0.0/tests/conftest.py +6 -0
- pyvbaanalysis-1.0.0/tests/oracle_support.py +119 -0
- pyvbaanalysis-1.0.0/tests/test_cli.py +222 -0
- pyvbaanalysis-1.0.0/tests/test_conditional_compilation.py +172 -0
- pyvbaanalysis-1.0.0/tests/test_dataflow.py +119 -0
- pyvbaanalysis-1.0.0/tests/test_diagnostics_engine.py +179 -0
- pyvbaanalysis-1.0.0/tests/test_evidence.py +33 -0
- pyvbaanalysis-1.0.0/tests/test_host_model.py +56 -0
- pyvbaanalysis-1.0.0/tests/test_integer_constant_expression.py +122 -0
- pyvbaanalysis-1.0.0/tests/test_lexer.py +101 -0
- pyvbaanalysis-1.0.0/tests/test_parser.py +292 -0
- pyvbaanalysis-1.0.0/tests/test_project.py +104 -0
- pyvbaanalysis-1.0.0/tests/test_project_index.py +238 -0
- pyvbaanalysis-1.0.0/tests/test_public_api.py +63 -0
- pyvbaanalysis-1.0.0/tests/test_reader.py +264 -0
- pyvbaanalysis-1.0.0/tests/test_rule_metadata.py +97 -0
- pyvbaanalysis-1.0.0/tests/test_rules_ambiguous_enum_member.py +171 -0
- pyvbaanalysis-1.0.0/tests/test_rules_argument_shape.py +58 -0
- pyvbaanalysis-1.0.0/tests/test_rules_argument_types.py +63 -0
- pyvbaanalysis-1.0.0/tests/test_rules_arrays.py +202 -0
- pyvbaanalysis-1.0.0/tests/test_rules_assignments.py +51 -0
- pyvbaanalysis-1.0.0/tests/test_rules_assignments_types.py +173 -0
- pyvbaanalysis-1.0.0/tests/test_rules_binary_operand_scalar.py +41 -0
- pyvbaanalysis-1.0.0/tests/test_rules_call_arity.py +60 -0
- pyvbaanalysis-1.0.0/tests/test_rules_control_flow.py +141 -0
- pyvbaanalysis-1.0.0/tests/test_rules_declarations.py +192 -0
- pyvbaanalysis-1.0.0/tests/test_rules_division_by_zero.py +55 -0
- pyvbaanalysis-1.0.0/tests/test_rules_duplicates.py +76 -0
- pyvbaanalysis-1.0.0/tests/test_rules_event_handler_module_scope.py +96 -0
- pyvbaanalysis-1.0.0/tests/test_rules_expression_calls.py +78 -0
- pyvbaanalysis-1.0.0/tests/test_rules_expressions.py +39 -0
- pyvbaanalysis-1.0.0/tests/test_rules_invalid_as_type_names.py +231 -0
- pyvbaanalysis-1.0.0/tests/test_rules_is_operator_non_object.py +70 -0
- pyvbaanalysis-1.0.0/tests/test_rules_lexical.py +62 -0
- pyvbaanalysis-1.0.0/tests/test_rules_member_not_found.py +173 -0
- pyvbaanalysis-1.0.0/tests/test_rules_module_kind.py +97 -0
- pyvbaanalysis-1.0.0/tests/test_rules_numeric_literals.py +34 -0
- pyvbaanalysis-1.0.0/tests/test_rules_object_state.py +98 -0
- pyvbaanalysis-1.0.0/tests/test_rules_parameter_defaults.py +58 -0
- pyvbaanalysis-1.0.0/tests/test_rules_property_setter_value_parameters.py +116 -0
- pyvbaanalysis-1.0.0/tests/test_rules_runtime_values.py +62 -0
- pyvbaanalysis-1.0.0/tests/test_rules_scalar_and_foreach.py +103 -0
- pyvbaanalysis-1.0.0/tests/test_rules_type_of_is.py +36 -0
- pyvbaanalysis-1.0.0/tests/test_rules_typeof_is_always_false.py +106 -0
- pyvbaanalysis-1.0.0/tests/test_rules_undeclared.py +131 -0
- pyvbaanalysis-1.0.0/tests/test_runtime_tables.py +39 -0
- pyvbaanalysis-1.0.0/tests/test_stripped_lines.py +50 -0
- pyvbaanalysis-1.0.0/tests/test_symbols.py +202 -0
- pyvbaanalysis-1.0.0/tests/test_token_helpers.py +86 -0
- pyvbaanalysis-1.0.0/tests/test_type_completion.py +92 -0
- pyvbaanalysis-1.0.0/tests/test_type_names.py +42 -0
- pyvbaanalysis-1.0.0/tools/extract_event_definitions.mjs +25 -0
- pyvbaanalysis-1.0.0/tools/extract_host_model.mjs +12 -0
- pyvbaanalysis-1.0.0/tools/extract_runtime_tables.mjs +10 -0
- pyvbaanalysis-1.0.0/tools/generate_diagnostics_catalogue.py +96 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Keep the GitHub Actions pinned in the workflows current.
|
|
4
|
+
- package-ecosystem: github-actions
|
|
5
|
+
directory: /
|
|
6
|
+
schedule:
|
|
7
|
+
interval: weekly
|
|
8
|
+
|
|
9
|
+
# Keep the Python tooling and the runtime dependency current.
|
|
10
|
+
- package-ecosystem: pip
|
|
11
|
+
directory: /
|
|
12
|
+
schedule:
|
|
13
|
+
interval: weekly
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
# Run the lint, type, and test gate on every push to main and every pull request,
|
|
4
|
+
# so a regression is caught before it can reach a release.
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
pull_request:
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
# A new push to the same branch or PR cancels the in-progress run.
|
|
15
|
+
concurrency:
|
|
16
|
+
group: ci-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
lint:
|
|
21
|
+
name: Lint and type check
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
- uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
cache: pip
|
|
29
|
+
cache-dependency-path: pyproject.toml
|
|
30
|
+
- run: python -m pip install -e ".[dev]"
|
|
31
|
+
- name: Ruff
|
|
32
|
+
run: python -m ruff check .
|
|
33
|
+
- name: Mypy
|
|
34
|
+
run: python -m mypy pyvbaanalysis
|
|
35
|
+
|
|
36
|
+
test:
|
|
37
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
strategy:
|
|
40
|
+
fail-fast: false
|
|
41
|
+
matrix:
|
|
42
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
- uses: actions/setup-python@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: ${{ matrix.python-version }}
|
|
48
|
+
cache: pip
|
|
49
|
+
cache-dependency-path: pyproject.toml
|
|
50
|
+
- run: python -m pip install -e ".[dev]"
|
|
51
|
+
- name: Pytest
|
|
52
|
+
run: python -m pytest -q
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Publishes pyvbaanalysis to PyPI when a GitHub Release is published, using PyPI
|
|
4
|
+
# Trusted Publishing (OIDC), so no API tokens are stored anywhere.
|
|
5
|
+
#
|
|
6
|
+
# One-time setup before the first release (see CONTRIBUTING.md for the full steps):
|
|
7
|
+
# 1. PyPI -> Account -> Publishing -> add a pending publisher:
|
|
8
|
+
# Project name: pyvbaanalysis
|
|
9
|
+
# Owner: WilliamSmithEdward
|
|
10
|
+
# Repository name: pyVBAanalysis
|
|
11
|
+
# Workflow name: publish.yml
|
|
12
|
+
# Environment name: pypi
|
|
13
|
+
# 2. GitHub -> repo Settings -> Environments -> create an environment named `pypi`.
|
|
14
|
+
|
|
15
|
+
on:
|
|
16
|
+
release:
|
|
17
|
+
types: [published]
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
publish:
|
|
24
|
+
name: Build and publish to PyPI
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
environment:
|
|
27
|
+
name: pypi
|
|
28
|
+
url: https://pypi.org/p/pyvbaanalysis
|
|
29
|
+
permissions:
|
|
30
|
+
id-token: write # OIDC token for PyPI Trusted Publishing
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
- uses: actions/setup-python@v5
|
|
34
|
+
with:
|
|
35
|
+
python-version: "3.12"
|
|
36
|
+
cache: pip
|
|
37
|
+
cache-dependency-path: pyproject.toml
|
|
38
|
+
- name: Install package + dev/build tools
|
|
39
|
+
run: python -m pip install -e ".[dev,build]"
|
|
40
|
+
- name: Test gate (pytest / ruff / mypy)
|
|
41
|
+
run: |
|
|
42
|
+
python -m pytest -q
|
|
43
|
+
python -m ruff check .
|
|
44
|
+
python -m mypy pyvbaanalysis
|
|
45
|
+
- name: Build sdist + wheel
|
|
46
|
+
run: python -m build
|
|
47
|
+
- name: Upload build artifacts
|
|
48
|
+
uses: actions/upload-artifact@v4
|
|
49
|
+
with:
|
|
50
|
+
name: dist
|
|
51
|
+
path: dist/*
|
|
52
|
+
- name: Publish to PyPI
|
|
53
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Byte-compiled / optimized
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.eggs/
|
|
11
|
+
*.egg
|
|
12
|
+
|
|
13
|
+
# Virtual environments
|
|
14
|
+
.venv/
|
|
15
|
+
venv/
|
|
16
|
+
env/
|
|
17
|
+
.python-version
|
|
18
|
+
|
|
19
|
+
# Test / type / lint caches
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
.ruff_cache/
|
|
23
|
+
.coverage
|
|
24
|
+
.coverage.*
|
|
25
|
+
htmlcov/
|
|
26
|
+
.tox/
|
|
27
|
+
|
|
28
|
+
# Editors / OS
|
|
29
|
+
.vscode/
|
|
30
|
+
.idea/
|
|
31
|
+
*.swp
|
|
32
|
+
.DS_Store
|
|
33
|
+
Thumbs.db
|
|
34
|
+
|
|
35
|
+
# Note: the vendored XLIDE data package under pyvbaanalysis/data/ is intentionally
|
|
36
|
+
# committed (it is the version-pinned contract surface), so it is NOT ignored here.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to pyVBAanalysis are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project aims to
|
|
5
|
+
follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html): a minor version
|
|
6
|
+
per milestone.
|
|
7
|
+
|
|
8
|
+
## 1.0.0 - 2026-06-20
|
|
9
|
+
|
|
10
|
+
The first public release: a pure-Python static analyzer for Excel VBA with a
|
|
11
|
+
no-false-positive discipline, where a diagnostic is reported only when it is
|
|
12
|
+
provably correct and anything unknown or ambiguous stays quiet.
|
|
13
|
+
|
|
14
|
+
### Analysis
|
|
15
|
+
|
|
16
|
+
* The complete analysis stack: lexer, parser, symbol and project index,
|
|
17
|
+
conditional compilation, type inference, the Excel host object model, the
|
|
18
|
+
member-completion surface, and the project-type registry.
|
|
19
|
+
* 85 diagnostic rules emitting a catalogue of 117 diagnostic codes, validated
|
|
20
|
+
against a corpus of 397 real Excel/VBE behavior cases.
|
|
21
|
+
|
|
22
|
+
### Ingestion and entry points
|
|
23
|
+
|
|
24
|
+
* `analyze_module` for one module's source text, and `analyze_project` for a set
|
|
25
|
+
of modules analyzed together with cross-module context.
|
|
26
|
+
* `analyze_loose_file` / `analyze_loose_files` for loose `.bas` / `.cls` / `.frm`
|
|
27
|
+
export files, and `analyze_workbook` for VBA read directly out of Excel
|
|
28
|
+
workbooks. `build_project_index` and `analyze_module_options_for` expose the
|
|
29
|
+
per-module options for a custom pass.
|
|
30
|
+
* A `pyvbaanalysis.reader` package that strips the VBE export header, infers the
|
|
31
|
+
module kind, and reads modules from Excel files.
|
|
32
|
+
* A command-line interface: `python -m pyvbaanalysis PATH ...` over loose files,
|
|
33
|
+
folders, and Excel workbooks, with `--only`, `--severity`, `--select` /
|
|
34
|
+
`--ignore`, `--fail-level`, `--format`, and CI-friendly exit codes.
|
|
35
|
+
* The headline entry points are re-exported from the package root, and the package
|
|
36
|
+
ships a `py.typed` marker.
|
|
37
|
+
|
|
38
|
+
### Packaging
|
|
39
|
+
|
|
40
|
+
* MIT license and a Trusted Publishing release workflow (OIDC, no API tokens).
|
|
41
|
+
* One runtime dependency, pyOpenVBA, used to read VBA out of Excel workbooks and
|
|
42
|
+
imported lazily.
|
|
43
|
+
|
|
44
|
+
### Documentation
|
|
45
|
+
|
|
46
|
+
* A usage guide, an API reference, a generated diagnostics catalogue, and a
|
|
47
|
+
contributing guide.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
pyVBAanalysis is a faithful Python port of the
|
|
4
|
+
[XLIDE](https://github.com/WilliamSmithEdward/xlide_vscode) VBA analyzer. The
|
|
5
|
+
overriding rule is the no-false-positive discipline: a diagnostic ships only when
|
|
6
|
+
it is provably correct. When in doubt, stay quiet.
|
|
7
|
+
|
|
8
|
+
## Development setup
|
|
9
|
+
|
|
10
|
+
Python 3.10 or later.
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
pip install -e ".[dev]"
|
|
14
|
+
```
|
|
15
|
+
|
|
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.
|
|
19
|
+
|
|
20
|
+
## Local checks
|
|
21
|
+
|
|
22
|
+
Run all three before sending a change. They are the same gate CI enforces:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
pytest
|
|
26
|
+
ruff check .
|
|
27
|
+
mypy pyvbaanalysis
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`mypy` runs in `--strict` mode. The suite is fast (a few seconds); run it often.
|
|
31
|
+
|
|
32
|
+
## The XLIDE port model
|
|
33
|
+
|
|
34
|
+
This repository ports XLIDE's TypeScript analyzer. XLIDE owns the language and
|
|
35
|
+
host knowledge; pyVBAanalysis reproduces its behavior in Python.
|
|
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.
|
|
39
|
+
* XLIDE also owns the oracle: the Excel/VBE evidence corpus and the provenance
|
|
40
|
+
audit. pyVBAanalysis consumes the emitted evidence verbatim as both porting spec
|
|
41
|
+
and test fixtures. Do not reimplement the oracle here.
|
|
42
|
+
* The vendored data lives in `pyvbaanalysis/data/` (the host object model, the
|
|
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.
|
|
46
|
+
|
|
47
|
+
The build plan, parity inventory, and module-by-module port map are in
|
|
48
|
+
[agent.md](agent.md).
|
|
49
|
+
|
|
50
|
+
## Adding or changing a rule
|
|
51
|
+
|
|
52
|
+
* Port the rule from its XLIDE source; match the behavior, not just the shape.
|
|
53
|
+
* A rule ships only with oracle backing. Validate it against the vendored corpus
|
|
54
|
+
and add direct tests for the positive and the no-false-positive control cases.
|
|
55
|
+
* The diagnostic rule registry order is a contract: it is the diagnostic
|
|
56
|
+
output order, and it must remain a faithful subsequence of XLIDE's `registry.ts`.
|
|
57
|
+
Place a new entry at its XLIDE position; do not reorder existing entries.
|
|
58
|
+
* Diagnostic codes and their metadata (default severity, category, evidence basis,
|
|
59
|
+
spec reference) live in the rule metadata. Regenerate the catalogue after a
|
|
60
|
+
metadata change:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
python tools/generate_diagnostics_catalogue.py
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Style
|
|
67
|
+
|
|
68
|
+
* Write plain ASCII. No em dashes or other non-ASCII in code, comments,
|
|
69
|
+
docstrings, or commit messages; use a comma, colon, period, or parentheses.
|
|
70
|
+
Test fixtures that deliberately exercise Unicode are the only exception.
|
|
71
|
+
* Avoid AI tells and marketing language. Prefer clear, direct prose.
|
|
72
|
+
* Keep changes small and focused, with names and structure that match the
|
|
73
|
+
surrounding code.
|
|
74
|
+
* Update the docs when behavior, setup, the API, or the architecture changes.
|
|
75
|
+
* Report status honestly: "done" means the checks above were run and passed.
|
|
76
|
+
|
|
77
|
+
## Continuous integration
|
|
78
|
+
|
|
79
|
+
`.github/workflows/ci.yml` runs the lint, type, and test gate on every push to
|
|
80
|
+
`main` and every pull request, across Python 3.10 to 3.13. Dependabot
|
|
81
|
+
(`.github/dependabot.yml`) opens weekly pull requests to update the GitHub Actions
|
|
82
|
+
and the Python tooling.
|
|
83
|
+
|
|
84
|
+
## Releasing
|
|
85
|
+
|
|
86
|
+
Publishing is automated by `.github/workflows/publish.yml`, which builds the sdist
|
|
87
|
+
and wheel and uploads them to PyPI through Trusted Publishing (OIDC, no API
|
|
88
|
+
tokens) when a GitHub Release is published.
|
|
89
|
+
|
|
90
|
+
One-time setup before the first release:
|
|
91
|
+
|
|
92
|
+
1. On PyPI, go to Account -> Publishing and add a pending publisher with project
|
|
93
|
+
name `pyvbaanalysis`, owner `WilliamSmithEdward`, repository `pyVBAanalysis`,
|
|
94
|
+
workflow `publish.yml`, and environment `pypi`.
|
|
95
|
+
2. On GitHub, go to repo Settings -> Environments and create an environment named
|
|
96
|
+
`pypi`. Optionally add required reviewers so a publish needs human approval.
|
|
97
|
+
|
|
98
|
+
To cut a release:
|
|
99
|
+
|
|
100
|
+
1. Bump `__version__` in `pyvbaanalysis/__init__.py` (the single source of the
|
|
101
|
+
version) and update `CHANGELOG.md`. Commit.
|
|
102
|
+
2. Tag and push: `git tag vX.Y.Z` then `git push origin vX.Y.Z`.
|
|
103
|
+
3. Publish a GitHub Release for that tag (for example
|
|
104
|
+
`gh release create vX.Y.Z --notes-file <notes>`). Publishing the release runs
|
|
105
|
+
`publish.yml`, which re-runs the gate, builds, and uploads to PyPI.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 William Smith Edward
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyvbaanalysis
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Pure-Python static analysis for Excel VBA
|
|
5
|
+
Project-URL: Homepage, https://github.com/WilliamSmithEdward/pyVBAanalysis
|
|
6
|
+
Project-URL: Repository, https://github.com/WilliamSmithEdward/pyVBAanalysis
|
|
7
|
+
Project-URL: Issues, https://github.com/WilliamSmithEdward/pyVBAanalysis/issues
|
|
8
|
+
Author: William Smith Edward
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: excel,linter,static-analysis,vba
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: pyopenvba>=3.0.1
|
|
21
|
+
Provides-Extra: build
|
|
22
|
+
Requires-Dist: build>=1.2; extra == 'build'
|
|
23
|
+
Requires-Dist: twine>=5; extra == 'build'
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
27
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# pyVBAanalysis
|
|
31
|
+
|
|
32
|
+
Static analysis for Excel VBA. It reads your macros and reports likely bugs and the
|
|
33
|
+
errors the VBA compiler would catch, without opening Excel or running any code.
|
|
34
|
+
|
|
35
|
+
Point it at a workbook or a set of exported module files, and it returns the
|
|
36
|
+
problems it finds, each with the exact line and a plain explanation.
|
|
37
|
+
|
|
38
|
+
## What it checks
|
|
39
|
+
|
|
40
|
+
It looks for more than a hundred kinds of problem, including:
|
|
41
|
+
|
|
42
|
+
- Type errors, such as assigning a string to a `Long` or passing the wrong type to
|
|
43
|
+
a procedure.
|
|
44
|
+
- Undeclared variables and calls to procedures or members that do not exist.
|
|
45
|
+
- Code the VBA compiler rejects: duplicate declarations, a missing `Option
|
|
46
|
+
Explicit`, malformed statements, or a `Declare` that lacks `PtrSafe` on 64-bit
|
|
47
|
+
Office.
|
|
48
|
+
- Likely run-time failures, such as dividing by a constant zero or a type mismatch
|
|
49
|
+
from a bad conversion.
|
|
50
|
+
|
|
51
|
+
It only reports a problem when it can prove one, and stays quiet otherwise, so the
|
|
52
|
+
output does not bury you in false alarms.
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
pip install pyvbaanalysis
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Python 3.10 or later. Nothing else to set up.
|
|
61
|
+
|
|
62
|
+
## Use it from Python
|
|
63
|
+
|
|
64
|
+
Analyze a workbook:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from pyvbaanalysis import analyze_workbook
|
|
68
|
+
|
|
69
|
+
for module, problems in analyze_workbook("Budget.xlsm").items():
|
|
70
|
+
for p in problems:
|
|
71
|
+
print(module, p.severity.value, p.code, p.message)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Analyze a single module's source:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from pyvbaanalysis import analyze_module
|
|
78
|
+
|
|
79
|
+
source = "Sub Test()\n Dim n As Long\n n = \"oops\"\nEnd Sub\n"
|
|
80
|
+
for p in analyze_module(source):
|
|
81
|
+
print(p.code, p.message)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Each result has a `code`, a `message`, a `severity` (`error`, `warning`, or
|
|
85
|
+
`information`), and a `span` giving the character offsets in the source.
|
|
86
|
+
|
|
87
|
+
Analyze several exported files together, so references between them resolve:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from pyvbaanalysis import analyze_loose_files
|
|
91
|
+
|
|
92
|
+
analyze_loose_files(["Module1.bas", "Sheet1.cls", "UserForm1.frm"])
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Use it from the command line
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
pyvbaanalysis Budget.xlsm
|
|
99
|
+
pyvbaanalysis ./exported_modules --format json
|
|
100
|
+
pyvbaanalysis Budget.xlsm --only Sheet1
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
A path can be a workbook, a folder of exported `.bas` / `.cls` / `.frm` files, or a
|
|
104
|
+
single file. The command exits 1 when it finds problems and 0 when the code is
|
|
105
|
+
clean, so it drops into a CI check.
|
|
106
|
+
|
|
107
|
+
## Scope
|
|
108
|
+
|
|
109
|
+
This analyzes Excel VBA. It does not run macros and does not need Excel installed.
|
|
110
|
+
Word and PowerPoint are not supported.
|
|
111
|
+
|
|
112
|
+
## Documentation
|
|
113
|
+
|
|
114
|
+
- [Usage guide](docs/usage.md)
|
|
115
|
+
- [API reference](docs/api-reference.md)
|
|
116
|
+
- [Diagnostic catalogue](docs/diagnostics-catalogue.md)
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# pyVBAanalysis
|
|
2
|
+
|
|
3
|
+
Static analysis for Excel VBA. It reads your macros and reports likely bugs and the
|
|
4
|
+
errors the VBA compiler would catch, without opening Excel or running any code.
|
|
5
|
+
|
|
6
|
+
Point it at a workbook or a set of exported module files, and it returns the
|
|
7
|
+
problems it finds, each with the exact line and a plain explanation.
|
|
8
|
+
|
|
9
|
+
## What it checks
|
|
10
|
+
|
|
11
|
+
It looks for more than a hundred kinds of problem, including:
|
|
12
|
+
|
|
13
|
+
- Type errors, such as assigning a string to a `Long` or passing the wrong type to
|
|
14
|
+
a procedure.
|
|
15
|
+
- Undeclared variables and calls to procedures or members that do not exist.
|
|
16
|
+
- Code the VBA compiler rejects: duplicate declarations, a missing `Option
|
|
17
|
+
Explicit`, malformed statements, or a `Declare` that lacks `PtrSafe` on 64-bit
|
|
18
|
+
Office.
|
|
19
|
+
- Likely run-time failures, such as dividing by a constant zero or a type mismatch
|
|
20
|
+
from a bad conversion.
|
|
21
|
+
|
|
22
|
+
It only reports a problem when it can prove one, and stays quiet otherwise, so the
|
|
23
|
+
output does not bury you in false alarms.
|
|
24
|
+
|
|
25
|
+
## Install
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
pip install pyvbaanalysis
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Python 3.10 or later. Nothing else to set up.
|
|
32
|
+
|
|
33
|
+
## Use it from Python
|
|
34
|
+
|
|
35
|
+
Analyze a workbook:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from pyvbaanalysis import analyze_workbook
|
|
39
|
+
|
|
40
|
+
for module, problems in analyze_workbook("Budget.xlsm").items():
|
|
41
|
+
for p in problems:
|
|
42
|
+
print(module, p.severity.value, p.code, p.message)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Analyze a single module's source:
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from pyvbaanalysis import analyze_module
|
|
49
|
+
|
|
50
|
+
source = "Sub Test()\n Dim n As Long\n n = \"oops\"\nEnd Sub\n"
|
|
51
|
+
for p in analyze_module(source):
|
|
52
|
+
print(p.code, p.message)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Each result has a `code`, a `message`, a `severity` (`error`, `warning`, or
|
|
56
|
+
`information`), and a `span` giving the character offsets in the source.
|
|
57
|
+
|
|
58
|
+
Analyze several exported files together, so references between them resolve:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from pyvbaanalysis import analyze_loose_files
|
|
62
|
+
|
|
63
|
+
analyze_loose_files(["Module1.bas", "Sheet1.cls", "UserForm1.frm"])
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Use it from the command line
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
pyvbaanalysis Budget.xlsm
|
|
70
|
+
pyvbaanalysis ./exported_modules --format json
|
|
71
|
+
pyvbaanalysis Budget.xlsm --only Sheet1
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
A path can be a workbook, a folder of exported `.bas` / `.cls` / `.frm` files, or a
|
|
75
|
+
single file. The command exits 1 when it finds problems and 0 when the code is
|
|
76
|
+
clean, so it drops into a CI check.
|
|
77
|
+
|
|
78
|
+
## Scope
|
|
79
|
+
|
|
80
|
+
This analyzes Excel VBA. It does not run macros and does not need Excel installed.
|
|
81
|
+
Word and PowerPoint are not supported.
|
|
82
|
+
|
|
83
|
+
## Documentation
|
|
84
|
+
|
|
85
|
+
- [Usage guide](docs/usage.md)
|
|
86
|
+
- [API reference](docs/api-reference.md)
|
|
87
|
+
- [Diagnostic catalogue](docs/diagnostics-catalogue.md)
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# API reference
|
|
2
|
+
|
|
3
|
+
The package root re-exports the headline entry points; the rest of the public
|
|
4
|
+
surface lives in the submodules listed below. This page is an import map, not a
|
|
5
|
+
full autodoc dump. For task-oriented examples see [usage.md](usage.md).
|
|
6
|
+
|
|
7
|
+
## Headline API (`pyvbaanalysis`)
|
|
8
|
+
|
|
9
|
+
These are re-exported at the package root for convenience:
|
|
10
|
+
|
|
11
|
+
| Symbol | Role |
|
|
12
|
+
| --- | --- |
|
|
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)` | Analyze a set of `ModuleInput`s with cross-module context; returns `dict[str, list[VbaDiagnostic]]`. |
|
|
15
|
+
| `analyze_loose_file(path, *, severity_overrides=None, conditional_compilation=None)` | Analyze one `.bas`/`.cls`/`.frm` file. |
|
|
16
|
+
| `analyze_loose_files(paths, *, only=None, severity_overrides=None, conditional_compilation=None)` | Analyze several loose files as one project. |
|
|
17
|
+
| `analyze_workbook(path, *, only=None, severity_overrides=None, conditional_compilation=None)` | Analyze the VBA in an Excel workbook (via pyOpenVBA). |
|
|
18
|
+
| `analyze_module_options_for(index, name, kind, *, severity_overrides=None, conditional_compilation=None)` | Build per-module `AnalyzeModuleOptions` from a populated `ProjectIndex`. |
|
|
19
|
+
| `build_project_index(modules)` | A `ProjectIndex` with every module registered. |
|
|
20
|
+
| `AnalyzeModuleOptions` | Inputs for `analyze_module` (name, kind, project context, overrides). |
|
|
21
|
+
| `VbaDiagnostic` | A single diagnostic (`code`, `message`, `severity`, `span`, `spec_reference`). |
|
|
22
|
+
| `ModuleInput` | One module fed into a project (`module_name`, `module_kind`, `source`). |
|
|
23
|
+
| `ModuleSymbolKind` | `STANDARD`, `CLASS`, `DOCUMENT`, `USERFORM`. |
|
|
24
|
+
| `ProjectIndex` | The cross-module symbol/type index. |
|
|
25
|
+
| `__version__` | The package version string. |
|
|
26
|
+
|
|
27
|
+
## Engine and result model (`pyvbaanalysis.diagnostics`)
|
|
28
|
+
|
|
29
|
+
* Entry point: `analyze_module`, `AnalyzeModuleOptions`, `RulePassContext`, `PushFn`,
|
|
30
|
+
`is_object_module_kind`.
|
|
31
|
+
* Result model: `VbaDiagnostic`, `VbaDiagnosticData`, `VbaEdit`, and the enums
|
|
32
|
+
`DiagnosticSeverity`, `DiagnosticCategory`, `DiagnosticEvidenceKind`,
|
|
33
|
+
`DiagnosticSuppressionScope`.
|
|
34
|
+
* Registry and metadata: `DIAGNOSTIC_RULE_REGISTRY`, `DiagnosticRuleEntry`,
|
|
35
|
+
`STRUCTURAL_DIAGNOSTIC_RULES`, `DIAGNOSTIC_RULES`, `DiagnosticRuleMetadata`,
|
|
36
|
+
`diagnostic_metadata_for_code`, `rule_metadata_by_code`, `load_rule_metadata`,
|
|
37
|
+
`normalize_diagnostic_severity_override`.
|
|
38
|
+
|
|
39
|
+
## Readers (`pyvbaanalysis.reader`)
|
|
40
|
+
|
|
41
|
+
* High level: `analyze_loose_file`, `analyze_loose_files`, `analyze_workbook`,
|
|
42
|
+
`load_loose_module`, `read_workbook_modules`.
|
|
43
|
+
* Building blocks: `LoadedModule`, `strip_export_header`, `classify_module_kind`,
|
|
44
|
+
`module_name_from_text`, `loaded_module_from_text`, `WorkbookReadError`,
|
|
45
|
+
`LOOSE_EXTENSIONS`, `EXCEL_EXTENSIONS`.
|
|
46
|
+
|
|
47
|
+
## Project model (`pyvbaanalysis.symbols`)
|
|
48
|
+
|
|
49
|
+
* Index: `ProjectIndex`, `ProjectIndexOptions`, `ModuleInput`, `ReferenceScope`,
|
|
50
|
+
`ShadowedSpan`.
|
|
51
|
+
* Module symbols: `build_module_symbols`, `BuildModuleSymbolsOptions`,
|
|
52
|
+
`ModuleSymbols`, `ModuleSymbolKind`, `SymbolVisibility`, `VbaSymbol`,
|
|
53
|
+
`VbaSymbolKind`, `VbaSymbolAttribute`, `VbaProcedureSignature`,
|
|
54
|
+
`VbaProcedureParam`, and the predicates `is_procedure_kind`,
|
|
55
|
+
`is_bare_callable_kind`, `procedure_signature_from_symbol`,
|
|
56
|
+
`qualified_procedure_key`.
|
|
57
|
+
* Name resolution: `resolve_bare_identifier_binding`, `source_identifier_names`,
|
|
58
|
+
`BareIdentifierContext`, `BareIdentifierResolution`.
|
|
59
|
+
|
|
60
|
+
## Lower-level building blocks
|
|
61
|
+
|
|
62
|
+
These are the analysis layers the engine is built on. Most consumers do not need
|
|
63
|
+
them directly, but they are public and stable.
|
|
64
|
+
|
|
65
|
+
| Package | What it provides |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| `pyvbaanalysis.lexer` | `tokenize`, `tokenize_cached`, `VbaToken`, `TokenKind`, and token helpers. |
|
|
68
|
+
| `pyvbaanalysis.parser` | `parse_module`, `parse_expression`, `ModuleNode`, and the AST nodes. |
|
|
69
|
+
| `pyvbaanalysis.conditional` | Conditional-compilation indexing and activity (`index_conditional_compilation`, `evaluate_conditional_expression`, ...). |
|
|
70
|
+
| `pyvbaanalysis.types` | Type-name helpers: `normalize_type`, `is_known_scalar_type`, `is_numeric_type`, `numeric_literal_bounds`. |
|
|
71
|
+
| `pyvbaanalysis.completion` | Member-completion surface and project-type resolution (`resolve_member_surface_at`, `resolve_type_name`, ...). |
|
|
72
|
+
| `pyvbaanalysis.host` | The Excel host object model (`get_excel_object_model`, `resolve_host_alias`, ...). |
|
|
73
|
+
| `pyvbaanalysis.runtime` | VBA runtime functions, constants, and objects (`resolve_runtime_function`, ...). |
|
|
74
|
+
| `pyvbaanalysis.call` | Call-statement shape helpers. |
|
|
75
|
+
| `pyvbaanalysis.flow` | Procedure labels and unstructured-flow detection. |
|
|
76
|
+
| `pyvbaanalysis.constants` | Integer constant-expression evaluation. |
|
|
77
|
+
|
|
78
|
+
Many helper free functions inside these packages are intentionally internal even
|
|
79
|
+
when importable. The symbols listed above are the supported surface.
|
|
80
|
+
|
|
81
|
+
## A note on the package root
|
|
82
|
+
|
|
83
|
+
The package root exports only the headline API plus `__version__`. Everything
|
|
84
|
+
else is imported from its submodule, e.g.
|
|
85
|
+
`from pyvbaanalysis.diagnostics import DiagnosticSeverity` or
|
|
86
|
+
`from pyvbaanalysis.symbols import ModuleSymbols`.
|