cg-code-graph 0.23.7__tar.gz → 0.23.8__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.
- {cg_code_graph-0.23.7/cg_code_graph.egg-info → cg_code_graph-0.23.8}/PKG-INFO +1 -1
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/__init__.py +1 -1
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/cli.py +6 -3
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/parity.py +77 -9
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/parity_structure.py +119 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8/cg_code_graph.egg-info}/PKG-INFO +1 -1
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/SOURCES.txt +1 -0
- cg_code_graph-0.23.8/tests/test_parity_fields.py +125 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/LICENSE +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/MANIFEST.in +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/README.md +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/__main__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/affected.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/agent_rules.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/agents.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/aitools.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/android_ipc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/apple_ipc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/apps.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/blindspots.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/bridges.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/brokers.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/cmake_sources.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/concepts.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/config.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/cache.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/detect.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/env.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/extractors.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/fsutil.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/generated.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/model.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/paths.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/redact.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/store.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/syntax_errors.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/coverage.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/dart_isolates.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/doctor.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/explore.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/external.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/graphql.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/guard_facts.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/hooks.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/indexer.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/insecure_transport.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/install_rules.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/jobs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/link.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/lint_async.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/local_ipc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/local_sockets.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/mcp_graphs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/mcp_install.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/mcp_server.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/payload.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plans.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/platform_scan.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/platforms.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/astro/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/astro/content.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/astro/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/cfamily/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/cfamily/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/cfamily/syntax.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/bridges.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/extractor/bin/extract.dart +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/extractor/pubspec.lock +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/extractor/pubspec.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/http.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/models.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/program.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/extras.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/models.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/schemas.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/shapes.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/urls.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/express/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/express/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/flutter/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/flutter/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/java/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/java/exact.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/java/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/jvm/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/jvm/interop.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/jvm/spring.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/exact.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/reparse.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/broadcast.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/massassign.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/tests.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/values.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/gates.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/runner.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/scipread.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/ts.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nest/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nest/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nextjs/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nextjs/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nuxt/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nuxt/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/external.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/extractor/composer.json +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/extractor/composer.lock +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/extractor/extract.php +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/gating.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/http_client.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/inline_guards.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/strings.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/aitools.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/external.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/fields.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/refs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/roots.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/socketio.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/subproc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/tests.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/values.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/pyweb/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/pyweb/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/pyweb/values.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/cargo.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/syntax.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/importer.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/scip.proto +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/scip_pb2.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/stubs/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/stubs/plugins.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/baseurl.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/exact.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/indexstore.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/packages.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/baseurl.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/extract.mjs +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/fw.mjs +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/package-lock.json +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/package.json +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/rr.mjs +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/nav.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/plugin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/react_router.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/tsweb/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/tsweb/common.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/tsweb/data.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/c_cpp.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/common.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/dart.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/django-ninja.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/django.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/djangorestframework.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/express.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/java.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/kotlin.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/laravel.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/nest.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/nextjs.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/nuxt.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/php.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/python.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/react-router.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/rust.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/spring.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/swift.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/typescript.yaml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/process_runs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/protocols/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/protocols/builtin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/protocols/matchers.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/protocols/view.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/query.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/realtime.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/realtime_events.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/realtime_native.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/realtime_ws.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/roundtrip.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/routes.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/rpc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/sdk_systems.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/sockets.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/ssrf_input.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/starters.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/surface.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/tests_index.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/udp_apps.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/update_check.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/__init__.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/graph.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/server.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/app.css +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/app.js +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/index.html +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/layered.js +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/VERSIONS.txt +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/cose-base.js +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/cytoscape-fcose.js +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/cytoscape.min.js +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/layout-base.js +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/tools/package-lock.json +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/tools/package.json +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/tools/shoot.mjs +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/watch.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/webhook_subs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/webhooks.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/xcode.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/dependency_links.txt +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/entry_points.txt +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/requires.txt +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/top_level.txt +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/pyproject.toml +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/setup.cfg +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_affected.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_agents_install.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_agents_md.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ai_tools.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_android_ipc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_apple_ipc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_astro.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_astro_content.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_astro_server.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_bridges.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_bridges_pigeon_monorepo.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_brokers.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_cache_clean.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_cache_invalidation.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_cache_migration.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_channels_tests.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_cli_output.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_cmake_sources.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_completeness.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_config_extras.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_coverage.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_coverage_ts_hint.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_dart_isolates.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_db_connections.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_dead_wrappers.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_dispatch_interfaces.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_django_flutter.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_docs_languages.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_docs_links.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_echo_ref.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_echo_wrapper.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_elysia.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_enum_constants.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_env.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_explore.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_external.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_fp_batch.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_gating.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_generated.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_graphql.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_hooks.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_impact_overrides.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_index_isolation.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_inherited_overrides.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_inline_guards.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_install_rules.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_192.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_201.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_202.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_203.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_204.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_205.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_206.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_207.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_208.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_209.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_210.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_211.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_211_used_at.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_212.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_212_langs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_218.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_219.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_222.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_java.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_java_exact.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_jobs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_js_refs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_js_runtime.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_binding.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_exact.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_fields.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_mixed.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_nav_consts.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_props.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_laravel_determinism.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_laravel_receiver_narrowing.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_laravel_resources.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_laravel_route_paths.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_link_origin.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_lint_async.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_listing_files.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_local_ipc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_local_sockets.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mass_assignment.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mcp.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mcp_index.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mcp_install.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mcp_instructions.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mcp_multi_graph.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_native_cfamily.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_native_concurrency.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_native_rust.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_nuxt_i18n.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_nuxt_import_dirs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_nuxt_nitro.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_nuxt_rootsrc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_nuxt_side_dirs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_packaging.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_parity.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_parity_structure.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_php_http.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_php_props.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_plain_js.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_plans.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_platform_gaps.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_platform_type_variants.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_platforms.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_platforms_apple.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_presets_config.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_process_ipc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_process_runs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_protocols.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_app_tests_module.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_collection_chains.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_compat.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_entry_refs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_fields.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_infer_cycles.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_roots.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_subprocess_tests.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_tests.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_web_hosts.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_web_routes.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_web_routes_more.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_react_router.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_readers_writers_specs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_realtime.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_realtime_native.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_redact_salt.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_request_keys.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_roundtrip.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_route_specs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_route_tables.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_routes_search_explain.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_rpc.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_scip_health.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_sdk_external.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_sdk_external_infra.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_sdk_external_mail.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_snippet.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_sockets.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_spring.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ssrf.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_starters_budget.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_surface.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_surface_transport.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_binding.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_exact.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_facts.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_fields.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_modules.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_more.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_nav_values.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_parse_errors.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_props.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_sdk.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_testing.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_values.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_tauri_events.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_tests_scope.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_fields.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_fields_js_vue.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_file_specs.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_frameworks.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_node_http.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_nuxt.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_src_tsconfig.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_unguarded.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_update_check.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_values.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_viz.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_vue_nav.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_watch.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_webhooks.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_webhooks_152.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_webhooks_152b.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_websockets.py +0 -0
- {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_workspace_link.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""code-graph: deterministic code knowledge graph (beta)."""
|
|
2
|
-
__version__ = "0.23.
|
|
2
|
+
__version__ = "0.23.8"
|
|
@@ -301,9 +301,12 @@ def main(argv=None):
|
|
|
301
301
|
p.add_argument("--strip-prefix", action="append", default=[], help="a name prefix one side adds (`Vault` in "
|
|
302
302
|
"VaultAddEditState for AddEditState), ignored when matching (repeatable)")
|
|
303
303
|
p.add_argument("--structure", action="store_true", help="also pair symbols whose names differ by what they use: "
|
|
304
|
-
"shared strings, localization keys, endpoints and already-paired callees,
|
|
305
|
-
"from the pairs found (#93); matches carry their
|
|
304
|
+
"shared strings, localization keys, resources, endpoints and already-paired callees, then types by "
|
|
305
|
+
"their declared fields, plus rename rules learned from the pairs found (#93); matches carry their "
|
|
306
|
+
"evidence")
|
|
306
307
|
p.add_argument("--no-learn", action="store_true", help="with --structure: no learned rename rules")
|
|
308
|
+
p.add_argument("--both-sides", action="store_true", help="also list the matched pairs and what only --against "
|
|
309
|
+
"has (target symbols no source symbol matched)")
|
|
307
310
|
p.add_argument("--write-map", help="with --structure: write the inferred pairs as a --map JSON file to review")
|
|
308
311
|
p.add_argument("--json", action="store_true"); p.add_argument("--max-items", type=int, default=200)
|
|
309
312
|
p = sub.add_parser("lint", help="heuristic lints (#88): `lint async-state` flags stale async results, state with "
|
|
@@ -574,7 +577,7 @@ def main(argv=None):
|
|
|
574
577
|
from . import parity as PA
|
|
575
578
|
mapping = json.loads(open(a.map, encoding="utf-8").read()) if a.map else None
|
|
576
579
|
res = PA.parity(a.db, a.against, mapping=mapping, fuzzy=not a.no_fuzzy, strip_prefixes=a.strip_prefix,
|
|
577
|
-
structure=a.structure, learn=not a.no_learn)
|
|
580
|
+
structure=a.structure, learn=not a.no_learn, both_sides=a.both_sides)
|
|
578
581
|
if a.write_map:
|
|
579
582
|
with open(a.write_map, "w", encoding="utf-8") as fh:
|
|
580
583
|
json.dump(PA.rename_map(res), fh, indent=1, sort_keys=True)
|
|
@@ -220,21 +220,27 @@ def _cat(sym: dict, is_type: bool) -> str:
|
|
|
220
220
|
return "type" if is_type else "const" if sym["kind"] in ("constant", "enum_case") else "func"
|
|
221
221
|
|
|
222
222
|
|
|
223
|
+
INFERRED = ("structure", "fields", "learned")
|
|
224
|
+
PREVIEW_NAME = re.compile(r"Preview")
|
|
225
|
+
|
|
226
|
+
|
|
223
227
|
def parity(source_db: str, target_db: str, mapping: dict | None = None, fuzzy: bool = True,
|
|
224
|
-
strip_prefixes: list[str] | None = None, structure: bool = False, learn: bool = True
|
|
228
|
+
strip_prefixes: list[str] | None = None, structure: bool = False, learn: bool = True,
|
|
229
|
+
both_sides: bool = False) -> dict:
|
|
225
230
|
"""See the module docstring. `strip_prefixes`: name prefixes one side adds (`Vault` in `VaultAddEditState`
|
|
226
231
|
for `AddEditState`), dropped before normalized matching on both sides. `structure` (#93): after the name rules,
|
|
227
232
|
pair the rest by shared strings, localization keys, endpoints and paired callees, and (`learn`) apply rename
|
|
228
|
-
rules learned from the pairs found (cg_code_graph/parity_structure.py); off, the output is the name matching alone.
|
|
233
|
+
rules learned from the pairs found (cg_code_graph/parity_structure.py); off, the output is the name matching alone.
|
|
234
|
+
`both_sides`: also list what only the target has (`target_only`)."""
|
|
229
235
|
_PREFIXES[:] = [p.lower() for p in strip_prefixes or ()]
|
|
230
236
|
try:
|
|
231
|
-
return _parity(source_db, target_db, mapping, fuzzy, structure, learn)
|
|
237
|
+
return _parity(source_db, target_db, mapping, fuzzy, structure, learn, both_sides)
|
|
232
238
|
finally:
|
|
233
239
|
_PREFIXES.clear()
|
|
234
240
|
|
|
235
241
|
|
|
236
242
|
def _parity(source_db: str, target_db: str, mapping: dict | None, fuzzy: bool, structure: bool = False,
|
|
237
|
-
learn: bool = True) -> dict:
|
|
243
|
+
learn: bool = True, both_sides: bool = False) -> dict:
|
|
238
244
|
S, T = load(source_db), load(target_db)
|
|
239
245
|
mapping = mapping or {}
|
|
240
246
|
exact_ix, norm_ix, comp_ix, all_short = defaultdict(list), defaultdict(list), defaultdict(list), defaultdict(list)
|
|
@@ -357,7 +363,7 @@ def _parity(source_db: str, target_db: str, mapping: dict | None, fuzzy: bool, s
|
|
|
357
363
|
tm.setdefault(_short(nt), T["types"][nt])
|
|
358
364
|
tm_norm = {norm_member(k): k for k in tm}
|
|
359
365
|
for nm, sym in sorted(S["members"].get(sfq, {}).items()):
|
|
360
|
-
if nm in
|
|
366
|
+
if nm in BOILERPLATE or sym["override"]:
|
|
361
367
|
out["skipped"] += 1 # lifecycle / platform overrides (viewDidLoad, onCreate) and boilerplate
|
|
362
368
|
continue
|
|
363
369
|
if nm in tm:
|
|
@@ -375,7 +381,7 @@ def _parity(source_db: str, target_db: str, mapping: dict | None, fuzzy: bool, s
|
|
|
375
381
|
match_members(tmap)
|
|
376
382
|
if structure:
|
|
377
383
|
_structure(S, T, out, tmap, learn)
|
|
378
|
-
inferred = {r["symbol"]: r["target"] for r in out["matched"] if r.get("confidence") in
|
|
384
|
+
inferred = {r["symbol"]: r["target"] for r in out["matched"] if r.get("confidence") in INFERRED
|
|
379
385
|
and r["symbol"] in S["types"] and r["target"] in T["types"]}
|
|
380
386
|
match_members(inferred)
|
|
381
387
|
counts = defaultdict(int)
|
|
@@ -387,10 +393,44 @@ def _parity(source_db: str, target_db: str, mapping: dict | None, fuzzy: bool, s
|
|
|
387
393
|
"missing": len(out["missing"]), "unknown": len(out["unknown"]),
|
|
388
394
|
"platform_only": len(out["platform_only"])}
|
|
389
395
|
if structure:
|
|
390
|
-
out["summary"]["inferred"] = sum(1 for r in out["matched"] if r["confidence"] in
|
|
396
|
+
out["summary"]["inferred"] = sum(1 for r in out["matched"] if r["confidence"] in INFERRED)
|
|
397
|
+
if both_sides:
|
|
398
|
+
_target_only(T, out, t_nested)
|
|
399
|
+
out["summary"]["target_only"] = len(out["target_only"])
|
|
391
400
|
return out
|
|
392
401
|
|
|
393
402
|
|
|
403
|
+
BOILERPLATE = ("body", "init", "deinit", "hash", "description", "encode", "hashValue")
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def _target_only(T, out, t_nested):
|
|
407
|
+
"""`--both-sides`: target types and top-level symbols no source symbol matched, and the unmatched members of
|
|
408
|
+
target types that were matched. Members of an unmatched type are counted under it, not listed."""
|
|
409
|
+
used = {r["target"] for r in out["matched"]}
|
|
410
|
+
rows, hidden = [], 0
|
|
411
|
+
for coll in (T["types"], T["top"]):
|
|
412
|
+
for fq, sym in sorted(coll.items()):
|
|
413
|
+
if fq in used:
|
|
414
|
+
continue
|
|
415
|
+
owner = fq.rsplit(".", 1)[0] if "." in fq else None
|
|
416
|
+
if owner in T["types"] and owner not in used:
|
|
417
|
+
continue # a nested type of an unmatched type: the type is listed
|
|
418
|
+
if PREVIEW_NAME.search(_short(fq)) or sym["file"] in T["err_files"]:
|
|
419
|
+
hidden += 1
|
|
420
|
+
continue
|
|
421
|
+
rows.append(_row(sym, None, None))
|
|
422
|
+
for o in sorted(o for o in T["members"] if o in used):
|
|
423
|
+
for nm, sym in sorted(T["members"][o].items()):
|
|
424
|
+
if f"{o}.{nm}" in used:
|
|
425
|
+
continue
|
|
426
|
+
if nm in BOILERPLATE or sym["override"] or sym["file"] in T["err_files"]:
|
|
427
|
+
hidden += 1
|
|
428
|
+
continue
|
|
429
|
+
rows.append(_row(sym, None, None))
|
|
430
|
+
out["target_only"] = rows
|
|
431
|
+
out["target_only_hidden"] = hidden
|
|
432
|
+
|
|
433
|
+
|
|
394
434
|
def _structure(S, T, out, tmap, learn):
|
|
395
435
|
from . import parity_structure as PS
|
|
396
436
|
sym_of, cat_of, t_syms, t_cat = {}, {}, {}, {}
|
|
@@ -409,7 +449,7 @@ def _structure(S, T, out, tmap, learn):
|
|
|
409
449
|
|
|
410
450
|
def rename_map(res: dict) -> dict:
|
|
411
451
|
"""The structure / learned matches as a `--map` file ({source: target}) to review and commit."""
|
|
412
|
-
return {r["symbol"]: r["target"] for r in res["matched"] if r.get("confidence") in
|
|
452
|
+
return {r["symbol"]: r["target"] for r in res["matched"] if r.get("confidence") in INFERRED}
|
|
413
453
|
|
|
414
454
|
|
|
415
455
|
def _row(sym, target, how, owner_match=None) -> dict:
|
|
@@ -435,6 +475,25 @@ def _group(file: str) -> str:
|
|
|
435
475
|
return "/".join(parts[:2]) if len(parts) > 2 else (parts[0] if parts else "")
|
|
436
476
|
|
|
437
477
|
|
|
478
|
+
def _grouped(lines, title, rows, total, max_items):
|
|
479
|
+
by = defaultdict(list)
|
|
480
|
+
for r in rows:
|
|
481
|
+
by[r["module"]].append(r)
|
|
482
|
+
if not by:
|
|
483
|
+
return
|
|
484
|
+
lines += ["", f"== {title}: {total}"]
|
|
485
|
+
shown = 0
|
|
486
|
+
for mod in sorted(by, key=lambda k: -len(by[k])):
|
|
487
|
+
lines.append(f" {mod or '.'} ({len(by[mod])})")
|
|
488
|
+
for r in by[mod]:
|
|
489
|
+
if shown >= max_items:
|
|
490
|
+
break
|
|
491
|
+
shown += 1
|
|
492
|
+
lines.append(f" {r['symbol']} [{r['kind']}] {r['file']}:{r['line']}")
|
|
493
|
+
if shown < total:
|
|
494
|
+
lines.append(f" ... {total - shown} more (--json for all)")
|
|
495
|
+
|
|
496
|
+
|
|
438
497
|
def render(res: dict, max_items: int = 200) -> str:
|
|
439
498
|
s = res["summary"]
|
|
440
499
|
m = s["matched"]
|
|
@@ -457,7 +516,14 @@ def render(res: dict, max_items: int = 200) -> str:
|
|
|
457
516
|
lines.append(f" {r['symbol']} [{r['kind']}] {r['file']}:{r['line']}")
|
|
458
517
|
if shown < s["missing"]:
|
|
459
518
|
lines.append(f" ... {s['missing'] - shown} more (--json for all)")
|
|
460
|
-
|
|
519
|
+
if "target_only" in res:
|
|
520
|
+
lines[1] += f"; {s['target_only']} only in the target"
|
|
521
|
+
lines += ["", f"== MATCHED pairs: {sum(m.values())}"]
|
|
522
|
+
for r in sorted(res["matched"], key=lambda r: (r["confidence"] != "explicit", r["symbol"]))[:max_items]:
|
|
523
|
+
lines.append(f" {r['symbol']} -> {r['target']} [{r['confidence']}]")
|
|
524
|
+
if sum(m.values()) > max_items:
|
|
525
|
+
lines.append(f" ... {sum(m.values()) - max_items} more (--json for all)")
|
|
526
|
+
inferred = [r for r in res["matched"] if r.get("confidence") in INFERRED]
|
|
461
527
|
if inferred:
|
|
462
528
|
lines += ["", f"== INFERRED matches (not by name): {len(inferred)}"]
|
|
463
529
|
for r in inferred[:max_items]:
|
|
@@ -467,6 +533,8 @@ def render(res: dict, max_items: int = 200) -> str:
|
|
|
467
533
|
if rule is (res.get("learned_rules") or [None])[0]:
|
|
468
534
|
lines += ["", "== LEARNED rename rules"]
|
|
469
535
|
lines.append(f" {rule['at']}: {rule['from']!r} -> {rule['to']!r} (seen {rule['support']}x)")
|
|
536
|
+
if "target_only" in res:
|
|
537
|
+
_grouped(lines, "ONLY IN TARGET (no source counterpart)", res["target_only"], s["target_only"], max_items)
|
|
470
538
|
if res["unknown"]:
|
|
471
539
|
lines += ["", f"== UNKNOWN (file parsed with syntax errors): {s['unknown']}"]
|
|
472
540
|
lines += [f" {r['symbol']} {r['file']}:{r['line']}" for r in res["unknown"][:max_items]]
|
|
@@ -11,8 +11,21 @@ its outgoing edges:
|
|
|
11
11
|
sym:<target> symbols it calls / instantiates / navigates to that are already paired (the source side is
|
|
12
12
|
rewritten to the target's name, so a call to a paired API on both sides is a shared feature)
|
|
13
13
|
call:<name> the names of the members it calls (two words or more)
|
|
14
|
+
res:<name> image and raw resources it uses (`Image("ic_lock")`, `UIImage(named:)`, `Asset.Images.icLock`,
|
|
15
|
+
`Image(.icLock)`, `R.drawable.ic_lock`, `Res.drawable.x`), case and `_` folded; colors are design
|
|
16
|
+
tokens shared by every screen and are left out
|
|
14
17
|
w:<stem> the stemmed content words of its own name
|
|
15
18
|
|
|
19
|
+
A use is specific when it appears in at most SPECIFIC_FILES files on each side (files, not symbols, since a type's span
|
|
20
|
+
holds its members'); a pair whose shared uses are all generic needs two shared name words, so two screens that only
|
|
21
|
+
share `l10n:cancel` / `l10n:yes` and one word do not pair.
|
|
22
|
+
|
|
23
|
+
Types that are still missing after that are paired by their declared fields (`fields`): stored properties, each under
|
|
24
|
+
its wire name when one is declared (Swift `CodingKeys` raw values, Kotlin `@SerialName` / `@SerializedName` /
|
|
25
|
+
`@Json(name =)`), and enum cases, kept apart from properties; case and `_` folded. A pair needs MIN_FIELDS shared
|
|
26
|
+
fields, an IDF-weighted overlap of at least MIN_FIELD_SCORE, a shared name word or a higher overlap, mutual best and
|
|
27
|
+
the margin.
|
|
28
|
+
|
|
16
29
|
A pair is accepted when it shares a use (any feature but w:) and either two uses or two name words, its IDF-weighted
|
|
17
30
|
cosine is at least MIN_SCORE, both symbols are each other's best candidate, the runner-up scores below MARGIN times
|
|
18
31
|
the best, and category, UI-ness and architecture role agree (`compatible`). Learned rules come from the
|
|
@@ -21,6 +34,7 @@ MIN_SUPPORT times, two thirds of the time for that source tail, is applied to th
|
|
|
21
34
|
top-level symbols. Every match carries its evidence; name matches are left as they are."""
|
|
22
35
|
from __future__ import annotations
|
|
23
36
|
|
|
37
|
+
import json
|
|
24
38
|
import math
|
|
25
39
|
import re
|
|
26
40
|
import sqlite3
|
|
@@ -32,9 +46,16 @@ MIN_SHARED = 2
|
|
|
32
46
|
MARGIN = 0.8 # the runner-up must score below MARGIN * best
|
|
33
47
|
MIN_SUPPORT = 2
|
|
34
48
|
MAX_DF = 40
|
|
49
|
+
SPECIFIC_FILES = 3 # a shared use found in more files than this on either side is generic (`l10n:cancel`)
|
|
50
|
+
MIN_FIELDS = 3
|
|
51
|
+
MIN_FIELD_SCORE = 0.5
|
|
35
52
|
PREVIEW = re.compile(r"Preview") # Compose @Preview functions / PreviewParameterProviders, SwiftUI previews # features shared by more symbols than this do not propose candidates
|
|
36
53
|
L10N = re.compile(r"\b(?:Localizations|L10n|R\.string|BitwardenString|CommonStrings|[A-Z]\w*Strings)\.([A-Za-z_]\w*)")
|
|
37
54
|
STR = re.compile(r'"((?:[^"\\\n]|\\.){5,80})"')
|
|
55
|
+
RES = re.compile(r"""\b(?:UI|NS)?Image\(\s*(?:named:\s*)?"([^"\n]+)"|\bAsset\.(?:Images|Assets)\.(\w+)|"""
|
|
56
|
+
r"""\bImage\(\s*\.(\w+)\s*\)|\b(?:R|Res)\.(?:drawable|mipmap|raw)\.(\w+)""")
|
|
57
|
+
WIRE = re.compile(r'@(?:SerialName|SerializedName|JsonProperty|Json\(\s*name\s*=)\s*\(?\s*(?:value\s*=\s*)?"([^"\n]+)"')
|
|
58
|
+
RAW_CASE = re.compile(r'\bcase\s+`?(\w+)`?\s*=\s*"([^"\n]+)"')
|
|
38
59
|
EDGE_KINDS = ("CALLS", "INSTANTIATES", "NAVIGATES_TO", "HTTP_CALLS", "USES_VALUE", "REFERENCES_FN", "USES_TYPE")
|
|
39
60
|
|
|
40
61
|
|
|
@@ -123,8 +144,40 @@ class Side:
|
|
|
123
144
|
for r in c.execute(q, EDGE_KINDS):
|
|
124
145
|
self.out[r["src"]].append((r["dst"], r["kind"]))
|
|
125
146
|
self.http = {r["id"]: (r["name"] or r["id"]) for r in c.execute("SELECT id, name FROM nodes WHERE kind='http'")}
|
|
147
|
+
self.decl = defaultdict(list) # owner fqn -> [(name, kind, file, line)] of stored fields / enum cases
|
|
148
|
+
for r in c.execute("SELECT kind, fqn, file, line, attrs FROM nodes WHERE kind IN ('field', 'enum_case') "
|
|
149
|
+
"AND fqn IS NOT NULL AND file IS NOT NULL"):
|
|
150
|
+
if ".Companion." in r["fqn"] or "." not in r["fqn"]:
|
|
151
|
+
continue
|
|
152
|
+
if r["kind"] == "field" and (json.loads(r["attrs"] or "{}").get("property") or "stored") != "stored":
|
|
153
|
+
continue
|
|
154
|
+
o, nm = r["fqn"].rsplit(".", 1)
|
|
155
|
+
self.decl[o].append((nm, r["kind"], r["file"], r["line"]))
|
|
126
156
|
c.close()
|
|
127
157
|
|
|
158
|
+
def fields(self, fq: str) -> set:
|
|
159
|
+
"""`field:<wire name>` for each stored property declared directly on the type: the explicit wire name
|
|
160
|
+
(`@SerialName("item_title")`, a `CodingKeys` case `title = "item_title"`) or else the property name; `case:<name>`
|
|
161
|
+
for each enum case, so an enum of field names does not meet the type that has those fields."""
|
|
162
|
+
raw = {}
|
|
163
|
+
for nm, kind, file, line in self.decl.get(fq + ".CodingKeys", ()):
|
|
164
|
+
m = RAW_CASE.search(self.text(file, line, line))
|
|
165
|
+
if m:
|
|
166
|
+
raw[m.group(1)] = m.group(2)
|
|
167
|
+
out = set()
|
|
168
|
+
for nm, kind, file, line in self.decl.get(fq, ()):
|
|
169
|
+
wire = raw.get(nm)
|
|
170
|
+
if not wire and kind == "field":
|
|
171
|
+
m = WIRE.search(self.text(file, line, line))
|
|
172
|
+
if not m and line > 1: # an annotation on its own line above
|
|
173
|
+
prev = self.text(file, line - 1, line - 1)
|
|
174
|
+
m = None if re.search(r"\b(?:val|var|let)\s", prev) else WIRE.search(prev)
|
|
175
|
+
wire = m.group(1) if m else None
|
|
176
|
+
k = _fold(wire or nm)
|
|
177
|
+
if len(k) > 1:
|
|
178
|
+
out.add(("case:" if kind == "enum_case" else "field:") + k)
|
|
179
|
+
return out
|
|
180
|
+
|
|
128
181
|
def text(self, file: str, a: int, b: int) -> str:
|
|
129
182
|
if file not in self.lines:
|
|
130
183
|
try:
|
|
@@ -139,6 +192,9 @@ class Side:
|
|
|
139
192
|
if file and a:
|
|
140
193
|
src = self.text(file, a, b)
|
|
141
194
|
f |= {"l10n:" + _fold(m) for m in L10N.findall(src)}
|
|
195
|
+
for m in RES.finditer(src):
|
|
196
|
+
f.add("res:" + _fold(next(g for g in m.groups() if g)))
|
|
197
|
+
src = RES.sub(" ", src)
|
|
142
198
|
for m in STR.findall(src):
|
|
143
199
|
s = m.strip().lstrip("/")
|
|
144
200
|
if len(s) >= 5 and re.search(r"[A-Za-z]{3}", s) and not re.search(r"\\\(|\$\{|%[@sd]", s):
|
|
@@ -250,6 +306,60 @@ def _apply_rules(rules, out, sym_of, cat_of, t_syms, t_cat, used):
|
|
|
250
306
|
out["missing"] = keep
|
|
251
307
|
|
|
252
308
|
|
|
309
|
+
def _by_fields(sS, sT, out, sym_of, cat_of, t_syms, t_cat, used, S, T):
|
|
310
|
+
"""Types still missing, paired by the fields they declare (`ViewItemState` / `VaultItemState`, a Swift
|
|
311
|
+
`Codable` model and its Kotlin `@Serializable` port)."""
|
|
312
|
+
src = {r["symbol"]: sS.fields(r["symbol"]) for r in out["missing"] if cat_of.get(r["symbol"]) == "type"
|
|
313
|
+
and "owner_matched" not in r}
|
|
314
|
+
src = {k: v for k, v in src.items() if len(v) >= MIN_FIELDS and _short(k) != "CodingKeys"}
|
|
315
|
+
tgt = {fq: sT.fields(fq) for fq in t_syms if t_cat.get(fq) == "type" and fq not in used}
|
|
316
|
+
tgt = {k: v for k, v in tgt.items() if len(v) >= MIN_FIELDS and _short(k) != "CodingKeys"}
|
|
317
|
+
if not src or not tgt:
|
|
318
|
+
return
|
|
319
|
+
df = Counter()
|
|
320
|
+
for fs in list(src.values()) + list(tgt.values()):
|
|
321
|
+
df.update(fs)
|
|
322
|
+
n = len(src) + len(tgt)
|
|
323
|
+
w = {f: math.log(1 + n / c) for f, c in df.items()}
|
|
324
|
+
inv = defaultdict(list)
|
|
325
|
+
for fq, fs in tgt.items():
|
|
326
|
+
for f in fs:
|
|
327
|
+
inv[f].append(fq)
|
|
328
|
+
|
|
329
|
+
def score(fq, t):
|
|
330
|
+
a, b = src[fq], tgt[t]
|
|
331
|
+
sh = a & b
|
|
332
|
+
if len(sh) < MIN_FIELDS:
|
|
333
|
+
return 0.0, sh
|
|
334
|
+
sc = sum(w[f] for f in sh) / sum(w[f] for f in a | b)
|
|
335
|
+
words = name_words(fq) & name_words(t)
|
|
336
|
+
if sc < MIN_FIELD_SCORE or (not words and sc < 0.75):
|
|
337
|
+
return 0.0, sh
|
|
338
|
+
return sc, sh | words
|
|
339
|
+
|
|
340
|
+
best = {}
|
|
341
|
+
for fq, fs in src.items():
|
|
342
|
+
cands = {t for f in fs if df[f] <= MAX_DF for t in inv[f]
|
|
343
|
+
if compatible(fq, "type", t, "type", S["_ui"].get(fq), T["_ui"].get(t))}
|
|
344
|
+
scored = sorted(((score(fq, t), t) for t in cands), key=lambda x: -x[0][0])
|
|
345
|
+
if scored and scored[0][0][0] > 0 and (len(scored) == 1 or scored[1][0][0] < MARGIN * scored[0][0][0]):
|
|
346
|
+
best[fq] = (scored[0][1], scored[0][0][0], scored[0][0][1])
|
|
347
|
+
by_t = defaultdict(list)
|
|
348
|
+
for fq, (t, sc, sh) in best.items():
|
|
349
|
+
by_t[t].append((sc, fq))
|
|
350
|
+
keep = []
|
|
351
|
+
for row in out["missing"]:
|
|
352
|
+
got = best.get(row["symbol"])
|
|
353
|
+
if got and max(by_t[got[0]])[1] == row["symbol"] and got[0] not in used:
|
|
354
|
+
t, sc, sh = got
|
|
355
|
+
used.add(t)
|
|
356
|
+
ev = sorted(sh, key=lambda f: (f.startswith("w:"), -w.get(f, 0), f))[:6]
|
|
357
|
+
out["matched"].append(dict(row, target=t, confidence="fields", score=round(sc, 2), evidence=ev))
|
|
358
|
+
else:
|
|
359
|
+
keep.append(row)
|
|
360
|
+
out["missing"] = keep
|
|
361
|
+
|
|
362
|
+
|
|
253
363
|
def _structure(S, T, out, sym_of, cat_of, t_syms, t_cat, used):
|
|
254
364
|
sS, sT = Side(S), Side(T)
|
|
255
365
|
pairs = {r["symbol"]: r["target"] for r in out["matched"]}
|
|
@@ -264,6 +374,12 @@ def _structure(S, T, out, sym_of, cat_of, t_syms, t_cat, used):
|
|
|
264
374
|
df = Counter()
|
|
265
375
|
for fs in list(src_f.values()) + list(tgt_f.values()):
|
|
266
376
|
df.update(fs)
|
|
377
|
+
spread = [defaultdict(set), defaultdict(set)] # feature -> files having it, per side
|
|
378
|
+
for k, (fsets, syms) in enumerate(((src_f, sym_of), (tgt_f, t_syms))):
|
|
379
|
+
for fq, fs in fsets.items():
|
|
380
|
+
for f in fs:
|
|
381
|
+
spread[k][f].add(syms[fq]["file"])
|
|
382
|
+
specific = {f for f in df if len(spread[0][f]) <= SPECIFIC_FILES and len(spread[1][f]) <= SPECIFIC_FILES}
|
|
267
383
|
n = max(1, len(src_f) + len(tgt_f))
|
|
268
384
|
w = {f: math.log(1 + n / c) for f, c in df.items()}
|
|
269
385
|
inv = defaultdict(list)
|
|
@@ -278,6 +394,8 @@ def _structure(S, T, out, sym_of, cat_of, t_syms, t_cat, used):
|
|
|
278
394
|
# what they use must carry the match: two shared uses, or one use and two shared name words
|
|
279
395
|
if nw < 1 or (nw < MIN_SHARED and len(sh) - nw < 2):
|
|
280
396
|
return 0.0, sh
|
|
397
|
+
if len(sh) - nw < 2 and not any(f in specific for f in sh if not f.startswith("w:")):
|
|
398
|
+
return 0.0, sh # only generic uses (`l10n:cancel`, `l10n:yes`) and one name word
|
|
281
399
|
return sum(w[f] for f in sh) / math.sqrt(sum(w[f] for f in a) * sum(w[f] for f in b)), sh
|
|
282
400
|
|
|
283
401
|
best_s = {}
|
|
@@ -305,3 +423,4 @@ def _structure(S, T, out, sym_of, cat_of, t_syms, t_cat, used):
|
|
|
305
423
|
else:
|
|
306
424
|
keep.append(row)
|
|
307
425
|
out["missing"] = keep
|
|
426
|
+
_by_fields(sS, sT, out, sym_of, cat_of, t_syms, t_cat, used, S, T)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""`cg parity --structure` part 2 (#93): types paired by their declared fields and wire names, views paired by the
|
|
2
|
+
image resources they use, generic shared keys not enough, and `--both-sides` (matched pairs plus what only the
|
|
3
|
+
target has). Invented app: a hiking app in Swift and its Kotlin port."""
|
|
4
|
+
import json
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
12
|
+
pytest.importorskip("tree_sitter_swift")
|
|
13
|
+
pytest.importorskip("tree_sitter_kotlin")
|
|
14
|
+
from test_parity import ROOT, build # noqa: E402
|
|
15
|
+
from cg_code_graph import parity as P # noqa: E402
|
|
16
|
+
from cg_code_graph import parity_structure as PS # noqa: E402
|
|
17
|
+
|
|
18
|
+
IOS = {
|
|
19
|
+
"Trails/Models/TrailSummaryResponse.swift":
|
|
20
|
+
"struct TrailSummaryResponse: Codable {\n let trailId: String\n let displayName: String\n"
|
|
21
|
+
" let elevationGain: Int\n let loopKind: String\n\n enum CodingKeys: String, CodingKey {\n"
|
|
22
|
+
' case trailId = "trail_id"\n case displayName = "display_name"\n'
|
|
23
|
+
' case elevationGain = "elevation_gain"\n case loopKind = "loop_kind"\n }\n}\n',
|
|
24
|
+
"Trails/Detail/HikeDetailState.swift":
|
|
25
|
+
"struct HikeDetailState {\n var title: String = \"\"\n var isFavorite = false\n var distanceText = \"\"\n"
|
|
26
|
+
" var difficulty = 0\n var photoCount = 0\n}\n",
|
|
27
|
+
"Trails/Badges/BadgeShelfView.swift":
|
|
28
|
+
"import SwiftUI\n\nstruct BadgeShelfView: View {\n var body: some View {\n HStack {\n"
|
|
29
|
+
' Image("badge_summit")\n Image("badge_sunrise")\n }\n }\n}\n',
|
|
30
|
+
"Trails/Trip/HikeShareSheet.swift":
|
|
31
|
+
"import SwiftUI\n\nstruct HikeShareSheet: View {\n var body: some View {\n HStack {\n"
|
|
32
|
+
" Text(Localizations.cancel)\n Text(Localizations.yes)\n }\n }\n}\n",
|
|
33
|
+
"Trails/Settings/SettingsStore.swift":
|
|
34
|
+
"final class SettingsStore {\n func reset() {}\n}\n",
|
|
35
|
+
"Trails/Widgets/LiveActivityWidget.swift":
|
|
36
|
+
'struct LiveActivityWidget {\n func kind() -> String { "live-activity-hike" }\n}\n',
|
|
37
|
+
}
|
|
38
|
+
ANDROID = {
|
|
39
|
+
"app/src/main/java/com/trailmate/data/TrailOverviewJson.kt":
|
|
40
|
+
"package com.trailmate.data\n\n@Serializable\ndata class TrailOverviewJson(\n"
|
|
41
|
+
' @SerialName("trail_id") val id: String,\n @SerialName("display_name") val name: String,\n'
|
|
42
|
+
' @SerialName("elevation_gain") val gain: Int,\n @SerialName("loop_kind") val loop: String,\n)\n',
|
|
43
|
+
"app/src/main/java/com/trailmate/detail/RouteDetailViewState.kt":
|
|
44
|
+
"package com.trailmate.detail\n\ndata class RouteDetailViewState(\n val title: String,\n"
|
|
45
|
+
" val isFavorite: Boolean,\n val distanceText: String,\n val difficulty: Int,\n val elevationText: String,\n)\n",
|
|
46
|
+
"app/src/main/java/com/trailmate/badges/AchievementRow.kt":
|
|
47
|
+
"package com.trailmate.badges\n\nimport androidx.compose.runtime.Composable\n\n@Composable\nfun AchievementRow() {\n"
|
|
48
|
+
" Image(painterResource(R.drawable.badge_summit), null)\n Image(painterResource(R.drawable.badge_sunrise), null)\n}\n",
|
|
49
|
+
"app/src/main/java/com/trailmate/trip/HikeDeleteDialog.kt":
|
|
50
|
+
"package com.trailmate.trip\n\nimport androidx.compose.runtime.Composable\n\n@Composable\nfun HikeDeleteDialog() {\n"
|
|
51
|
+
" Text(stringResource(R.string.cancel))\n Text(stringResource(R.string.yes))\n}\n",
|
|
52
|
+
# cancel / yes are on every prompt: generic keys
|
|
53
|
+
**{f"app/src/main/java/com/trailmate/common/{n}Prompt.kt":
|
|
54
|
+
f"package com.trailmate.common\n\nclass {n}Prompt {{\n fun confirm{n}() {{\n show(R.string.cancel)\n"
|
|
55
|
+
f" show(R.string.yes)\n }}\n}}\n" for n in ("Exit", "Logout", "Unfollow", "Archive")},
|
|
56
|
+
"app/src/main/java/com/trailmate/settings/SettingsStore.kt":
|
|
57
|
+
"package com.trailmate.settings\n\nclass SettingsStore {\n fun reset() {}\n fun exportBackup() {}\n}\n",
|
|
58
|
+
"app/src/main/java/com/trailmate/wear/WearTileService.kt":
|
|
59
|
+
"package com.trailmate.wear\n\nclass WearTileService {\n fun onTileRequest() {}\n}\n",
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@pytest.fixture(scope="module")
|
|
64
|
+
def dbs():
|
|
65
|
+
return build(IOS, "fios"), build(ANDROID, "fandroid")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_default_output_unchanged(dbs):
|
|
69
|
+
res = P.parity(*dbs)
|
|
70
|
+
assert "target_only" not in res and "inferred" not in res["summary"]
|
|
71
|
+
assert not [r for r in res["matched"] if r["confidence"] in P.INFERRED]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_fields_resources_and_generic_keys(dbs):
|
|
75
|
+
res = P.parity(*dbs, structure=True)
|
|
76
|
+
m = {r["symbol"]: r for r in res["matched"]}
|
|
77
|
+
# wire names: CodingKeys raw values meet @SerialName, although every property is renamed
|
|
78
|
+
t = m["TrailSummaryResponse"]
|
|
79
|
+
assert t["target"] == "com.trailmate.data.TrailOverviewJson", t
|
|
80
|
+
assert {"str:trail_id", "field:trailid"} & set(t["evidence"]), t
|
|
81
|
+
# screen state by its stored properties
|
|
82
|
+
h = m["HikeDetailState"]
|
|
83
|
+
assert h["target"] == "com.trailmate.detail.RouteDetailViewState" and h["confidence"] == "fields", h
|
|
84
|
+
# image resources: Image("badge_summit") / R.drawable.badge_summit
|
|
85
|
+
b = m["BadgeShelfView"]
|
|
86
|
+
assert b["target"] == "com.trailmate.badges.AchievementRow" and b["confidence"] == "structure", b
|
|
87
|
+
assert "res:badgesummit" in b["evidence"]
|
|
88
|
+
# only generic keys (cancel / yes on every prompt) in common: no match
|
|
89
|
+
missing = {r["symbol"] for r in res["missing"]}
|
|
90
|
+
assert "HikeShareSheet" in missing and "LiveActivityWidget" in missing, missing
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_generic_guard_is_what_keeps_them_apart(dbs, monkeypatch):
|
|
94
|
+
monkeypatch.setattr(PS, "SPECIFIC_FILES", 10 ** 6)
|
|
95
|
+
m = {r["symbol"]: r["target"] for r in P.parity(*dbs, structure=True)["matched"]}
|
|
96
|
+
# one name word and two generic keys in common: IDF alone would pair a share sheet with a delete dialog
|
|
97
|
+
assert m.get("HikeShareSheet") == "com.trailmate.trip.HikeDeleteDialog"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_both_sides(dbs):
|
|
101
|
+
res = P.parity(*dbs, structure=True, both_sides=True)
|
|
102
|
+
only = {r["symbol"] for r in res["target_only"]}
|
|
103
|
+
assert "com.trailmate.wear.WearTileService" in only
|
|
104
|
+
assert "com.trailmate.settings.SettingsStore.exportBackup" in only # member of a matched type
|
|
105
|
+
assert "com.trailmate.wear.WearTileService.onTileRequest" not in only # counted under its type
|
|
106
|
+
assert "com.trailmate.data.TrailOverviewJson" not in only
|
|
107
|
+
assert res["summary"]["target_only"] == len(res["target_only"])
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_cli_both_sides(dbs):
|
|
111
|
+
r = subprocess.run([sys.executable, "-m", "cg_code_graph.cli", "parity", "--db", dbs[0], "--against", dbs[1],
|
|
112
|
+
"--structure", "--both-sides"], capture_output=True, text=True, cwd=ROOT)
|
|
113
|
+
assert r.returncode == 0, r.stderr
|
|
114
|
+
assert "== MATCHED pairs:" in r.stdout and "== ONLY IN TARGET (no source counterpart):" in r.stdout
|
|
115
|
+
assert "SettingsStore -> com.trailmate.settings.SettingsStore [exact]" in r.stdout
|
|
116
|
+
assert "[fields" in r.stdout
|
|
117
|
+
j = json.loads(subprocess.run([sys.executable, "-m", "cg_code_graph.cli", "parity", "--db", dbs[0], "--against",
|
|
118
|
+
dbs[1], "--both-sides", "--json"], capture_output=True, text=True, cwd=ROOT).stdout)
|
|
119
|
+
assert "target_only" in j and "inferred" not in j["summary"]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def test_wire_names(dbs):
|
|
123
|
+
want = {"field:trailid", "field:displayname", "field:elevationgain", "field:loopkind"}
|
|
124
|
+
assert PS.Side(P.load(dbs[0])).fields("TrailSummaryResponse") == want # CodingKeys raw values
|
|
125
|
+
assert PS.Side(P.load(dbs[1])).fields("com.trailmate.data.TrailOverviewJson") == want # @SerialName
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|