cg-code-graph 0.23.1__tar.gz → 0.23.2__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.1/cg_code_graph.egg-info → cg_code_graph-0.23.2}/PKG-INFO +1 -1
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/__init__.py +1 -1
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/cli.py +20 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/model.py +1 -1
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/doctor.py +13 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/nuxt/plugin.py +336 -19
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/extractor/extract.mjs +23 -3
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/query.py +36 -5
- cg_code_graph-0.23.2/cg_code_graph/update_check.py +122 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2/cg_code_graph.egg-info}/PKG-INFO +1 -1
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph.egg-info/SOURCES.txt +4 -0
- cg_code_graph-0.23.2/tests/test_nuxt_i18n.py +89 -0
- cg_code_graph-0.23.2/tests/test_nuxt_nitro.py +103 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_snippet.py +4 -1
- cg_code_graph-0.23.2/tests/test_update_check.py +96 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/LICENSE +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/MANIFEST.in +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/README.md +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/__main__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/affected.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/agent_rules.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/agents.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/aitools.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/android_ipc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/apple_ipc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/apps.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/blindspots.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/bridges.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/brokers.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/concepts.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/config.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/cache.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/detect.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/env.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/extractors.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/fsutil.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/generated.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/paths.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/redact.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/store.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/core/syntax_errors.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/coverage.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/dart_isolates.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/explore.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/external.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/graphql.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/guard_facts.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/hooks.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/indexer.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/insecure_transport.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/install_rules.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/jobs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/link.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/lint_async.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/local_ipc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/local_sockets.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/mcp_graphs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/mcp_install.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/mcp_server.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/parity.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/parity_structure.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/payload.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plans.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/platform_scan.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/platforms.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/astro/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/astro/content.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/astro/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/cfamily/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/cfamily/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/cfamily/syntax.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/dart/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/dart/bridges.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/dart/extractor/bin/extract.dart +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/dart/extractor/pubspec.lock +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/dart/extractor/pubspec.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/dart/http.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/dart/models.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/dart/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/dart/program.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/django/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/django/extras.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/django/models.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/django/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/django/schemas.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/django/shapes.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/django/urls.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/express/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/express/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/flutter/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/flutter/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/java/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/java/exact.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/java/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/jvm/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/jvm/interop.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/jvm/spring.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/kotlin/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/kotlin/exact.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/kotlin/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/kotlin/reparse.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/laravel/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/laravel/broadcast.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/laravel/massassign.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/laravel/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/laravel/tests.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/laravel/values.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/native/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/native/gates.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/native/runner.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/native/scipread.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/native/ts.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/nest/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/nest/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/nextjs/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/nextjs/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/nuxt/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/php/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/php/external.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/php/extractor/composer.json +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/php/extractor/composer.lock +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/php/extractor/extract.php +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/php/gating.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/php/http_client.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/php/inline_guards.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/php/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/php/strings.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/aitools.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/external.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/fields.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/refs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/roots.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/socketio.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/subproc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/tests.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/python/values.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/pyweb/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/pyweb/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/pyweb/values.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/rust/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/rust/cargo.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/rust/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/rust/syntax.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/scip/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/scip/importer.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/scip/scip.proto +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/scip/scip_pb2.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/stubs/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/stubs/plugins.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/swift/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/swift/baseurl.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/swift/exact.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/swift/indexstore.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/swift/packages.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/swift/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/baseurl.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/extractor/fw.mjs +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/extractor/package-lock.json +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/extractor/package.json +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/extractor/rr.mjs +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/nav.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/plugin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/react_router.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/tsweb/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/tsweb/common.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/tsweb/data.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/c_cpp.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/common.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/dart.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/django-ninja.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/django.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/djangorestframework.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/express.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/java.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/kotlin.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/laravel.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/nest.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/nextjs.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/nuxt.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/php.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/python.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/react-router.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/rust.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/spring.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/swift.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/presets/typescript.yaml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/process_runs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/protocols/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/protocols/builtin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/protocols/matchers.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/protocols/view.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/realtime.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/realtime_events.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/realtime_native.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/realtime_ws.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/roundtrip.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/routes.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/rpc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/sdk_systems.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/sockets.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/ssrf_input.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/starters.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/surface.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/tests_index.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/udp_apps.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/__init__.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/graph.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/server.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/static/app.css +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/static/app.js +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/static/index.html +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/static/layered.js +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/static/vendor/VERSIONS.txt +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/static/vendor/cose-base.js +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/static/vendor/cytoscape-fcose.js +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/static/vendor/cytoscape.min.js +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/static/vendor/layout-base.js +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/tools/package-lock.json +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/tools/package.json +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/viz/tools/shoot.mjs +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/watch.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/webhook_subs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/webhooks.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/xcode.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph.egg-info/dependency_links.txt +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph.egg-info/entry_points.txt +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph.egg-info/requires.txt +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph.egg-info/top_level.txt +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/pyproject.toml +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/setup.cfg +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_affected.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_agents_install.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_agents_md.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_ai_tools.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_android_ipc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_apple_ipc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_astro.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_astro_content.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_astro_server.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_bridges.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_bridges_pigeon_monorepo.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_brokers.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_cache_clean.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_cache_invalidation.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_cache_migration.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_channels_tests.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_cli_output.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_completeness.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_config_extras.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_coverage.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_coverage_ts_hint.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_dart_isolates.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_db_connections.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_dead_wrappers.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_dispatch_interfaces.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_django_flutter.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_docs_languages.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_docs_links.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_echo_ref.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_echo_wrapper.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_elysia.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_enum_constants.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_env.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_explore.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_external.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_fp_batch.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_gating.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_generated.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_graphql.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_hooks.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_impact_overrides.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_index_isolation.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_inherited_overrides.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_inline_guards.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_install_rules.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_192.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_202.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_203.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_205.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_206.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_207.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_208.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_209.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_210.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_211.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_issue_211_used_at.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_java.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_java_exact.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_jobs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_js_refs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_js_runtime.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_kotlin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_kotlin_binding.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_kotlin_exact.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_kotlin_fields.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_kotlin_mixed.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_kotlin_nav_consts.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_kotlin_props.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_laravel_determinism.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_laravel_resources.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_link_origin.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_lint_async.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_listing_files.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_local_ipc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_local_sockets.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_mass_assignment.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_mcp.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_mcp_index.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_mcp_install.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_mcp_instructions.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_mcp_multi_graph.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_native_cfamily.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_native_concurrency.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_native_rust.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_nuxt_import_dirs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_nuxt_rootsrc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_nuxt_side_dirs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_packaging.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_parity.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_parity_structure.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_php_http.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_php_props.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_plain_js.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_plans.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_platform_gaps.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_platform_type_variants.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_platforms.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_platforms_apple.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_presets_config.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_process_ipc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_process_runs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_protocols.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_app_tests_module.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_collection_chains.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_compat.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_entry_refs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_fields.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_infer_cycles.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_roots.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_subprocess_tests.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_tests.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_web_hosts.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_web_routes.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_python_web_routes_more.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_react_router.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_readers_writers_specs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_realtime.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_realtime_native.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_redact_salt.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_request_keys.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_roundtrip.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_route_specs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_route_tables.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_routes_search_explain.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_rpc.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_scip_health.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_sdk_external.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_sdk_external_infra.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_sdk_external_mail.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_sockets.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_spring.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_ssrf.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_starters_budget.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_surface.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_surface_transport.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_binding.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_exact.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_facts.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_fields.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_modules.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_more.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_nav_values.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_parse_errors.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_props.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_sdk.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_testing.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_swift_values.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_tests_scope.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_ts_fields.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_ts_fields_js_vue.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_ts_file_specs.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_ts_frameworks.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_ts_node_http.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_ts_nuxt.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_ts_src_tsconfig.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_unguarded.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_values.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_viz.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_vue_nav.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_watch.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_webhooks.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_webhooks_152.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_webhooks_152b.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/tests/test_websockets.py +0 -0
- {cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/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.2"
|
|
@@ -100,9 +100,24 @@ def _impact_labels(rows: list[dict], name_of, group_of) -> list[str]:
|
|
|
100
100
|
return labels
|
|
101
101
|
|
|
102
102
|
|
|
103
|
+
def _version_text(version: str) -> str:
|
|
104
|
+
"""`cg X.Y.Z`, plus a second line when the cached newer-release check (written by `cg doctor`) knows of a newer
|
|
105
|
+
release. Reads the cache only: never connects (#98)."""
|
|
106
|
+
try:
|
|
107
|
+
from .update_check import check, notice
|
|
108
|
+
n = notice(check(version, network=False))
|
|
109
|
+
except Exception:
|
|
110
|
+
n = None
|
|
111
|
+
return f"cg {version}" + (f"\n{n}" if n else "")
|
|
112
|
+
|
|
113
|
+
|
|
103
114
|
def main(argv=None):
|
|
104
115
|
from . import __version__
|
|
105
116
|
ap = argparse.ArgumentParser(prog="cg")
|
|
117
|
+
args_in = sys.argv[1:] if argv is None else list(argv)
|
|
118
|
+
if args_in[:1] == ["--version"]:
|
|
119
|
+
print(_version_text(__version__)) # printed here: argparse's version action re-wraps a second line
|
|
120
|
+
return 0
|
|
106
121
|
ap.add_argument("--version", action="version", version=f"cg {__version__}")
|
|
107
122
|
sub = ap.add_subparsers(dest="cmd", required=True)
|
|
108
123
|
p = sub.add_parser("index", help="detect languages / frameworks under ROOT and build the graph DB (stats JSON on stdout, coverage on stderr)"); p.add_argument("root"); p.add_argument("--db", required=True); p.add_argument("--name"); p.add_argument("--scip", action="append"); p.add_argument("--gates", help="gate scenarios JSON (e.g. examples/bookstore.gates.json)")
|
|
@@ -862,6 +877,11 @@ def render_node(d: dict) -> str:
|
|
|
862
877
|
unk = at.get("platform_unknown") or []
|
|
863
878
|
ps = ", ".join(p + ("?" if p in unk else "") for p in at["platforms"]) or "none of the targets"
|
|
864
879
|
out.append(f" platforms: {ps}" + (f" ({at['platform_expr']})" if at.get("platform_expr") else ""))
|
|
880
|
+
if n.get("kind") == "i18n" and at.get("definitions"):
|
|
881
|
+
out.append(" definitions: " + ", ".join(f"{x.get('locale') or '-'} {x['file']}:{x['line']}" for x in at["definitions"]))
|
|
882
|
+
if at.get("missing_locales"):
|
|
883
|
+
out.append(" missing locales: " + ", ".join(at["missing_locales"]))
|
|
884
|
+
at = {k: v for k, v in at.items() if k not in ("definitions", "defined_in", "missing_locales")}
|
|
865
885
|
rest = {k: v for k, v in at.items() if k not in ("platforms", "platform_unknown", "platform_expr", "platform_at", "platforms_other")}
|
|
866
886
|
if rest:
|
|
867
887
|
out.append(" attrs: " + ", ".join(f"{k}={v if isinstance(v, str) else json.dumps(v, default=str, ensure_ascii=False)}"
|
|
@@ -56,7 +56,7 @@ EDGE_KINDS: dict[str, tuple[bool, str]] = {
|
|
|
56
56
|
"HTTP_CALLS": (True, "client code calls an HTTP endpoint (method + path template)"),
|
|
57
57
|
"MATCHES_ROUTE": (True, "client endpoint matched to a backend route (cross-repo link)"),
|
|
58
58
|
"USES_LAYOUT": (False, "page uses layout"),
|
|
59
|
-
"USES_I18N": (
|
|
59
|
+
"USES_I18N": (True, "code/template uses i18n key (propagating: a key's users are its dependents in reaches / impact, #182)"),
|
|
60
60
|
"REFERENCES_TYPE": (False, "code references a type/interface"),
|
|
61
61
|
# value facts
|
|
62
62
|
"READS_SETTING": (True, "code reads a JSON settings key (getSetting('a.b', default))"),
|
|
@@ -407,12 +407,25 @@ def report(root: str | Path | None = None, scip: list | None = None) -> dict:
|
|
|
407
407
|
"legacy_cache": cache.legacy_report(),
|
|
408
408
|
**({"hooks_outdated": _outdated_hooks(rootp)} if rootp is not None else {}),
|
|
409
409
|
"update": "uv tool upgrade cg-code-graph | pipx upgrade cg-code-graph | install.sh --update",
|
|
410
|
+
"latest": _latest(),
|
|
410
411
|
**({"scip": [scip_health(x) for x in scip]} if scip else {}),
|
|
411
412
|
}
|
|
412
413
|
|
|
413
414
|
|
|
415
|
+
def _latest() -> dict:
|
|
416
|
+
"""Newer-release check (#98): PyPI at most once a day, cached; never fails or blocks for long."""
|
|
417
|
+
from .update_check import check
|
|
418
|
+
try:
|
|
419
|
+
return check()
|
|
420
|
+
except Exception:
|
|
421
|
+
return {"current": __version__, "latest": None, "newer": False, "source": "none", "disabled": None}
|
|
422
|
+
|
|
423
|
+
|
|
414
424
|
def render(r: dict) -> str:
|
|
415
425
|
out = [f"cg {r['cg']} (Python {r['python']}, {r['os']}; {r['package']}{', checkout' if r['checkout'] else ''})"]
|
|
426
|
+
from .update_check import notice
|
|
427
|
+
if (n := notice(r.get("latest") or {})):
|
|
428
|
+
out.append(f"newer release: {n}")
|
|
416
429
|
out.append("tools:")
|
|
417
430
|
for k, v in r["tools"].items():
|
|
418
431
|
out.append(f" {k:<14} {v['version'] or 'not found'}" + (f" ({v['path']})" if v["path"] else "")
|
|
@@ -11,7 +11,9 @@ register_hooks: finds the source dir (nuxt.config `srcDir`, else `app/` (Nuxt 4)
|
|
|
11
11
|
say which one was used (`prepared`: nuxi | generated).
|
|
12
12
|
contribute: file-based routing (route path per page), entry points (pages = ui_page; app.vue,
|
|
13
13
|
layouts, global middleware, plugins = ui_global), USES_LAYOUT, i18n keys (USES_I18N; defining
|
|
14
|
-
locale files)
|
|
14
|
+
locale files), Nitro server routes (server/api/** -> `route:<METHOD> /api/...`, server/routes/** without the
|
|
15
|
+
prefix; ROUTES_TO the default-export handler, USES_MIDDLEWARE every server/middleware handler, MATCHES_ROUTE
|
|
16
|
+
from same-origin $fetch / useFetch / useLazyFetch calls of the app) (#216).
|
|
15
17
|
"""
|
|
16
18
|
from __future__ import annotations
|
|
17
19
|
|
|
@@ -851,6 +853,229 @@ def generate_types(root: Path, src_dir: str) -> tuple[Path, dict]:
|
|
|
851
853
|
"import_scan": plan["scan"], "import_global": plan["global"], "auto_import": plan["auto_import"]}
|
|
852
854
|
|
|
853
855
|
|
|
856
|
+
# Nitro file-based routing (https://nitro.build/guide/routing): <name>[.<method>][.<env>].<ext>
|
|
857
|
+
NITRO_METHODS = ("get", "post", "put", "patch", "delete", "head", "options", "connect", "trace")
|
|
858
|
+
_NITRO_EXT = re.compile(r"\.(ts|mts|cts|js|mjs|cjs)$")
|
|
859
|
+
_NITRO_SKIP = re.compile(r"\.(test|spec)\.[cm]?[jt]s$|\.d\.ts$")
|
|
860
|
+
_PROXY_CALL = re.compile(r"\b(proxyRequest|sendProxy)\s*\(")
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
def nitro_route(rel: str, prefix: str = "") -> tuple[str, str] | None:
|
|
864
|
+
"""Path of a file inside server/api or server/routes -> (METHOD, uri), or None for a non-route file.
|
|
865
|
+
|
|
866
|
+
`plants/[id].get.ts` with prefix `/api` -> (GET, /api/plants/{id}); no method suffix -> ANY; `index` is the
|
|
867
|
+
directory; `[...slug]` -> {slug*}, `[...]` -> {_*}; `(group)` directories are dropped; `.dev` / `.prod` /
|
|
868
|
+
`.prerender` env suffixes are ignored."""
|
|
869
|
+
if not _NITRO_EXT.search(rel) or _NITRO_SKIP.search(rel):
|
|
870
|
+
return None
|
|
871
|
+
parts = [p for p in _NITRO_EXT.sub("", rel).split("/") if p]
|
|
872
|
+
if not parts:
|
|
873
|
+
return None
|
|
874
|
+
last = parts[-1]
|
|
875
|
+
last = re.sub(r"\.(dev|prod|prerender)$", "", last)
|
|
876
|
+
method = "ANY"
|
|
877
|
+
m = re.match(r"^(.+)\.(%s)$" % "|".join(NITRO_METHODS), last)
|
|
878
|
+
if m:
|
|
879
|
+
last, method = m.group(1), m.group(2).upper()
|
|
880
|
+
parts[-1] = last
|
|
881
|
+
segs = []
|
|
882
|
+
for i, s in enumerate(parts):
|
|
883
|
+
if re.fullmatch(r"\(.*\)", s):
|
|
884
|
+
continue
|
|
885
|
+
if s == "index" and i == len(parts) - 1:
|
|
886
|
+
continue
|
|
887
|
+
if s == "[...]":
|
|
888
|
+
segs.append("{_*}")
|
|
889
|
+
continue
|
|
890
|
+
mm = re.fullmatch(r"\[\.\.\.(\w+)\]", s)
|
|
891
|
+
if mm:
|
|
892
|
+
segs.append("{%s*}" % mm.group(1))
|
|
893
|
+
continue
|
|
894
|
+
segs.append(re.sub(r"\[(\w+)\]", r"{\1}", s))
|
|
895
|
+
return method, "/" + "/".join(s.strip("/") for s in [prefix.strip("/")] + segs if s.strip("/"))
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
def server_dirs(root: Path, src_dir: str) -> list[str]:
|
|
899
|
+
"""Nitro server dirs of a Nuxt project: the root server/ (Nuxt 4 serverDir) and <srcDir>/server (Nuxt 3)."""
|
|
900
|
+
cands = ["server"] + ([] if src_dir in ("", ".") else [f"{src_dir.strip('/')}/server"])
|
|
901
|
+
return [d for d in dict.fromkeys(cands) if (root / d).is_dir()]
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
# ------------------------------------------------------------ i18n locale files (#182)
|
|
905
|
+
# a top-level key shaped like a locale code: en, pt-BR, zh_Hant, es-419
|
|
906
|
+
LOCALE_RE = re.compile(r"^[a-z]{2,3}(?:[-_](?:[A-Z]{2}|[A-Z][a-z]{3}|\d{3}))*$")
|
|
907
|
+
_KNOWN_LOCALES = {"en", "ar", "ku", "fr", "de"}
|
|
908
|
+
LOCALE_EXTS = (".json", ".yaml", ".yml")
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
def json_key_lines(text: str) -> dict[str, int]:
|
|
912
|
+
"""Dotted key path -> line of the key, for the objects of a JSON document (keys inside arrays are skipped,
|
|
913
|
+
as flatten() treats arrays as values)."""
|
|
914
|
+
out: dict[str, int] = {}
|
|
915
|
+
stack: list[list] = [] # [type, current key, expecting a key]
|
|
916
|
+
pending = None
|
|
917
|
+
i, n, line = 0, len(text), 1
|
|
918
|
+
while i < n:
|
|
919
|
+
c = text[i]
|
|
920
|
+
if c == "\n":
|
|
921
|
+
line += 1
|
|
922
|
+
elif c == '"':
|
|
923
|
+
j = i + 1
|
|
924
|
+
while j < n and text[j] != '"':
|
|
925
|
+
j += 2 if text[j] == "\\" else 1
|
|
926
|
+
raw = text[i:j + 1]
|
|
927
|
+
if stack and stack[-1][0] == "obj" and stack[-1][2]:
|
|
928
|
+
try:
|
|
929
|
+
pending = (json.loads(raw), line)
|
|
930
|
+
except ValueError:
|
|
931
|
+
pending = (raw.strip('"'), line)
|
|
932
|
+
line += raw.count("\n")
|
|
933
|
+
i = j + 1
|
|
934
|
+
continue
|
|
935
|
+
elif c == ":" and pending is not None and stack and stack[-1][0] == "obj":
|
|
936
|
+
stack[-1][1], stack[-1][2] = pending[0], False
|
|
937
|
+
if all(f[0] == "obj" for f in stack):
|
|
938
|
+
out.setdefault(".".join(str(f[1]) for f in stack), pending[1])
|
|
939
|
+
pending = None
|
|
940
|
+
elif c == "{":
|
|
941
|
+
stack.append(["obj", None, True])
|
|
942
|
+
elif c == "[":
|
|
943
|
+
stack.append(["arr", None, False])
|
|
944
|
+
elif c in "}]":
|
|
945
|
+
if stack:
|
|
946
|
+
stack.pop()
|
|
947
|
+
elif c == "," and stack and stack[-1][0] == "obj":
|
|
948
|
+
stack[-1][2] = True
|
|
949
|
+
i += 1
|
|
950
|
+
return out
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
def yaml_key_lines(text: str) -> dict[str, int]:
|
|
954
|
+
import yaml
|
|
955
|
+
out: dict[str, int] = {}
|
|
956
|
+
|
|
957
|
+
def walk(node, prefix):
|
|
958
|
+
if isinstance(node, yaml.MappingNode):
|
|
959
|
+
for k, v in node.value:
|
|
960
|
+
key = f"{prefix}.{k.value}" if prefix else str(k.value)
|
|
961
|
+
out.setdefault(key, k.start_mark.line + 1)
|
|
962
|
+
walk(v, key)
|
|
963
|
+
try:
|
|
964
|
+
walk(yaml.compose(text), "")
|
|
965
|
+
except Exception:
|
|
966
|
+
pass
|
|
967
|
+
return out
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
def load_locale_file(f: Path) -> tuple[object, dict[str, int]]:
|
|
971
|
+
"""(data, key path -> line) of a JSON / YAML locale file; (None, {}) when it does not parse."""
|
|
972
|
+
try:
|
|
973
|
+
text = f.read_text(errors="replace")
|
|
974
|
+
if f.suffix == ".json":
|
|
975
|
+
return json.loads(text), json_key_lines(text)
|
|
976
|
+
import yaml
|
|
977
|
+
return yaml.safe_load(text), yaml_key_lines(text)
|
|
978
|
+
except Exception:
|
|
979
|
+
return None, {}
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
def nuxt_i18n_config(root: Path) -> dict:
|
|
983
|
+
"""Literal slice of nuxt.config `i18n`: defaultLocale, langDir, locale codes and their files."""
|
|
984
|
+
cfg = _config_path(root)
|
|
985
|
+
if not cfg:
|
|
986
|
+
return {}
|
|
987
|
+
try:
|
|
988
|
+
obj = _find_config_object(cfg.read_text(errors="replace"))
|
|
989
|
+
except Exception:
|
|
990
|
+
return {}
|
|
991
|
+
i18n = obj.get("i18n") if isinstance(obj.get("i18n"), dict) else {}
|
|
992
|
+
codes, files = [], {}
|
|
993
|
+
for loc in i18n.get("locales") or [] if isinstance(i18n.get("locales"), list) else []:
|
|
994
|
+
if isinstance(loc, str):
|
|
995
|
+
codes.append(loc)
|
|
996
|
+
elif isinstance(loc, dict) and isinstance(loc.get("code"), str):
|
|
997
|
+
codes.append(loc["code"])
|
|
998
|
+
fs = [loc["file"]] if isinstance(loc.get("file"), str) else []
|
|
999
|
+
fs += [x for x in loc.get("files") or [] if isinstance(x, str)] if isinstance(loc.get("files"), list) else []
|
|
1000
|
+
fs += [x["path"] for x in loc.get("files") or [] if isinstance(x, dict) and isinstance(x.get("path"), str)] \
|
|
1001
|
+
if isinstance(loc.get("files"), list) else []
|
|
1002
|
+
for x in fs:
|
|
1003
|
+
files[x.lstrip("./")] = loc["code"]
|
|
1004
|
+
return {"default_locale": i18n.get("defaultLocale") if isinstance(i18n.get("defaultLocale"), str) else None,
|
|
1005
|
+
"lang_dir": i18n.get("langDir") if isinstance(i18n.get("langDir"), str) else None,
|
|
1006
|
+
"locales": codes, "files": files}
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
def locale_dirs(root: Path, src_dir: str, lang_dir: str | None) -> list[str]:
|
|
1010
|
+
dirs = ["i18n/locales", f"{src_dir}/locales" if src_dir not in ("", ".") else "locales", "app/locales", "locales"]
|
|
1011
|
+
if lang_dir:
|
|
1012
|
+
ld = lang_dir.strip().lstrip("./").rstrip("/")
|
|
1013
|
+
dirs = [f"i18n/{ld}", (f"{src_dir}/{ld}" if src_dir not in ("", ".") else ld), ld] + dirs
|
|
1014
|
+
return [d for d in dict.fromkeys(dirs) if d and (root / d).is_dir()]
|
|
1015
|
+
|
|
1016
|
+
|
|
1017
|
+
def _sfc_key_lines(text: str, keys: list[str]) -> dict[str, int]:
|
|
1018
|
+
"""Line of each key's last segment inside the SFC's <i18n> block (the block's line when it is not found)."""
|
|
1019
|
+
m = re.search(r"<i18n\b[^>]*>", text)
|
|
1020
|
+
if not m:
|
|
1021
|
+
return {}
|
|
1022
|
+
base = text.count("\n", 0, m.start()) + 1
|
|
1023
|
+
body = text[m.end():]
|
|
1024
|
+
end = body.find("</i18n>")
|
|
1025
|
+
body = body if end < 0 else body[:end]
|
|
1026
|
+
out = {}
|
|
1027
|
+
for k in keys:
|
|
1028
|
+
last = k.split(".")[-1]
|
|
1029
|
+
km = re.search(r"[\"']?%s[\"']?\s*:" % re.escape(last), body)
|
|
1030
|
+
out[k] = base + (body.count("\n", 0, km.start()) if km else 0)
|
|
1031
|
+
return out
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
def i18n_definitions(root: Path, src_dir: str, sfc_i18n: dict) -> tuple[dict, list[str], str | None]:
|
|
1035
|
+
"""key -> [{locale, file, line}], the project's locales, and the default locale (nuxt.config defaultLocale, else
|
|
1036
|
+
the first locale found). A file keyed by locale codes ({"en": {...}, "pt-BR": {...}}) defines every locale."""
|
|
1037
|
+
cfg = nuxt_i18n_config(root)
|
|
1038
|
+
configured = set(cfg.get("locales") or [])
|
|
1039
|
+
defs: dict[str, list[dict]] = {}
|
|
1040
|
+
seen_locales: list[str] = []
|
|
1041
|
+
|
|
1042
|
+
def add(key, locale, rel, line):
|
|
1043
|
+
defs.setdefault(key, []).append({"locale": locale, "file": rel, "line": line or 1})
|
|
1044
|
+
if locale and locale not in seen_locales:
|
|
1045
|
+
seen_locales.append(locale)
|
|
1046
|
+
|
|
1047
|
+
for d in locale_dirs(root, src_dir, cfg.get("lang_dir")):
|
|
1048
|
+
for f in sorted(p for p in (root / d).glob("*") if p.suffix in LOCALE_EXTS and p.is_file()):
|
|
1049
|
+
data, lines = load_locale_file(f)
|
|
1050
|
+
if not isinstance(data, dict) or not data:
|
|
1051
|
+
continue
|
|
1052
|
+
rel = f.relative_to(root).as_posix()
|
|
1053
|
+
top = list(data)
|
|
1054
|
+
stem_locale = f.stem if (LOCALE_RE.match(f.stem) or f.stem in configured) else None
|
|
1055
|
+
keyed = all(isinstance(data[k], dict) and isinstance(k, str) for k in top) and (
|
|
1056
|
+
set(top) <= (configured or _KNOWN_LOCALES) or set(top) <= _KNOWN_LOCALES
|
|
1057
|
+
or (stem_locale is None and all(LOCALE_RE.match(k) for k in top)))
|
|
1058
|
+
if keyed:
|
|
1059
|
+
for loc in top:
|
|
1060
|
+
for k in flatten(data[loc]):
|
|
1061
|
+
add(k, loc, rel, lines.get(f"{loc}.{k}"))
|
|
1062
|
+
else:
|
|
1063
|
+
loc = cfg.get("files", {}).get(f.name) or cfg.get("files", {}).get(rel) or stem_locale
|
|
1064
|
+
for k in flatten(data):
|
|
1065
|
+
add(k, loc, rel, lines.get(k))
|
|
1066
|
+
for f, keys in sfc_i18n.items():
|
|
1067
|
+
try:
|
|
1068
|
+
text = (root / f).read_text(errors="replace")
|
|
1069
|
+
except OSError:
|
|
1070
|
+
text = ""
|
|
1071
|
+
kl = _sfc_key_lines(text, keys)
|
|
1072
|
+
for k in keys:
|
|
1073
|
+
add(k, None, f, kl.get(k, 1))
|
|
1074
|
+
default = cfg.get("default_locale") or (seen_locales[0] if seen_locales else None)
|
|
1075
|
+
locales = list(dict.fromkeys([*configured, *seen_locales]))
|
|
1076
|
+
return defs, locales, default
|
|
1077
|
+
|
|
1078
|
+
|
|
854
1079
|
def flatten(d, prefix=""):
|
|
855
1080
|
if isinstance(d, dict):
|
|
856
1081
|
for k, v in d.items():
|
|
@@ -928,27 +1153,119 @@ class NuxtPlugin(FrameworkPlugin):
|
|
|
928
1153
|
if lay in layouts:
|
|
929
1154
|
builder.add_edge(n.id, layouts[lay], "USES_LAYOUT", file=n.file, line=1,
|
|
930
1155
|
confidence="exact" if n.file in meta and meta[n.file].get("layout") else "resolved")
|
|
931
|
-
# i18n: keys used in code/templates, and where they are defined
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
for f in sorted((project.root / d).glob("*.json")) if (project.root / d).exists() else []:
|
|
935
|
-
try:
|
|
936
|
-
data = json.loads(f.read_text())
|
|
937
|
-
except Exception:
|
|
938
|
-
continue
|
|
939
|
-
locs = {"en", "ar", "ku", "fr", "de"}
|
|
940
|
-
if isinstance(data, dict) and set(data) and set(data) <= locs:
|
|
941
|
-
data = next(iter(data.values()))
|
|
942
|
-
for k in flatten(data):
|
|
943
|
-
defined.setdefault(k, []).append(str(f.relative_to(project.root)))
|
|
944
|
-
for f, keys in (ctx.facts.get("sfc_i18n") or {}).items():
|
|
945
|
-
for k in keys:
|
|
946
|
-
defined.setdefault(k, []).append(f)
|
|
1156
|
+
# i18n: keys used in code/templates, and where they are defined (#182)
|
|
1157
|
+
defs, locales, default = i18n_definitions(project.root, self.src_dir, ctx.facts.get("sfc_i18n") or {})
|
|
1158
|
+
used: dict[str, int] = {}
|
|
947
1159
|
for u in ctx.facts.get("i18n") or []:
|
|
948
|
-
|
|
1160
|
+
used[u["key"]] = used.get(u["key"], 0) + 1
|
|
1161
|
+
for u in ctx.facts.get("i18n") or []:
|
|
1162
|
+
key = u["key"]
|
|
1163
|
+
ds = defs.get(key) or []
|
|
1164
|
+
home = next((d for d in ds if default and d["locale"] == default), ds[0] if ds else None)
|
|
1165
|
+
attrs = {"defined_in": list(dict.fromkeys(d["file"] for d in ds)), "definitions": ds, "uses": used[key]}
|
|
1166
|
+
have = {d["locale"] for d in ds if d["locale"]}
|
|
1167
|
+
if default and default in have:
|
|
1168
|
+
missing = sorted(set(locales) - have)
|
|
1169
|
+
if missing:
|
|
1170
|
+
attrs["missing_locales"] = missing
|
|
1171
|
+
nid = builder.add_node("i18n", key, key, lang="ts", file=home["file"] if home else None,
|
|
1172
|
+
line=home["line"] if home else None, attrs=attrs)
|
|
949
1173
|
builder.add_edge(u["src"], nid, "USES_I18N", file=u["file"], line=u["line"],
|
|
950
|
-
confidence="exact" if
|
|
1174
|
+
confidence="exact" if key in defs else "heuristic")
|
|
1175
|
+
defined = defs
|
|
1176
|
+
st["i18n_locales"] = sorted(locales)
|
|
1177
|
+
st["i18n_default_locale"] = default
|
|
951
1178
|
st["i18n_keys_used"] = len({u["key"] for u in ctx.facts.get("i18n") or []})
|
|
1179
|
+
st["nitro"] = self._nitro(project, builder)
|
|
952
1180
|
st["i18n_keys_defined"] = len(defined)
|
|
953
1181
|
st["i18n_used_but_undefined"] = len({u["key"] for u in ctx.facts.get("i18n") or []} - set(defined))
|
|
954
1182
|
return st
|
|
1183
|
+
|
|
1184
|
+
# ------------------------------------------------------------ Nitro server routes (#216)
|
|
1185
|
+
def _nitro(self, project: Project, b: GraphBuilder) -> dict:
|
|
1186
|
+
from ..tsweb.common import add_route
|
|
1187
|
+
st = {"routes": 0, "middleware": 0, "plugins": 0, "proxy_routes": 0, "linked_calls": 0}
|
|
1188
|
+
dirs = server_dirs(project.root, self.src_dir)
|
|
1189
|
+
if not dirs:
|
|
1190
|
+
return st
|
|
1191
|
+
files = sorted({n.file for n in b.nodes.values() if n.lang == "ts" and n.kind == "module" and n.file})
|
|
1192
|
+
|
|
1193
|
+
def handler(f: str) -> tuple[str | None, str]:
|
|
1194
|
+
for nid in (f"function:{f}#default", f"function:{f}#handler"):
|
|
1195
|
+
if b.has(nid):
|
|
1196
|
+
return nid, "exact"
|
|
1197
|
+
return (f"module:{f}", "resolved") if b.has(f"module:{f}") else (None, "heuristic")
|
|
1198
|
+
|
|
1199
|
+
def label(f: str, kind: str):
|
|
1200
|
+
for nid in (f"module:{f}", handler(f)[0]):
|
|
1201
|
+
if nid and b.has(nid):
|
|
1202
|
+
b.nodes[nid].attrs["nitro"] = kind
|
|
1203
|
+
|
|
1204
|
+
middleware, routes = [], []
|
|
1205
|
+
for d in dirs:
|
|
1206
|
+
for f in files:
|
|
1207
|
+
if not f.startswith(d + "/"):
|
|
1208
|
+
continue
|
|
1209
|
+
rest = f[len(d) + 1:]
|
|
1210
|
+
top, _, inner = rest.partition("/")
|
|
1211
|
+
if top == "middleware" and inner and nitro_route(inner) is not None:
|
|
1212
|
+
h, _c = handler(f)
|
|
1213
|
+
if h:
|
|
1214
|
+
label(f, "middleware")
|
|
1215
|
+
middleware.append((h, f"nitro:{_NITRO_EXT.sub('', inner)}", "resolved"))
|
|
1216
|
+
st["middleware"] += 1
|
|
1217
|
+
elif top == "plugins" and inner and nitro_route(inner) is not None:
|
|
1218
|
+
h, _c = handler(f)
|
|
1219
|
+
if h:
|
|
1220
|
+
label(f, "plugin")
|
|
1221
|
+
b.nodes[h].entry_kind = b.nodes[h].entry_kind or "main"
|
|
1222
|
+
st["plugins"] += 1
|
|
1223
|
+
elif top in ("api", "routes") and inner:
|
|
1224
|
+
r = nitro_route(inner, "/api" if top == "api" else "")
|
|
1225
|
+
if r:
|
|
1226
|
+
routes.append((f, top, r))
|
|
1227
|
+
for f, top, (method, uri) in routes:
|
|
1228
|
+
h, conf = handler(f)
|
|
1229
|
+
line = (b.nodes[h].line or 1) if h else 1
|
|
1230
|
+
attrs = {"file_route": True, "nitro_dir": top, "method_from": "file suffix" if method != "ANY" else "any"}
|
|
1231
|
+
try:
|
|
1232
|
+
src = (project.root / f).read_text(errors="replace")
|
|
1233
|
+
except OSError:
|
|
1234
|
+
src = ""
|
|
1235
|
+
if _PROXY_CALL.search(src):
|
|
1236
|
+
attrs["proxy"] = True
|
|
1237
|
+
st["proxy_routes"] += 1
|
|
1238
|
+
if not h or h.startswith("module:"):
|
|
1239
|
+
attrs["handler_unresolved"] = True
|
|
1240
|
+
add_route(b, method, uri, [h] if h else [], f, line, "nuxt", conf, attrs, middleware)
|
|
1241
|
+
label(f, "route")
|
|
1242
|
+
st["routes"] += 1
|
|
1243
|
+
st["linked_calls"] = self._link_nitro(b)
|
|
1244
|
+
return st
|
|
1245
|
+
|
|
1246
|
+
def _link_nitro(self, b: GraphBuilder) -> int:
|
|
1247
|
+
"""Same-origin client calls of this app (relative URLs: `$fetch('/api/x')`, `useFetch`) -> its Nitro routes.
|
|
1248
|
+
Proxy routes (proxyRequest / sendProxy) forward elsewhere and are not link targets."""
|
|
1249
|
+
from ...link import match_endpoint
|
|
1250
|
+
routes = []
|
|
1251
|
+
for n in b.nodes.values():
|
|
1252
|
+
a = n.attrs
|
|
1253
|
+
if n.kind == "route" and a.get("framework") == "nuxt" and a.get("uri") and not a.get("proxy"):
|
|
1254
|
+
routes.append({"id": n.id, "uri": a["uri"], "method": a["method"], "uris": [("as-declared", a["uri"])],
|
|
1255
|
+
"file": n.file, "line": n.line})
|
|
1256
|
+
if not routes:
|
|
1257
|
+
return 0
|
|
1258
|
+
rmap = {r["id"]: r for r in routes}
|
|
1259
|
+
linked = 0
|
|
1260
|
+
for n in list(b.nodes.values()):
|
|
1261
|
+
a = n.attrs
|
|
1262
|
+
if n.kind != "http" or n.lang != "ts" or a.get("origin_kind") != "same-origin":
|
|
1263
|
+
continue
|
|
1264
|
+
res = match_endpoint(a.get("method", "GET"), a.get("path", ""), routes, "api", None)
|
|
1265
|
+
for m in res["matched"]:
|
|
1266
|
+
r = rmap[m["route"]]
|
|
1267
|
+
b.add_edge(n.id, m["route"], "MATCHES_ROUTE", file=r["file"], line=r["line"], confidence=m["confidence"],
|
|
1268
|
+
client_path=a.get("path"), uri_variant=m["uri_variant"], segments=m["segments"], in_repo=True)
|
|
1269
|
+
if res["matched"]:
|
|
1270
|
+
linked += 1
|
|
1271
|
+
return linked
|
{cg_code_graph-0.23.1 → cg_code_graph-0.23.2}/cg_code_graph/plugins/ts/extractor/extract.mjs
RENAMED
|
@@ -63,7 +63,11 @@ const INDEX_TESTS = cfg.index_tests !== false
|
|
|
63
63
|
const TEST_FILE_RE = /\.(test|spec|e2e-spec|e2e|cy)\.(t|j)sx?$/
|
|
64
64
|
const TEST_DIR_RE = /(^|\/)(__tests__|e2e|tests?|cypress|playwright)\//
|
|
65
65
|
const TEST_ROOTS = ['e2e', 'test', 'tests', 'cypress', 'playwright', 'src/test', 'src/tests', 'src/e2e']
|
|
66
|
-
|
|
66
|
+
// nested test trees (#156): a `playwright/` or `cypress/` directory below the top level (help/playwright/), and a nested
|
|
67
|
+
// `e2e/` outside the source dirs, are test roots like the top-level ones (filled once the source dirs are known)
|
|
68
|
+
const NESTED_TEST_NAMES = new Set(['playwright', 'cypress', 'e2e'])
|
|
69
|
+
const nestedTestRoots = []
|
|
70
|
+
const isTestRel = r => TEST_FILE_RE.test(r) || /(^|\/)__tests__\//.test(r) || TEST_ROOTS.some(d => r.startsWith(d + '/')) || nestedTestRoots.some(d => r.startsWith(d + '/'))
|
|
67
71
|
|
|
68
72
|
// ---------- file kinds (from the framework plugin: [[prefix, kind], ...]) ----------
|
|
69
73
|
function fileKind(r) {
|
|
@@ -270,9 +274,25 @@ function walkTests(d, all, forced = false) {
|
|
|
270
274
|
else if (SRC_EXT.test(e.name) && (e.isFile() || (e.isSymbolicLink() && !skippedLinks.includes(rel(p)) && fileEntry(e, p))) && !e.name.endsWith('.d.ts') && (all || isTestRel(rel(p)))) testFiles.add(p)
|
|
271
275
|
}
|
|
272
276
|
}
|
|
277
|
+
function findNestedTestRoots(d, depth) {
|
|
278
|
+
if (depth > 6) return
|
|
279
|
+
let ents = []
|
|
280
|
+
try { ents = fs.readdirSync(d, { withFileTypes: true }) } catch { return }
|
|
281
|
+
for (const e of ents) {
|
|
282
|
+
if (!e.isDirectory()) continue
|
|
283
|
+
const p = path.join(d, e.name), r = rel(p)
|
|
284
|
+
if (skipDir(e.name, r, TEST_SKIP_NAMES, false) || excludedRel(r + '/') || TEST_ROOTS.includes(r)) continue
|
|
285
|
+
if (depth > 0 && NESTED_TEST_NAMES.has(e.name) && (e.name !== 'e2e' || !srcDirs.some(s => p === s || p.startsWith(s + path.sep)))) {
|
|
286
|
+
nestedTestRoots.push(r)
|
|
287
|
+
continue
|
|
288
|
+
}
|
|
289
|
+
findNestedTestRoots(p, depth + 1)
|
|
290
|
+
}
|
|
291
|
+
}
|
|
273
292
|
if (INDEX_TESTS) {
|
|
293
|
+
findNestedTestRoots(ROOT, 0)
|
|
274
294
|
for (const d of srcDirs) walkTests(d, false)
|
|
275
|
-
for (const d of TEST_ROOTS) { const p = path.resolve(ROOT, d); if (fs.existsSync(p) && fs.statSync(p).isDirectory()) walkTests(p, true) }
|
|
295
|
+
for (const d of [...TEST_ROOTS, ...nestedTestRoots]) { const p = path.resolve(ROOT, d); if (fs.existsSync(p) && fs.statSync(p).isDirectory()) walkTests(p, true) }
|
|
276
296
|
}
|
|
277
297
|
// scripts the tests run in a subprocess (`spawnSync('node', [path.join(__dirname, '..', 'tools', 'gen.js')])`,
|
|
278
298
|
// `execSync('node tools/gen.js')`) outside every source dir are source files too, so the subprocess link
|
|
@@ -3728,6 +3748,6 @@ fs.writeFileSync(cfg.out, JSON.stringify({ nodes, edges, api_calls: apiCalls, i1
|
|
|
3728
3748
|
// for `cg coverage` (#106): the files analysed, and the roots they come from (source dirs, source files, test trees);
|
|
3729
3749
|
// a discovered file outside every root was never read, so it is not indexed rather than exact
|
|
3730
3750
|
seen_files: [...new Set(sourceFiles.map(sf => rel(realFile(sf))))].sort(),
|
|
3731
|
-
roots: [...srcDirs.map(d => rel(d) + '/'), ...[...srcFiles].map(rel), ...TEST_ROOTS.map(d => d + '/')].filter(r => r && r !== '/' && !r.startsWith('..')),
|
|
3751
|
+
roots: [...srcDirs.map(d => rel(d) + '/'), ...[...srcFiles].map(rel), ...TEST_ROOTS.map(d => d + '/'), ...nestedTestRoots.map(d => d + '/')].filter(r => r && r !== '/' && !r.startsWith('..')),
|
|
3732
3752
|
stats }))
|
|
3733
3753
|
console.log(JSON.stringify(stats))
|
|
@@ -44,6 +44,14 @@ def resolve_targets(st: GraphStore, spec: str) -> list[str]:
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
def _search_hint(spec: str, ambiguous: bool = False) -> str:
|
|
48
|
+
"""One line pointing at `cg search` (the MCP `search` tool) for a snippet spec that matched several nodes or none (#156)."""
|
|
49
|
+
q = spec if re.fullmatch(r"[\w.:#/$-]+", spec or "") else repr(spec)
|
|
50
|
+
if ambiguous:
|
|
51
|
+
return f"run `cg search {q}` (MCP: search) to see the matches with file:line, then snippet one id or FQN"
|
|
52
|
+
return f"try `cg search {q}` (MCP: search) with part of the name, then snippet a listed id or FQN"
|
|
53
|
+
|
|
54
|
+
|
|
47
55
|
def snippet(st: GraphStore, spec: str, context: int = 0, max_lines: int = 200) -> dict:
|
|
48
56
|
"""Source of one symbol, read from disk via the node file / line / end_line. Returns a dict
|
|
49
57
|
whose "status" is one of: ok (id, kind, file, start, end, shown_start, shown_end,
|
|
@@ -52,14 +60,15 @@ def snippet(st: GraphStore, spec: str, context: int = 0, max_lines: int = 200) -
|
|
|
52
60
|
disk, with the paths tried). context adds lines around the span; max_lines caps the body."""
|
|
53
61
|
ids = list(dict.fromkeys(resolve_targets(st, spec)))
|
|
54
62
|
if not ids:
|
|
55
|
-
return {"status": "none", "spec": spec}
|
|
63
|
+
return {"status": "none", "spec": spec, "hint": _search_hint(spec)}
|
|
56
64
|
if len(ids) > 1:
|
|
57
65
|
cands = []
|
|
58
66
|
for nid in ids[:20]:
|
|
59
67
|
n = st.node(nid)
|
|
60
68
|
cands.append({"id": nid, "kind": n["kind"] if n else "?",
|
|
61
69
|
"file": n["file"] if n else None, "line": n["line"] if n else None})
|
|
62
|
-
return {"status": "ambiguous", "spec": spec, "count": len(ids), "candidates": cands
|
|
70
|
+
return {"status": "ambiguous", "spec": spec, "count": len(ids), "candidates": cands,
|
|
71
|
+
"hint": _search_hint(spec, ambiguous=True)}
|
|
63
72
|
nid = ids[0]
|
|
64
73
|
n = st.node(nid)
|
|
65
74
|
if not n or not n["file"] or not n["line"]:
|
|
@@ -95,7 +104,7 @@ def render_snippet(res: dict) -> str:
|
|
|
95
104
|
error line for a non-ok status."""
|
|
96
105
|
status = res.get("status")
|
|
97
106
|
if status == "none":
|
|
98
|
-
return f"no node matches {res['spec']!r};
|
|
107
|
+
return f"no node matches {res['spec']!r}; {res.get('hint') or _search_hint(res['spec'])}"
|
|
99
108
|
if status == "no_source":
|
|
100
109
|
return f"{res['id']}: no source location recorded (nothing to show)"
|
|
101
110
|
if status == "missing":
|
|
@@ -106,6 +115,7 @@ def render_snippet(res: dict) -> str:
|
|
|
106
115
|
for c in res["candidates"]:
|
|
107
116
|
loc = f"{c['file']}:{c['line']}" if c.get("file") else "(no source location)"
|
|
108
117
|
out.append(f" {c['id']} [{c['kind']}] {loc}")
|
|
118
|
+
out.append(res.get("hint") or _search_hint(res["spec"], ambiguous=True))
|
|
109
119
|
return "\n".join(out)
|
|
110
120
|
lines = res["lines"]
|
|
111
121
|
out = [f"{res['file']}:{res['start']}-{res['end']}"]
|
|
@@ -1301,6 +1311,13 @@ def with_generated(row: dict) -> dict:
|
|
|
1301
1311
|
"""A node row without its raw attrs, plus `generated` (the reason) for a node from a generated / copied / vendored
|
|
1302
1312
|
file (indexed with --include-generated)."""
|
|
1303
1313
|
raw = row.pop("attrs", None)
|
|
1314
|
+
if raw and row.get("kind") == "i18n":
|
|
1315
|
+
try:
|
|
1316
|
+
a = json.loads(raw) or {}
|
|
1317
|
+
except ValueError:
|
|
1318
|
+
a = {}
|
|
1319
|
+
row["i18n"] = {"locales": len({d.get("locale") or d.get("file") for d in a.get("definitions") or []}),
|
|
1320
|
+
"uses": a.get("uses") or 0, "missing_locales": a.get("missing_locales") or []}
|
|
1304
1321
|
if raw and ('"platforms"' in raw or '"available"' in raw):
|
|
1305
1322
|
from .platforms import node_platforms
|
|
1306
1323
|
row.update(node_platforms(raw))
|
|
@@ -1592,10 +1609,12 @@ def _impact(st: GraphStore, spec: str, min_conf: str, platform: str | None) -> d
|
|
|
1592
1609
|
built = [t for t in targets if t not in set(not_built)]
|
|
1593
1610
|
targets = built
|
|
1594
1611
|
kinds = CALL_LIKE + DATA_USE if any(t.startswith(DATA_TARGET) for t in targets) else CALL_LIKE
|
|
1612
|
+
if any(t.startswith("i18n:") for t in targets):
|
|
1613
|
+
kinds = kinds + ["USES_I18N"] # the components / pages showing a translation key are its callers (#182)
|
|
1595
1614
|
si = _has_class_target(targets)
|
|
1596
1615
|
rel = override_relations(st, targets, min_conf)
|
|
1597
1616
|
below = override_seeds(st, spec, targets, min_conf)
|
|
1598
|
-
cols = _table_columns(st, targets) if
|
|
1617
|
+
cols = _table_columns(st, targets) if any(t.startswith(DATA_TARGET) for t in targets) else []
|
|
1599
1618
|
seeds = targets + cols + below
|
|
1600
1619
|
depth = reverse_closure(st, seeds, kinds=kinds, min_conf=min_conf, seed_inst=si, platform=platform)
|
|
1601
1620
|
own = reverse_closure(st, targets + cols, kinds=kinds, min_conf=min_conf, seed_inst=si, platform=platform) if below else depth
|
|
@@ -2517,6 +2536,18 @@ def search(st: GraphStore, name: str, kind: str | None = None, limit: int = 20,
|
|
|
2517
2536
|
return out
|
|
2518
2537
|
|
|
2519
2538
|
|
|
2539
|
+
def _i18n_label(r: dict) -> str:
|
|
2540
|
+
"""` (2 locales, 1 use)` for an i18n key row of search (#182)."""
|
|
2541
|
+
a = r.get("i18n")
|
|
2542
|
+
if not a:
|
|
2543
|
+
return ""
|
|
2544
|
+
locs, uses = a.get("locales") or 0, a.get("uses") or 0
|
|
2545
|
+
out = f" ({locs} locale{'s' if locs != 1 else ''}, {uses} use{'s' if uses != 1 else ''})"
|
|
2546
|
+
if a.get("missing_locales"):
|
|
2547
|
+
out += f" missing: {', '.join(a['missing_locales'])}"
|
|
2548
|
+
return out
|
|
2549
|
+
|
|
2550
|
+
|
|
2520
2551
|
def render_search(res: dict, limit_routes: int = 8) -> str:
|
|
2521
2552
|
out = []
|
|
2522
2553
|
if res.get("platform"):
|
|
@@ -2526,7 +2557,7 @@ def render_search(res: dict, limit_routes: int = 8) -> str:
|
|
|
2526
2557
|
out.append(f"{res['platform']['matches_not_built']} matching symbols are not built for {res['platform']['platform']} "
|
|
2527
2558
|
f"(search without platform lists them)")
|
|
2528
2559
|
for r in res["nodes"]:
|
|
2529
|
-
out.append(f"{r['kind']:10} {r['id']} {r['file'] or '?'}:{r['line']}{platform_label(r)}")
|
|
2560
|
+
out.append(f"{r['kind']:10} {r['id']} {r['file'] or '?'}:{r['line']}{platform_label(r)}{_i18n_label(r)}")
|
|
2530
2561
|
if res["guards"]:
|
|
2531
2562
|
if out:
|
|
2532
2563
|
out.append("")
|