strawberry icon indicating copy to clipboard operation
strawberry copied to clipboard

add `locate-definition` command to cli

Open millar opened this issue 5 months ago • 7 comments

Description

Adds a command to locate the definition of an entity within the source code.

Types of Changes

  • [ ] Core
  • [ ] Bugfix
  • [X] New feature
  • [ ] Enhancement/optimization
  • [x] Documentation

Checklist

  • [X] My code follows the code style of this project.
  • [X] My change requires a change to the documentation.
  • [x] I have updated the documentation accordingly.
  • [X] I have read the CONTRIBUTING document.
  • [X] I have added tests to cover my changes.
  • [x] I have tested the changes and verified that they work and don't break anything (as well as I can manage).

Summary by Sourcery

Add a new strawberry locate-definition command backed by a locate_definition utility to locate schema class and field definitions in source code, extend the source finder to detect methods, and include tests and documentation.

New Features:

  • Introduce locate-definition CLI command to find source locations of schema types and fields
  • Add locate_definition utility in strawberry.utils to locate class and attribute definitions

Enhancements:

  • Extend SourceFinder to recognize method definitions when locating class attributes

Documentation:

  • Add CLI user guide for locate-definition and update release notes

Tests:

  • Add CLI and utility tests for successful and missing definition lookups

millar avatar Jun 12 '25 11:06 millar

Reviewer's Guide

Introduces a new locate-definition CLI command backed by a dedicated utility and enhanced SourceFinder logic, registers it in the CLI, and provides corresponding tests and documentation.

Sequence Diagram for locate-definition Command Execution

sequenceDiagram
    title "Sequence Diagram for `locate-definition` Command Execution"
    actor User
    participant CLI
    participant cmd_handler as "LocateDefinitionCommand\n.locate_definition()"
    participant load_schema as "strawberry.cli.utils.load_schema()"
    participant util as "LocateDefinitionUtil\n.locate_definition()"
    participant schema_inst as "Schema Instance"
    participant finder_inst as "SourceFinder Instance"

    User->>CLI: strawberry locate-definition <schema_path> <symbol>
    CLI->>cmd_handler: execute(schema_path, symbol, app_dir)
    cmd_handler->>load_schema: load_schema(schema_path, app_dir)
    load_schema-->>cmd_handler: schema_instance
    cmd_handler->>util: locate_definition(schema_instance, symbol)
    activate util
    util->>finder_inst: new SourceFinder()
    util->>schema_inst: get_type_by_name(model_name from symbol)
    schema_inst-->>util: schema_type
    alt field specified in symbol
        util->>finder_inst: find_class_attribute_from_object(schema_type.origin, field_name from symbol)
        finder_inst-->>util: location_info
    else field not specified
        util->>finder_inst: find_class_from_object(schema_type.origin)
        finder_inst-->>util: location_info
    end
    util-->>cmd_handler: "path:line:col" | None
    deactivate util
    alt location_info is not None
        cmd_handler->>User: output "path:line:col"
    else location_info is None
        cmd_handler->>User: output "Definition not found"
    end

File-Level Changes

Change Details Files
Introduce locate-definition CLI command
  • Create a new Typer command module defining locate-definition with schema loading and error handling
  • Register the command in the CLI entry point
strawberry/cli/commands/locate_definition.py
strawberry/cli/__init__.py
Extend SourceFinder to handle function definitions
  • Include FunctionDef in the pattern matching for class attributes
  • Adjust regex alternatives to detect methods as attributes
strawberry/exceptions/utils/source_finder.py
Implement locate_definition utility function
  • Add locate_definition module using SourceFinder and to_snake_case
  • Parse symbols into model and optional field, lookup source location, and format path with line and column
strawberry/utils/locate_definition.py
Add tests for locate-definition feature
  • Add CLI integration tests for model and field resolution and missing cases
  • Add unit tests for the utility function covering existing and absent symbols
tests/cli/test_locate_definition.py
tests/utils/test_locate_definition.py
Update documentation for the new command
  • Add a CLI docs page detailing usage and examples
  • Update release notes with command description and output format
docs/cli/locate-definition.md
RELEASE.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an issue from a review comment by replying to it. You can also reply to a review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull request title to generate a title at any time. You can also comment @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in the pull request body to generate a PR summary at any time exactly where you want it. You can also comment @sourcery-ai summary on the pull request to (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the pull request to resolve all Sourcery comments. Useful if you've already addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull request to dismiss all existing Sourcery reviews. Especially useful if you want to start fresh with a new review - don't forget to comment @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

  • Contact our support team for questions or feedback.
  • Visit our documentation for detailed guides and information.
  • Keep in touch with the Sourcery team by following us on X/Twitter, LinkedIn or GitHub.

sourcery-ai[bot] avatar Jun 12 '25 11:06 sourcery-ai[bot]

Nice! Is this to add support for the Relay LSP? :D

patrick91 avatar Jun 12 '25 15:06 patrick91

CodSpeed Performance Report

Merging #3902 will not alter performance

Comparing millar:millar-locate-definition (0893bf7) with main (377e6f3)

Summary

✅ 21 untouched benchmarks

codspeed-hq[bot] avatar Jun 12 '25 15:06 codspeed-hq[bot]

Thanks for adding the RELEASE.md file!

Here's a preview of the changelog:


Adds a new CLI command strawberry locate-definition that allows you to find the source location of a definition in the schema.

strawberry locate-definition path.to.schema:schema ObjectName
strawberry locate-definition path.to.schema:schema ObjectName.fieldName

Results take the form of path/to/file.py:line:column, for example: src/models/user.py:45:12.

This can be used, for example, with the go to definition feature of VS Code's Relay extension (configured via the relay.pathToLocateCommand setting).

Here's the tweet text:

🆕 Release (next) is out! Thanks to Sam Millar for the PR 👏

✨ New CLI command: `strawberry locate-definition` - find source locations of
schema definitions! Perfect for @code's Relay extension 🎯 /cc @RelayFramework

Get it here 👉 https://strawberry.rocks/release/(next)

botberry avatar Jun 13 '25 09:06 botberry

@patrick91 yep!

I have been able to get this working in django with the following management command:

# .../graphql/management/commands/graphql_locate.py
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from strawberry.schema import Schema
from strawberry.utils.importer import import_module_symbol
from strawberry.utils.locate_definition import locate_definition


class CommandArguments(BaseCommand):
    def add_arguments(self, parser):
        parser.add_argument("entity", type=str)


class Command(CommandArguments):
    help = "Lookup an entity in the GraphQL schema and return the location of its definition"
    requires_system_checks: list = []

    def handle(self, *args, **options):
        schema_symbol = import_module_symbol(
            settings.GRAPHQL_SCHEMA, default_symbol_name="schema"
        )

        if not (entity := options.get("entity")):
            raise CommandError("Specify an entity to locate")

        if not schema_symbol:
            raise CommandError("Specify schema on GRAPHQL_SCHEMA setting")

        if not isinstance(schema_symbol, Schema):
            raise CommandError("Schema is not a valid Strawberry Schema")

        if location := locate_definition(schema_symbol, entity):
            print(location)
        else:
            raise CommandError(f"Entity `{entity}` not found")

and this bash script

#!/bin/sh

uv run manage.py graphql_locate "$2"

and setting the relay.pathToLocateCommand setting to: ./scripts/graphql_locate.sh

millar avatar Jun 13 '25 10:06 millar

awesome! will properly review this next week 😊 thank you!

patrick91 avatar Jun 14 '25 21:06 patrick91

Codecov Report

Attention: Patch coverage is 46.47059% with 91 lines in your changes missing coverage. Please review.

Project coverage is 94.75%. Comparing base (758cd0b) to head (0893bf7). Report is 25 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3902      +/-   ##
==========================================
- Coverage   95.06%   94.75%   -0.31%     
==========================================
  Files         515      519       +4     
  Lines       33583    33772     +189     
  Branches     1736     1739       +3     
==========================================
+ Hits        31924    32000      +76     
- Misses       1377     1491     +114     
+ Partials      282      281       -1     
:rocket: New features to boost your workflow:
  • :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

codecov[bot] avatar Jun 14 '25 21:06 codecov[bot]

My last two comments look the same 🤣 anyway, this is a really appreciated feature, I can't wait to try it

I've pushed a small change to add support for finding Enums and a couple of tests

patrick91 avatar Jun 20 '25 10:06 patrick91

ok, we also need scalars and unions, I can work on that 😊

patrick91 avatar Jun 20 '25 11:06 patrick91

This should be ready! I'll wait for the tests and then merge it 😊

patrick91 avatar Jun 20 '25 20:06 patrick91

Thanks for contributing to Strawberry! 🎉 You've been invited to join the Strawberry GraphQL organisation 😊

You can also request a free sticker by filling this form: https://forms.gle/dmnfQUPoY5gZbVT67

And don't forget to join our discord server: https://strawberry.rocks/discord 🔥

botberry avatar Jun 20 '25 20:06 botberry